Merge remote-tracking branch 'RuudBurger/develop' into tv

Conflicts:
	couchpotato/core/plugins/quality/main.py
This commit is contained in:
Dean Gardiner
2014-07-27 23:49:49 +12:00
79 changed files with 957 additions and 609 deletions
+14 -14
View File
@@ -21,7 +21,7 @@
# SOFTWARE.
"""
pyUnRAR2 is a ctypes based wrapper around the free UnRAR.dll.
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.
@@ -45,8 +45,8 @@ if in_windows:
from windows import RarFileImplementation
else:
from unix import RarFileImplementation
import fnmatch, time, weakref
class RarInfo(object):
@@ -62,7 +62,7 @@ class RarInfo(object):
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.
"""
@@ -74,7 +74,7 @@ class RarInfo(object):
self.size = data['size']
self.datetime = data['datetime']
self.comment = data['comment']
def __str__(self):
@@ -86,7 +86,7 @@ class RarInfo(object):
class RarFile(RarFileImplementation):
def __init__(self, archiveName, password=None):
def __init__(self, archiveName, password=None, custom_path = None):
"""Instantiate the archive.
archiveName is the name of the RAR file.
@@ -99,7 +99,7 @@ class RarFile(RarFileImplementation):
This is a test.
"""
self.archiveName = archiveName
RarFileImplementation.init(self, password)
RarFileImplementation.init(self, password, custom_path)
def __del__(self):
self.destruct()
@@ -130,31 +130,31 @@ class RarFile(RarFileImplementation):
"""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
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) -
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)
+21 -9
View File
@@ -21,25 +21,37 @@
# SOFTWARE.
# Unix version uses unrar command line executable
import platform
import stat
import subprocess
import gc
import os, os.path
import time, re
import os
import os.path
import time
import re
from rar_exceptions import *
class UnpackerNotInstalled(Exception): pass
rar_executable_cached = None
rar_executable_version = None
def call_unrar(params):
osx_unrar = os.path.join(os.path.dirname(__file__), 'unrar')
if os.path.isfile(osx_unrar) and 'darwin' in platform.platform().lower():
try:
st = os.stat(osx_unrar)
os.chmod(osx_unrar, st.st_mode | stat.S_IEXEC)
except:
pass
def call_unrar(params, custom_path = None):
"Calls rar/unrar command line executable, returns stdout pipe"
global rar_executable_cached
if rar_executable_cached is None:
for command in ('unrar', 'rar', os.path.join(os.path.dirname(__file__), 'unrar')):
for command in (custom_path, 'unrar', 'rar', osx_unrar):
if not command: continue
try:
subprocess.Popen([command], stdout = subprocess.PIPE)
rar_executable_cached = command
@@ -59,10 +71,10 @@ def call_unrar(params):
class RarFileImplementation(object):
def init(self, password = None):
def init(self, password = None, custom_path = None):
global rar_executable_version
self.password = password
self.custom_path = custom_path
stdoutdata, stderrdata = self.call('v', []).communicate()
@@ -118,7 +130,7 @@ class RarFileImplementation(object):
def call(self, cmd, options = [], files = []):
options2 = options + ['p' + self.escaped_password()]
soptions = ['-' + x for x in options2]
return call_unrar([cmd] + soptions + ['--', self.archiveName] + files)
return call_unrar([cmd] + soptions + ['--', self.archiveName] + files, self.custom_path)
def infoiter(self):
+12 -12
View File
@@ -174,7 +174,7 @@ class PassiveReader:
def __init__(self, usercallback = None):
self.buf = []
self.ucb = usercallback
def _callback(self, msg, UserData, P1, P2):
if msg == UCM_PROCESSDATA:
data = (ctypes.c_char*P2).from_address(P1).raw
@@ -183,7 +183,7 @@ class PassiveReader:
else:
self.buf.append(data)
return 1
def get_result(self):
return ''.join(self.buf)
@@ -197,10 +197,10 @@ class RarInfoIterator(object):
raise IncorrectRARPassword
self.arc.lockStatus = "locked"
self.arc.needskip = False
def __iter__(self):
return self
def next(self):
if self.index>0:
if self.arc.needskip:
@@ -208,9 +208,9 @@ class RarInfoIterator(object):
self.res = RARReadHeaderEx(self.arc._handle, ctypes.byref(self.headerData))
if self.res:
raise StopIteration
raise StopIteration
self.arc.needskip = True
data = {}
data['index'] = self.index
data['filename'] = self.headerData.FileName
@@ -224,7 +224,7 @@ class RarInfoIterator(object):
self.index += 1
return data
def __del__(self):
self.arc.lockStatus = "finished"
@@ -237,7 +237,7 @@ def generate_password_provider(password):
class RarFileImplementation(object):
def init(self, password=None):
def init(self, password=None, custom_path = None):
self.password = password
archiveData = RAROpenArchiveDataEx(ArcNameW=self.archiveName, OpenMode=RAR_OM_EXTRACT)
self._handle = RAROpenArchiveEx(ctypes.byref(archiveData))
@@ -254,9 +254,9 @@ class RarFileImplementation(object):
if password:
RARSetPassword(self._handle, password)
self.lockStatus = "ready"
def destruct(self):
@@ -287,7 +287,7 @@ class RarFileImplementation(object):
self.needskip = False
res.append((info, reader.get_result()))
return res
def extract(self, checker, path, withSubpath, overwrite):
res = []
@@ -300,7 +300,7 @@ class RarFileImplementation(object):
fn = os.path.split(fn)[-1]
target = os.path.join(path, fn)
else:
raise DeprecationWarning, "Condition callbacks returning strings are deprecated and only supported in Windows"
raise DeprecationWarning, "Condition callbacks returning strings are deprecated and only supported in Windows"
target = checkres
if overwrite or (not os.path.exists(target)):
tmpres = RARProcessFile(self._handle, RAR_EXTRACT, None, target)