[med-svn] [python-oset] 01/11: Imported Upstream version 0.1.3
Kevin Murray
daube-guest at moszumanska.debian.org
Fri Oct 9 10:15:43 UTC 2015
This is an automated email from the git hooks/post-receive script.
daube-guest pushed a commit to branch master
in repository python-oset.
commit dcd6df4257eee76aeafc845afde282110a67a4f3
Author: Kevin Murray <spam at kdmurray.id.au>
Date: Thu Oct 8 14:40:19 2015 +1100
Imported Upstream version 0.1.3
---
LICENSE.rst | 29 ++
MANIFEST.in | 2 +
PKG-INFO | 85 ++++++
README.rst | 40 +++
setup.cfg | 5 +
setup.py | 38 +++
src/oset.egg-info/PKG-INFO | 85 ++++++
src/oset.egg-info/SOURCES.txt | 15 +
src/oset.egg-info/dependency_links.txt | 1 +
src/oset.egg-info/namespace_packages.txt | 1 +
src/oset.egg-info/requires.txt | 1 +
src/oset.egg-info/top_level.txt | 1 +
src/oset.egg-info/zip-safe | 1 +
src/oset/__init__.py | 3 +
src/oset/_abc.py | 475 +++++++++++++++++++++++++++++++
src/oset/pyoset.py | 85 ++++++
src/oset/tests.py | 44 +++
17 files changed, 911 insertions(+)
diff --git a/LICENSE.rst b/LICENSE.rst
new file mode 100644
index 0000000..aef85dd
--- /dev/null
+++ b/LICENSE.rst
@@ -0,0 +1,29 @@
+License
+=======
+
+Copyright (c) 2009, Raymond Hettinger, and others
+All rights reserved.
+
+Package structured based on the one developed to odict
+Copyright (c) 2010, BlueDynamics Alliance, Austria
+
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+* Neither the name of the BlueDynamics Alliance nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY BlueDynamics Alliance ``AS IS`` AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL BlueDynamics Alliance BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..f67510e
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,2 @@
+include *.rst
+
diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..c3a6dd8
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,85 @@
+Metadata-Version: 1.1
+Name: oset
+Version: 0.1.3
+Summary: Ordered Set.
+Home-page: https://gitorious.com/sleipnir/python-oset
+Author: Carlos Martin
+Author-email: inean.es at gmail.com
+License: Python Software Foundation License
+Description: oset
+ =====
+
+ Set that remembers original insertion order.
+
+ Runs on Py2.5 or later (and runs on 3.0 or later without any modifications). For Python2.5, a local backport of ABC classes is also used.
+
+ Implementation based on a doubly linked link and an internal dictionary. This design gives OrderedSet the same big-Oh running times as regular sets including O(1) adds, removes, and lookups as well as O(n) iteration.
+
+ Usage
+ -----
+
+ Import and create ordered set.
+ ::
+
+ >>> from oset import oset
+ >>> os = oset()
+
+ Requires
+ --------
+
+ - Python 2.5+
+
+ Changes
+ =======
+
+ Version 0.1
+ -------------
+ - http://code.activestate.com/recipes/576694-orderedset/
+ - Raymond Hettinger, 19 Mar 2009
+
+ Contributors
+ ============
+
+ - Raymond Hettinger, (All kudos to him :)
+
+ - Carlos Martin <inean.es at gmail.com>
+
+ under the `Python Software Foundation License
+ <http://www.opensource.org/licenses/PythonSoftFoundation.php>`_.
+ License
+ =======
+
+ Copyright (c) 2009, Raymond Hettinger, and others
+ All rights reserved.
+
+ Package structured based on the one developed to odict
+ Copyright (c) 2010, BlueDynamics Alliance, Austria
+
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+ * Neither the name of the BlueDynamics Alliance nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY BlueDynamics Alliance ``AS IS`` AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL BlueDynamics Alliance BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Keywords: oset ordered set collection
+Platform: UNKNOWN
+Classifier: Development Status :: 4 - Beta
+Classifier: License :: OSI Approved :: Python Software Foundation License
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python
+Classifier: Topic :: Software Development
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..739bb49
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,40 @@
+oset
+=====
+
+Set that remembers original insertion order.
+
+Runs on Py2.5 or later (and runs on 3.0 or later without any modifications). For Python2.5, a local backport of ABC classes is also used.
+
+Implementation based on a doubly linked link and an internal dictionary. This design gives OrderedSet the same big-Oh running times as regular sets including O(1) adds, removes, and lookups as well as O(n) iteration.
+
+Usage
+-----
+
+Import and create ordered set.
+::
+
+ >>> from oset import oset
+ >>> os = oset()
+
+Requires
+--------
+
+- Python 2.5+
+
+Changes
+=======
+
+Version 0.1
+-------------
+- http://code.activestate.com/recipes/576694-orderedset/
+- Raymond Hettinger, 19 Mar 2009
+
+Contributors
+============
+
+- Raymond Hettinger, (All kudos to him :)
+
+- Carlos Martin <inean.es at gmail.com>
+
+under the `Python Software Foundation License
+<http://www.opensource.org/licenses/PythonSoftFoundation.php>`_.
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..861a9f5
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,5 @@
+[egg_info]
+tag_build =
+tag_date = 0
+tag_svn_revision = 0
+
diff --git a/setup.py b/setup.py
new file mode 100755
index 0000000..4346c1f
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+# -*- mode:python; tab-width: 2; coding: utf-8 -*-
+
+"""Main setup.py file"""
+
+
+from setuptools import setup, find_packages
+import os
+
+version = '0.1.3'
+shortdesc = 'Ordered Set.'
+longdesc = open(os.path.join(os.path.dirname(__file__), 'README.rst')).read()
+longdesc += open(os.path.join(os.path.dirname(__file__), 'LICENSE.rst')).read()
+
+setup(name='oset',
+ version=version,
+ description=shortdesc,
+ long_description=longdesc,
+ classifiers=[
+ 'Development Status :: 4 - Beta',
+ 'License :: OSI Approved :: Python Software Foundation License',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python',
+ 'Topic :: Software Development',
+ ],
+ keywords='oset ordered set collection',
+ url='https://gitorious.com/sleipnir/python-oset',
+ license='Python Software Foundation License',
+ packages=find_packages('src'),
+ package_dir={'': 'src'},
+ maintainer="Carlos Martin",
+ maintainer_email="inean.es at gmail.com",
+ namespace_packages=[],
+ include_package_data=True,
+ zip_safe=True,
+ install_requires=['setuptools'],
+ test_suite="oset.tests.test_suite",
+)
diff --git a/src/oset.egg-info/PKG-INFO b/src/oset.egg-info/PKG-INFO
new file mode 100644
index 0000000..c3a6dd8
--- /dev/null
+++ b/src/oset.egg-info/PKG-INFO
@@ -0,0 +1,85 @@
+Metadata-Version: 1.1
+Name: oset
+Version: 0.1.3
+Summary: Ordered Set.
+Home-page: https://gitorious.com/sleipnir/python-oset
+Author: Carlos Martin
+Author-email: inean.es at gmail.com
+License: Python Software Foundation License
+Description: oset
+ =====
+
+ Set that remembers original insertion order.
+
+ Runs on Py2.5 or later (and runs on 3.0 or later without any modifications). For Python2.5, a local backport of ABC classes is also used.
+
+ Implementation based on a doubly linked link and an internal dictionary. This design gives OrderedSet the same big-Oh running times as regular sets including O(1) adds, removes, and lookups as well as O(n) iteration.
+
+ Usage
+ -----
+
+ Import and create ordered set.
+ ::
+
+ >>> from oset import oset
+ >>> os = oset()
+
+ Requires
+ --------
+
+ - Python 2.5+
+
+ Changes
+ =======
+
+ Version 0.1
+ -------------
+ - http://code.activestate.com/recipes/576694-orderedset/
+ - Raymond Hettinger, 19 Mar 2009
+
+ Contributors
+ ============
+
+ - Raymond Hettinger, (All kudos to him :)
+
+ - Carlos Martin <inean.es at gmail.com>
+
+ under the `Python Software Foundation License
+ <http://www.opensource.org/licenses/PythonSoftFoundation.php>`_.
+ License
+ =======
+
+ Copyright (c) 2009, Raymond Hettinger, and others
+ All rights reserved.
+
+ Package structured based on the one developed to odict
+ Copyright (c) 2010, BlueDynamics Alliance, Austria
+
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+ * Neither the name of the BlueDynamics Alliance nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY BlueDynamics Alliance ``AS IS`` AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL BlueDynamics Alliance BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Keywords: oset ordered set collection
+Platform: UNKNOWN
+Classifier: Development Status :: 4 - Beta
+Classifier: License :: OSI Approved :: Python Software Foundation License
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python
+Classifier: Topic :: Software Development
diff --git a/src/oset.egg-info/SOURCES.txt b/src/oset.egg-info/SOURCES.txt
new file mode 100644
index 0000000..67f6a8f
--- /dev/null
+++ b/src/oset.egg-info/SOURCES.txt
@@ -0,0 +1,15 @@
+LICENSE.rst
+MANIFEST.in
+README.rst
+setup.py
+src/oset/__init__.py
+src/oset/_abc.py
+src/oset/pyoset.py
+src/oset/tests.py
+src/oset.egg-info/PKG-INFO
+src/oset.egg-info/SOURCES.txt
+src/oset.egg-info/dependency_links.txt
+src/oset.egg-info/namespace_packages.txt
+src/oset.egg-info/requires.txt
+src/oset.egg-info/top_level.txt
+src/oset.egg-info/zip-safe
\ No newline at end of file
diff --git a/src/oset.egg-info/dependency_links.txt b/src/oset.egg-info/dependency_links.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/src/oset.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/src/oset.egg-info/namespace_packages.txt b/src/oset.egg-info/namespace_packages.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/src/oset.egg-info/namespace_packages.txt
@@ -0,0 +1 @@
+
diff --git a/src/oset.egg-info/requires.txt b/src/oset.egg-info/requires.txt
new file mode 100644
index 0000000..8b6d003
--- /dev/null
+++ b/src/oset.egg-info/requires.txt
@@ -0,0 +1 @@
+setuptools
\ No newline at end of file
diff --git a/src/oset.egg-info/top_level.txt b/src/oset.egg-info/top_level.txt
new file mode 100644
index 0000000..bba988d
--- /dev/null
+++ b/src/oset.egg-info/top_level.txt
@@ -0,0 +1 @@
+oset
diff --git a/src/oset.egg-info/zip-safe b/src/oset.egg-info/zip-safe
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/src/oset.egg-info/zip-safe
@@ -0,0 +1 @@
+
diff --git a/src/oset/__init__.py b/src/oset/__init__.py
new file mode 100644
index 0000000..ec720da
--- /dev/null
+++ b/src/oset/__init__.py
@@ -0,0 +1,3 @@
+"""Main Ordered Set module """
+
+from oset.pyoset import oset
diff --git a/src/oset/_abc.py b/src/oset/_abc.py
new file mode 100644
index 0000000..b155c74
--- /dev/null
+++ b/src/oset/_abc.py
@@ -0,0 +1,475 @@
+#!/usr/bin/env python
+# -*- mode:python; tab-width: 2; coding: utf-8 -*-
+
+"""Partially backported python ABC classes"""
+
+from __future__ import absolute_import
+
+import sys
+import types
+
+if sys.version_info > (2, 6):
+ raise ImportError("Use native ABC classes istead of this one.")
+
+
+# Instance of old-style class
+class _C:
+ pass
+
+_InstanceType = type(_C())
+
+
+def abstractmethod(funcobj):
+ """A decorator indicating abstract methods.
+
+ Requires that the metaclass is ABCMeta or derived from it. A
+ class that has a metaclass derived from ABCMeta cannot be
+ instantiated unless all of its abstract methods are overridden.
+ The abstract methods can be called using any of the normal
+ 'super' call mechanisms.
+
+ Usage:
+
+ class C:
+ __metaclass__ = ABCMeta
+ @abstractmethod
+ def my_abstract_method(self, ...):
+ ...
+ """
+ funcobj.__isabstractmethod__ = True
+ return funcobj
+
+
+class ABCMeta(type):
+
+ """Metaclass for defining Abstract Base Classes (ABCs).
+
+ Use this metaclass to create an ABC. An ABC can be subclassed
+ directly, and then acts as a mix-in class. You can also register
+ unrelated concrete classes (even built-in classes) and unrelated
+ ABCs as 'virtual subclasses' -- these and their descendants will
+ be considered subclasses of the registering ABC by the built-in
+ issubclass() function, but the registering ABC won't show up in
+ their MRO (Method Resolution Order) nor will method
+ implementations defined by the registering ABC be callable (not
+ even via super()).
+
+ """
+
+ # A global counter that is incremented each time a class is
+ # registered as a virtual subclass of anything. It forces the
+ # negative cache to be cleared before its next use.
+ _abc_invalidation_counter = 0
+
+ def __new__(mcls, name, bases, namespace):
+ cls = super(ABCMeta, mcls).__new__(mcls, name, bases, namespace)
+ # Compute set of abstract method names
+ abstracts = set(name
+ for name, value in namespace.items()
+ if getattr(value, "__isabstractmethod__", False))
+ for base in bases:
+ for name in getattr(base, "__abstractmethods__", set()):
+ value = getattr(cls, name, None)
+ if getattr(value, "__isabstractmethod__", False):
+ abstracts.add(name)
+ cls.__abstractmethods__ = frozenset(abstracts)
+ # Set up inheritance registry
+ cls._abc_registry = set()
+ cls._abc_cache = set()
+ cls._abc_negative_cache = set()
+ cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter
+ return cls
+
+ def register(cls, subclass):
+ """Register a virtual subclass of an ABC."""
+ if not isinstance(subclass, (type, types.ClassType)):
+ raise TypeError("Can only register classes")
+ if issubclass(subclass, cls):
+ return # Already a subclass
+ # Subtle: test for cycles *after* testing for "already a subclass";
+ # this means we allow X.register(X) and interpret it as a no-op.
+ if issubclass(cls, subclass):
+ # This would create a cycle, which is bad for the algorithm below
+ raise RuntimeError("Refusing to create an inheritance cycle")
+ cls._abc_registry.add(subclass)
+ ABCMeta._abc_invalidation_counter += 1 # Invalidate negative cache
+
+ def _dump_registry(cls, file=None):
+ """Debug helper to print the ABC registry."""
+ print >> file, "Class: %s.%s" % (cls.__module__, cls.__name__)
+ print >> file, "Inv.counter: %s" % ABCMeta._abc_invalidation_counter
+ for name in sorted(cls.__dict__.keys()):
+ if name.startswith("_abc_"):
+ value = getattr(cls, name)
+ print >> file, "%s: %r" % (name, value)
+
+ def __instancecheck__(cls, instance):
+ """Override for isinstance(instance, cls)."""
+ # Inline the cache checking when it's simple.
+ subclass = getattr(instance, '__class__', None)
+ if subclass in cls._abc_cache:
+ return True
+ subtype = type(instance)
+ # Old-style instances
+ if subtype is _InstanceType:
+ subtype = subclass
+ if subtype is subclass or subclass is None:
+ if (cls._abc_negative_cache_version ==
+ ABCMeta._abc_invalidation_counter and
+ subtype in cls._abc_negative_cache):
+ return False
+ # Fall back to the subclass check.
+ return cls.__subclasscheck__(subtype)
+ return (cls.__subclasscheck__(subclass) or
+ cls.__subclasscheck__(subtype))
+
+ def __subclasscheck__(cls, subclass):
+ """Override for issubclass(subclass, cls)."""
+ # Check cache
+ if subclass in cls._abc_cache:
+ return True
+ # Check negative cache; may have to invalidate
+ if cls._abc_negative_cache_version < ABCMeta._abc_invalidation_counter:
+ # Invalidate the negative cache
+ cls._abc_negative_cache = set()
+ cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter
+ elif subclass in cls._abc_negative_cache:
+ return False
+ # Check the subclass hook
+ ok = cls.__subclasshook__(subclass)
+ if ok is not NotImplemented:
+ assert isinstance(ok, bool)
+ if ok:
+ cls._abc_cache.add(subclass)
+ else:
+ cls._abc_negative_cache.add(subclass)
+ return ok
+ # Check if it's a direct subclass
+ if cls in getattr(subclass, '__mro__', ()):
+ cls._abc_cache.add(subclass)
+ return True
+ # Check if it's a subclass of a registered class (recursive)
+ for rcls in cls._abc_registry:
+ if issubclass(subclass, rcls):
+ cls._abc_cache.add(subclass)
+ return True
+ # Check if it's a subclass of a subclass (recursive)
+ for scls in cls.__subclasses__():
+ if issubclass(subclass, scls):
+ cls._abc_cache.add(subclass)
+ return True
+ # No dice; update negative cache
+ cls._abc_negative_cache.add(subclass)
+ return False
+
+
+def _hasattr(C, attr):
+ try:
+ return any(attr in B.__dict__ for B in C.__mro__)
+ except AttributeError:
+ # Old-style class
+ return hasattr(C, attr)
+
+
+class Sized:
+ __metaclass__ = ABCMeta
+
+ @abstractmethod
+ def __len__(self):
+ return 0
+
+ @classmethod
+ def __subclasshook__(cls, C):
+ if cls is Sized:
+ if _hasattr(C, "__len__"):
+ return True
+ return NotImplemented
+
+
+class Container:
+ __metaclass__ = ABCMeta
+
+ @abstractmethod
+ def __contains__(self, x):
+ return False
+
+ @classmethod
+ def __subclasshook__(cls, C):
+ if cls is Container:
+ if _hasattr(C, "__contains__"):
+ return True
+ return NotImplemented
+
+
+class Iterable:
+ __metaclass__ = ABCMeta
+
+ @abstractmethod
+ def __iter__(self):
+ while False:
+ yield None
+
+ @classmethod
+ def __subclasshook__(cls, C):
+ if cls is Iterable:
+ if _hasattr(C, "__iter__"):
+ return True
+ return NotImplemented
+
+Iterable.register(str)
+
+
+class Set(Sized, Iterable, Container):
+ """A set is a finite, iterable container.
+
+ This class provides concrete generic implementations of all
+ methods except for __contains__, __iter__ and __len__.
+
+ To override the comparisons (presumably for speed, as the
+ semantics are fixed), all you have to do is redefine __le__ and
+ then the other operations will automatically follow suit.
+ """
+
+ def __le__(self, other):
+ if not isinstance(other, Set):
+ return NotImplemented
+ if len(self) > len(other):
+ return False
+ for elem in self:
+ if elem not in other:
+ return False
+ return True
+
+ def __lt__(self, other):
+ if not isinstance(other, Set):
+ return NotImplemented
+ return len(self) < len(other) and self.__le__(other)
+
+ def __gt__(self, other):
+ if not isinstance(other, Set):
+ return NotImplemented
+ return other < self
+
+ def __ge__(self, other):
+ if not isinstance(other, Set):
+ return NotImplemented
+ return other <= self
+
+ def __eq__(self, other):
+ if not isinstance(other, Set):
+ return NotImplemented
+ return len(self) == len(other) and self.__le__(other)
+
+ def __ne__(self, other):
+ return not (self == other)
+
+ @classmethod
+ def _from_iterable(cls, it):
+ '''Construct an instance of the class from any iterable input.
+
+ Must override this method if the class constructor signature
+ does not accept an iterable for an input.
+ '''
+ return cls(it)
+
+ def __and__(self, other):
+ if not isinstance(other, Iterable):
+ return NotImplemented
+ return self._from_iterable(value for value in other if value in self)
+
+ def isdisjoint(self, other):
+ for value in other:
+ if value in self:
+ return False
+ return True
+
+ def __or__(self, other):
+ if not isinstance(other, Iterable):
+ return NotImplemented
+ chain = (e for s in (self, other) for e in s)
+ return self._from_iterable(chain)
+
+ def __sub__(self, other):
+ if not isinstance(other, Set):
+ if not isinstance(other, Iterable):
+ return NotImplemented
+ other = self._from_iterable(other)
+ return self._from_iterable(value for value in self
+ if value not in other)
+
+ def __xor__(self, other):
+ if not isinstance(other, Set):
+ if not isinstance(other, Iterable):
+ return NotImplemented
+ other = self._from_iterable(other)
+ return (self - other) | (other - self)
+
+ # Sets are not hashable by default, but subclasses can change this
+ __hash__ = None
+
+ def _hash(self):
+ """Compute the hash value of a set.
+
+ Note that we don't define __hash__: not all sets are hashable.
+ But if you define a hashable set type, its __hash__ should
+ call this function.
+
+ This must be compatible __eq__.
+
+ All sets ought to compare equal if they contain the same
+ elements, regardless of how they are implemented, and
+ regardless of the order of the elements; so there's not much
+ freedom for __eq__ or __hash__. We match the algorithm used
+ by the built-in frozenset type.
+ """
+ MAX = sys.maxint
+ MASK = 2 * MAX + 1
+ n = len(self)
+ h = 1927868237 * (n + 1)
+ h &= MASK
+ for x in self:
+ hx = hash(x)
+ h ^= (hx ^ (hx << 16) ^ 89869747) * 3644798167
+ h &= MASK
+ h = h * 69069 + 907133923
+ h &= MASK
+ if h > MAX:
+ h -= MASK + 1
+ if h == -1:
+ h = 590923713
+ return h
+
+Set.register(frozenset)
+
+
+class MutableSet(Set):
+
+ @abstractmethod
+ def add(self, value):
+ """Add an element."""
+ raise NotImplementedError
+
+ @abstractmethod
+ def discard(self, value):
+ """Remove an element. Do not raise an exception if absent."""
+ raise NotImplementedError
+
+ def remove(self, value):
+ """Remove an element. If not a member, raise a KeyError."""
+ if value not in self:
+ raise KeyError(value)
+ self.discard(value)
+
+ def pop(self):
+ """Return the popped value. Raise KeyError if empty."""
+ it = iter(self)
+ try:
+ value = it.next()
+ except StopIteration:
+ raise KeyError
+ self.discard(value)
+ return value
+
+ def clear(self):
+ """This is slow (creates N new iterators!) but effective."""
+ try:
+ while True:
+ self.pop()
+ except KeyError:
+ pass
+
+ def __ior__(self, it):
+ for value in it:
+ self.add(value)
+ return self
+
+ def __iand__(self, it):
+ for value in (self - it):
+ self.discard(value)
+ return self
+
+ def __ixor__(self, it):
+ if not isinstance(it, Set):
+ it = self._from_iterable(it)
+ for value in it:
+ if value in self:
+ self.discard(value)
+ else:
+ self.add(value)
+ return self
+
+ def __isub__(self, it):
+ for value in it:
+ self.discard(value)
+ return self
+
+MutableSet.register(set)
+
+
+class OrderedSet(MutableSet):
+
+ def __init__(self, iterable=None):
+ self.end = end = []
+ end += [None, end, end] # sentinel node for doubly linked list
+ self.map = {} # key --> [key, prev, next]
+ if iterable is not None:
+ self |= iterable
+
+ def __len__(self):
+ return len(self.map)
+
+ def __contains__(self, key):
+ return key in self.map
+
+ def __getitem__(self, key):
+ return list(self)[key]
+
+ def add(self, key):
+ if key not in self.map:
+ end = self.end
+ curr = end[PREV]
+ curr[NEXT] = end[PREV] = self.map[key] = [key, curr, end]
+
+ def discard(self, key):
+ if key in self.map:
+ key, prev, next = self.map.pop(key)
+ prev[NEXT] = next
+ next[PREV] = prev
+
+ def __iter__(self):
+ end = self.end
+ curr = end[NEXT]
+ while curr is not end:
+ yield curr[KEY]
+ curr = curr[NEXT]
+
+ def __reversed__(self):
+ end = self.end
+ curr = end[PREV]
+ while curr is not end:
+ yield curr[KEY]
+ curr = curr[PREV]
+
+ def pop(self, last=True):
+ if not self:
+ raise KeyError('set is empty')
+ key = reversed(self).next() if last else iter(self).next()
+ self.discard(key)
+ return key
+
+ def __repr__(self):
+ if not self:
+ return '%s()' % (self.__class__.__name__,)
+ return '%s(%r)' % (self.__class__.__name__, list(self))
+
+ def __eq__(self, other):
+ if isinstance(other, OrderedSet):
+ return len(self) == len(other) and list(self) == list(other)
+ return set(self) == set(other)
+
+ def __del__(self):
+ self.clear() # remove circular references
+
+if __name__ == '__main__':
+ print(OrderedSet('abracadaba'))
+ print(OrderedSet('simsalabim'))
diff --git a/src/oset/pyoset.py b/src/oset/pyoset.py
new file mode 100644
index 0000000..6177d6a
--- /dev/null
+++ b/src/oset/pyoset.py
@@ -0,0 +1,85 @@
+#!/usr/bin/env python
+# -*- mode:python; tab-width: 2; coding: utf-8 -*-
+
+"""Partially backported python ABC classes"""
+
+from __future__ import absolute_import
+
+import sys
+
+if sys.version_info < (2, 6):
+ # Running in Python <= 2.5
+ from ._abc import MutableSet
+ def next(it):
+ return it.next()
+else:
+ from collections import MutableSet
+
+KEY, PREV, NEXT = range(3)
+
+
+class OrderedSet(MutableSet):
+
+ def __init__(self, iterable=None):
+ self.end = end = []
+ end += [None, end, end] # sentinel node for doubly linked list
+ self.map = {} # key --> [key, prev, next]
+ if iterable is not None:
+ self |= iterable
+
+ def __len__(self):
+ return len(self.map)
+
+ def __contains__(self, key):
+ return key in self.map
+
+ def __getitem__(self, key):
+ return list(self)[key]
+
+ def add(self, key):
+ if key not in self.map:
+ end = self.end
+ curr = end[PREV]
+ curr[NEXT] = end[PREV] = self.map[key] = [key, curr, end]
+
+ def discard(self, key):
+ if key in self.map:
+ key, prev, next = self.map.pop(key)
+ prev[NEXT] = next
+ next[PREV] = prev
+
+ def __iter__(self):
+ end = self.end
+ curr = end[NEXT]
+ while curr is not end:
+ yield curr[KEY]
+ curr = curr[NEXT]
+
+ def __reversed__(self):
+ end = self.end
+ curr = end[PREV]
+ while curr is not end:
+ yield curr[KEY]
+ curr = curr[PREV]
+
+ def pop(self, last=True):
+ if not self:
+ raise KeyError('set is empty')
+ key = next(reversed(self)) if last else next(iter(self))
+ self.discard(key)
+ return key
+
+ def __repr__(self):
+ if not self:
+ return '%s()' % (self.__class__.__name__,)
+ return '%s(%r)' % (self.__class__.__name__, list(self))
+
+ def __eq__(self, other):
+ if isinstance(other, OrderedSet):
+ return len(self) == len(other) and list(self) == list(other)
+ return set(self) == set(other)
+
+ def __del__(self):
+ self.clear() # remove circular references
+
+oset = OrderedSet
diff --git a/src/oset/tests.py b/src/oset/tests.py
new file mode 100644
index 0000000..36f53f2
--- /dev/null
+++ b/src/oset/tests.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python
+# -*- mode:python; tab-width: 2; coding: utf-8 -*-
+
+"""Partially backported python ABC classes"""
+
+from __future__ import absolute_import
+
+import doctest
+import unittest
+
+optionflags = doctest.NORMALIZE_WHITESPACE | \
+ doctest.ELLIPSIS | \
+ doctest.REPORT_ONLY_FIRST_FAILURE
+
+TESTFILES = [
+ 'pyoset.txt',
+]
+
+
+def test_suite():
+ """Simple tes suite"""
+
+ globs = {}
+ try:
+ from pprint import pprint
+ globs['pprint'] = pprint
+ except Exception:
+ pass
+ try:
+ from interlude import interact
+ globs['interact'] = interact
+ except Exception:
+ pass
+
+ return unittest.TestSuite([
+ doctest.DocFileSuite(
+ file,
+ optionflags=optionflags,
+ globs=globs,
+ ) for file in TESTFILES
+ ])
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='test_suite')
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/python-oset.git
More information about the debian-med-commit
mailing list