]> Frank Brehm's Git Trees - pixelpark/ldap-migration.git/commitdiff
Adding lib/ldap_migration/istringset.py
authorFrank Brehm <frank.brehm@pixelpark.com>
Thu, 19 Nov 2020 17:00:23 +0000 (18:00 +0100)
committerFrank Brehm <frank.brehm@pixelpark.com>
Thu, 19 Nov 2020 17:00:23 +0000 (18:00 +0100)
lib/ldap_migration/istringset.py

index 5855d12a1a4cf33ddee2d5d5d0d3cd7b184008e2..302becd88df363e2d5174be471272fc951b24169 100644 (file)
@@ -10,7 +10,6 @@ from __future__ import absolute_import
 
 # Standard module
 import logging
-import copy
 
 try:
     from collections.abc import MutableSet
@@ -20,9 +19,7 @@ except ImportError:
 # Third party modules
 
 # Own modules
-from fb_tools.common import pp
 from fb_tools.errors import FbError
-from fb_tools.obj import FbBaseObject
 
 __version__ = '0.1.0'
 
@@ -30,11 +27,13 @@ LOG = logging.getLogger(__name__)
 
 # =============================================================================
 class WrongItemTypeError(TypeError, FbError):
+    """Exeception class for the case, that a given parameter ist not of type str."""
 
     # -------------------------------------------------------------------------
     def __init__(self, item):
 
         self.item = item
+        super(WrongItemTypeError, self).__init__()
 
     # -------------------------------------------------------------------------
     def __str__(self):
@@ -45,11 +44,14 @@ class WrongItemTypeError(TypeError, FbError):
 
 # =============================================================================
 class WrongCompareSetClassError(TypeError, FbError):
+    """Exeception class for the case, that a given class ist not of an
+       instance of CaseInsensitiveStringSet."""
 
     # -------------------------------------------------------------------------
     def __init__(self, other):
 
         self.other_class = other.__class__.__name__
+        super(WrongCompareSetClassError, self).__init__()
 
     # -------------------------------------------------------------------------
     def __str__(self):
@@ -71,15 +73,14 @@ class CaseInsensitiveStringSet(MutableSet):
     # -------------------------------------------------------------------------
     def __init__(self, iterable):
 
-        self._items = []
+        self._items = {}
 
         for item in iterable:
 
             if not isinstance(item, str):
                 raise WrongItemTypeError(item)
 
-            if item not in self:
-                self._items.append(item)
+            self.add(item)
 
     # -------------------------------------------------------------------------
     # Mandatory methods (ABC methods)
@@ -87,68 +88,44 @@ class CaseInsensitiveStringSet(MutableSet):
     # -------------------------------------------------------------------------
     def __iter__(self):
 
-        return iter(self._items)
+        for key in sorted(self._items.keys()):
+            yield self._items[key]
 
     # -------------------------------------------------------------------------
     def __contains__(self, value):
+        """ The 'in' operator."""
 
         if not isinstance(value, str):
             raise WrongItemTypeError(value)
 
-        for item in self._items:
-            if item.lower() == value.lower():
-                return True
-
-        return value in self.elements
+        ival = value.lower()
+        if ival in self._items:
+            return True
+        return False
 
     # -------------------------------------------------------------------------
     def __len__(self):
         return len(self._items)
 
-    # ------------------------------------------------------------------------- 
+    # -------------------------------------------------------------------------
     def add(self, value):
 
         if not isinstance(value, str):
             raise WrongItemTypeError(value)
 
-        if value in self:
-
-            index = 0
-            for item in self._items:
-                if item.lower() == value.lower():
-                    if item != value:
-                        self._items[index] = value
-                    break
-                index += 1
-
-        else:
-            self._items.append(value)
+        ival = value.lower()
+        self._items[ival] = value
 
     # -------------------------------------------------------------------------
     def discard(self, value):
 
-        index = 0
-        for item in self._items:
-            if item.lower() == value.lower():
-                del self._items[index]
-                break
-            index += 1
+        ival = value.lower()
+        if ival in self._items:
+            del self._items[ival]
 
     # -------------------------------------------------------------------------
     # Nice to have methods
 
-    # -------------------------------------------------------------------------
-    def isdisjoint(self, other):
-
-        if not isinstance(other, CaseInsensitiveStringSet):
-            raise WrongCompareSetClassError(other)
-
-        for item in self._items:
-            if item in other:
-                return False
-
-        return True
-
     # -------------------------------------------------------------------------
     def issubset(self, other):
 
@@ -163,6 +140,7 @@ class CaseInsensitiveStringSet(MutableSet):
 
     # -------------------------------------------------------------------------
     def __le__(self, other):
+        """The '<=' operator."""
 
         if not isinstance(other, CaseInsensitiveStringSet):
             raise WrongCompareSetClassError(other)
@@ -171,6 +149,7 @@ class CaseInsensitiveStringSet(MutableSet):
 
     # -------------------------------------------------------------------------
     def __eq__(self, other):
+        """The '==' operator."""
 
         if not isinstance(other, CaseInsensitiveStringSet):
             raise WrongCompareSetClassError(other)
@@ -186,6 +165,7 @@ class CaseInsensitiveStringSet(MutableSet):
 
     # -------------------------------------------------------------------------
     def __ne__(self, other):
+        """The '!=' operator."""
 
         if not isinstance(other, CaseInsensitiveStringSet):
             raise WrongCompareSetClassError(other)
@@ -196,6 +176,7 @@ class CaseInsensitiveStringSet(MutableSet):
 
     # -------------------------------------------------------------------------
     def __lt__(self, other):
+        """The '<' operator."""
 
         if not isinstance(other, CaseInsensitiveStringSet):
             raise WrongCompareSetClassError(other)
@@ -209,6 +190,311 @@ class CaseInsensitiveStringSet(MutableSet):
                 return True
         return False
 
+    # -------------------------------------------------------------------------
+    def __gt__(self, other):
+        """The '>' operator."""
+
+        if not isinstance(other, CaseInsensitiveStringSet):
+            raise WrongCompareSetClassError(other)
+
+        if self.__le__(other):
+            return False
+        return True
+
+    # -------------------------------------------------------------------------
+    def __ge__(self, other):
+        """The '>=' operator."""
+
+        if not isinstance(other, CaseInsensitiveStringSet):
+            raise WrongCompareSetClassError(other)
+
+        if self.__lt__(other):
+            return False
+        return True
+
+    # -------------------------------------------------------------------------
+    def __copy__(self):
+
+        empty = []
+        new_set = self.__class__(empty)
+        for item in self:
+            new_set.add(item)
+
+        return new_set
+
+    # -------------------------------------------------------------------------
+    def copy(self):
+        return self.__copy__()
+
+    # -------------------------------------------------------------------------
+    def values(self):
+
+        ret = []
+        for item in self:
+            ret.append(item)
+        return ret
+
+    # -------------------------------------------------------------------------
+    def __str__(self):
+
+        if len(self) == 0:
+            return "{}()".format(self.__class__.__name__)
+
+        ret = "{}(".format(self.__class__.__name__)
+        ret += ', '.join(map(lambda x: "{!r}".format(x), self.values()))
+        ret += ')'
+
+        return ret
+
+    # -------------------------------------------------------------------------
+    def __repr__(self):
+        return str(self)
+
+    # -------------------------------------------------------------------------
+    def union(self, *others):
+
+        for other in others:
+            if not isinstance(other, CaseInsensitiveStringSet):
+                raise WrongCompareSetClassError(other)
+
+        new_set = self.__copy__()
+        for other in others:
+            for item in other:
+                if item not in new_set:
+                    new_set.add(item)
+
+        return new_set
+
+    # -------------------------------------------------------------------------
+    def __or__(self, *others):
+        """The '|' operator."""
+
+        for other in others:
+            if not isinstance(other, CaseInsensitiveStringSet):
+                raise WrongCompareSetClassError(other)
+
+        return self.union(*others)
+
+    # -------------------------------------------------------------------------
+    def intersection(self, *others):
+
+        for other in others:
+            if not isinstance(other, CaseInsensitiveStringSet):
+                raise WrongCompareSetClassError(other)
+
+        empty = []
+        new_set = self.__class__(empty)
+        for item in self:
+            do_add = True
+            for other in others:
+                if item not in other:
+                    do_add = False
+            if do_add:
+                new_set.add(item)
+
+        return new_set
+
+    # -------------------------------------------------------------------------
+    def __and__(self, *others):
+        """The '&' operator."""
+
+        for other in others:
+            if not isinstance(other, CaseInsensitiveStringSet):
+                raise WrongCompareSetClassError(other)
+
+        return self.intersection(*others)
+
+    # -------------------------------------------------------------------------
+    def difference(self, *others):
+
+        for other in others:
+            if not isinstance(other, CaseInsensitiveStringSet):
+                raise WrongCompareSetClassError(other)
+
+        empty = []
+        new_set = self.__class__(empty)
+        for item in self:
+            do_add = True
+            for other in others:
+                if item in other:
+                    do_add = False
+            if do_add:
+                new_set.add(item)
+
+        return new_set
+
+    # -------------------------------------------------------------------------
+    def __sub__(self, *others):
+        """The '-' operator."""
+
+        for other in others:
+            if not isinstance(other, CaseInsensitiveStringSet):
+                raise WrongCompareSetClassError(other)
+
+        return self.difference(*others)
+
+    # -------------------------------------------------------------------------
+    def symmetric_difference(self, other):
+
+        if not isinstance(other, CaseInsensitiveStringSet):
+            raise WrongCompareSetClassError(other)
+
+        empty = []
+        new_set = self.__class__(empty)
+
+        for item in self:
+            if item not in other:
+                new_set.add(item)
+
+        for item in other:
+            if item not in self:
+                new_set.add(item)
+
+        return new_set
+
+    # -------------------------------------------------------------------------
+    def __xor__(self, other):
+        """The '^' operator."""
+
+        if not isinstance(other, CaseInsensitiveStringSet):
+            raise WrongCompareSetClassError(other)
+
+        return self.symmetric_difference(other)
+
+    # -------------------------------------------------------------------------
+    def isdisjoint(self, other):
+
+        if not isinstance(other, CaseInsensitiveStringSet):
+            raise WrongCompareSetClassError(other)
+
+        for item in self:
+            if item in other:
+                return False
+
+        for item in other:
+            if item in self:
+                return False
+
+        return True
+
+    # -------------------------------------------------------------------------
+    def update(self, *others):
+
+        for other in others:
+            if not isinstance(other, CaseInsensitiveStringSet):
+                raise WrongCompareSetClassError(other)
+
+        for other in others:
+            for item in other:
+                if item not in self:
+                    self.add(item)
+
+    # -------------------------------------------------------------------------
+    def __ior__(self, *others):
+        """The '|=' operator."""
+
+        for other in others:
+            if not isinstance(other, CaseInsensitiveStringSet):
+                raise WrongCompareSetClassError(other)
+
+        self.update(*others)
+
+    # -------------------------------------------------------------------------
+    def intersection_update(self, *others):
+
+        for other in others:
+            if not isinstance(other, CaseInsensitiveStringSet):
+                raise WrongCompareSetClassError(other)
+
+        for item in self:
+            for other in others:
+                if item not in other:
+                    self.discard(item)
+                    break
+
+    # -------------------------------------------------------------------------
+    def __iand__(self, *others):
+        """The '&=' operator."""
+
+        for other in others:
+            if not isinstance(other, CaseInsensitiveStringSet):
+                raise WrongCompareSetClassError(other)
+
+        self.intersection_update(*others)
+
+    # -------------------------------------------------------------------------
+    def difference_update(self, *others):
+
+        for other in others:
+            if not isinstance(other, CaseInsensitiveStringSet):
+                raise WrongCompareSetClassError(other)
+
+        for item in self:
+            for other in others:
+                if item in other:
+                    self.discard(item)
+                    break
+
+    # -------------------------------------------------------------------------
+    def __isub__(self, *others):
+        """The '-=' operator."""
+
+        for other in others:
+            if not isinstance(other, CaseInsensitiveStringSet):
+                raise WrongCompareSetClassError(other)
+
+        self.difference_update(*others)
+
+    # -------------------------------------------------------------------------
+    def symmetric_difference_update(self, other):
+
+        if not isinstance(other, CaseInsensitiveStringSet):
+            raise WrongCompareSetClassError(other)
+
+        for item in self:
+            if item in other:
+                self.discard(item)
+
+        for item in other:
+            if item not in self:
+                self.add(item)
+
+    # -------------------------------------------------------------------------
+    def __ixor__(self, other):
+        """The '|=' operator."""
+
+        if not isinstance(other, CaseInsensitiveStringSet):
+            raise WrongCompareSetClassError(other)
+
+        self.symmetric_difference_update(other)
+
+    # -------------------------------------------------------------------------
+    def remove(self, value):
+
+        ival = value.lower()
+        if ival in self._items:
+            del self._items[ival]
+            return
+
+        raise KeyError(value)
+
+    # -------------------------------------------------------------------------
+    def pop(self):
+
+        if len(self) == 0:
+            raise IndexError("pop() from empty list")
+
+        key = self._items.keys()[0]
+        value = self._items[key]
+        del self._items[key]
+
+        return value
+
+    # -------------------------------------------------------------------------
+    def clear(self):
+
+        self._items = {}
+
 
 # =============================================================================
 if __name__ == "__main__":