Hello community, here is the log from the commit of package python-dotmap for openSUSE:Factory checked in at 2020-10-22 14:25:24 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-dotmap (Old) and /work/SRC/openSUSE:Factory/.python-dotmap.new.3463 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-dotmap" Thu Oct 22 14:25:24 2020 rev:3 rq:843296 version:1.3.22 Changes: -------- --- /work/SRC/openSUSE:Factory/python-dotmap/python-dotmap.changes 2020-06-18 10:22:15.443741533 +0200 +++ /work/SRC/openSUSE:Factory/.python-dotmap.new.3463/python-dotmap.changes 2020-10-22 14:26:47.150992857 +0200 @@ -1,0 +2,6 @@ +Thu Oct 22 03:56:59 UTC 2020 - Steve Kowalik <[email protected]> + +- Update to 1.3.22: + * No changelog + +------------------------------------------------------------------- Old: ---- dotmap-1.3.17.tar.gz New: ---- dotmap-1.3.22.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-dotmap.spec ++++++ --- /var/tmp/diff_new_pack.v6TuCS/_old 2020-10-22 14:26:47.626993285 +0200 +++ /var/tmp/diff_new_pack.v6TuCS/_new 2020-10-22 14:26:47.630993288 +0200 @@ -18,11 +18,10 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-dotmap -Version: 1.3.17 +Version: 1.3.22 Release: 0 Summary: Python ordered, dynamically-expandable dot-access dictionary License: MIT -Group: Development/Languages/Python URL: https://github.com/drgrib/dotmap Source: https://files.pythonhosted.org/packages/source/d/dotmap/dotmap-%{version}.tar.gz BuildRequires: %{python_module setuptools} ++++++ dotmap-1.3.17.tar.gz -> dotmap-1.3.22.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dotmap-1.3.17/PKG-INFO new/dotmap-1.3.22/PKG-INFO --- old/dotmap-1.3.17/PKG-INFO 2020-06-04 17:37:03.381507600 +0200 +++ new/dotmap-1.3.22/PKG-INFO 2020-10-11 22:47:28.335612800 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: dotmap -Version: 1.3.17 +Version: 1.3.22 Summary: ordered, dynamically-expandable dot-access dictionary Home-page: https://github.com/drgrib/dotmap Author: Chris Redford diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dotmap-1.3.17/dotmap/__init__.py new/dotmap-1.3.22/dotmap/__init__.py --- old/dotmap-1.3.17/dotmap/__init__.py 2020-06-04 17:33:56.000000000 +0200 +++ new/dotmap-1.3.22/dotmap/__init__.py 2020-10-11 22:47:16.000000000 +0200 @@ -1,9 +1,9 @@ from __future__ import print_function from collections import OrderedDict try: - from collections.abc import MutableMapping + from collections.abc import MutableMapping, Iterable except ImportError: - from collections import MutableMapping + from collections import MutableMapping, Iterable from json import dumps from pprint import pprint from sys import version_info @@ -16,39 +16,48 @@ out += '({})'.format(item) print(out) +__all__ = ['DotMap'] class DotMap(MutableMapping, OrderedDict): def __init__(self, *args, **kwargs): self._map = OrderedDict() - self._dynamic = True - if kwargs: - if '_dynamic' in kwargs: - self._dynamic = kwargs['_dynamic'] + self._dynamic = kwargs.pop('_dynamic', True) + self._prevent_method_masking = kwargs.pop('_prevent_method_masking', False) + if args: d = args[0] # for recursive assignment handling trackedIDs = {id(d): self} - if isinstance(d, dict): - for k,v in self.__call_items(d): - if isinstance(v, dict): - if id(v) in trackedIDs: - v = trackedIDs[id(v)] - else: - v = self.__class__(v, _dynamic=self._dynamic) - trackedIDs[id(v)] = v - if type(v) is list: - l = [] - for i in v: - n = i - if isinstance(i, dict): - n = self.__class__(i, _dynamic=self._dynamic) - l.append(n) - v = l - self._map[k] = v + + src = [] + if isinstance(d, MutableMapping): + src = self.__call_items(d) + elif isinstance(d, Iterable): + src = d + + for k,v in src: + if self._prevent_method_masking and k in reserved_keys: + raise KeyError('"{}" is reserved'.format(k)) + if isinstance(v, dict): + if id(v) in trackedIDs: + v = trackedIDs[id(v)] + else: + v = self.__class__(v, _dynamic=self._dynamic, _prevent_method_masking = self._prevent_method_masking) + trackedIDs[id(v)] = v + if type(v) is list: + l = [] + for i in v: + n = i + if isinstance(i, dict): + n = self.__class__(i, _dynamic=self._dynamic, _prevent_method_masking = self._prevent_method_masking) + l.append(n) + v = l + self._map[k] = v if kwargs: for k,v in self.__call_items(kwargs): - if k != '_dynamic': - self._map[k] = v + if self._prevent_method_masking and k in reserved_keys: + raise KeyError('"{}" is reserved'.format(k)) + self._map[k] = v def __call_items(self, obj): if hasattr(obj, 'iteritems') and ismethod(getattr(obj, 'iteritems')): @@ -77,8 +86,10 @@ return self._map[k] def __setattr__(self, k, v): - if k in {'_map','_dynamic', '_ipython_canary_method_should_not_exist_'}: + if k in {'_map','_dynamic', '_ipython_canary_method_should_not_exist_', '_prevent_method_masking'}: super(DotMap, self).__setattr__(k,v) + elif self._prevent_method_masking and k in reserved_keys: + raise KeyError('"{}" is reserved'.format(k)) else: self[k] = v @@ -112,12 +123,17 @@ msg = "unsupported operand type(s) for +: '{}' and '{}'" raise TypeError(msg.format(self_type, other_type)) - def __str__(self): + def __str__(self, seen = None): items = [] + seen = {id(self)} if seen is None else seen for k,v in self.__call_items(self._map): - # recursive assignment case - if id(v) == id(self): - items.append('{0}={1}(...)'.format(k, self.__class__.__name__)) + # circular assignment case + if isinstance(v, self.__class__): + if id(v) in seen: + items.append('{0}={1}(...)'.format(k, self.__class__.__name__)) + else: + seen.add(id(v)) + items.append('{0}={1}'.format(k, v.__str__(seen))) else: items.append('{0}={1}'.format(k, repr(v))) joined = ', '.join(items) @@ -316,6 +332,7 @@ s = '\n'.join(lines) return s +reserved_keys = {i for i in dir(DotMap) if not i.startswith('__') and not i.endswith('__')} if __name__ == '__main__': # basics @@ -591,5 +608,44 @@ p.first.second.third = 456 print(p.first.second.third) + print('\n== DotMap method masking ==') + # method masking tests + d = DotMap(a=1,get='mango') + d = DotMap((('a',1),('get','mango'))) + d = DotMap({'a':1, 'get': 'mango'}) + d = DotMap({'a':1, 'b': {'get': 'mango'}}) + d.a = {'get':'mongo'} + + try: + d = DotMap(a=1,get='mango', _prevent_method_masking = True) + raise RuntimeError("this should fail with KeyError") + except KeyError: + print('kwargs method masking ok') + + try: + d = DotMap((('a',1),('get','mango')), _prevent_method_masking = True) + raise RuntimeError("this should fail with KeyError") + except KeyError: + print('iterable method masking ok') + + try: + d = DotMap({'a':1, 'get': 'mango'}, _prevent_method_masking = True) + raise RuntimeError("this should fail with KeyError") + except KeyError: + print('dict method masking ok') + + try: + d = DotMap({'a':1, 'b': {'get': 'mango'}}, _prevent_method_masking = True) + raise RuntimeError("this should fail with KeyError") + except KeyError: + print('nested dict method masking ok') + + try: + d = DotMap({'a':1, 'b': {}}, _prevent_method_masking = True) + d.b.get = 7 + raise RuntimeError("this should fail with KeyError") + except KeyError: + print('nested dict attrib masking ok') + # final print print() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dotmap-1.3.17/dotmap.egg-info/PKG-INFO new/dotmap-1.3.22/dotmap.egg-info/PKG-INFO --- old/dotmap-1.3.17/dotmap.egg-info/PKG-INFO 2020-06-04 17:37:03.000000000 +0200 +++ new/dotmap-1.3.22/dotmap.egg-info/PKG-INFO 2020-10-11 22:47:28.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: dotmap -Version: 1.3.17 +Version: 1.3.22 Summary: ordered, dynamically-expandable dot-access dictionary Home-page: https://github.com/drgrib/dotmap Author: Chris Redford diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dotmap-1.3.17/setup.py new/dotmap-1.3.22/setup.py --- old/dotmap-1.3.17/setup.py 2020-06-04 17:36:57.000000000 +0200 +++ new/dotmap-1.3.22/setup.py 2020-10-11 22:47:21.000000000 +0200 @@ -4,7 +4,7 @@ long_description = fh.read() setup( - version = '1.3.17', + version = '1.3.22', name='dotmap', packages=['dotmap'], # this must be the same as the name above description='ordered, dynamically-expandable dot-access dictionary',
