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!
344 lines
12 KiB
Python
344 lines
12 KiB
Python
try:
|
|
from types import ModuleType
|
|
except:
|
|
from new import module as ModuleType
|
|
import re
|
|
import types
|
|
|
|
import _base
|
|
from html5lib import ihatexml
|
|
from html5lib import constants
|
|
from html5lib.constants import namespaces
|
|
|
|
tag_regexp = re.compile("{([^}]*)}(.*)")
|
|
|
|
moduleCache = {}
|
|
|
|
def getETreeModule(ElementTreeImplementation, fullTree=False):
|
|
name = "_" + ElementTreeImplementation.__name__+"builder"
|
|
if name in moduleCache:
|
|
return moduleCache[name]
|
|
else:
|
|
mod = ModuleType("_" + ElementTreeImplementation.__name__+"builder")
|
|
objs = getETreeBuilder(ElementTreeImplementation, fullTree)
|
|
mod.__dict__.update(objs)
|
|
moduleCache[name] = mod
|
|
return mod
|
|
|
|
def getETreeBuilder(ElementTreeImplementation, fullTree=False):
|
|
ElementTree = ElementTreeImplementation
|
|
class Element(_base.Node):
|
|
def __init__(self, name, namespace=None):
|
|
self._name = name
|
|
self._namespace = namespace
|
|
self._element = ElementTree.Element(self._getETreeTag(name,
|
|
namespace))
|
|
if namespace is None:
|
|
self.nameTuple = namespaces["html"], self._name
|
|
else:
|
|
self.nameTuple = self._namespace, self._name
|
|
self.parent = None
|
|
self._childNodes = []
|
|
self._flags = []
|
|
|
|
def _getETreeTag(self, name, namespace):
|
|
if namespace is None:
|
|
etree_tag = name
|
|
else:
|
|
etree_tag = "{%s}%s"%(namespace, name)
|
|
return etree_tag
|
|
|
|
def _setName(self, name):
|
|
self._name = name
|
|
self._element.tag = self._getETreeTag(self._name, self._namespace)
|
|
|
|
def _getName(self):
|
|
return self._name
|
|
|
|
name = property(_getName, _setName)
|
|
|
|
def _setNamespace(self, namespace):
|
|
self._namespace = namespace
|
|
self._element.tag = self._getETreeTag(self._name, self._namespace)
|
|
|
|
def _getNamespace(self):
|
|
return self._namespace
|
|
|
|
namespace = property(_getNamespace, _setNamespace)
|
|
|
|
def _getAttributes(self):
|
|
return self._element.attrib
|
|
|
|
def _setAttributes(self, attributes):
|
|
#Delete existing attributes first
|
|
#XXX - there may be a better way to do this...
|
|
for key in self._element.attrib.keys():
|
|
del self._element.attrib[key]
|
|
for key, value in attributes.iteritems():
|
|
if isinstance(key, tuple):
|
|
name = "{%s}%s"%(key[2], key[1])
|
|
else:
|
|
name = key
|
|
self._element.set(name, value)
|
|
|
|
attributes = property(_getAttributes, _setAttributes)
|
|
|
|
def _getChildNodes(self):
|
|
return self._childNodes
|
|
def _setChildNodes(self, value):
|
|
del self._element[:]
|
|
self._childNodes = []
|
|
for element in value:
|
|
self.insertChild(element)
|
|
|
|
childNodes = property(_getChildNodes, _setChildNodes)
|
|
|
|
def hasContent(self):
|
|
"""Return true if the node has children or text"""
|
|
return bool(self._element.text or len(self._element))
|
|
|
|
def appendChild(self, node):
|
|
self._childNodes.append(node)
|
|
self._element.append(node._element)
|
|
node.parent = self
|
|
|
|
def insertBefore(self, node, refNode):
|
|
index = list(self._element).index(refNode._element)
|
|
self._element.insert(index, node._element)
|
|
node.parent = self
|
|
|
|
def removeChild(self, node):
|
|
self._element.remove(node._element)
|
|
node.parent=None
|
|
|
|
def insertText(self, data, insertBefore=None):
|
|
if not(len(self._element)):
|
|
if not self._element.text:
|
|
self._element.text = ""
|
|
self._element.text += data
|
|
elif insertBefore is None:
|
|
#Insert the text as the tail of the last child element
|
|
if not self._element[-1].tail:
|
|
self._element[-1].tail = ""
|
|
self._element[-1].tail += data
|
|
else:
|
|
#Insert the text before the specified node
|
|
children = list(self._element)
|
|
index = children.index(insertBefore._element)
|
|
if index > 0:
|
|
if not self._element[index-1].tail:
|
|
self._element[index-1].tail = ""
|
|
self._element[index-1].tail += data
|
|
else:
|
|
if not self._element.text:
|
|
self._element.text = ""
|
|
self._element.text += data
|
|
|
|
def cloneNode(self):
|
|
element = type(self)(self.name, self.namespace)
|
|
for name, value in self.attributes.iteritems():
|
|
element.attributes[name] = value
|
|
return element
|
|
|
|
def reparentChildren(self, newParent):
|
|
if newParent.childNodes:
|
|
newParent.childNodes[-1]._element.tail += self._element.text
|
|
else:
|
|
if not newParent._element.text:
|
|
newParent._element.text = ""
|
|
if self._element.text is not None:
|
|
newParent._element.text += self._element.text
|
|
self._element.text = ""
|
|
_base.Node.reparentChildren(self, newParent)
|
|
|
|
class Comment(Element):
|
|
def __init__(self, data):
|
|
#Use the superclass constructor to set all properties on the
|
|
#wrapper element
|
|
self._element = ElementTree.Comment(data)
|
|
self.parent = None
|
|
self._childNodes = []
|
|
self._flags = []
|
|
|
|
def _getData(self):
|
|
return self._element.text
|
|
|
|
def _setData(self, value):
|
|
self._element.text = value
|
|
|
|
data = property(_getData, _setData)
|
|
|
|
class DocumentType(Element):
|
|
def __init__(self, name, publicId, systemId):
|
|
Element.__init__(self, "<!DOCTYPE>")
|
|
self._element.text = name
|
|
self.publicId = publicId
|
|
self.systemId = systemId
|
|
|
|
def _getPublicId(self):
|
|
return self._element.get(u"publicId", "")
|
|
|
|
def _setPublicId(self, value):
|
|
if value is not None:
|
|
self._element.set(u"publicId", value)
|
|
|
|
publicId = property(_getPublicId, _setPublicId)
|
|
|
|
def _getSystemId(self):
|
|
return self._element.get(u"systemId", "")
|
|
|
|
def _setSystemId(self, value):
|
|
if value is not None:
|
|
self._element.set(u"systemId", value)
|
|
|
|
systemId = property(_getSystemId, _setSystemId)
|
|
|
|
class Document(Element):
|
|
def __init__(self):
|
|
Element.__init__(self, "<DOCUMENT_ROOT>")
|
|
|
|
class DocumentFragment(Element):
|
|
def __init__(self):
|
|
Element.__init__(self, "<DOCUMENT_FRAGMENT>")
|
|
|
|
def testSerializer(element):
|
|
rv = []
|
|
finalText = None
|
|
def serializeElement(element, indent=0):
|
|
if not(hasattr(element, "tag")):
|
|
element = element.getroot()
|
|
if element.tag == "<!DOCTYPE>":
|
|
if element.get("publicId") or element.get("systemId"):
|
|
publicId = element.get("publicId") or ""
|
|
systemId = element.get("systemId") or ""
|
|
rv.append( """<!DOCTYPE %s "%s" "%s">"""%(
|
|
element.text, publicId, systemId))
|
|
else:
|
|
rv.append("<!DOCTYPE %s>"%(element.text,))
|
|
elif element.tag == "<DOCUMENT_ROOT>":
|
|
rv.append("#document")
|
|
if element.text:
|
|
rv.append("|%s\"%s\""%(' '*(indent+2), element.text))
|
|
if element.tail:
|
|
finalText = element.tail
|
|
elif element.tag == ElementTree.Comment:
|
|
rv.append("|%s<!-- %s -->"%(' '*indent, element.text))
|
|
else:
|
|
assert type(element.tag) in types.StringTypes, "Expected unicode, got %s"%type(element.tag)
|
|
nsmatch = tag_regexp.match(element.tag)
|
|
|
|
if nsmatch is None:
|
|
name = element.tag
|
|
else:
|
|
ns, name = nsmatch.groups()
|
|
prefix = constants.prefixes[ns]
|
|
name = "%s %s"%(prefix, name)
|
|
rv.append("|%s<%s>"%(' '*indent, name))
|
|
|
|
if hasattr(element, "attrib"):
|
|
attributes = []
|
|
for name, value in element.attrib.iteritems():
|
|
nsmatch = tag_regexp.match(name)
|
|
if nsmatch is not None:
|
|
ns, name = nsmatch.groups()
|
|
prefix = constants.prefixes[ns]
|
|
attr_string = "%s %s"%(prefix, name)
|
|
else:
|
|
attr_string = name
|
|
attributes.append((attr_string, value))
|
|
|
|
for name, value in sorted(attributes):
|
|
rv.append('|%s%s="%s"' % (' '*(indent+2), name, value))
|
|
if element.text:
|
|
rv.append("|%s\"%s\"" %(' '*(indent+2), element.text))
|
|
indent += 2
|
|
for child in element:
|
|
serializeElement(child, indent)
|
|
if element.tail:
|
|
rv.append("|%s\"%s\"" %(' '*(indent-2), element.tail))
|
|
serializeElement(element, 0)
|
|
|
|
if finalText is not None:
|
|
rv.append("|%s\"%s\""%(' '*2, finalText))
|
|
|
|
return "\n".join(rv)
|
|
|
|
def tostring(element):
|
|
"""Serialize an element and its child nodes to a string"""
|
|
rv = []
|
|
finalText = None
|
|
filter = ihatexml.InfosetFilter()
|
|
def serializeElement(element):
|
|
if type(element) == type(ElementTree.ElementTree):
|
|
element = element.getroot()
|
|
|
|
if element.tag == "<!DOCTYPE>":
|
|
if element.get("publicId") or element.get("systemId"):
|
|
publicId = element.get("publicId") or ""
|
|
systemId = element.get("systemId") or ""
|
|
rv.append( """<!DOCTYPE %s PUBLIC "%s" "%s">"""%(
|
|
element.text, publicId, systemId))
|
|
else:
|
|
rv.append("<!DOCTYPE %s>"%(element.text,))
|
|
elif element.tag == "<DOCUMENT_ROOT>":
|
|
if element.text:
|
|
rv.append(element.text)
|
|
if element.tail:
|
|
finalText = element.tail
|
|
|
|
for child in element:
|
|
serializeElement(child)
|
|
|
|
elif type(element.tag) == type(ElementTree.Comment):
|
|
rv.append("<!--%s-->"%(element.text,))
|
|
else:
|
|
#This is assumed to be an ordinary element
|
|
if not element.attrib:
|
|
rv.append("<%s>"%(filter.fromXmlName(element.tag),))
|
|
else:
|
|
attr = " ".join(["%s=\"%s\""%(
|
|
filter.fromXmlName(name), value)
|
|
for name, value in element.attrib.iteritems()])
|
|
rv.append("<%s %s>"%(element.tag, attr))
|
|
if element.text:
|
|
rv.append(element.text)
|
|
|
|
for child in element:
|
|
serializeElement(child)
|
|
|
|
rv.append("</%s>"%(element.tag,))
|
|
|
|
if element.tail:
|
|
rv.append(element.tail)
|
|
|
|
serializeElement(element)
|
|
|
|
if finalText is not None:
|
|
rv.append("%s\""%(' '*2, finalText))
|
|
|
|
return "".join(rv)
|
|
|
|
class TreeBuilder(_base.TreeBuilder):
|
|
documentClass = Document
|
|
doctypeClass = DocumentType
|
|
elementClass = Element
|
|
commentClass = Comment
|
|
fragmentClass = DocumentFragment
|
|
|
|
def testSerializer(self, element):
|
|
return testSerializer(element)
|
|
|
|
def getDocument(self):
|
|
if fullTree:
|
|
return self.document._element
|
|
else:
|
|
if self.defaultNamespace is not None:
|
|
return self.document._element.find(
|
|
"{%s}html"%self.defaultNamespace)
|
|
else:
|
|
return self.document._element.find("html")
|
|
|
|
def getFragment(self):
|
|
return _base.TreeBuilder.getFragment(self)._element
|
|
|
|
return locals()
|