Hello community, here is the log from the commit of package python-atom for openSUSE:Factory checked in at 2020-08-29 20:38:29 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-atom (Old) and /work/SRC/openSUSE:Factory/.python-atom.new.3399 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-atom" Sat Aug 29 20:38:29 2020 rev:4 rq:829857 version:0.5.2 Changes: -------- --- /work/SRC/openSUSE:Factory/python-atom/python-atom.changes 2020-05-07 14:55:54.578446479 +0200 +++ /work/SRC/openSUSE:Factory/.python-atom.new.3399/python-atom.changes 2020-08-29 20:38:39.973372377 +0200 @@ -1,0 +2,8 @@ +Thu Aug 27 05:05:29 UTC 2020 - Steve Kowalik <[email protected]> + +- Update to 0.5.2: + * make comparison used in C safe (fix bug introduced in 0.5.0) PR #107 + * fix bug in using atomlist from C PR #102 + * clarify Unicode deprecation warning PR #102 + +------------------------------------------------------------------- Old: ---- 0.5.0.tar.gz New: ---- 0.5.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-atom.spec ++++++ --- /var/tmp/diff_new_pack.5bSZD7/_old 2020-08-29 20:38:42.349373378 +0200 +++ /var/tmp/diff_new_pack.5bSZD7/_new 2020-08-29 20:38:42.353373381 +0200 @@ -19,7 +19,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %define skip_python2 1 Name: python-atom -Version: 0.5.0 +Version: 0.5.2 Release: 0 Summary: Memory efficient Python objects License: BSD-3-Clause ++++++ 0.5.0.tar.gz -> 0.5.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.5.0/.github/workflows/ci.yml new/atom-0.5.2/.github/workflows/ci.yml --- old/atom-0.5.0/.github/workflows/ci.yml 2020-03-27 03:22:43.000000000 +0100 +++ new/atom-0.5.2/.github/workflows/ci.yml 2020-07-05 21:38:25.000000000 +0200 @@ -25,7 +25,7 @@ steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v1 + uses: actions/setup-python@v2 with: python-version: ${{ matrix.python-version }} - name: Install dependencies @@ -38,9 +38,15 @@ run: | python setup.py develop - name: Test with pytest + if: matrix.python-version == '3.6' run: | pip install pytest-cov - pytest tests --cov atom --cov-report xml + python -m pytest tests --cov atom --cov-report xml + - name: Test with pytest + if: matrix.python-version != '3.6' + run: | + pip install pytest-cov + python -X dev -m pytest tests --cov atom --cov-report xml - name: Upload coverage to Codecov uses: codecov/codecov-action@v1 if: matrix.os == 'windows-latest' @@ -49,7 +55,6 @@ file: ./coverage.xml flags: unittests name: codecov-umbrella - yml: ./codecov.yml fail_ci_if_error: true - name: Upload coverage to Codecov uses: codecov/codecov-action@v1 @@ -58,5 +63,4 @@ token: ${{ secrets.CODECOV_TOKEN }} flags: unittests name: codecov-umbrella - yml: ./codecov.yml fail_ci_if_error: true diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.5.0/atom/scalars.py new/atom-0.5.2/atom/scalars.py --- old/atom-0.5.0/atom/scalars.py 2020-03-27 03:22:43.000000000 +0100 +++ new/atom-0.5.2/atom/scalars.py 2020-07-05 21:38:25.000000000 +0200 @@ -223,7 +223,8 @@ __slots__ = () def __init__(self, default=u'', factory=None, strict=False): - msg = 'Unicode is deprecated and will be removed in atom 0.6.0' + msg = ('Unicode is deprecated and will be removed in atom 0.6.0, ' + 'use Str instead.') warnings.warn(FutureWarning(msg)) super(Unicode, self).__init__(default, factory) if strict: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.5.0/atom/src/atomlist.cpp new/atom-0.5.2/atom/src/atomlist.cpp --- old/atom-0.5.0/atom/src/atomlist.cpp 2020-03-27 03:22:43.000000000 +0100 +++ new/atom-0.5.2/atom/src/atomlist.cpp 2020-07-05 21:38:25.000000000 +0200 @@ -794,7 +794,7 @@ bool obs = observer_check(); if( obs ) { - olditem = PyList_GetItem( m_list.get(), index ); + olditem = cppy::xincref(PyList_GetItem( m_list.get(), index )); if( !olditem ) return -1; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.5.0/atom/src/member.cpp new/atom-0.5.2/atom/src/member.cpp --- old/atom-0.5.0/atom/src/member.cpp 2020-03-27 03:22:43.000000000 +0100 +++ new/atom-0.5.2/atom/src/member.cpp 2020-07-05 21:38:25.000000000 +0200 @@ -967,7 +967,7 @@ std::vector<cppy::ptr>::iterator end = static_observers->end(); for( it = static_observers->begin(); it != end; ++it ) { - if( *it == obptr || it->richcmp( obptr, Py_EQ ) ) + if( *it == obptr || utils::safe_richcompare( it->get(), obptr, Py_EQ ) ) return; } static_observers->push_back( obptr ); @@ -991,7 +991,7 @@ std::vector<cppy::ptr>::iterator end = static_observers->end(); for( it = static_observers->begin(); it != end; ++it ) { - if( *it == obptr || it->richcmp( obptr, Py_EQ ) ) + if( *it == obptr || utils::safe_richcompare( it->get(), obptr, Py_EQ ) ) { static_observers->erase( it ); if( static_observers->size() == 0 ) @@ -1016,7 +1016,7 @@ std::vector<cppy::ptr>::iterator end = static_observers->end(); for( it = static_observers->begin(); it != end; ++it ) { - if( *it == obptr || it->richcmp( obptr, Py_EQ ) ) + if( *it == obptr || utils::safe_richcompare( it->get(), obptr, Py_EQ ) ) return true; } return false; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.5.0/atom/src/observerpool.cpp new/atom-0.5.2/atom/src/observerpool.cpp --- old/atom-0.5.0/atom/src/observerpool.cpp 2020-03-27 03:22:43.000000000 +0100 +++ new/atom-0.5.2/atom/src/observerpool.cpp 2020-07-05 21:38:25.000000000 +0200 @@ -6,6 +6,7 @@ | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ #include "observerpool.h" +#include "utils.h" namespace atom @@ -82,7 +83,7 @@ obs_end = obs_it + topic_it->m_count; for( ; obs_it != obs_end; ++obs_it ) { - if( *obs_it == observer || obs_it->richcmp( observer, Py_EQ ) ) + if( *obs_it == observer || utils::safe_richcompare( obs_it->get(), observer, Py_EQ ) ) return true; } return false; @@ -117,7 +118,7 @@ obs_free = obs_end; for( ; obs_it != obs_end; ++obs_it ) { - if( *obs_it == observer || obs_it->richcmp( observer, Py_EQ ) ) + if( *obs_it == observer || utils::safe_richcompare( obs_it->get(), observer, Py_EQ ) ) return; if( !obs_it->is_truthy() ) obs_free = obs_it; @@ -160,7 +161,7 @@ obs_end = obs_it + topic_it->m_count; for( ; obs_it != obs_end; ++obs_it ) { - if( *obs_it == observer || obs_it->richcmp( observer, Py_EQ ) ) + if( *obs_it == observer || utils::safe_richcompare( obs_it->get(), observer, Py_EQ ) ) { m_observers.erase( obs_it ); if( ( --topic_it->m_count ) == 0 ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.5.0/atom/src/observerpool.h new/atom-0.5.2/atom/src/observerpool.h --- old/atom-0.5.0/atom/src/observerpool.h 2020-03-27 03:22:43.000000000 +0100 +++ new/atom-0.5.2/atom/src/observerpool.h 2020-07-05 21:38:25.000000000 +0200 @@ -11,6 +11,8 @@ #include <cppy/cppy.h> #include "platstdint.h" #include "modifyguard.h" +#include "utils.h" + namespace atom { @@ -26,7 +28,7 @@ ~Topic() {} bool match( cppy::ptr& topic ) { - return m_topic == topic || m_topic.richcmp( topic, Py_EQ ); + return m_topic == topic || utils::safe_richcompare( m_topic, topic, Py_EQ ); } cppy::ptr m_topic; uint32_t m_count; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.5.0/atom/src/propertyhelper.cpp new/atom-0.5.2/atom/src/propertyhelper.cpp --- old/atom-0.5.0/atom/src/propertyhelper.cpp 2020-03-27 03:22:43.000000000 +0100 +++ new/atom-0.5.2/atom/src/propertyhelper.cpp 2020-07-05 21:38:25.000000000 +0200 @@ -10,6 +10,7 @@ #include "catom.h" #include "member.h" #include "memberchange.h" +#include "utils.h" namespace atom @@ -80,7 +81,7 @@ return 0; } bool cached = member->get_getattr_mode() == GetAttr::CachedProperty; - if( !cached || !oldptr.richcmp( newptr, Py_EQ ) ) + if( !cached || !utils::safe_richcompare( oldptr, newptr, Py_EQ ) ) { cppy::ptr argsptr( property_args( atom, member, oldptr.get(), newptr.get() ) ); if( !argsptr ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.5.0/atom/src/setattrbehavior.cpp new/atom-0.5.2/atom/src/setattrbehavior.cpp --- old/atom-0.5.0/atom/src/setattrbehavior.cpp 2020-03-27 03:22:43.000000000 +0100 +++ new/atom-0.5.2/atom/src/setattrbehavior.cpp 2020-07-05 21:38:25.000000000 +0200 @@ -8,6 +8,7 @@ #include <cppy/cppy.h> #include "member.h" #include "memberchange.h" +#include "utils.h" namespace atom @@ -130,7 +131,7 @@ cppy::ptr argsptr; if( member->has_observers() ) { - if( valid_old && oldptr.richcmp( newptr, Py_EQ ) ) + if( valid_old && utils::safe_richcompare( oldptr, newptr, Py_EQ ) ) return 0; if( valid_old ) argsptr = updated_args( atom, member, oldptr.get(), newptr.get() ); @@ -145,7 +146,7 @@ { if( !argsptr ) { - if( valid_old && oldptr.richcmp( newptr, Py_EQ ) ) + if( valid_old && utils::safe_richcompare( oldptr, newptr, Py_EQ ) ) return 0; if( valid_old ) argsptr = updated_args( atom, member, oldptr.get(), newptr.get() ); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.5.0/atom/src/sortedmap.cpp new/atom-0.5.2/atom/src/sortedmap.cpp --- old/atom-0.5.0/atom/src/sortedmap.cpp 2020-03-27 03:22:43.000000000 +0100 +++ new/atom-0.5.2/atom/src/sortedmap.cpp 2020-07-05 21:38:25.000000000 +0200 @@ -11,6 +11,7 @@ #include <iostream> #include <sstream> #include "packagenaming.h" +#include "utils.h" #ifdef __clang__ #pragma clang diagnostic ignored "-Wdeprecated-writable-strings" @@ -24,80 +25,6 @@ namespace { -/** - * A fallback 3way comparison function for when PyObject_RichCompareBool - * fails to compare "unorderable types" on Python 3. - * - * This is based on Python 2's `default_3way_compare`. - * - * This function will not change the Python exception state. - */ -inline int -fallback_3way_compare( PyObject* first, PyObject* second ) -{ - // Compare pointer values if the types are the same. - if( first->ob_type == second->ob_type ) { - Py_uintptr_t fp = reinterpret_cast<Py_uintptr_t>( first ); - Py_uintptr_t sp = reinterpret_cast<Py_uintptr_t>( second ); - return (fp < sp) ? -1 : (fp > sp) ? 1 : 0; - } - - // None is smaller than anything. - if( first == Py_None ) - return -1; - if( second == Py_None ) - return 1; - - // Compare based on type names, numbers are smaller. - const char* fn = PyNumber_Check( first ) ? "" : first->ob_type->tp_name; - const char* sn = PyNumber_Check( second ) ? "" : second->ob_type->tp_name; - int c = strcmp( fn, sn ); - if( c < 0 ) - return -1; - if( c > 0 ) - return 1; - - // Finally, fall back to comparing type pointers. - Py_uintptr_t ftp = reinterpret_cast<Py_uintptr_t>( first->ob_type ); - Py_uintptr_t stp = reinterpret_cast<Py_uintptr_t>( second->ob_type ); - return ftp < stp ? -1 : 1; -} - - -bool richcompare( PyObject* first, PyObject* second, int opid ) -{ - // Start with Python's rich compare. - int r = PyObject_RichCompareBool( first, second, opid ); - - // Handle a successful comparison. - if( r == 1 ) - return true; - if( r == 0 ) - return false; - - // Clear the error if one happened because we attempted an invalid - // comparison. - if( PyErr_Occurred() ) - PyErr_Clear(); - - // Fallback to the Python 2 default 3 way compare. - int c = fallback_3way_compare( first, second ); - - // Convert the 3way comparison result based on the `opid`. - switch (opid) { - case Py_EQ: return c == 0; - case Py_NE: return c != 0; - case Py_LE: return c <= 0; - case Py_GE: return c >= 0; - case Py_LT: return c < 0; - case Py_GT: return c > 0; - } - - // Return `false` if the `opid` is not handled. - return false; -} - - class MapItem { @@ -142,21 +69,21 @@ { if( first.m_key == second.m_key ) return false; - return richcompare( first.m_key.get(), second.m_key.get(), Py_LT ); + return atom::utils::safe_richcompare( first.m_key.get(), second.m_key.get(), Py_LT ); } bool operator()( MapItem& first, PyObject* second ) { if( first.m_key == second ) return false; - return richcompare( first.m_key.get(), second, Py_LT ); + return atom::utils::safe_richcompare( first.m_key.get(), second, Py_LT ); } bool operator()( PyObject* first, MapItem& second ) { if( first == second.m_key ) return false; - return richcompare( first, second.m_key.get(), Py_LT ); + return atom::utils::safe_richcompare( first, second.m_key.get(), Py_LT ); } }; @@ -166,21 +93,21 @@ { if( first.m_key == second.m_key ) return true; - return richcompare( first.m_key.get(), second.m_key.get(), Py_EQ ); + return atom::utils::safe_richcompare( first.m_key.get(), second.m_key.get(), Py_EQ ); } bool operator()( MapItem& first, PyObject* second ) { if( first.m_key == second ) return true; - return richcompare( first.m_key.get(), second, Py_EQ ); + return atom::utils::safe_richcompare( first.m_key.get(), second, Py_EQ ); } bool operator()( PyObject* first, MapItem& second ) { if( first == second.m_key ) return true; - return richcompare( first, second.m_key.get(), Py_EQ ); + return atom::utils::safe_richcompare( first, second.m_key.get(), Py_EQ ); } }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.5.0/atom/src/utils.h new/atom-0.5.2/atom/src/utils.h --- old/atom-0.5.0/atom/src/utils.h 2020-03-27 03:22:43.000000000 +0100 +++ new/atom-0.5.2/atom/src/utils.h 2020-07-05 21:38:25.000000000 +0200 @@ -92,6 +92,61 @@ } +/** + * A safe richcomparison that will never fail and fallback to 3way compare + * if the conventional rich compare fails. + */ +inline bool safe_richcompare( PyObject* first, PyObject* second, int opid ) +{ + // Start with Python's rich compare. + int r = PyObject_RichCompareBool( first, second, opid ); + + // Handle a successful comparison. + if( r == 1 ) + return true; + if( r == 0 ) + return false; + + // Clear the error if one happened because we attempted an invalid + // comparison. + if( PyErr_Occurred() ) + PyErr_Clear(); + + // Fallback to the Python 2 default 3 way compare. + int c = fallback_3way_compare( first, second ); + + // Convert the 3way comparison result based on the `opid`. + switch (opid) { + case Py_EQ: return c == 0; + case Py_NE: return c != 0; + case Py_LE: return c <= 0; + case Py_GE: return c >= 0; + case Py_LT: return c < 0; + case Py_GT: return c > 0; + } + + // Return `false` if the `opid` is not handled. + return false; +} + +inline bool safe_richcompare( cppy::ptr first, PyObject* second, int opid ) +{ + return safe_richcompare( first.get(), second, opid ); +} + + +inline bool safe_richcompare( PyObject* first, cppy::ptr second, int opid ) +{ + return safe_richcompare( first, second.get(), opid ); +} + + +inline bool safe_richcompare( cppy::ptr first, cppy::ptr second, int opid ) +{ + return safe_richcompare( first.get(), second.get(), opid ); +} + + } // namespace utils } // namespace atom diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.5.0/atom/version.py new/atom-0.5.2/atom/version.py --- old/atom-0.5.0/atom/version.py 2020-03-27 03:22:43.000000000 +0100 +++ new/atom-0.5.2/atom/version.py 2020-07-05 21:38:25.000000000 +0200 @@ -22,7 +22,7 @@ # The micro release number. The micro release number is incremented # for bug fix releases and small feature additions. -MICRO = 0 +MICRO = 2 # The status indicate if this is a development or pre-release version STATUS = '' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.5.0/codecov.yml new/atom-0.5.2/codecov.yml --- old/atom-0.5.0/codecov.yml 2020-03-27 03:22:43.000000000 +0100 +++ new/atom-0.5.2/codecov.yml 2020-07-05 21:38:25.000000000 +0200 @@ -8,7 +8,7 @@ status: project: yes patch: yes - changes: no + changes: yes parsers: gcov: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.5.0/releasenotes.rst new/atom-0.5.2/releasenotes.rst --- old/atom-0.5.0/releasenotes.rst 2020-03-27 03:22:43.000000000 +0100 +++ new/atom-0.5.2/releasenotes.rst 2020-07-05 21:38:25.000000000 +0200 @@ -1,7 +1,17 @@ Atom Release Notes ================== -0.5.0 - unreleased +0.5.2 - 04/07/2020 +------------------ +- make comparison used in C safe (fix bug introduced in 0.5.0) PR #107 + +0.5.1 - 03/06/2020 +------------------ +- fix bug in using atomlist from C PR #102 +- clarify Unicode deprecation warning PR #102 + + +0.5.0 - 26/03/2020 ------------------ - drop Python 2 support PR #83 - use cppy to write the c++ extension PR #83 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.5.0/tests/datastructure/test_sortedmap.py new/atom-0.5.2/tests/datastructure/test_sortedmap.py --- old/atom-0.5.0/tests/datastructure/test_sortedmap.py 2020-03-27 03:22:43.000000000 +0100 +++ new/atom-0.5.2/tests/datastructure/test_sortedmap.py 2020-07-05 21:38:25.000000000 +0200 @@ -161,6 +161,33 @@ smap[1] = 4 assert [k for k in smap.keys()] == [1, '0', 'a', 'b', 'c', 'd'] + # Test ordering None, which is smaller than anything + s = sortedmap() + s[1] = 1 + s[None] = 1 + assert [k for k in s.keys()] == [None, 1] + + s = sortedmap() + s[None] = 1 + s[1] = 1 + assert [k for k in s.keys()] == [None, 1] + + # Test ordering class that cannot be ordered through the usual mean + class T: + pass + t1 = T() + t2 = T() + oT = T + class T: + pass + u = T() + s = sortedmap() + s[t1] = 1 + s[t2] = 1 + assert [k for k in s.keys()] == [t1, t2] if id(t1) < id(t2) else [t2, t1] + s[u] = 1 + assert [k for k in s.keys()][0] is u if id(T) < id(oT) else [k for k in s.keys()][-1] is u + def test_deleting_keys(smap): """Test deleting items. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.5.0/tests/test_observe.py new/atom-0.5.2/tests/test_observe.py --- old/atom-0.5.0/tests/test_observe.py 2020-03-27 03:22:43.000000000 +0100 +++ new/atom-0.5.2/tests/test_observe.py 2020-07-05 21:38:25.000000000 +0200 @@ -11,6 +11,13 @@ import pytest from atom.api import Atom, Int, List, Value, Event, Signal, observe + +class NonComparableObject: + + def __eq__(self, other): + raise ValueError() + + # --- Static observer manipulations @pytest.fixture @@ -66,8 +73,15 @@ """Test manually managing static observers. """ - def react(change): - change['object'].changes.append(change['name']) + # Force the use of safe comparison (error cleaning and fallback) + class Observer: + def __eq__(self, other): + raise ValueError() + + def __call__(self, change): + change['object'].changes.append(change['name']) + + react = Observer() # We have 2 static observers hence 2 removals member = static_atom.get_member('val2') @@ -236,6 +250,11 @@ def react(self, change): self.count += 1 + # Force the use of safe equality comparison (ie clean error and fallback + # on pointer comparison) + def __eq__(self, other): + raise ValueError() + class DynamicAtom(Atom): """Atom used to test dynamic observers. @@ -559,11 +578,12 @@ self.count = 0 def react(self, change): + print(change) self.count += 1 class NotifTest(Atom): - val = Int() + val = Value() count = Int() @@ -575,6 +595,7 @@ self.observe('val', self.observer.react) def _observe_val(self, change): + print(change) self.count += 1 return NotifTest() @@ -617,8 +638,43 @@ assert sd_observed_atom.observer.count == 2 +def test_notification_on_setting_non_comparable_value(sd_observed_atom): + """Test that notifiers are called when setting a value. + + """ + o1 = NonComparableObject() + sd_observed_atom.val = 0 + + assert sd_observed_atom.count == 1 + assert sd_observed_atom.observer.count == 1 + + # And also test update of values + sd_observed_atom.val = 1 + + assert sd_observed_atom.count == 2 + assert sd_observed_atom.observer.count == 2 + + # No notification on equal assignment + sd_observed_atom.val = 1 + + assert sd_observed_atom.count == 2 + assert sd_observed_atom.observer.count == 2 + + # Check notification on invalid comparison + sd_observed_atom.val = o1 + + assert sd_observed_atom.count == 3 + assert sd_observed_atom.observer.count == 3 + + # Check no notification on equal value assignment + sd_observed_atom.val = o1 + + assert sd_observed_atom.count == 3 + assert sd_observed_atom.observer.count == 3 + + def test_enabling_disabling_notifications(sd_observed_atom): - """Test enabling/disabling motification on an atom. + """Test enabling/disabling notification on an atom. """ assert sd_observed_atom.notifications_enabled() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.5.0/tests/test_property.py new/atom-0.5.2/tests/test_property.py --- old/atom-0.5.0/tests/test_property.py 2020-03-27 03:22:43.000000000 +0100 +++ new/atom-0.5.2/tests/test_property.py 2020-07-05 21:38:25.000000000 +0200 @@ -9,8 +9,8 @@ """ import pytest -from atom.api import (Atom, Int, Property, GetAttr, SetAttr, - observe, cached_property) +from atom.api import (Atom, GetAttr, Int, Property, SetAttr, Value, + cached_property, observe) from atom.catom import DelAttr, reset_property @@ -167,9 +167,17 @@ """Test observing a property. """ + class NonComparableObject: + + def __eq__(self, other): + raise ValueError() + + def __add__(self, other): + return other + 5 + class PropertyTest(Atom): - i = Int() + i = Value(0) counter = Int() @@ -188,9 +196,11 @@ assert pt.prop == 1 assert pt.prop == 2 + pt.i = NonComparableObject() pt.observe('prop', pt.observe_cp) pt.get_member('prop').reset(pt) assert pt.counter == 2 + assert pt.prop == 7 def test_wrong_reset_arguments():
