mirror of
https://github.com/SickGear/SickGear.git
synced 2024-11-23 13:25:04 +00:00
183 lines
5.2 KiB
Python
183 lines
5.2 KiB
Python
|
"""
|
||
|
Dictionnary classes which store values order.
|
||
|
"""
|
||
|
|
||
|
|
||
|
class UniqKeyError(Exception):
|
||
|
"""
|
||
|
Error raised when a value is set whereas the key already exist in a
|
||
|
dictionnary.
|
||
|
"""
|
||
|
pass
|
||
|
|
||
|
|
||
|
class Dict(object):
|
||
|
"""
|
||
|
This class works like classic Python dict() but has an important method:
|
||
|
__iter__() which allow to iterate into the dictionnary _values_ (and not
|
||
|
keys like Python's dict does).
|
||
|
"""
|
||
|
|
||
|
def __init__(self, values=None):
|
||
|
self._index = {} # key => index
|
||
|
self._key_list = [] # index => key
|
||
|
self._value_list = [] # index => value
|
||
|
if values:
|
||
|
for key, value in values:
|
||
|
self.append(key, value)
|
||
|
|
||
|
def _getValues(self):
|
||
|
return self._value_list
|
||
|
values = property(_getValues)
|
||
|
|
||
|
def index(self, key):
|
||
|
"""
|
||
|
Search a value by its key and returns its index
|
||
|
Returns None if the key doesn't exist.
|
||
|
|
||
|
>>> d=Dict( (("two", "deux"), ("one", "un")) )
|
||
|
>>> d.index("two")
|
||
|
0
|
||
|
>>> d.index("one")
|
||
|
1
|
||
|
>>> d.index("three") is None
|
||
|
True
|
||
|
"""
|
||
|
return self._index.get(key)
|
||
|
|
||
|
def __getitem__(self, key):
|
||
|
"""
|
||
|
Get item with specified key.
|
||
|
To get a value by it's index, use mydict.values[index]
|
||
|
|
||
|
>>> d=Dict( (("two", "deux"), ("one", "un")) )
|
||
|
>>> d["one"]
|
||
|
'un'
|
||
|
"""
|
||
|
return self._value_list[self._index[key]]
|
||
|
|
||
|
def __setitem__(self, key, value):
|
||
|
self._value_list[self._index[key]] = value
|
||
|
|
||
|
def append(self, key, value):
|
||
|
"""
|
||
|
Append new value
|
||
|
"""
|
||
|
if key in self._index:
|
||
|
raise UniqKeyError("Key '%s' already exists" % key)
|
||
|
self._index[key] = len(self._value_list)
|
||
|
self._key_list.append(key)
|
||
|
self._value_list.append(value)
|
||
|
|
||
|
def __len__(self):
|
||
|
return len(self._value_list)
|
||
|
|
||
|
def __contains__(self, key):
|
||
|
return key in self._index
|
||
|
|
||
|
def __iter__(self):
|
||
|
return iter(self._value_list)
|
||
|
|
||
|
def items(self):
|
||
|
"""
|
||
|
Create a generator to iterate on: (key, value).
|
||
|
|
||
|
>>> d=Dict( (("two", "deux"), ("one", "un")) )
|
||
|
>>> for key, value in d.items():
|
||
|
... print("%r: %r" % (key, value))
|
||
|
...
|
||
|
'two': 'deux'
|
||
|
'one': 'un'
|
||
|
"""
|
||
|
for index in range(len(self)):
|
||
|
yield (self._key_list[index], self._value_list[index])
|
||
|
|
||
|
def itervalues(self):
|
||
|
"""
|
||
|
Create an iterator on values
|
||
|
"""
|
||
|
return iter(self._value_list)
|
||
|
|
||
|
def iterkeys(self):
|
||
|
"""
|
||
|
Create an iterator on keys
|
||
|
"""
|
||
|
return iter(self._key_list)
|
||
|
|
||
|
def replace(self, oldkey, newkey, new_value):
|
||
|
"""
|
||
|
Replace an existing value with another one
|
||
|
|
||
|
>>> d=Dict( (("two", "deux"), ("one", "un")) )
|
||
|
>>> d.replace("one", "three", 3)
|
||
|
>>> d
|
||
|
{'two': 'deux', 'three': 3}
|
||
|
|
||
|
You can also use the classic form:
|
||
|
|
||
|
>>> d['three'] = 4
|
||
|
>>> d
|
||
|
{'two': 'deux', 'three': 4}
|
||
|
"""
|
||
|
index = self._index[oldkey]
|
||
|
self._value_list[index] = new_value
|
||
|
if oldkey != newkey:
|
||
|
del self._index[oldkey]
|
||
|
self._index[newkey] = index
|
||
|
self._key_list[index] = newkey
|
||
|
|
||
|
def __delitem__(self, index):
|
||
|
"""
|
||
|
Delete item at position index. May raise IndexError.
|
||
|
|
||
|
>>> d=Dict( ((6, 'six'), (9, 'neuf'), (4, 'quatre')) )
|
||
|
>>> del d[1]
|
||
|
>>> d
|
||
|
{6: 'six', 4: 'quatre'}
|
||
|
"""
|
||
|
if index < 0:
|
||
|
index += len(self._value_list)
|
||
|
if not (0 <= index < len(self._value_list)):
|
||
|
raise IndexError("list assignment index out of range (%s/%s)"
|
||
|
% (index, len(self._value_list)))
|
||
|
del self._value_list[index]
|
||
|
del self._key_list[index]
|
||
|
|
||
|
# First loop which may alter self._index
|
||
|
for key, item_index in self._index.items():
|
||
|
if item_index == index:
|
||
|
del self._index[key]
|
||
|
break
|
||
|
|
||
|
# Second loop update indexes
|
||
|
for key, item_index in self._index.items():
|
||
|
if index < item_index:
|
||
|
self._index[key] -= 1
|
||
|
|
||
|
def insert(self, index, key, value):
|
||
|
"""
|
||
|
Insert an item at specified position index.
|
||
|
|
||
|
>>> d=Dict( ((6, 'six'), (9, 'neuf'), (4, 'quatre')) )
|
||
|
>>> d.insert(1, '40', 'quarante')
|
||
|
>>> d
|
||
|
{6: 'six', '40': 'quarante', 9: 'neuf', 4: 'quatre'}
|
||
|
"""
|
||
|
if key in self:
|
||
|
raise UniqKeyError("Insert error: key '%s' ready exists" % key)
|
||
|
_index = index
|
||
|
if index < 0:
|
||
|
index += len(self._value_list)
|
||
|
if not(0 <= index <= len(self._value_list)):
|
||
|
raise IndexError("Insert error: index '%s' is invalid" % _index)
|
||
|
for item_key, item_index in self._index.items():
|
||
|
if item_index >= index:
|
||
|
self._index[item_key] += 1
|
||
|
self._index[key] = index
|
||
|
self._key_list.insert(index, key)
|
||
|
self._value_list.insert(index, value)
|
||
|
|
||
|
def __repr__(self):
|
||
|
items = ("%r: %r" % (key, value) for key, value in self.items())
|
||
|
return "{%s}" % ", ".join(items)
|