SickGear/lib/hachoir/parser/guess.py
JackDandy 980e05cc99 Change Hachoir can't support PY2 so backport their PY3 to prevent a need for system dependant external binaries like mediainfo.
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.
2018-03-28 00:43:11 +01:00

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)