Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-tri.declarative for 
openSUSE:Factory checked in at 2021-01-25 18:23:35
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-tri.declarative (Old)
 and      /work/SRC/openSUSE:Factory/.python-tri.declarative.new.28504 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-tri.declarative"

Mon Jan 25 18:23:35 2021 rev:6 rq:866163 version:5.7.0

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-tri.declarative/python-tri.declarative.changes
    2020-07-26 16:19:39.328825765 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-tri.declarative.new.28504/python-tri.declarative.changes
 2021-01-25 18:23:53.388452139 +0100
@@ -1,0 +2,18 @@
+Fri Jan 22 15:42:07 UTC 2021 - Benjamin Greiner <c...@bnavigator.de>
+
+- Update to 5.7.0
+
+  * Make getattr_path more in line with the standard library 
+    getattr semantics
+  * If a default value is provided, return that on missing 
+    attributes
+  * If no default value is given, give a more detailed 
+    error message of what was missing
+  * Added the special case of the empty path returning the object
+- Changes in 5.6.0
+  * Fix corner case of class Meta failing to merge with 
+    None namespace values
+- Changes in 5.5.0
+  * Include tri.struct 4.x as possible requirement 
+
+-------------------------------------------------------------------

Old:
----
  tri.declarative-5.4.1.tar.gz

New:
----
  tri.declarative-5.7.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-tri.declarative.spec ++++++
--- /var/tmp/diff_new_pack.VdKmHw/_old  2021-01-25 18:23:54.128453215 +0100
+++ /var/tmp/diff_new_pack.VdKmHw/_new  2021-01-25 18:23:54.128453215 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-tri.declarative
 #
-# Copyright (c) 2020 SUSE LLC
+# Copyright (c) 2021 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -19,7 +19,7 @@
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 %define skip_python2 1
 Name:           python-tri.declarative
-Version:        5.4.1
+Version:        5.7.0
 Release:        0
 Summary:        Python class decorators in the style of Django model classes
 License:        BSD-3-Clause
@@ -53,13 +53,12 @@
 %python_expand %fdupes %{buildroot}%{$python_sitelib}
 
 %check
-# test_namespace_missing_call_target - pytest5 incompatible usage
-#   https://github.com/TriOptima/tri.declarative/issues/9
-%pytest -k 'not test_namespace_missing_call_target'
+%pytest
 
 %files %{python_files}
 %doc AUTHORS.rst README.rst
 %license LICENSE
-%{python_sitelib}/*
+%{python_sitelib}/tri_declarative
+%{python_sitelib}/tri.declarative-%{version}*-info
 
 %changelog

++++++ tri.declarative-5.4.1.tar.gz -> tri.declarative-5.7.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tri.declarative-5.4.1/HISTORY.rst 
new/tri.declarative-5.7.0/HISTORY.rst
--- old/tri.declarative-5.4.1/HISTORY.rst       2020-06-24 09:04:52.000000000 
+0200
+++ new/tri.declarative-5.7.0/HISTORY.rst       2020-12-18 13:01:42.000000000 
+0100
@@ -1,6 +1,30 @@
 Changelog
 ---------
 
+5.7.0 (2020-12-18)
+------------------
+
+* Make getattr_path more in line with the standard library getattr semantics
+
+  If a default value is provided, return that on missing attributes
+
+  If no default value is given, give a more detailed error message of what was 
missing
+
+* Added the special case of the empty path returning the object
+
+
+5.6.0 (2020-12-02)
+------------------
+
+* Fix corner case of class Meta failing to merge with None namespace values
+
+
+5.5.0 (2020-08-21)
+------------------
+
+* Include tri.struct 4.x as possible requirement
+
+
 5.4.1 (2020-06-34)
 ------------------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/tri.declarative-5.4.1/lib/tri_declarative/__init__.py 
new/tri.declarative-5.7.0/lib/tri_declarative/__init__.py
--- old/tri.declarative-5.4.1/lib/tri_declarative/__init__.py   2020-06-24 
09:04:52.000000000 +0200
+++ new/tri.declarative-5.7.0/lib/tri_declarative/__init__.py   2020-12-18 
13:01:42.000000000 +0100
@@ -39,7 +39,7 @@
 )
 from .with_meta import with_meta
 
-__version__ = '5.4.1'
+__version__ = '5.7.0'
 
 __all__ = [
     'assert_kwargs_empty',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/tri.declarative-5.4.1/lib/tri_declarative/namespace.py 
new/tri.declarative-5.7.0/lib/tri_declarative/namespace.py
--- old/tri.declarative-5.4.1/lib/tri_declarative/namespace.py  2020-06-24 
09:04:52.000000000 +0200
+++ new/tri.declarative-5.7.0/lib/tri_declarative/namespace.py  2020-12-18 
13:01:42.000000000 +0100
@@ -126,18 +126,35 @@
     return __target__
 
 
-def getattr_path(obj, path):
+_MISSING = object()
+
+
+def getattr_path(obj, path, default=_MISSING):
     """
         Get an attribute path, as defined by a string separated by '__'.
         getattr_path(foo, 'a__b__c') is roughly equivalent to foo.a.b.c but
         will short circuit to return None if something on the path is None.
+        If no default value is provided AttributeError is raised if an 
attribute
+        is missing somewhere along the path. If a default value is provided 
that
+        value is returned.
     """
-    path = path.split('__')
-    for name in path:
-        obj = getattr(obj, name)
-        if obj is None:
+    if path == '':
+        return obj
+    current = obj
+    parts = path.split('__')
+    for name in parts:
+        if default is _MISSING:
+            try:
+                current = getattr(current, name)
+            except AttributeError as e:
+                raise AttributeError(f"'{type(obj).__name__}' object has no 
attribute path '{path}', since {e}")
+        else:
+            current = getattr(current, name, _MISSING)
+            if current is _MISSING:
+                return default
+        if current is None:
             return None
-    return obj
+    return current
 
 
 def setattr_path(obj, path, value):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tri.declarative-5.4.1/lib/tri_declarative/util.py 
new/tri.declarative-5.7.0/lib/tri_declarative/util.py
--- old/tri.declarative-5.4.1/lib/tri_declarative/util.py       2020-06-24 
09:04:52.000000000 +0200
+++ new/tri.declarative-5.7.0/lib/tri_declarative/util.py       2020-12-18 
13:01:42.000000000 +0100
@@ -44,8 +44,12 @@
         new_args = args
 
     for k, v in kwargs.items():
-        if merge_namespaces and isinstance(new_kwargs.get(k, None), Namespace):
-            new_kwargs[k] = Namespace(new_kwargs[k], v)
+        new_value = new_kwargs.get(k, None)
+        if merge_namespaces and isinstance(new_value, Namespace):
+            if v is not None:
+                new_kwargs[k] = Namespace(new_value, v)
+            else:
+                new_kwargs[k] = None
         else:
             new_kwargs[k] = v
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tri.declarative-5.4.1/requirements.txt 
new/tri.declarative-5.7.0/requirements.txt
--- old/tri.declarative-5.4.1/requirements.txt  2020-06-24 09:04:52.000000000 
+0200
+++ new/tri.declarative-5.7.0/requirements.txt  2020-12-18 13:01:42.000000000 
+0100
@@ -1 +1 @@
-tri.struct>=3.0.0,<4.0.0
+tri.struct>=3.0.0,<5.0.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tri.declarative-5.4.1/setup.cfg 
new/tri.declarative-5.7.0/setup.cfg
--- old/tri.declarative-5.4.1/setup.cfg 2020-06-24 09:04:52.000000000 +0200
+++ new/tri.declarative-5.7.0/setup.cfg 2020-12-18 13:01:42.000000000 +0100
@@ -1,7 +1,7 @@
 [wheel]
 universal = 1
 
-[tools:pytest]
+[tool:pytest]
 testpaths=tests
 # --strict: warnings become errors.
 # -r fEsxXw: show extra test summary info for everything.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tri.declarative-5.4.1/tests/test_dispatch.py 
new/tri.declarative-5.7.0/tests/test_dispatch.py
--- old/tri.declarative-5.4.1/tests/test_dispatch.py    2020-06-24 
09:04:52.000000000 +0200
+++ new/tri.declarative-5.7.0/tests/test_dispatch.py    2020-12-18 
13:01:42.000000000 +0100
@@ -84,3 +84,27 @@
         return a + b + c + x + y
 
     assert foo('1', '2', '3', bar__quux__title='7', baz__a='A', baz__b='B', 
baz__c='C') == '1235X7ABC'
+
+
+def test_semantics_after_none_from_meta():
+    class MyForm:
+        @dispatch(
+            actions=None
+        )
+        def __init__(self, **kwargs):
+            self.kwargs = kwargs
+
+    form = MyForm(actions__magic__display_name="A magic button")
+    assert form.kwargs == Namespace(actions__magic__display_name="A magic 
button")
+
+
+def test_none_semantics_over_meta():
+    class MyForm:
+        @dispatch(
+            actions__magic__display_name="A magic button"
+        )
+        def __init__(self, **kwargs):
+            self.kwargs = kwargs
+
+    form = MyForm(actions=None)
+    assert form.kwargs == Namespace(actions=None)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tri.declarative-5.4.1/tests/test_namespace.py 
new/tri.declarative-5.7.0/tests/test_namespace.py
--- old/tri.declarative-5.4.1/tests/test_namespace.py   2020-06-24 
09:04:52.000000000 +0200
+++ new/tri.declarative-5.7.0/tests/test_namespace.py   2020-12-18 
13:01:42.000000000 +0100
@@ -38,6 +38,31 @@
     assert foo.bar is None
 
 
+def test_getattr_empty_path():
+    obj = object()
+    assert getattr_path(obj, '') is obj
+
+
+def test_getattr_missing_attribute():
+    obj = object()
+
+    with pytest.raises(AttributeError) as e:
+        getattr_path(obj, 'foo')
+    assert str(e.value) == "'object' object has no attribute path 'foo', since 
'object' object has no attribute 'foo'"
+
+    with pytest.raises(AttributeError) as e:
+        getattr_path(Struct(foo=object()), 'foo__bar')
+    assert str(e.value) == "'Struct' object has no attribute path 'foo__bar', 
since 'object' object has no attribute 'bar'"
+
+
+def test_getattr_default():
+    assert getattr_path(object(), 'foo', 17) == 17
+    assert getattr_path(Struct(foo=object()), 'foo__bar', 42) == 42
+
+    assert getattr_path(object(), 'foo', default=17) == 17
+    assert getattr_path(Struct(foo=object()), 'foo__bar', default=42) == 42
+
+
 def test_setdefaults_path_1():
     assert setdefaults_path(dict(), x=17) == dict(x=17)
 
@@ -471,3 +496,11 @@
     assert isinstance(EMPTY, Namespace)
     with pytest.raises(TypeError):
         EMPTY['foo'] = 'bar'
+
+
+def test_none_semantics():
+    assert Namespace(Namespace(foo=None), foo__bar='baz') == 
Namespace(foo__bar='baz')
+
+
+def test_none_overwrite_semantics():
+    assert Namespace(Namespace(foo__bar='baz'), foo=None) == 
Namespace(foo=None)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tri.declarative-5.4.1/tests/test_with_meta.py 
new/tri.declarative-5.7.0/tests/test_with_meta.py
--- old/tri.declarative-5.4.1/tests/test_with_meta.py   2020-06-24 
09:04:52.000000000 +0200
+++ new/tri.declarative-5.7.0/tests/test_with_meta.py   2020-12-18 
13:01:42.000000000 +0100
@@ -232,6 +232,106 @@
     )
 
 
+def test_semantics_after_none_from_meta():
+    @with_meta
+    class MyForm:
+        class Meta:
+            actions = None
+
+        @dispatch
+        def __init__(self, **kwargs):
+            self.kwargs = kwargs
+
+    form = MyForm(actions__magic__display_name="A magic button")
+    assert form.kwargs == Namespace(actions__magic__display_name="A magic 
button")
+
+
+def test_none_semantics_over_meta():
+    @with_meta
+    class MyForm:
+        class Meta:
+            actions__magic__display_name = "A magic button"
+
+        @dispatch
+        def __init__(self, **kwargs):
+            self.kwargs = kwargs
+
+    form = MyForm(actions=None)
+    assert form.kwargs == Namespace(actions=None)
+
+
+def test_dispatch_semantics_after_none_from_meta():
+    @with_meta
+    class MyForm:
+        class Meta:
+            actions = None
+
+        @dispatch(
+            actions__magic__display_name="A magic button"
+        )
+        def __init__(self, **kwargs):
+            self.kwargs = kwargs
+
+    form = MyForm()
+    assert form.kwargs == Namespace(actions=None)
+
+
+def test_dispatch_none_semantics_after_meta():
+    @with_meta
+    class MyForm:
+        class Meta:
+            actions__magic__display_name = "A magic button"
+
+        @dispatch(
+            actions=None
+        )
+        def __init__(self, **kwargs):
+            self.kwargs = kwargs
+
+    form = MyForm()
+    assert form.kwargs == Namespace(actions__magic__display_name="A magic 
button")
+
+
+def test_dispatch_none_semantics_after_superclass_meta():
+    @with_meta
+    class MyForm:
+        class Meta:
+            actions__magic__display_name = "A magic button"
+
+        def __init__(self, **kwargs):
+            super().__init__(**kwargs)
+
+    class SubForm(MyForm):
+        @dispatch(
+            actions=None
+        )
+        def __init__(self, **kwargs):
+            self.kwargs = kwargs
+
+    form = SubForm()
+    assert form.kwargs == Namespace(actions=None)
+
+
+def test_dispatch_semantics_after_none_superclass_meta():
+    @with_meta
+    class MyForm:
+        class Meta:
+            actions = None
+
+        def __init__(self, **kwargs):
+            super().__init__(**kwargs)
+
+    class SubForm(MyForm):
+        @dispatch(
+            actions__magic__display_name="A magic button"
+        )
+        def __init__(self, **kwargs):
+            self.kwargs = kwargs
+
+    form = SubForm()
+    assert form.kwargs == Namespace(actions__magic__display_name="A magic 
button")
+
+
 def test_meta_staticmethod():
     @with_meta
     class Foo:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tri.declarative-5.4.1/tox.ini 
new/tri.declarative-5.7.0/tox.ini
--- old/tri.declarative-5.4.1/tox.ini   2020-06-24 09:04:52.000000000 +0200
+++ new/tri.declarative-5.7.0/tox.ini   2020-12-18 13:01:42.000000000 +0100
@@ -37,7 +37,7 @@
 basepython = python3.7
 usedevelop = True
 commands =
-    {envpython} -m flake8 lib/ tests setup.py {posargs}
+    {envpython} -m flake8 lib/tri_declarative tests setup.py {posargs}
 deps =
     flake8
 

Reply via email to