mirror of
https://github.com/SickGear/SickGear.git
synced 2024-12-01 00:43:37 +00:00
176 lines
4.8 KiB
Python
176 lines
4.8 KiB
Python
|
try:
|
||
|
frozenset
|
||
|
except NameError:
|
||
|
#Import from the sets module for python 2.3
|
||
|
from sets import Set as set
|
||
|
from sets import ImmutableSet as frozenset
|
||
|
|
||
|
class MethodDispatcher(dict):
|
||
|
"""Dict with 2 special properties:
|
||
|
|
||
|
On initiation, keys that are lists, sets or tuples are converted to
|
||
|
multiple keys so accessing any one of the items in the original
|
||
|
list-like object returns the matching value
|
||
|
|
||
|
md = MethodDispatcher({("foo", "bar"):"baz"})
|
||
|
md["foo"] == "baz"
|
||
|
|
||
|
A default value which can be set through the default attribute.
|
||
|
"""
|
||
|
|
||
|
def __init__(self, items=()):
|
||
|
# Using _dictEntries instead of directly assigning to self is about
|
||
|
# twice as fast. Please do careful performance testing before changing
|
||
|
# anything here.
|
||
|
_dictEntries = []
|
||
|
for name,value in items:
|
||
|
if type(name) in (list, tuple, frozenset, set):
|
||
|
for item in name:
|
||
|
_dictEntries.append((item, value))
|
||
|
else:
|
||
|
_dictEntries.append((name, value))
|
||
|
dict.__init__(self, _dictEntries)
|
||
|
self.default = None
|
||
|
|
||
|
def __getitem__(self, key):
|
||
|
return dict.get(self, key, self.default)
|
||
|
|
||
|
#Pure python implementation of deque taken from the ASPN Python Cookbook
|
||
|
#Original code by Raymond Hettinger
|
||
|
|
||
|
class deque(object):
|
||
|
|
||
|
def __init__(self, iterable=(), maxsize=-1):
|
||
|
if not hasattr(self, 'data'):
|
||
|
self.left = self.right = 0
|
||
|
self.data = {}
|
||
|
self.maxsize = maxsize
|
||
|
self.extend(iterable)
|
||
|
|
||
|
def append(self, x):
|
||
|
self.data[self.right] = x
|
||
|
self.right += 1
|
||
|
if self.maxsize != -1 and len(self) > self.maxsize:
|
||
|
self.popleft()
|
||
|
|
||
|
def appendleft(self, x):
|
||
|
self.left -= 1
|
||
|
self.data[self.left] = x
|
||
|
if self.maxsize != -1 and len(self) > self.maxsize:
|
||
|
self.pop()
|
||
|
|
||
|
def pop(self):
|
||
|
if self.left == self.right:
|
||
|
raise IndexError('cannot pop from empty deque')
|
||
|
self.right -= 1
|
||
|
elem = self.data[self.right]
|
||
|
del self.data[self.right]
|
||
|
return elem
|
||
|
|
||
|
def popleft(self):
|
||
|
if self.left == self.right:
|
||
|
raise IndexError('cannot pop from empty deque')
|
||
|
elem = self.data[self.left]
|
||
|
del self.data[self.left]
|
||
|
self.left += 1
|
||
|
return elem
|
||
|
|
||
|
def clear(self):
|
||
|
self.data.clear()
|
||
|
self.left = self.right = 0
|
||
|
|
||
|
def extend(self, iterable):
|
||
|
for elem in iterable:
|
||
|
self.append(elem)
|
||
|
|
||
|
def extendleft(self, iterable):
|
||
|
for elem in iterable:
|
||
|
self.appendleft(elem)
|
||
|
|
||
|
def rotate(self, n=1):
|
||
|
if self:
|
||
|
n %= len(self)
|
||
|
for i in xrange(n):
|
||
|
self.appendleft(self.pop())
|
||
|
|
||
|
def __getitem__(self, i):
|
||
|
if i < 0:
|
||
|
i += len(self)
|
||
|
try:
|
||
|
return self.data[i + self.left]
|
||
|
except KeyError:
|
||
|
raise IndexError
|
||
|
|
||
|
def __setitem__(self, i, value):
|
||
|
if i < 0:
|
||
|
i += len(self)
|
||
|
try:
|
||
|
self.data[i + self.left] = value
|
||
|
except KeyError:
|
||
|
raise IndexError
|
||
|
|
||
|
def __delitem__(self, i):
|
||
|
size = len(self)
|
||
|
if not (-size <= i < size):
|
||
|
raise IndexError
|
||
|
data = self.data
|
||
|
if i < 0:
|
||
|
i += size
|
||
|
for j in xrange(self.left+i, self.right-1):
|
||
|
data[j] = data[j+1]
|
||
|
self.pop()
|
||
|
|
||
|
def __len__(self):
|
||
|
return self.right - self.left
|
||
|
|
||
|
def __cmp__(self, other):
|
||
|
if type(self) != type(other):
|
||
|
return cmp(type(self), type(other))
|
||
|
return cmp(list(self), list(other))
|
||
|
|
||
|
def __repr__(self, _track=[]):
|
||
|
if id(self) in _track:
|
||
|
return '...'
|
||
|
_track.append(id(self))
|
||
|
r = 'deque(%r)' % (list(self),)
|
||
|
_track.remove(id(self))
|
||
|
return r
|
||
|
|
||
|
def __getstate__(self):
|
||
|
return (tuple(self),)
|
||
|
|
||
|
def __setstate__(self, s):
|
||
|
self.__init__(s[0])
|
||
|
|
||
|
def __hash__(self):
|
||
|
raise TypeError
|
||
|
|
||
|
def __copy__(self):
|
||
|
return self.__class__(self)
|
||
|
|
||
|
def __deepcopy__(self, memo={}):
|
||
|
from copy import deepcopy
|
||
|
result = self.__class__()
|
||
|
memo[id(self)] = result
|
||
|
result.__init__(deepcopy(tuple(self), memo))
|
||
|
return result
|
||
|
|
||
|
#Some utility functions to dal with weirdness around UCS2 vs UCS4
|
||
|
#python builds
|
||
|
|
||
|
def encodingType():
|
||
|
if len() == 2:
|
||
|
return "UCS2"
|
||
|
else:
|
||
|
return "UCS4"
|
||
|
|
||
|
def isSurrogatePair(data):
|
||
|
return (len(data) == 2 and
|
||
|
ord(data[0]) >= 0xD800 and ord(data[0]) <= 0xDBFF and
|
||
|
ord(data[1]) >= 0xDC00 and ord(data[1]) <= 0xDFFF)
|
||
|
|
||
|
def surrogatePairToCodepoint(data):
|
||
|
char_val = (0x10000 + (ord(data[0]) - 0xD800) * 0x400 +
|
||
|
(ord(data[1]) - 0xDC00))
|
||
|
return char_val
|