Loading collections.py +52 −2 Original line number Diff line number Diff line Loading @@ -16,7 +16,8 @@ # You should have received a copy of the GNU Lesser General Public License # along with Ammsml. If not, see <http://www.gnu.org/licenses/>. from collections.abc import Sequence from collections.abc import Sequence, Mapping, Hashable def is_string(seq): Loading Loading @@ -55,11 +56,14 @@ def count(seq): Resembles the `collections.Counter` class functionality, which is deprecated since version 3.3, will be removed in version 3.9 It is meant to be replaced when the we find something equivalent in maybe collections.abc It is meant to be replaced when we find something equivalent in maybe collections.abc this code also runs on Python 2.6.* where collections.Counter is not available. :param seq: :return: """ if not is_iterable(seq): raise Exception('Argument provided is not an iterable') Loading @@ -69,3 +73,49 @@ def count(seq): for elem in seq: counters[elem] = counters.get(elem, 0) + 1 return counters class ImmutableDict(Hashable, Mapping): """ Dictionary that cannot be updated """ def __init__(self, *args, **kwargs): self._store = dict(*args, **kwargs) def __getitem__(self, key): return self._store[key] def __iter__(self): return self._store.__iter__() def __len__(self): return self._store.__len__() def __hash__(self): return hash(frozenset(self.items())) def __repr__(self): return 'ImmutableDict({0})'.format(repr(self._store)) def union(self, overriding_mapping): """ Create an ImmutableDict as a combination of the original and overriding_mapping :param overriding_mapping: A Mapping of replacement and additional items :return: A copy of the ImmutableDict with key-value pairs from the overriding_mapping added If any of the keys in overriding_mapping are already present in the original ImmutableDict, the overriding_mapping item replaces the one in the original ImmutableDict. """ return ImmutableDict(self._store, **overriding_mapping) def difference(self, subtractive_iterable): """ Create an ImmutableDict as a combination of the original minus keys in subtractive_iterable :param subtractive_iterable: Any iterable containing keys that should not be present in the new ImmutableDict :return: A copy of the ImmutableDict with keys from the subtractive_iterable removed """ remove_keys = frozenset(subtractive_iterable) keys = (k for k in self._store.keys() if k not in remove_keys) return ImmutableDict((k, self._store[k]) for k in keys) parsing/__init__.py +15 −1 Original line number Diff line number Diff line Loading @@ -79,6 +79,20 @@ def is_quoted(data): return len(data) > 1 and data[0] == data[-1] and data[0] in ('"', "'") and data[-2] != '\\' def humanize_time(d) -> str: """ Return a human-friendly description of elapsed time :param d: :return: """ human = "" if d >= 3600: human += "%dh" % (int(d) // 3600) d %= 3600 if d >= 60: human += "%dm" % (int(d) // 60) d %= 60 human += ("%.3fs" % d) return human singleton.py +15 −0 Original line number Diff line number Diff line Loading @@ -57,3 +57,18 @@ def with_metaclass(meta, *bases): def __prepare__(cls, name, this_bases): return meta.__prepare__(name, bases) return type.__new__(metaclass, 'temporary_class', (), {}) def add_metaclass(metaclass): """Class decorator for creating a class with a metaclass.""" def wrapper(cls): orig_vars = cls.__dict__.copy() slots = orig_vars.get('__slots__') if slots is not None: if isinstance(slots, str): slots = [slots] for slots_var in slots: orig_vars.pop(slots_var) orig_vars.pop('__dict__', None) orig_vars.pop('__weakref__', None) return metaclass(cls.__name__, cls.__bases__, orig_vars) return wrapper No newline at end of file tests/test_parsing/test_humanize_time.py 0 → 100644 +11 −0 Original line number Diff line number Diff line import unittest from ammsml.utils.parsing import humanize_time class Test_humanize_time(unittest.TestCase): def test_something(self): self.assertEqual(True, False) # TODO if __name__ == '__main__': unittest.main() Loading
collections.py +52 −2 Original line number Diff line number Diff line Loading @@ -16,7 +16,8 @@ # You should have received a copy of the GNU Lesser General Public License # along with Ammsml. If not, see <http://www.gnu.org/licenses/>. from collections.abc import Sequence from collections.abc import Sequence, Mapping, Hashable def is_string(seq): Loading Loading @@ -55,11 +56,14 @@ def count(seq): Resembles the `collections.Counter` class functionality, which is deprecated since version 3.3, will be removed in version 3.9 It is meant to be replaced when the we find something equivalent in maybe collections.abc It is meant to be replaced when we find something equivalent in maybe collections.abc this code also runs on Python 2.6.* where collections.Counter is not available. :param seq: :return: """ if not is_iterable(seq): raise Exception('Argument provided is not an iterable') Loading @@ -69,3 +73,49 @@ def count(seq): for elem in seq: counters[elem] = counters.get(elem, 0) + 1 return counters class ImmutableDict(Hashable, Mapping): """ Dictionary that cannot be updated """ def __init__(self, *args, **kwargs): self._store = dict(*args, **kwargs) def __getitem__(self, key): return self._store[key] def __iter__(self): return self._store.__iter__() def __len__(self): return self._store.__len__() def __hash__(self): return hash(frozenset(self.items())) def __repr__(self): return 'ImmutableDict({0})'.format(repr(self._store)) def union(self, overriding_mapping): """ Create an ImmutableDict as a combination of the original and overriding_mapping :param overriding_mapping: A Mapping of replacement and additional items :return: A copy of the ImmutableDict with key-value pairs from the overriding_mapping added If any of the keys in overriding_mapping are already present in the original ImmutableDict, the overriding_mapping item replaces the one in the original ImmutableDict. """ return ImmutableDict(self._store, **overriding_mapping) def difference(self, subtractive_iterable): """ Create an ImmutableDict as a combination of the original minus keys in subtractive_iterable :param subtractive_iterable: Any iterable containing keys that should not be present in the new ImmutableDict :return: A copy of the ImmutableDict with keys from the subtractive_iterable removed """ remove_keys = frozenset(subtractive_iterable) keys = (k for k in self._store.keys() if k not in remove_keys) return ImmutableDict((k, self._store[k]) for k in keys)
parsing/__init__.py +15 −1 Original line number Diff line number Diff line Loading @@ -79,6 +79,20 @@ def is_quoted(data): return len(data) > 1 and data[0] == data[-1] and data[0] in ('"', "'") and data[-2] != '\\' def humanize_time(d) -> str: """ Return a human-friendly description of elapsed time :param d: :return: """ human = "" if d >= 3600: human += "%dh" % (int(d) // 3600) d %= 3600 if d >= 60: human += "%dm" % (int(d) // 60) d %= 60 human += ("%.3fs" % d) return human
singleton.py +15 −0 Original line number Diff line number Diff line Loading @@ -57,3 +57,18 @@ def with_metaclass(meta, *bases): def __prepare__(cls, name, this_bases): return meta.__prepare__(name, bases) return type.__new__(metaclass, 'temporary_class', (), {}) def add_metaclass(metaclass): """Class decorator for creating a class with a metaclass.""" def wrapper(cls): orig_vars = cls.__dict__.copy() slots = orig_vars.get('__slots__') if slots is not None: if isinstance(slots, str): slots = [slots] for slots_var in slots: orig_vars.pop(slots_var) orig_vars.pop('__dict__', None) orig_vars.pop('__weakref__', None) return metaclass(cls.__name__, cls.__bases__, orig_vars) return wrapper No newline at end of file
tests/test_parsing/test_humanize_time.py 0 → 100644 +11 −0 Original line number Diff line number Diff line import unittest from ammsml.utils.parsing import humanize_time class Test_humanize_time(unittest.TestCase): def test_something(self): self.assertEqual(True, False) # TODO if __name__ == '__main__': unittest.main()