mirror of
https://github.com/SickGear/SickGear.git
synced 2024-12-01 00:43:37 +00:00
0d9fbc1ad7
This version of SickBeard uses both TVDB and TVRage to search and gather it's series data from allowing you to now have access to and download shows that you couldn't before because of being locked into only what TheTVDB had to offer. Also this edition is based off the code we used in our XEM editon so it does come with scene numbering support as well as all the other features our XEM edition has to offer. Please before using this with your existing database (sickbeard.db) please make a backup copy of it and delete any other database files such as cache.db and failed.db if present, we HIGHLY recommend starting out with no database files at all to make this a fresh start but the choice is at your own risk! Enjoy!
177 lines
7 KiB
Python
177 lines
7 KiB
Python
# Copyright (c) 2003-2005 Jimmy Retzlaff, 2008 Konstantin Yegupov
|
|
#
|
|
# Permission is hereby granted, free of charge, to any person obtaining
|
|
# a copy of this software and associated documentation files (the
|
|
# "Software"), to deal in the Software without restriction, including
|
|
# without limitation the rights to use, copy, modify, merge, publish,
|
|
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
# permit persons to whom the Software is furnished to do so, subject to
|
|
# the following conditions:
|
|
#
|
|
# The above copyright notice and this permission notice shall be
|
|
# included in all copies or substantial portions of the Software.
|
|
#
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
# SOFTWARE.
|
|
|
|
"""
|
|
pyUnRAR2 is a ctypes based wrapper around the free UnRAR.dll.
|
|
|
|
It is an modified version of Jimmy Retzlaff's pyUnRAR - more simple,
|
|
stable and foolproof.
|
|
Notice that it has INCOMPATIBLE interface.
|
|
|
|
It enables reading and unpacking of archives created with the
|
|
RAR/WinRAR archivers. There is a low-level interface which is very
|
|
similar to the C interface provided by UnRAR. There is also a
|
|
higher level interface which makes some common operations easier.
|
|
"""
|
|
|
|
__version__ = '0.99.3'
|
|
|
|
try:
|
|
WindowsError
|
|
in_windows = True
|
|
except NameError:
|
|
in_windows = False
|
|
|
|
if in_windows:
|
|
from windows import RarFileImplementation
|
|
else:
|
|
from unix import RarFileImplementation
|
|
|
|
|
|
import fnmatch, time, weakref
|
|
|
|
class RarInfo(object):
|
|
"""Represents a file header in an archive. Don't instantiate directly.
|
|
Use only to obtain information about file.
|
|
YOU CANNOT EXTRACT FILE CONTENTS USING THIS OBJECT.
|
|
USE METHODS OF RarFile CLASS INSTEAD.
|
|
|
|
Properties:
|
|
index - index of file within the archive
|
|
filename - name of the file in the archive including path (if any)
|
|
datetime - file date/time as a struct_time suitable for time.strftime
|
|
isdir - True if the file is a directory
|
|
size - size in bytes of the uncompressed file
|
|
comment - comment associated with the file
|
|
|
|
Note - this is not currently intended to be a Python file-like object.
|
|
"""
|
|
|
|
def __init__(self, rarfile, data):
|
|
self.rarfile = weakref.proxy(rarfile)
|
|
self.index = data['index']
|
|
self.filename = data['filename']
|
|
self.isdir = data['isdir']
|
|
self.size = data['size']
|
|
self.datetime = data['datetime']
|
|
self.comment = data['comment']
|
|
|
|
|
|
|
|
def __str__(self):
|
|
try :
|
|
arcName = self.rarfile.archiveName
|
|
except ReferenceError:
|
|
arcName = "[ARCHIVE_NO_LONGER_LOADED]"
|
|
return '<RarInfo "%s" in "%s">' % (self.filename, arcName)
|
|
|
|
class RarFile(RarFileImplementation):
|
|
|
|
def __init__(self, archiveName, password=None):
|
|
"""Instantiate the archive.
|
|
|
|
archiveName is the name of the RAR file.
|
|
password is used to decrypt the files in the archive.
|
|
|
|
Properties:
|
|
comment - comment associated with the archive
|
|
|
|
>>> print RarFile('test.rar').comment
|
|
This is a test.
|
|
"""
|
|
self.archiveName = archiveName
|
|
RarFileImplementation.init(self, password)
|
|
|
|
def __del__(self):
|
|
self.destruct()
|
|
|
|
def infoiter(self):
|
|
"""Iterate over all the files in the archive, generating RarInfos.
|
|
|
|
>>> import os
|
|
>>> for fileInArchive in RarFile('test.rar').infoiter():
|
|
... print os.path.split(fileInArchive.filename)[-1],
|
|
... print fileInArchive.isdir,
|
|
... print fileInArchive.size,
|
|
... print fileInArchive.comment,
|
|
... print tuple(fileInArchive.datetime)[0:5],
|
|
... print time.strftime('%a, %d %b %Y %H:%M', fileInArchive.datetime)
|
|
test True 0 None (2003, 6, 30, 1, 59) Mon, 30 Jun 2003 01:59
|
|
test.txt False 20 None (2003, 6, 30, 2, 1) Mon, 30 Jun 2003 02:01
|
|
this.py False 1030 None (2002, 2, 8, 16, 47) Fri, 08 Feb 2002 16:47
|
|
"""
|
|
for params in RarFileImplementation.infoiter(self):
|
|
yield RarInfo(self, params)
|
|
|
|
def infolist(self):
|
|
"""Return a list of RarInfos, descripting the contents of the archive."""
|
|
return list(self.infoiter())
|
|
|
|
def read_files(self, condition='*'):
|
|
"""Read specific files from archive into memory.
|
|
If "condition" is a list of numbers, then return files which have those positions in infolist.
|
|
If "condition" is a string, then it is treated as a wildcard for names of files to extract.
|
|
If "condition" is a function, it is treated as a callback function, which accepts a RarInfo object
|
|
and returns boolean True (extract) or False (skip).
|
|
If "condition" is omitted, all files are returned.
|
|
|
|
Returns list of tuples (RarInfo info, str contents)
|
|
"""
|
|
checker = condition2checker(condition)
|
|
return RarFileImplementation.read_files(self, checker)
|
|
|
|
|
|
def extract(self, condition='*', path='.', withSubpath=True, overwrite=True):
|
|
"""Extract specific files from archive to disk.
|
|
|
|
If "condition" is a list of numbers, then extract files which have those positions in infolist.
|
|
If "condition" is a string, then it is treated as a wildcard for names of files to extract.
|
|
If "condition" is a function, it is treated as a callback function, which accepts a RarInfo object
|
|
and returns either boolean True (extract) or boolean False (skip).
|
|
DEPRECATED: If "condition" callback returns string (only supported for Windows) -
|
|
that string will be used as a new name to save the file under.
|
|
If "condition" is omitted, all files are extracted.
|
|
|
|
"path" is a directory to extract to
|
|
"withSubpath" flag denotes whether files are extracted with their full path in the archive.
|
|
"overwrite" flag denotes whether extracted files will overwrite old ones. Defaults to true.
|
|
|
|
Returns list of RarInfos for extracted files."""
|
|
checker = condition2checker(condition)
|
|
return RarFileImplementation.extract(self, checker, path, withSubpath, overwrite)
|
|
|
|
def condition2checker(condition):
|
|
"""Converts different condition types to callback"""
|
|
if type(condition) in [str, unicode]:
|
|
def smatcher(info):
|
|
return fnmatch.fnmatch(info.filename, condition)
|
|
return smatcher
|
|
elif type(condition) in [list, tuple] and type(condition[0]) in [int, long]:
|
|
def imatcher(info):
|
|
return info.index in condition
|
|
return imatcher
|
|
elif callable(condition):
|
|
return condition
|
|
else:
|
|
raise TypeError
|
|
|
|
|