Browse Source

Add TwoWaysOrderedDict on utils

doc-issue-template
MrS0m30n3 9 years ago
parent
commit
5a298b7d08
1 changed files with 229 additions and 0 deletions
  1. 229
      youtube_dl_gui/utils.py

229
youtube_dl_gui/utils.py

@ -3,6 +3,8 @@
"""Youtubedlg module that contains util functions.
Attributes:
RANDOM_OBJECT (object): Object that it's used as a default parameter.
YOUTUBEDL_BIN (string): Youtube-dl binary filename.
"""
@ -13,6 +15,9 @@ import sys
import subprocess
RANDOM_OBJECT = object()
YOUTUBEDL_BIN = 'youtube-dl'
if os.name == 'nt':
YOUTUBEDL_BIN += '.exe'
@ -156,3 +161,227 @@ def get_icon_file():
return icon_file
return None
class TwoWayOrderedDict(object):
"""Custom data structure which implements a two way ordrered dictionary.
TwoWayOrderedDict it's a custom dictionary in which you can get the
key:value relationship but you can also get the value:key relationship.
It also remembers the order in which the items were inserted and supports
almost all the features of the build-in dict.
Note:
Ways to create a new dictionary.
*) d = TwoWayOrderedDict(a=1, b=2) (Unordered)
*) d = TwoWayOrderedDict({'a': 1, 'b': 2}) (Unordered)
*) d = TwoWayOrderedDict([('a', 1), ('b', 2)]) (Ordered)
*) d = TwoWayOrderedDict(zip(['a', 'b', 'c'], [1, 2, 3])) (Ordered)
Examples:
>>> d = TwoWayOrderedDict(a=1, b=2)
>>> d['a']
1
>>> d[1]
'a'
>>> print d
{'a': 1, 'b': 2}
"""
def __init__(self, *args, **kwargs):
self._items = list()
self._load_into_dict(args, kwargs)
def __getitem__(self, key):
try:
item = self._find_item(key)
return self._get_value(key, item)
except KeyError as error:
raise error
def __setitem__(self, key, value):
index = 0
while index < len(self._items):
item = self._items[index]
if (key == item[0] or key == item[1] or
value == item[0] or value == item[1]):
self._items.remove(item)
else:
index += 1
self._items.append((key, value))
def __delitem__(self, key):
try:
item = self._find_item(key)
self._items.remove(item)
except KeyError as error:
raise error
def __len__(self):
return len(self._items)
def __iter__(self):
for item in self._items:
yield item[0]
def __contains__(self, item):
"""Return True if the item matches either a
dictionary key or value else False. """
try:
self._find_item(item)
except KeyError:
return False
return True
def __repr__(self):
return str(self._items)
def __str__(self):
return str(dict(self._items))
def _get_value(self, key, item):
"""Return the key:value or value:key relationship
for the given item. """
if key == item[0]:
return item[1]
if key == item[1]:
return item[0]
def _find_item(self, key):
"""Search for the item which contains the given key.
This method will compare the key both with the key and the value
of the item until it finds a match else it will raise a KeyError
exception.
Returns:
item (tuple): Tuple which contains the (key, value).
Raises:
KeyError
"""
for item in self._items:
if key == item[0] or key == item[1]:
return item
raise KeyError(key)
def _load_into_dict(self, args, kwargs):
"""Load new items into the dictionary. This method handles the
items insertion for the __init__ and update methods. """
for item in args:
if type(item) == dict:
item = item.items()
for key, value in item:
self.__setitem__(key, value)
for key, value in kwargs.items():
self.__setitem__(key, value)
def items(self):
"""Return the item list instead of returning the dict view. """
return self._items
def values(self):
"""Return a list with all the values of the dictionary instead of
returning the dict view for the values. """
return [item[1] for item in self._items]
def keys(self):
"""Return a list with all the keys of the dictionary instead of
returning the dict view for the keys. """
return [item[0] for item in self._items]
def get(self, key, default=None):
"""Return the value for key or the key for value if key
is in the dictionary else default.
Note:
This method does NOT raise a KeyError.
"""
try:
return self.__getitem__(key)
except KeyError:
return default
def pop(self, key, default=RANDOM_OBJECT):
"""If key is in the dictionary remove it and return its value
else return default. If default is not given and key is not in
the dictionary a KeyError is raised. """
try:
item = self._find_item(key)
value = self._get_value(key, item)
self._items.remove(item)
except KeyError as error:
if default == RANDOM_OBJECT:
raise error
value = default
return value
def popitem(self):
"""Remove and return a (key, value) pair from the dictionary.
If the dictionary is empty calling popitem() raises a KeyError.
Note:
popitem() is useful to destructively iterate over a dictionary.
Raises:
KeyError
"""
if len(self._items) == 0:
raise KeyError('popitem(): dictionary is empty')
return self._items.pop()
def setdefault(self, key, default=None):
"""If key is in the dictionary return its value else
insert a new key with a value of default and return default. """
try:
return self.__getitem__(key)
except KeyError:
self.__setitem__(key, default)
return default
def update(self, *args, **kwargs):
"""Update the dictionary with the (key, value) pairs
overwriting existing keys.
Example:
>>d = TwoWayOrderedDict(a=1, b=2)
>>print d
{'a': 1, 'b': 2}
>>d.update({'a': 0, 'b': 1, 'c': 2})
{'a': 0, 'b': 1, 'c': 2}
>>d.update(d=3)
{'a': 0, 'b': 1, 'c': 2, 'd': 3}
"""
self._load_into_dict(args, kwargs)
def copy(self):
"""Return a copy of our custom dictionary. """
return TwoWayOrderedDict(self._items)
def clear(self):
"""Remove all items from the dictionary. """
del self._items[:]
Loading…
Cancel
Save