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 <[email protected]>
+
+- 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