mirror of
https://github.com/SickGear/SickGear.git
synced 2024-12-01 08:53: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!
217 lines
7.7 KiB
Python
217 lines
7.7 KiB
Python
import re
|
|
import types
|
|
from lib.hachoir_core.error import error
|
|
from lib.hachoir_core.i18n import _
|
|
from lib.hachoir_parser import Parser, HachoirParser
|
|
import sys
|
|
|
|
### Parser list ################################################################
|
|
|
|
class ParserList(object):
|
|
VALID_CATEGORY = ("archive", "audio", "container", "file_system",
|
|
"game", "image", "misc", "program", "video")
|
|
ID_REGEX = re.compile("^[a-z0-9][a-z0-9_]{2,}$")
|
|
|
|
def __init__(self):
|
|
self.parser_list = []
|
|
self.bytag = { "id": {}, "category": {} }
|
|
|
|
def translate(self, name, value):
|
|
if name in ("magic",):
|
|
return True
|
|
elif name == "min_size":
|
|
return - value < 0 or "Invalid minimum size (min_size)"
|
|
elif name == "description":
|
|
return isinstance(value, (str, unicode)) and bool(value) or "Invalid description"
|
|
elif name == "category":
|
|
if value not in self.VALID_CATEGORY:
|
|
return "Invalid category: %r" % value
|
|
elif name == "id":
|
|
if type(value) is not str or not self.ID_REGEX.match(value):
|
|
return "Invalid identifier: %r" % value
|
|
parser = self.bytag[name].get(value)
|
|
if parser:
|
|
return "Duplicate parser id: %s already used by %s" % \
|
|
(value, parser[0].__name__)
|
|
# TODO: lists should be forbidden
|
|
if isinstance(value, list):
|
|
value = tuple(value)
|
|
elif not isinstance(value, tuple):
|
|
value = value,
|
|
return name, value
|
|
|
|
def validParser(self, parser, tags):
|
|
if "id" not in tags:
|
|
return "No identifier"
|
|
if "description" not in tags:
|
|
return "No description"
|
|
# TODO: Allow simple strings for file_ext/mime ?
|
|
# (see also HachoirParser.createFilenameSuffix)
|
|
file_ext = tags.get("file_ext", ())
|
|
if not isinstance(file_ext, (tuple, list)):
|
|
return "File extension is not a tuple or list"
|
|
mimes = tags.get("mime", ())
|
|
if not isinstance(mimes, tuple):
|
|
return "MIME type is not a tuple"
|
|
for mime in mimes:
|
|
if not isinstance(mime, unicode):
|
|
return "MIME type %r is not an unicode string" % mime
|
|
|
|
return ""
|
|
|
|
def add(self, parser):
|
|
tags = parser.getParserTags()
|
|
err = self.validParser(parser, tags)
|
|
if err:
|
|
error("Skip parser %s: %s" % (parser.__name__, err))
|
|
return
|
|
|
|
_tags = []
|
|
for tag in tags.iteritems():
|
|
tag = self.translate(*tag)
|
|
if isinstance(tag, tuple):
|
|
_tags.append(tag)
|
|
elif tag is not True:
|
|
error("[%s] %s" % (parser.__name__, tag))
|
|
return
|
|
|
|
self.parser_list.append(parser)
|
|
|
|
for name, values in _tags:
|
|
byname = self.bytag.setdefault(name,{})
|
|
for value in values:
|
|
byname.setdefault(value,[]).append(parser)
|
|
|
|
def __iter__(self):
|
|
return iter(self.parser_list)
|
|
|
|
def print_(self, title=None, out=None, verbose=False, format="one-line"):
|
|
"""Display a list of parser with its title
|
|
* out: output file
|
|
* title : title of the list to display
|
|
* format: "rest", "trac", "file-ext", "mime" or "one_line" (default)
|
|
"""
|
|
if out is None:
|
|
out = sys.stdout
|
|
|
|
if format in ("file-ext", "mime"):
|
|
# Create file extension set
|
|
extensions = set()
|
|
for parser in self:
|
|
file_ext = parser.getParserTags().get(format, ())
|
|
file_ext = list(file_ext)
|
|
try:
|
|
file_ext.remove("")
|
|
except ValueError:
|
|
pass
|
|
extensions |= set(file_ext)
|
|
|
|
# Remove empty extension
|
|
extensions -= set(('',))
|
|
|
|
# Convert to list and sort by ASCII order
|
|
extensions = list(extensions)
|
|
extensions.sort()
|
|
|
|
# Print list
|
|
text = ", ".join( str(item) for item in extensions )
|
|
if format == "file-ext":
|
|
print >>out, "File extensions: %s." % text
|
|
print >>out
|
|
print >>out, "Total: %s file extensions." % len(extensions)
|
|
else:
|
|
print >>out, "MIME types: %s." % text
|
|
print >>out
|
|
print >>out, "Total: %s MIME types." % len(extensions)
|
|
return
|
|
|
|
if format == "trac":
|
|
print >>out, "== List of parsers =="
|
|
print >>out
|
|
print >>out, "Total: %s parsers" % len(self.parser_list)
|
|
print >>out
|
|
elif format == "one_line":
|
|
if title:
|
|
print >>out, title
|
|
else:
|
|
print >>out, _("List of Hachoir parsers.")
|
|
print >>out
|
|
|
|
# Create parser list sorted by module
|
|
bycategory = self.bytag["category"]
|
|
for category in sorted(bycategory.iterkeys()):
|
|
if format == "one_line":
|
|
parser_list = [ parser.PARSER_TAGS["id"] for parser in bycategory[category] ]
|
|
parser_list.sort()
|
|
print >>out, "- %s: %s" % (category.title(), ", ".join(parser_list))
|
|
else:
|
|
if format == "rest":
|
|
print >>out, category.replace("_", " ").title()
|
|
print >>out, "-" * len(category)
|
|
print >>out
|
|
elif format == "trac":
|
|
print >>out, "=== %s ===" % category.replace("_", " ").title()
|
|
print >>out
|
|
else:
|
|
print >>out, "[%s]" % category
|
|
parser_list = sorted(bycategory[category],
|
|
key=lambda parser: parser.PARSER_TAGS["id"])
|
|
if format == "rest":
|
|
for parser in parser_list:
|
|
tags = parser.getParserTags()
|
|
print >>out, "* %s: %s" % (tags["id"], tags["description"])
|
|
elif format == "trac":
|
|
for parser in parser_list:
|
|
tags = parser.getParserTags()
|
|
desc = tags["description"]
|
|
desc = re.sub(r"([A-Z][a-z]+[A-Z][^ ]+)", r"!\1", desc)
|
|
print >>out, " * %s: %s" % (tags["id"], desc)
|
|
else:
|
|
for parser in parser_list:
|
|
parser.print_(out, verbose)
|
|
print >>out
|
|
if format != "trac":
|
|
print >>out, "Total: %s parsers" % len(self.parser_list)
|
|
|
|
|
|
class HachoirParserList(ParserList):
|
|
_instance = None
|
|
|
|
@classmethod
|
|
def getInstance(cls):
|
|
if cls._instance is None:
|
|
cls._instance = cls()
|
|
return cls._instance
|
|
|
|
def __init__(self):
|
|
ParserList.__init__(self)
|
|
self._load()
|
|
|
|
def _load(self):
|
|
"""
|
|
Load all parsers from "hachoir.parser" module.
|
|
|
|
Return the list of loaded parsers.
|
|
"""
|
|
# Parser list is already loaded?
|
|
if self.parser_list:
|
|
return self.parser_list
|
|
|
|
todo = []
|
|
from lib import hachoir_parser
|
|
module = hachoir_parser
|
|
for attrname in dir(module):
|
|
attr = getattr(module, attrname)
|
|
if isinstance(attr, types.ModuleType):
|
|
todo.append(attr)
|
|
|
|
for module in todo:
|
|
for name in dir(module):
|
|
attr = getattr(module, name)
|
|
if isinstance(attr, type) \
|
|
and issubclass(attr, HachoirParser) \
|
|
and attr not in (Parser, HachoirParser):
|
|
self.add(attr)
|
|
assert 1 <= len(self.parser_list)
|
|
return self.parser_list
|
|
|