Mercurial > repos > shellac > guppy_basecaller
diff env/lib/python3.7/site-packages/humanfriendly/case.py @ 2:6af9afd405e9 draft
"planemo upload commit 0a63dd5f4d38a1f6944587f52a8cd79874177fc1"
author | shellac |
---|---|
date | Thu, 14 May 2020 14:56:58 -0400 |
parents | 26e78fe6e8c4 |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/env/lib/python3.7/site-packages/humanfriendly/case.py Thu May 14 14:56:58 2020 -0400 @@ -0,0 +1,157 @@ +# Human friendly input/output in Python. +# +# Author: Peter Odding <peter@peterodding.com> +# Last Change: April 19, 2020 +# URL: https://humanfriendly.readthedocs.io + +""" +Simple case insensitive dictionaries. + +The :class:`CaseInsensitiveDict` class is a dictionary whose string keys +are case insensitive. It works by automatically coercing string keys to +:class:`CaseInsensitiveKey` objects. Keys that are not strings are +supported as well, just without case insensitivity. + +At its core this module works by normalizing strings to lowercase before +comparing or hashing them. It doesn't support proper case folding nor +does it support Unicode normalization, hence the word "simple". +""" + +# Standard library modules. +import collections + +try: + # Python >= 3.3. + from collections.abc import Iterable, Mapping +except ImportError: + # Python 2.7. + from collections import Iterable, Mapping + +# Modules included in our package. +from humanfriendly.compat import basestring, unicode + +# Public identifiers that require documentation. +__all__ = ("CaseInsensitiveDict", "CaseInsensitiveKey") + + +class CaseInsensitiveDict(collections.OrderedDict): + + """ + Simple case insensitive dictionary implementation (that remembers insertion order). + + This class works by overriding methods that deal with dictionary keys to + coerce string keys to :class:`CaseInsensitiveKey` objects before calling + down to the regular dictionary handling methods. While intended to be + complete this class has not been extensively tested yet. + """ + + def __init__(self, other=None, **kw): + """Initialize a :class:`CaseInsensitiveDict` object.""" + # Initialize our superclass. + super(CaseInsensitiveDict, self).__init__() + # Handle the initializer arguments. + self.update(other, **kw) + + def coerce_key(self, key): + """ + Coerce string keys to :class:`CaseInsensitiveKey` objects. + + :param key: The value to coerce (any type). + :returns: If `key` is a string then a :class:`CaseInsensitiveKey` + object is returned, otherwise the value of `key` is + returned unmodified. + """ + if isinstance(key, basestring): + key = CaseInsensitiveKey(key) + return key + + @classmethod + def fromkeys(cls, iterable, value=None): + """Create a case insensitive dictionary with keys from `iterable` and values set to `value`.""" + return cls((k, value) for k in iterable) + + def get(self, key, default=None): + """Get the value of an existing item.""" + return super(CaseInsensitiveDict, self).get(self.coerce_key(key), default) + + def pop(self, key, default=None): + """Remove an item from a case insensitive dictionary.""" + return super(CaseInsensitiveDict, self).pop(self.coerce_key(key), default) + + def setdefault(self, key, default=None): + """Get the value of an existing item or add a new item.""" + return super(CaseInsensitiveDict, self).setdefault(self.coerce_key(key), default) + + def update(self, other=None, **kw): + """Update a case insensitive dictionary with new items.""" + if isinstance(other, Mapping): + # Copy the items from the given mapping. + for key, value in other.items(): + self[key] = value + elif isinstance(other, Iterable): + # Copy the items from the given iterable. + for key, value in other: + self[key] = value + elif other is not None: + # Complain about unsupported values. + msg = "'%s' object is not iterable" + type_name = type(value).__name__ + raise TypeError(msg % type_name) + # Copy the keyword arguments (if any). + for key, value in kw.items(): + self[key] = value + + def __contains__(self, key): + """Check if a case insensitive dictionary contains the given key.""" + return super(CaseInsensitiveDict, self).__contains__(self.coerce_key(key)) + + def __delitem__(self, key): + """Delete an item in a case insensitive dictionary.""" + return super(CaseInsensitiveDict, self).__delitem__(self.coerce_key(key)) + + def __getitem__(self, key): + """Get the value of an item in a case insensitive dictionary.""" + return super(CaseInsensitiveDict, self).__getitem__(self.coerce_key(key)) + + def __setitem__(self, key, value): + """Set the value of an item in a case insensitive dictionary.""" + return super(CaseInsensitiveDict, self).__setitem__(self.coerce_key(key), value) + + +class CaseInsensitiveKey(unicode): + + """ + Simple case insensitive dictionary key implementation. + + The :class:`CaseInsensitiveKey` class provides an intentionally simple + implementation of case insensitive strings to be used as dictionary keys. + + If you need features like Unicode normalization or proper case folding + please consider using a more advanced implementation like the :pypi:`istr` + package instead. + """ + + def __new__(cls, value): + """Create a :class:`CaseInsensitiveKey` object.""" + # Delegate string object creation to our superclass. + obj = unicode.__new__(cls, value) + # Store the lowercased string and its hash value. + normalized = obj.lower() + obj._normalized = normalized + obj._hash_value = hash(normalized) + return obj + + def __hash__(self): + """Get the hash value of the lowercased string.""" + return self._hash_value + + def __eq__(self, other): + """Compare two strings as lowercase.""" + if isinstance(other, CaseInsensitiveKey): + # Fast path (and the most common case): Comparison with same type. + return self._normalized == other._normalized + elif isinstance(other, unicode): + # Slow path: Comparison with strings that need lowercasing. + return self._normalized == other.lower() + else: + return NotImplemented