mirror of
https://github.com/SickGear/SickGear.git
synced 2024-12-05 02:43:37 +00:00
980e05cc99
Backported 400 revisions from rev 1de4961-8897c5b (2018-2014). Move core/benchmark, core/cmd_line, core/memory, core/profiler and core/timeout to core/optional/* Remove metadata/qt* PORT: Version 2.0a3 (inline with 3.0a3 @ f80c7d5). Basic Support for XMP Packets. tga: improvements to adhere more closely to the spec. pdf: slightly improved parsing. rar: fix TypeError on unknown block types. Add MacRoman win32 codepage. tiff/exif: support SubIFDs and tiled images. Add method to export metadata in dictionary. mpeg_video: don't attempt to parse Stream past length. mpeg_video: parse ESCR correctly, add SCR value. Change centralise CustomFragments. field: don't set parser class if class is None, to enable autodetect. field: add value/display for CustomFragment. parser: inline warning to enable tracebacks in debug mode. Fix empty bytestrings in makePrintable. Fix contentSize in jpeg.py to account for image_data blocks. Fix the ELF parser. Enhance the AR archive parser. elf parser: fix wrong wrong fields order in parsing little endian section flags. elf parser: add s390 as a machine type. Flesh out mp4 parser. PORT: Version 2.0a1 (inline with 3.0a1). Major refactoring and PEP8. Fix ResourceWarning warnings on files. Add a close() method and support for the context manager protocol ("with obj: ...") to parsers, input and output streams. metadata: get comment from ZIP. Support for InputIOStream.read(0). Fix sizeGe when size is None. Remove unused new_seekable_field_set file. Remove parser Mapsforge .map. Remove parser Parallel Realities Starfighter .pak files. sevenzip: fix for newer archives. java: update access flags and modifiers for Java 1.7 and update description text for most recent Java. Support ustar prefix field in tar archives. Remove file_system* parsers. Remove misc parsers 3d0, 3ds, gnome_keyring, msoffice*, mstask, ole*, word*. Remove program parsers macho, nds, prc. Support non-8bit Character subclasses. Python parser supports Python 3.7. Enhance mpeg_ts parser to support MTS/M2TS. Support for creation date in tiff. Change don't hardcode errno constant. PORT: 1.9.1 Internal Only: The following are legacy reference to upstream commit messages. Relevant changes up to b0a115f8. Use integer division. Replace HACHOIR_ERRORS with Exception. Fix metadata.Data: make it sortable. Import fixes from e7de492. PORT: Version 2.0a1 (inline with 3.0a1 @ e9f8fad). Replace hachoir.core.field with hachoir.field Replace hachoir.core.stream with hachoir.stream Remove the compatibility module for PY1.5 to PY2.5. metadata: support TIFF picture. metadata: fix string normalization. metadata: fix datetime regex Fix hachoir bug #57. FileFromInputStream: fix comparison between None and an int. InputIOStream: open the file in binary mode.
142 lines
4.4 KiB
Python
142 lines
4.4 KiB
Python
"""
|
|
Parser list managment:
|
|
- createParser() find the best parser for a file.
|
|
"""
|
|
|
|
import os
|
|
from hachoir.core.error import warning, info
|
|
from hachoir.parser import ValidateError, HachoirParserList
|
|
from hachoir.stream import FileInputStream
|
|
from hachoir.core.i18n import _
|
|
import weakref
|
|
|
|
|
|
class QueryParser(object):
|
|
fallback = None
|
|
other = None
|
|
|
|
def __init__(self, tags):
|
|
self.validate = True
|
|
self.use_fallback = False
|
|
self.parser_args = None
|
|
self.db = HachoirParserList.getInstance()
|
|
self.parsers = set(self.db)
|
|
parsers = []
|
|
for tag in tags:
|
|
if not self.parsers:
|
|
break
|
|
parsers += self._getByTag(tag)
|
|
if self.fallback is None:
|
|
self.fallback = len(parsers) == 1
|
|
if self.parsers:
|
|
other = len(parsers)
|
|
parsers += list(self.parsers)
|
|
self.other = parsers[other]
|
|
self.parsers = parsers
|
|
|
|
def __iter__(self):
|
|
return iter(self.parsers)
|
|
|
|
def translate(self, name, value):
|
|
if name == "filename":
|
|
filename = os.path.basename(value).split(".")
|
|
if len(filename) <= 1:
|
|
value = ""
|
|
else:
|
|
value = filename[-1].lower()
|
|
name = "file_ext"
|
|
return name, value
|
|
|
|
def _getByTag(self, tag):
|
|
if tag is None:
|
|
self.parsers.clear()
|
|
return []
|
|
elif callable(tag):
|
|
parsers = [parser for parser in self.parsers if tag(parser)]
|
|
for parser in parsers:
|
|
self.parsers.remove(parser)
|
|
elif tag[0] == "class":
|
|
self.validate = False
|
|
return [tag[1]]
|
|
elif tag[0] == "args":
|
|
self.parser_args = tag[1]
|
|
return []
|
|
else:
|
|
tag = self.translate(*tag)
|
|
parsers = []
|
|
if tag is not None:
|
|
key = tag[0]
|
|
byname = self.db.bytag.get(key, {})
|
|
if tag[1] is None:
|
|
values = byname.itervalues()
|
|
else:
|
|
values = byname.get(tag[1], ()),
|
|
if key == "id" and values:
|
|
self.validate = False
|
|
for value in values:
|
|
for parser in value:
|
|
if parser in self.parsers:
|
|
parsers.append(parser)
|
|
self.parsers.remove(parser)
|
|
return parsers
|
|
|
|
def parse(self, stream, fallback=True):
|
|
if hasattr(stream, "_cached_parser"):
|
|
parser = stream._cached_parser()
|
|
else:
|
|
parser = None
|
|
if parser is not None:
|
|
if parser.__class__ in self.parsers:
|
|
return parser
|
|
parser = self.doparse(stream, fallback)
|
|
if parser is not None:
|
|
stream._cached_parser = weakref.ref(parser)
|
|
else:
|
|
try:
|
|
stream._input.close()
|
|
except:
|
|
pass
|
|
return parser
|
|
|
|
def doparse(self, stream, fallback=True):
|
|
fb = None
|
|
warn = warning
|
|
for parser in self.parsers:
|
|
try:
|
|
parser_obj = parser(stream, validate=self.validate)
|
|
if self.parser_args:
|
|
for key, value in self.parser_args.iteritems():
|
|
setattr(parser_obj, key, value)
|
|
return parser_obj
|
|
except ValidateError as err:
|
|
if fallback and self.fallback:
|
|
fb = parser
|
|
if parser == self.other:
|
|
warn = info
|
|
warn("Skip parser '%s': %s" % (parser.__name__, err))
|
|
except Exception as err:
|
|
if parser == self.other:
|
|
warn = info
|
|
warn("Skip parser '%s': %s" % (parser.__name__, err))
|
|
fallback = False
|
|
if self.use_fallback and fb:
|
|
warning(_("Force use of parser '%s'") % fb.__name__)
|
|
return fb(stream)
|
|
|
|
|
|
def guessParser(stream):
|
|
return QueryParser(stream.tags).parse(stream)
|
|
|
|
|
|
def createParser(filename, real_filename=None, tags=None):
|
|
"""
|
|
Create a parser from a file or returns None on error.
|
|
|
|
Options:
|
|
- filename (unicode): Input file name ;
|
|
- real_filename (str|unicode): Real file name.
|
|
"""
|
|
if not tags:
|
|
tags = []
|
|
stream = FileInputStream(filename, real_filename, tags=tags)
|
|
return guessParser(stream)
|