aboutsummaryrefslogtreecommitdiffstats
path: root/markdown/odict.py
diff options
context:
space:
mode:
authorWaylan Limberg <waylan@gmail.com>2013-02-27 09:10:47 -0500
committerWaylan Limberg <waylan@gmail.com>2013-02-27 09:10:47 -0500
commit579288c5eb684dd09d1ef298929a566f40151205 (patch)
treed10a50f91b8606cd1dea38764168abab92958b0f /markdown/odict.py
parentb37ab16ba56ac6fe4e64f87521996bad323058f2 (diff)
downloadmarkdown-579288c5eb684dd09d1ef298929a566f40151205.tar.gz
markdown-579288c5eb684dd09d1ef298929a566f40151205.tar.bz2
markdown-579288c5eb684dd09d1ef298929a566f40151205.zip
Now using universal code for Python 2 & 3.
The most notable changes are the use of unicode_literals and absolute_imports. Actually, absolute_imports was the biggest deal as it gives us relative imports. For the first time extensions import markdown relative to themselves. This allows other packages to embed the markdown lib in a subdir of their project and still be able to use our extensions.
Diffstat (limited to 'markdown/odict.py')
-rw-r--r--markdown/odict.py102
1 files changed, 62 insertions, 40 deletions
diff --git a/markdown/odict.py b/markdown/odict.py
index 02864bf..578cc76 100644
--- a/markdown/odict.py
+++ b/markdown/odict.py
@@ -1,3 +1,7 @@
+from __future__ import unicode_literals
+from __future__ import absolute_import
+from . import util
+
class OrderedDict(dict):
"""
A dictionary that keeps its keys in the order in which they're inserted.
@@ -11,34 +15,44 @@ class OrderedDict(dict):
return instance
def __init__(self, data=None):
- if data is None:
- data = {}
- super(OrderedDict, self).__init__(data)
- if isinstance(data, dict):
- self.keyOrder = data.keys()
+ if data is None or isinstance(data, dict):
+ data = data or []
+ super(OrderedDict, self).__init__(data)
+ self.keyOrder = list(data) if data else []
else:
- self.keyOrder = []
+ super(OrderedDict, self).__init__()
+ super_set = super(OrderedDict, self).__setitem__
for key, value in data:
- if key not in self.keyOrder:
+ # Take the ordering from first key
+ if key not in self:
self.keyOrder.append(key)
+ # But override with last value in data (dict() does this)
+ super_set(key, value)
def __deepcopy__(self, memo):
- from copy import deepcopy
- return self.__class__([(key, deepcopy(value, memo))
- for key, value in self.iteritems()])
+ return self.__class__([(key, copy.deepcopy(value, memo))
+ for key, value in self.items()])
+
+ def __copy__(self):
+ # The Python's default copy implementation will alter the state
+ # of self. The reason for this seems complex but is likely related to
+ # subclassing dict.
+ return self.copy()
def __setitem__(self, key, value):
- super(OrderedDict, self).__setitem__(key, value)
- if key not in self.keyOrder:
+ if key not in self:
self.keyOrder.append(key)
+ super(OrderedDict, self).__setitem__(key, value)
def __delitem__(self, key):
super(OrderedDict, self).__delitem__(key)
self.keyOrder.remove(key)
def __iter__(self):
- for k in self.keyOrder:
- yield k
+ return iter(self.keyOrder)
+
+ def __reversed__(self):
+ return reversed(self.keyOrder)
def pop(self, k, *args):
result = super(OrderedDict, self).pop(k, *args)
@@ -54,41 +68,51 @@ class OrderedDict(dict):
self.keyOrder.remove(result[0])
return result
- def items(self):
- return zip(self.keyOrder, self.values())
+ def _iteritems(self):
+ for key in self.keyOrder:
+ yield key, self[key]
- def iteritems(self):
+ def _iterkeys(self):
for key in self.keyOrder:
- yield key, super(OrderedDict, self).__getitem__(key)
+ yield key
- def keys(self):
- return self.keyOrder[:]
+ def _itervalues(self):
+ for key in self.keyOrder:
+ yield self[key]
- def iterkeys(self):
- return iter(self.keyOrder)
+ if util.PY3:
+ items = _iteritems
+ keys = _iterkeys
+ values = _itervalues
+ else:
+ iteritems = _iteritems
+ iterkeys = _iterkeys
+ itervalues = _itervalues
- def values(self):
- return [super(OrderedDict, self).__getitem__(k) for k in self.keyOrder]
+ def items(self):
+ return [(k, self[k]) for k in self.keyOrder]
- def itervalues(self):
- for key in self.keyOrder:
- yield super(OrderedDict, self).__getitem__(key)
+ def keys(self):
+ return self.keyOrder[:]
+
+ def values(self):
+ return [self[k] for k in self.keyOrder]
def update(self, dict_):
- for k, v in dict_.items():
- self.__setitem__(k, v)
+ for k, v in six.iteritems(dict_):
+ self[k] = v
def setdefault(self, key, default):
- if key not in self.keyOrder:
+ if key not in self:
self.keyOrder.append(key)
return super(OrderedDict, self).setdefault(key, default)
def value_for_index(self, index):
- """Return the value of the item at the given zero-based index."""
+ """Returns the value of the item at the given zero-based index."""
return self[self.keyOrder[index]]
def insert(self, index, key, value):
- """Insert the key, value pair before the item with the given index."""
+ """Inserts the key, value pair before the item with the given index."""
if key in self.keyOrder:
n = self.keyOrder.index(key)
del self.keyOrder[n]
@@ -98,18 +122,16 @@ class OrderedDict(dict):
super(OrderedDict, self).__setitem__(key, value)
def copy(self):
- """Return a copy of this object."""
+ """Returns a copy of this object."""
# This way of initializing the copy means it works for subclasses, too.
- obj = self.__class__(self)
- obj.keyOrder = self.keyOrder[:]
- return obj
+ return self.__class__(self)
def __repr__(self):
"""
- Replace the normal dict.__repr__ with a version that returns the keys
- in their sorted order.
+ Replaces the normal dict.__repr__ with a version that returns the keys
+ in their Ordered order.
"""
- return '{%s}' % ', '.join(['%r: %r' % (k, v) for k, v in self.items()])
+ return '{%s}' % ', '.join(['%r: %r' % (k, v) for k, v in six.iteritems(self)])
def clear(self):
super(OrderedDict, self).clear()
@@ -159,7 +181,7 @@ class OrderedDict(dict):
self.keyOrder.insert(i, key)
else:
self.keyOrder.append(key)
- except Exception, e:
+ except Exception as e:
# restore to prevent data loss and reraise
self.keyOrder.insert(n, key)
raise e