[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