# Standard module
import logging
-import copy
try:
from collections.abc import MutableSet
# 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'
# =============================================================================
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):
# =============================================================================
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):
# -------------------------------------------------------------------------
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)
# -------------------------------------------------------------------------
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):
# -------------------------------------------------------------------------
def __le__(self, other):
+ """The '<=' operator."""
if not isinstance(other, CaseInsensitiveStringSet):
raise WrongCompareSetClassError(other)
# -------------------------------------------------------------------------
def __eq__(self, other):
+ """The '==' operator."""
if not isinstance(other, CaseInsensitiveStringSet):
raise WrongCompareSetClassError(other)
# -------------------------------------------------------------------------
def __ne__(self, other):
+ """The '!=' operator."""
if not isinstance(other, CaseInsensitiveStringSet):
raise WrongCompareSetClassError(other)
# -------------------------------------------------------------------------
def __lt__(self, other):
+ """The '<' operator."""
if not isinstance(other, CaseInsensitiveStringSet):
raise WrongCompareSetClassError(other)
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__":