Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-atom for openSUSE:Factory checked in at 2023-10-05 20:04:59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-atom (Old) and /work/SRC/openSUSE:Factory/.python-atom.new.28202 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-atom" Thu Oct 5 20:04:59 2023 rev:12 rq:1115791 version:0.10.3 Changes: -------- --- /work/SRC/openSUSE:Factory/python-atom/python-atom.changes 2023-06-01 17:20:05.070361018 +0200 +++ /work/SRC/openSUSE:Factory/.python-atom.new.28202/python-atom.changes 2023-10-05 20:06:12.169323573 +0200 @@ -1,0 +2,9 @@ +Thu Oct 5 09:46:45 UTC 2023 - Dirk Müller <[email protected]> + +- update to 0.10.3: + * fix a an issue when using add_member to override an existing + membe + * fix a memory leak caused by Dict, Defaultdict and Set members + * add support for Python 3.12 PR #200 + +------------------------------------------------------------------- Old: ---- atom-0.10.0.tar.gz New: ---- atom-0.10.3.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-atom.spec ++++++ --- /var/tmp/diff_new_pack.nVToNP/_old 2023-10-05 20:06:13.257362881 +0200 +++ /var/tmp/diff_new_pack.nVToNP/_new 2023-10-05 20:06:13.257362881 +0200 @@ -18,7 +18,7 @@ %{?sle15_python_module_pythons} Name: python-atom -Version: 0.10.0 +Version: 0.10.3 Release: 0 Summary: Memory efficient Python objects License: BSD-3-Clause ++++++ atom-0.10.0.tar.gz -> atom-0.10.3.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.10.0/.github/workflows/ci.yml new/atom-0.10.3/.github/workflows/ci.yml --- old/atom-0.10.0/.github/workflows/ci.yml 2023-05-05 10:02:54.000000000 +0200 +++ new/atom-0.10.3/.github/workflows/ci.yml 2023-10-04 10:36:05.000000000 +0200 @@ -22,9 +22,9 @@ runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.10'] + python-version: ['3.11'] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: @@ -65,7 +65,7 @@ matrix: python-version: ['3.8', '3.9'] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Get history and tags for SCM versioning to work run: | git fetch --prune --unshallow @@ -97,9 +97,9 @@ strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] - python-version: ['3.8', '3.9', '3.10', '3.11'] + python-version: ['3.8', '3.9', '3.10', '3.11', '3.12-dev'] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Get history and tags for SCM versioning to work run: | git fetch --prune --unshallow @@ -120,7 +120,7 @@ CPPFLAGS: --coverage # Build extensions manually to allow getting C coverage data run: | - python setup.py develop + pip install -e . - name: Test with pytest # XXX Disabled warnings check ( -W error) to be able to test on 3.11 # (pyparsing deprecation) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.10.0/.github/workflows/docs.yml new/atom-0.10.3/.github/workflows/docs.yml --- old/atom-0.10.0/.github/workflows/docs.yml 2023-05-05 10:02:54.000000000 +0200 +++ new/atom-0.10.3/.github/workflows/docs.yml 2023-10-04 10:36:05.000000000 +0200 @@ -21,7 +21,7 @@ name: Docs building runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Get history and tags for SCM versioning to work run: | git fetch --prune --unshallow diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.10.0/.github/workflows/release.yml new/atom-0.10.3/.github/workflows/release.yml --- old/atom-0.10.0/.github/workflows/release.yml 2023-05-05 10:02:54.000000000 +0200 +++ new/atom-0.10.3/.github/workflows/release.yml 2023-10-04 10:36:05.000000000 +0200 @@ -13,7 +13,7 @@ runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Get history and tags for SCM versioning to work run: | git fetch --prune --unshallow @@ -45,10 +45,10 @@ strategy: matrix: os: [windows-latest, ubuntu-latest, macos-latest] - python: [38, 39, 310, 311] + python: [38, 39, 310, 311, 312] steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Get history and tags for SCM versioning to work run: | git fetch --prune --unshallow diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.10.0/PKG-INFO new/atom-0.10.3/PKG-INFO --- old/atom-0.10.0/PKG-INFO 2023-05-05 10:03:22.152537300 +0200 +++ new/atom-0.10.3/PKG-INFO 2023-10-04 10:36:34.202414300 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: atom -Version: 0.10.0 +Version: 0.10.3 Summary: Memory efficient Python objects Author-email: The Nucleic Development Team <[email protected]> Maintainer-email: "Matthieu C. Dartiailh" <[email protected]> @@ -98,6 +98,7 @@ Requires-Python: >=3.8 Description-Content-Type: text/x-rst License-File: LICENSE +Requires-Dist: typing_extensions; python_version < "3.11" Welcome to Atom =============== diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.10.0/atom/meta/atom_meta.py new/atom-0.10.3/atom/meta/atom_meta.py --- old/atom-0.10.0/atom/meta/atom_meta.py 2023-05-05 10:02:54.000000000 +0200 +++ new/atom-0.10.3/atom/meta/atom_meta.py 2023-10-04 10:36:05.000000000 +0200 @@ -55,8 +55,8 @@ """Add or override a member after the class creation.""" existing = cls.__atom_members__.get(name) if existing is not None: - member.set_index(member.index) - member.copy_static_observers(member) + member.set_index(existing.index) + member.copy_static_observers(existing) else: member.set_index(len(cls.__atom_members__)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.10.0/atom/src/atomdict.cpp new/atom-0.10.3/atom/src/atomdict.cpp --- old/atom-0.10.0/atom/src/atomdict.cpp 2023-05-05 10:02:54.000000000 +0200 +++ new/atom-0.10.3/atom/src/atomdict.cpp 2023-10-04 10:36:05.000000000 +0200 @@ -114,8 +114,11 @@ void AtomDict_dealloc( AtomDict* self ) { + PyObject_GC_UnTrack( self ); cppy::clear( &self->m_key_validator ); cppy::clear( &self->m_value_validator ); + delete atomdict_cast( self )->pointer; + atomdict_cast( self )->pointer = 0; PyDict_Type.tp_dealloc( pyobject_cast( self ) ); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.10.0/atom/src/atomlist.cpp new/atom-0.10.3/atom/src/atomlist.cpp --- old/atom-0.10.0/atom/src/atomlist.cpp 2023-05-05 10:02:54.000000000 +0200 +++ new/atom-0.10.3/atom/src/atomlist.cpp 2023-10-04 10:36:05.000000000 +0200 @@ -310,9 +310,9 @@ AtomList_dealloc( AtomList* self ) { PyObject_GC_UnTrack( self ); + cppy::clear( &self->validator ); delete self->pointer; self->pointer = 0; - Py_CLEAR( self->validator ); PyList_Type.tp_dealloc( pyobject_cast( self ) ); } @@ -466,62 +466,166 @@ namespace PySStr { - class PyStringMaker - { - - public: - - PyStringMaker( const char* string ) : m_pystring( 0 ) - { - m_pystring = PyUnicode_FromString( string ); - } - - PyObject* operator()() - { - return m_pystring.get(); - } - - private: - - PyStringMaker(); - cppy::ptr m_pystring; - }; + static PyObject* typestr; + static PyObject* namestr; + static PyObject* objectstr; + static PyObject* valuestr ; + static PyObject* operationstr ; + static PyObject* itemstr ; + static PyObject* itemsstr ; + static PyObject* indexstr ; + static PyObject* keystr ; + static PyObject* reversestr ; + static PyObject* containerstr ; + static PyObject* __delitem__str ; + static PyObject* __iadd__str ; + static PyObject* __imul__str ; + static PyObject* __setitem__str ; + static PyObject* appendstr ; + static PyObject* extendstr ; + static PyObject* insertstr ; + static PyObject* popstr ; + static PyObject* removestr ; + static PyObject* sortstr ; + static PyObject* olditemstr ; + static PyObject* newitemstr ; + static PyObject* countstr ; +} // namespace PySStr - #define _STATIC_STRING( name ) \ - static PyObject* \ - name() \ - { \ - static PyStringMaker string( #name ); \ - return string(); \ - } - _STATIC_STRING( type ) - _STATIC_STRING( name ) - _STATIC_STRING( object ) - _STATIC_STRING( value ) - _STATIC_STRING( operation ) - _STATIC_STRING( item ) - _STATIC_STRING( items ) - _STATIC_STRING( index ) - _STATIC_STRING( key ) - _STATIC_STRING( reverse ) - _STATIC_STRING( container ) - _STATIC_STRING( __delitem__ ) - _STATIC_STRING( __iadd__ ) - _STATIC_STRING( __imul__ ) - _STATIC_STRING( __setitem__ ) - _STATIC_STRING( append ) - _STATIC_STRING( extend ) - _STATIC_STRING( insert ) - _STATIC_STRING( pop ) - _STATIC_STRING( remove ) - _STATIC_STRING( sort ) - _STATIC_STRING( olditem ) - _STATIC_STRING( newitem ) - _STATIC_STRING( count ) +bool +init_containerlistchange() +{ + static bool alloced = false; + if( alloced ) + { + return true; + } -} // namespace PySStr + PySStr::typestr = PyUnicode_InternFromString( "type" ); + if( !PySStr::typestr ) + { + return false; + } + PySStr::namestr = PyUnicode_InternFromString( "name" ); + if( !PySStr::namestr ) + { + return false; + } + PySStr::objectstr = PyUnicode_InternFromString( "object" ); + if( !PySStr::objectstr ) + { + return false; + } + PySStr::valuestr = PyUnicode_InternFromString( "value" ); + if( !PySStr::valuestr ) + { + return false; + } + PySStr::operationstr = PyUnicode_InternFromString( "operation" ); + if( !PySStr::operationstr ) + { + return false; + } + PySStr::itemstr = PyUnicode_InternFromString( "item" ); + if( !PySStr::itemstr ) + { + return false; + } + PySStr::itemsstr = PyUnicode_InternFromString( "items" ); + if( !PySStr::itemsstr ) + { + return false; + } + PySStr::indexstr = PyUnicode_InternFromString( "index" ); + if( !PySStr::indexstr ) + { + return false; + } + PySStr::keystr = PyUnicode_InternFromString( "key" ); + if( !PySStr::keystr ) + { + return false; + } + PySStr::reversestr = PyUnicode_InternFromString( "reverse" ); + if( !PySStr::reversestr ) + { + return false; + } + PySStr::containerstr = PyUnicode_InternFromString( "container" ); + if( !PySStr::containerstr ) + { + return false; + } + PySStr::__delitem__str = PyUnicode_InternFromString( "__delitem__" ); + if( !PySStr::typestr ) + { + return false; + } + PySStr::__iadd__str = PyUnicode_InternFromString( "__iadd__" ); + if( !PySStr::__iadd__str ) + { + return false; + } + PySStr::__imul__str = PyUnicode_InternFromString( "__imul__" ); + if( !PySStr::__imul__str ) + { + return false; + } + PySStr::__setitem__str = PyUnicode_InternFromString( "__setitem__" ); + if( !PySStr::__setitem__str ) + { + return false; + } + PySStr::appendstr = PyUnicode_InternFromString( "append" ); + if( !PySStr::appendstr ) + { + return false; + } + PySStr::extendstr = PyUnicode_InternFromString( "extend" ); + if( !PySStr::extendstr ) + { + return false; + } + PySStr::insertstr = PyUnicode_InternFromString( "insert" ); + if( !PySStr::insertstr ) + { + return false; + } + PySStr::popstr = PyUnicode_InternFromString( "pop" ); + if( !PySStr::popstr ) + { + return false; + } + PySStr::removestr = PyUnicode_InternFromString( "remove" ); + if( !PySStr::removestr ) + { + return false; + } + PySStr::sortstr = PyUnicode_InternFromString( "sort" ); + if( !PySStr::sortstr ) + { + return false; + } + PySStr::olditemstr = PyUnicode_InternFromString( "olditem" ); + if( !PySStr::olditemstr ) + { + return false; + } + PySStr::newitemstr = PyUnicode_InternFromString( "newitem" ); + if( !PySStr::newitemstr ) + { + return false; + } + PySStr::countstr = PyUnicode_InternFromString( "count" ); + if( !PySStr::countstr ) + { + return false; + } + alloced = true; + return true; +} namespace @@ -559,9 +663,9 @@ cppy::ptr c( prepare_change() ); if( !c ) return 0; // LCOV_EXCL_LINE - if( PyDict_SetItem( c.get(), PySStr::operation(), PySStr::append() ) != 0 ) + if( PyDict_SetItem( c.get(), PySStr::operationstr, PySStr::appendstr ) != 0 ) return 0; - if( PyDict_SetItem( c.get(), PySStr::item(), m_validated.get() ) != 0 ) + if( PyDict_SetItem( c.get(), PySStr::itemstr, m_validated.get() ) != 0 ) return 0; if( !post_change( c ) ) return 0; @@ -580,15 +684,15 @@ cppy::ptr c( prepare_change() ); if( !c ) return 0; // LCOV_EXCL_LINE - if( PyDict_SetItem( c.get(), PySStr::operation(), PySStr::insert() ) != 0 ) + if( PyDict_SetItem( c.get(), PySStr::operationstr, PySStr::insertstr ) != 0 ) return 0; // if the superclass call succeeds, then this is safe. Py_ssize_t where = PyLong_AsSsize_t( PyTuple_GET_ITEM( args, 0 ) ); clip_index( where, size ); cppy::ptr index( PyLong_FromSsize_t( where ) ); - if( PyDict_SetItem( c.get(), PySStr::index(), index.get() ) != 0 ) + if( PyDict_SetItem( c.get(), PySStr::indexstr, index.get() ) != 0 ) return 0; - if( PyDict_SetItem( c.get(), PySStr::item(), m_validated.get() ) != 0) + if( PyDict_SetItem( c.get(), PySStr::itemstr, m_validated.get() ) != 0) return 0; if( !post_change( c ) ) return 0; @@ -606,9 +710,9 @@ cppy::ptr c( prepare_change() ); if( !c ) return 0; // LCOV_EXCL_LINE - if( PyDict_SetItem( c.get(), PySStr::operation(), PySStr::extend() ) != 0 ) + if( PyDict_SetItem( c.get(), PySStr::operationstr, PySStr::extendstr ) != 0 ) return 0; - if( PyDict_SetItem( c.get(), PySStr::items(), m_validated.get() ) != 0 ) + if( PyDict_SetItem( c.get(), PySStr::itemsstr, m_validated.get() ) != 0 ) return 0; if( !post_change( c ) ) return 0; @@ -633,7 +737,7 @@ cppy::ptr c( prepare_change() ); if( !c ) return 0; // LCOV_EXCL_LINE - if( PyDict_SetItem( c.get(), PySStr::operation(), PySStr::pop() ) != 0 ) + if( PyDict_SetItem( c.get(), PySStr::operationstr, PySStr::popstr ) != 0 ) return 0; // if the superclass call succeeds, then this is safe. Py_ssize_t i = -1; @@ -642,9 +746,9 @@ if( i < 0 ) i += size; cppy::ptr index( PyLong_FromSsize_t( i ) ); - if( PyDict_SetItem( c.get(), PySStr::index(), index.get() ) != 0 ) + if( PyDict_SetItem( c.get(), PySStr::indexstr, index.get() ) != 0 ) return 0; - if( PyDict_SetItem( c.get(), PySStr::item(), res.get() ) != 0 ) + if( PyDict_SetItem( c.get(), PySStr::itemstr, res.get() ) != 0 ) return 0; if( !post_change( c ) ) return 0; @@ -662,9 +766,9 @@ cppy::ptr c( prepare_change() ); if( !c ) return 0; // LCOV_EXCL_LINE - if( PyDict_SetItem( c.get(), PySStr::operation(), PySStr::remove() ) != 0) + if( PyDict_SetItem( c.get(), PySStr::operationstr, PySStr::removestr ) != 0) return 0; - if( PyDict_SetItem( c.get(), PySStr::item(), value ) != 0 ) + if( PyDict_SetItem( c.get(), PySStr::itemstr, value ) != 0 ) return 0; if( !post_change( c ) ) return 0; @@ -682,7 +786,7 @@ cppy::ptr c( prepare_change() ); if( !c ) return 0; // LCOV_EXCL_LINE - if( PyDict_SetItem( c.get(), PySStr::operation(), PySStr::reverse() ) != 0) + if( PyDict_SetItem( c.get(), PySStr::operationstr, PySStr::reversestr ) != 0) return 0; if( !post_change( c ) ) return 0; @@ -713,16 +817,16 @@ cppy::ptr c( prepare_change() ); if( !c ) return 0; // LCOV_EXCL_LINE - if( PyDict_SetItem( c.get(), PySStr::operation(), PySStr::sort() ) != 0 ) + if( PyDict_SetItem( c.get(), PySStr::operationstr, PySStr::sortstr ) != 0 ) return 0; PyObject* key = Py_None; int rev = 0; if( !PyArg_ParseTupleAndKeywords( args, kwargs, "|Oi", kwlist, &key, &rev ) ) return 0; - if( PyDict_SetItem( c.get(), PySStr::key(), key ) != 0) + if( PyDict_SetItem( c.get(), PySStr::keystr, key ) != 0) return 0; - if( PyDict_SetItem( c.get(), PySStr::reverse(), rev ? Py_True : Py_False ) != 0 ) + if( PyDict_SetItem( c.get(), PySStr::reversestr, rev ? Py_True : Py_False ) != 0 ) return 0; if( !post_change( c ) ) return 0; @@ -740,9 +844,9 @@ cppy::ptr c( prepare_change() ); if( !c ) return 0; // LCOV_EXCL_LINE - if( PyDict_SetItem( c.get(), PySStr::operation(), PySStr::__iadd__() ) != 0 ) + if( PyDict_SetItem( c.get(), PySStr::operationstr, PySStr::__iadd__str ) != 0 ) return 0; - if( PyDict_SetItem( c.get(), PySStr::items(), m_validated.get() ) != 0 ) + if( PyDict_SetItem( c.get(), PySStr::itemsstr, m_validated.get() ) != 0 ) return 0; if( !post_change( c ) ) return 0; @@ -761,12 +865,12 @@ cppy::ptr c( prepare_change() ); if( !c ) return 0; // LCOV_EXCL_LINE - if( PyDict_SetItem( c.get(), PySStr::operation(), PySStr::__imul__() ) != 0 ) + if( PyDict_SetItem( c.get(), PySStr::operationstr, PySStr::__imul__str ) != 0 ) return 0; cppy::ptr pycount( PyLong_FromSsize_t( count ) ); if( !pycount ) return 0; - if( PyDict_SetItem( c.get(), PySStr::count(), pycount.get() ) != 0 ) + if( PyDict_SetItem( c.get(), PySStr::countstr, pycount.get() ) != 0 ) return 0; if( !post_change( c ) ) return 0; @@ -848,13 +952,13 @@ cppy::ptr c( PyDict_New() ); if( !c ) return 0; - if( PyDict_SetItem( c.get(), PySStr::type(), PySStr::container() ) != 0 ) + if( PyDict_SetItem( c.get(), PySStr::typestr, PySStr::containerstr ) != 0 ) return 0; - if( PyDict_SetItem( c.get(), PySStr::name(), member()->name ) != 0 ) + if( PyDict_SetItem( c.get(), PySStr::namestr, member()->name ) != 0 ) return 0; - if( PyDict_SetItem( c.get(), PySStr::object(), pyobject_cast( atom() ) ) != 0 ) + if( PyDict_SetItem( c.get(), PySStr::objectstr, pyobject_cast( atom() ) ) != 0 ) return 0; - if( PyDict_SetItem( c.get(), PySStr::value(), m_list.get() ) != 0 ) + if( PyDict_SetItem( c.get(), PySStr::valuestr, m_list.get() ) != 0 ) return 0; return c.release(); } @@ -885,21 +989,21 @@ return -1; if( n ) { - if( PyDict_SetItem( c.get(), PySStr::operation(), PySStr::__setitem__() ) != 0 ) + if( PyDict_SetItem( c.get(), PySStr::operationstr, PySStr::__setitem__str ) != 0 ) return -1; - if( PyDict_SetItem( c.get(), PySStr::olditem(), o.get() ) != 0) + if( PyDict_SetItem( c.get(), PySStr::olditemstr, o.get() ) != 0) return -1; - if( PyDict_SetItem( c.get(), PySStr::newitem(), n.get() ) != 0) + if( PyDict_SetItem( c.get(), PySStr::newitemstr, n.get() ) != 0) return -1; } else { - if( PyDict_SetItem( c.get(), PySStr::operation(), PySStr::__delitem__() ) != 0 ) + if( PyDict_SetItem( c.get(), PySStr::operationstr, PySStr::__delitem__str ) != 0 ) return -1; - if( PyDict_SetItem( c.get(), PySStr::item(), o.get() ) != 0 ) + if( PyDict_SetItem( c.get(), PySStr::itemstr, o.get() ) != 0 ) return -1; } - if( PyDict_SetItem( c.get(), PySStr::index(), i.get() ) != 0 ) + if( PyDict_SetItem( c.get(), PySStr::indexstr, i.get() ) != 0 ) return -1; if( !post_change( c ) ) return -1; @@ -936,10 +1040,10 @@ AtomCList_dealloc( AtomCList* self ) { PyObject_GC_UnTrack( self ); - Py_CLEAR( self->member ); + cppy::clear( &self->member ); + cppy::clear( &atomlist_cast( self )->validator ); delete atomlist_cast( self )->pointer; atomlist_cast( self )->pointer = 0; - Py_CLEAR( atomlist_cast( self )->validator ); PyList_Type.tp_dealloc( pyobject_cast( self ) ); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.10.0/atom/src/atomlist.h new/atom-0.10.3/atom/src/atomlist.h --- old/atom-0.10.0/atom/src/atomlist.h 2023-05-05 10:02:54.000000000 +0200 +++ new/atom-0.10.3/atom/src/atomlist.h 2023-10-04 10:36:05.000000000 +0200 @@ -41,6 +41,9 @@ }; +bool +init_containerlistchange(); + // POD struct - all member fields are considered private struct AtomCList diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.10.0/atom/src/atomset.cpp new/atom-0.10.3/atom/src/atomset.cpp --- old/atom-0.10.0/atom/src/atomset.cpp 2023-05-05 10:02:54.000000000 +0200 +++ new/atom-0.10.3/atom/src/atomset.cpp 2023-10-04 10:36:05.000000000 +0200 @@ -95,7 +95,10 @@ void AtomSet_dealloc( AtomSet* self ) { + PyObject_GC_UnTrack( self ); cppy::clear( &self->m_value_validator ); + delete atomset_cast( self )->pointer; + atomset_cast( self )->pointer = 0; PySet_Type.tp_dealloc( pyobject_cast( self ) ); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.10.0/atom/src/catommodule.cpp new/atom-0.10.3/atom/src/catommodule.cpp --- old/atom-0.10.0/atom/src/catommodule.cpp 2023-05-05 10:02:54.000000000 +0200 +++ new/atom-0.10.3/atom/src/catommodule.cpp 2023-10-04 10:36:05.000000000 +0200 @@ -178,6 +178,10 @@ { return -1; } + if( !atom::init_containerlistchange() ) + { + return -1; + } if( !add_objects( mod ) ) { return -1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.10.0/atom/version.py new/atom-0.10.3/atom/version.py --- old/atom-0.10.0/atom/version.py 2023-05-05 10:03:21.000000000 +0200 +++ new/atom-0.10.3/atom/version.py 2023-10-04 10:36:33.000000000 +0200 @@ -12,7 +12,7 @@ #: A namedtuple of the version info for the current release. _version_info = namedtuple("_version_info", "major minor micro status") -parts = "0.10.0".split(".", 3) +parts = "0.10.3".split(".", 3) version_info = _version_info( int(parts[0]), int(parts[1]), @@ -23,4 +23,4 @@ # Remove everything but the 'version_info' from this module. del namedtuple, _version_info, parts -__version__ = "0.10.0" +__version__ = "0.10.3" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.10.0/atom.egg-info/PKG-INFO new/atom-0.10.3/atom.egg-info/PKG-INFO --- old/atom-0.10.0/atom.egg-info/PKG-INFO 2023-05-05 10:03:22.000000000 +0200 +++ new/atom-0.10.3/atom.egg-info/PKG-INFO 2023-10-04 10:36:34.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: atom -Version: 0.10.0 +Version: 0.10.3 Summary: Memory efficient Python objects Author-email: The Nucleic Development Team <[email protected]> Maintainer-email: "Matthieu C. Dartiailh" <[email protected]> @@ -98,6 +98,7 @@ Requires-Python: >=3.8 Description-Content-Type: text/x-rst License-File: LICENSE +Requires-Dist: typing_extensions; python_version < "3.11" Welcome to Atom =============== diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.10.0/atom.egg-info/SOURCES.txt new/atom-0.10.3/atom.egg-info/SOURCES.txt --- old/atom-0.10.0/atom.egg-info/SOURCES.txt 2023-05-05 10:03:22.000000000 +0200 +++ new/atom-0.10.3/atom.egg-info/SOURCES.txt 2023-10-04 10:36:34.000000000 +0200 @@ -205,6 +205,7 @@ tests/test_get_behaviors.py tests/test_get_set_state.py tests/test_getstate_behaviors.py +tests/test_mem.py tests/test_member.py tests/test_observe.py tests/test_post_behaviors.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.10.0/releasenotes.rst new/atom-0.10.3/releasenotes.rst --- old/atom-0.10.0/releasenotes.rst 2023-05-05 10:02:54.000000000 +0200 +++ new/atom-0.10.3/releasenotes.rst 2023-10-04 10:36:05.000000000 +0200 @@ -1,6 +1,25 @@ Atom Release Notes ================== +0.10.3 - 04/10/2023 +------------------- + +- fix a an issue when using add_member to override an existing member PR #204 + + Once again a huge thanks to @frmdstryr for the report and fix + +0.10.2 - 02/10/2023 +------------------- + +- fix a memory leak caused by Dict, Defaultdict and Set members #202 + + A huge thanks to @frmdstryr for the report and fix + +0.10.1 - 11/09/2023 +------------------- + +- add support for Python 3.12 PR #200 + 0.10.0 - 05/05/2023 ------------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.10.0/test_requirements.txt new/atom-0.10.3/test_requirements.txt --- old/atom-0.10.0/test_requirements.txt 2023-05-05 10:02:54.000000000 +0200 +++ new/atom-0.10.3/test_requirements.txt 2023-10-04 10:36:05.000000000 +0200 @@ -2,3 +2,4 @@ pytest-cov pytest-mypy-plugins pytest-benchmark +psutil diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.10.0/tests/test_atom.py new/atom-0.10.3/tests/test_atom.py --- old/atom-0.10.0/tests/test_atom.py 2023-05-05 10:02:54.000000000 +0200 +++ new/atom-0.10.3/tests/test_atom.py 2023-10-04 10:36:05.000000000 +0200 @@ -164,6 +164,29 @@ assert "a" in B().members() +def test_add_member_overridden_member(): + class A(Atom): + a = Int() + b = Int() + + def _observe_b(self, change): + pass + + class B(A): + c = Int() + + new = Str() + add_member(B, "b", new) + + r = B(a=1, b="abc") + assert r.a == 1 + assert r.b == "abc" + assert B.a.index == 0 + assert B.b.index == 1 + assert B.c.index == 2 + assert B.b.has_observer("_observe_b") + + def test_cloning_members(): """Test cloning a member when appropriate. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.10.0/tests/test_atomlist.py new/atom-0.10.3/tests/test_atomlist.py --- old/atom-0.10.0/tests/test_atomlist.py 2023-05-05 10:02:54.000000000 +0200 +++ new/atom-0.10.3/tests/test_atomlist.py 2023-10-04 10:36:05.000000000 +0200 @@ -396,8 +396,8 @@ self.model = None def test_list_types(self): - assert type(self.model.untyped) == atomlist - assert type(self.model.typed) == atomlist + assert type(self.model.untyped) is atomlist + assert type(self.model.typed) is atomlist def test_pickle(self): data = list(range(10)) @@ -454,8 +454,8 @@ self.model = None def test_list_types(self): - assert type(self.model.untyped) == atomclist - assert type(self.model.typed) == atomclist + assert type(self.model.untyped) is atomclist + assert type(self.model.typed) is atomclist @pytest.fixture diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/atom-0.10.0/tests/test_mem.py new/atom-0.10.3/tests/test_mem.py --- old/atom-0.10.0/tests/test_mem.py 1970-01-01 01:00:00.000000000 +0100 +++ new/atom-0.10.3/tests/test_mem.py 2023-10-04 10:36:05.000000000 +0200 @@ -0,0 +1,101 @@ +# -------------------------------------------------------------------------------------- +# Copyright (c) 2023, Nucleic Development Team. +# +# Distributed under the terms of the Modified BSD License. +# +# The full license is in the file LICENSE, distributed with this software. +# -------------------------------------------------------------------------------------- +import gc +import time +from multiprocessing import Process + +import pytest + +from atom.api import Atom, DefaultDict, Dict, Int, List, Set, atomref + +try: + import psutil + + PSUTIL_UNAVAILABLE = False +except ImportError: + PSUTIL_UNAVAILABLE = True + +TIMEOUT = 6 + + +class DictObj(Atom): + data = Dict(default={"a": 0}) + + +class DefaultDictObj(Atom): + data = DefaultDict(value=Int(), default={1: 1}) + + +class ListObj(Atom): + data = List(default=[1, 2, 3]) + + +class SetObj(Atom): + data = Set(default={1, 2, 3}) + + +class RefObj(Atom): + data = Int() + + +MEM_TESTS = { + "dict": DictObj, + "defaultdict": DefaultDictObj, + "list": ListObj, + "set": SetObj, + "atomref": RefObj, +} + + +def memtest(cls): + # Create object in a loop + # Memory usage should settle out and not change + while True: + obj = cls() + obj.data # Force creation + del obj + gc.collect() + + +def atomreftest(cls): + obj = cls() + obj.data + while True: + ref = atomref(obj) # noqa + del ref + gc.collect() + + [email protected](PSUTIL_UNAVAILABLE, reason="psutil is not installed") [email protected]("label", MEM_TESTS.keys()) +def test_mem_usage(label): + TestClass = MEM_TESTS[label] + if "atomref" in label: + target = atomreftest + else: + target = memtest + + p = Process(target=target, args=(TestClass,)) + p.start() + try: + stats = psutil.Process(p.pid) + time.sleep(TIMEOUT * 1 / 4) + first_info = stats.memory_info() + time.sleep(TIMEOUT * 3 / 4) + last_info = stats.memory_info() + # Allow slight memory decrease over time to make tests more resilient + if first_info != last_info: + assert ( + first_info.rss >= last_info.rss >= 0 + ), "Memory leaked:\n {}\n {}".format(first_info, last_info) + assert ( + first_info.vms >= last_info.vms >= 0 + ), "Memory leaked:\n {}\n {}".format(first_info, last_info) + finally: + p.kill() + p.join()
