Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-dill for openSUSE:Factory checked in at 2024-10-23 21:09:46 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-dill (Old) and /work/SRC/openSUSE:Factory/.python-dill.new.26871 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-dill" Wed Oct 23 21:09:46 2024 rev:15 rq:1217040 version:0.3.9 Changes: -------- --- /work/SRC/openSUSE:Factory/python-dill/python-dill.changes 2024-09-01 19:21:49.356987558 +0200 +++ /work/SRC/openSUSE:Factory/.python-dill.new.26871/python-dill.changes 2024-10-23 21:10:53.960245404 +0200 @@ -1,0 +2,19 @@ +Tue Oct 22 13:27:09 UTC 2024 - Dirk Müller <[email protected]> + +- update to 0.3.9: + * further skip BufferedRandomType if does not exist + * remove stray import of dbm in objects + * Add `UnpicklingError` import for `dill.load_session()` to fix + #648 + * fix fencepost error when getting source inside decorator in + interpreter (fixes #603) + * type check for Integral, bool by value + * diff USE_NUMPY imports numpy.ma + * adjust testing to account for frame.f_locals as a proxy in + 3.13 + * better handle import strings of numpy scalars + * handle a ThreadHandleType + * more extensive testing for dill.source + * add formal support for python 3.13 + +------------------------------------------------------------------- Old: ---- dill-0.3.8.tar.gz New: ---- dill-0.3.9.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-dill.spec ++++++ --- /var/tmp/diff_new_pack.vvVCxs/_old 2024-10-23 21:10:54.552270116 +0200 +++ /var/tmp/diff_new_pack.vvVCxs/_new 2024-10-23 21:10:54.552270116 +0200 @@ -18,7 +18,7 @@ %{?sle15_python_module_pythons} Name: python-dill -Version: 0.3.8 +Version: 0.3.9 Release: 0 Summary: Module to serialize all of Python License: BSD-3-Clause ++++++ dill-0.3.8.tar.gz -> dill-0.3.9.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dill-0.3.8/.travis.yml new/dill-0.3.9/.travis.yml --- old/dill-0.3.8/.travis.yml 2024-01-28 00:44:53.000000000 +0100 +++ new/dill-0.3.9/.travis.yml 2024-09-29 02:04:07.000000000 +0200 @@ -26,15 +26,14 @@ - python: 'pypy3.8-7.3.9' # at 7.3.11 env: - - python: 'pypy3.9-7.3.9' # at 7.3.15 + - python: 'pypy3.9-7.3.9' # at 7.3.16 env: - - python: 'pypy3.10-7.3.15' + - python: 'pypy3.10-7.3.17' env: allow_failures: - - python: '3.13-dev' - - python: 'pypy3.10-7.3.15' # CI missing + - python: 'pypy3.10-7.3.17' # CI missing fast_finish: true cache: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dill-0.3.8/dill/__diff.py new/dill-0.3.9/dill/__diff.py --- old/dill-0.3.8/dill/__diff.py 2024-01-28 00:44:53.000000000 +0100 +++ new/dill-0.3.9/dill/__diff.py 2024-09-29 02:04:07.000000000 +0200 @@ -15,7 +15,7 @@ import sys import types try: - import numpy + import numpy.ma HAS_NUMPY = True except ImportError: HAS_NUMPY = False diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dill-0.3.8/dill/_dill.py new/dill-0.3.9/dill/_dill.py --- old/dill-0.3.8/dill/_dill.py 2024-01-28 00:44:53.000000000 +0100 +++ new/dill-0.3.9/dill/_dill.py 2024-09-29 02:04:07.000000000 +0200 @@ -56,6 +56,14 @@ from pickle import GLOBAL, POP from _thread import LockType from _thread import RLock as RLockType +try: + from _thread import _ExceptHookArgs as ExceptHookArgsType +except ImportError: + ExceptHookArgsType = None +try: + from _thread import _ThreadHandle as ThreadHandleType +except ImportError: + ThreadHandleType = None #from io import IOBase from types import CodeType, FunctionType, MethodType, GeneratorType, \ TracebackType, FrameType, ModuleType, BuiltinMethodType @@ -775,6 +783,14 @@ return typing.Tuple[()] return typing.Tuple[argz] +if ThreadHandleType: + def _create_thread_handle(ident, done, *args): #XXX: ignores 'blocking' + from threading import _make_thread_handle + handle = _make_thread_handle(ident) + if done: + handle._set_done() + return handle + def _create_lock(locked, *args): #XXX: ignores 'blocking' from threading import Lock lock = Lock() @@ -1306,7 +1322,15 @@ logger.trace(pickler, "# Ga2") return -@register(LockType) +if ThreadHandleType: + @register(ThreadHandleType) + def save_thread_handle(pickler, obj): + logger.trace(pickler, "Th: %s", obj) + pickler.save_reduce(_create_thread_handle, (obj.ident, obj.is_done()), obj=obj) + logger.trace(pickler, "# Th") + return + +@register(LockType) #XXX: copied Thread will have new Event (due to new Lock) def save_lock(pickler, obj): logger.trace(pickler, "Lo: %s", obj) pickler.save_reduce(_create_lock, (obj.locked(),), obj=obj) @@ -1773,7 +1797,7 @@ logger.trace(pickler, "# T6") return - # special cases: NoneType, NotImplementedType, EllipsisType, EnumMeta + # special caes: NoneType, NotImplementedType, EllipsisType, EnumMeta, etc elif obj is type(None): logger.trace(pickler, "T7: %s", obj) #XXX: pickler.save_reduce(type, (None,), obj=obj) @@ -1791,6 +1815,10 @@ logger.trace(pickler, "T7: %s", obj) pickler.write(GLOBAL + b'enum\nEnumMeta\n') logger.trace(pickler, "# T7") + elif obj is ExceptHookArgsType: #NOTE: must be after NoneType for pypy + logger.trace(pickler, "T7: %s", obj) + pickler.write(GLOBAL + b'threading\nExceptHookArgs\n') + logger.trace(pickler, "# T7") else: _byref = getattr(pickler, '_byref', None) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dill-0.3.8/dill/_objects.py new/dill-0.3.9/dill/_objects.py --- old/dill-0.3.8/dill/_objects.py 2024-01-28 00:44:53.000000000 +0100 +++ new/dill-0.3.9/dill/_objects.py 2024-09-29 02:04:07.000000000 +0200 @@ -16,7 +16,7 @@ import warnings; warnings.filterwarnings("ignore", category=DeprecationWarning) import sys import queue as Queue -import dbm as anydbm +#import dbm as anydbm #XXX: delete foo from io import BytesIO as StringIO import re import array @@ -72,6 +72,8 @@ HAS_CTYPES = False IS_PYPY = False +IS_PYODIDE = sys.platform == 'emscripten' + # helper objects class _class: def _method(self): @@ -250,13 +252,15 @@ a['SliceType'] = slice(1) a['UnboundMethodType'] = _class._method #XXX: works when not imported! d['TextWrapperType'] = open(os.devnull, 'r') # same as mode='w','w+','r+' -d['BufferedRandomType'] = open(os.devnull, 'r+b') # same as mode='w+b' +if not IS_PYODIDE: + d['BufferedRandomType'] = open(os.devnull, 'r+b') # same as mode='w+b' d['BufferedReaderType'] = open(os.devnull, 'rb') # (default: buffering=-1) d['BufferedWriterType'] = open(os.devnull, 'wb') try: # oddities: deprecated from _pyio import open as _open d['PyTextWrapperType'] = _open(os.devnull, 'r', buffering=-1) - d['PyBufferedRandomType'] = _open(os.devnull, 'r+b', buffering=-1) + if not IS_PYODIDE: + d['PyBufferedRandomType'] = _open(os.devnull, 'r+b', buffering=-1) d['PyBufferedReaderType'] = _open(os.devnull, 'rb', buffering=-1) d['PyBufferedWriterType'] = _open(os.devnull, 'wb', buffering=-1) except ImportError: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dill-0.3.8/dill/logger.py new/dill-0.3.9/dill/logger.py --- old/dill-0.3.8/dill/logger.py 2024-01-28 00:44:53.000000000 +0100 +++ new/dill-0.3.9/dill/logger.py 2024-09-29 02:04:07.000000000 +0200 @@ -253,7 +253,7 @@ arg: a boolean value, or an optional file-like or path-like object for the context manager mode: mode string for ``open()`` if a file name is passed as the first argument """ - if not isinstance(arg, bool): + if repr(arg) not in ('False', 'True'): return TraceManager(file=arg, mode=mode) logger.setLevel(logging.INFO if arg else logging.WARNING) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dill-0.3.8/dill/session.py new/dill-0.3.9/dill/session.py --- old/dill-0.3.8/dill/session.py 2024-01-28 00:44:53.000000000 +0100 +++ new/dill-0.3.9/dill/session.py 2024-09-29 02:04:07.000000000 +0200 @@ -19,22 +19,21 @@ import os import sys import warnings +import pathlib +import tempfile + +TEMPDIR = pathlib.PurePath(tempfile.gettempdir()) + +# Type hints. +from typing import Optional, Union from dill import _dill, Pickler, Unpickler from ._dill import ( BuiltinMethodType, FunctionType, MethodType, ModuleType, TypeType, _import_module, _is_builtin_module, _is_imported_module, _main_module, - _reverse_typemap, __builtin__, + _reverse_typemap, __builtin__, UnpicklingError, ) -# Type hints. -from typing import Optional, Union - -import pathlib -import tempfile - -TEMPDIR = pathlib.PurePath(tempfile.gettempdir()) - def _module_map(): """get map of imported modules""" from collections import defaultdict diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dill-0.3.8/dill/source.py new/dill-0.3.9/dill/source.py --- old/dill-0.3.8/dill/source.py 2024-01-28 00:44:53.000000000 +0100 +++ new/dill-0.3.9/dill/source.py 2024-09-29 02:04:07.000000000 +0200 @@ -150,7 +150,7 @@ if err: raise IOError(err) lbuf = readline.get_current_history_length() - lines = [readline.get_history_item(i)+'\n' for i in range(1,lbuf)] + lines = [readline.get_history_item(i)+'\n' for i in range(1,lbuf+1)] else: try: # special handling for class instances if not isclass(object) and isclass(type(object)): # __class__ @@ -481,7 +481,8 @@ def indent(code, spaces=4): '''indent a block of code with whitespace (default is 4 spaces)''' indent = indentsize(code) - if type(spaces) is int: spaces = ' '*spaces + from numbers import Integral + if isinstance(spaces, Integral): spaces = ' '*spaces # if '\t' is provided, will indent with a tab nspaces = indentsize(spaces) # blank lines (etc) need to be ignored @@ -529,7 +530,7 @@ return '\n'.join(_outdent(code.split('\n'), spaces=spaces, all=all)) -#XXX: not sure what the point of _wrap is... +# _wrap provides an wrapper to correctly exec and load into locals __globals__ = globals() __locals__ = locals() def _wrap(f): @@ -601,10 +602,13 @@ def getname(obj, force=False, fqn=False): #XXX: throw(?) to raise error on fail? """get the name of the object. for lambdas, get the name of the pointer """ - if fqn: return '.'.join(_namespace(obj)) + if fqn: return '.'.join(_namespace(obj)) #NOTE: returns 'type' module = getmodule(obj) if not module: # things like "None" and "1" - if not force: return None + if not force: return None #NOTE: returns 'instance' NOT 'type' #FIXME? + # handle some special cases + if hasattr(obj, 'dtype') and not obj.shape: + return getname(obj.__class__) + "(" + repr(obj.tolist()) + ")" return repr(obj) try: #XXX: 'wrong' for decorators and curried functions ? @@ -739,6 +743,8 @@ except Exception: # it's probably something 'importable' if head in ['builtins','__builtin__']: name = repr(obj) #XXX: catch [1,2], (1,2), set([1,2])... others? + elif _isinstance(obj): + name = getname(obj, force=True).split('(')[0] else: name = repr(obj).split('(')[0] #if not repr(obj).startswith('<'): name = repr(obj).split('(')[0] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dill-0.3.8/dill/tests/test_detect.py new/dill-0.3.9/dill/tests/test_detect.py --- old/dill-0.3.8/dill/tests/test_detect.py 2024-01-28 00:44:53.000000000 +0100 +++ new/dill-0.3.9/dill/tests/test_detect.py 2024-09-29 02:04:07.000000000 +0200 @@ -29,7 +29,8 @@ s = set([(err.__class__.__name__,err.args[0]) for err in list(errors(f, 1).values())]) a = dict(s) if not os.environ.get('COVERAGE'): #XXX: travis-ci - assert len(s) is len(a) # TypeError (and possibly PicklingError) + proxy = 0 if type(f.f_locals) is dict else 1 + assert len(s) == len(a) + proxy # TypeError (and possibly PicklingError) n = 2 assert len(a) is n if 'PicklingError' in a.keys() else n-1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dill-0.3.8/dill/tests/test_selected.py new/dill-0.3.9/dill/tests/test_selected.py --- old/dill-0.3.8/dill/tests/test_selected.py 2024-01-28 00:44:53.000000000 +0100 +++ new/dill-0.3.9/dill/tests/test_selected.py 2024-09-29 02:04:07.000000000 +0200 @@ -45,7 +45,8 @@ # some clean-up #FIXME: should happen internal to dill objects['TemporaryFileType'].close() objects['TextWrapperType'].close() -objects['BufferedRandomType'].close() +if 'BufferedRandomType' in objects: + objects['BufferedRandomType'].close() objects['BufferedReaderType'].close() objects['BufferedWriterType'].close() objects['FileType'].close() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dill-0.3.8/dill/tests/test_source.py new/dill-0.3.9/dill/tests/test_source.py --- old/dill-0.3.8/dill/tests/test_source.py 2024-01-28 00:44:53.000000000 +0100 +++ new/dill-0.3.9/dill/tests/test_source.py 2024-09-29 02:04:07.000000000 +0200 @@ -6,8 +6,8 @@ # License: 3-clause BSD. The full license text is available at: # - https://github.com/uqfoundation/dill/blob/master/LICENSE -from dill.source import getsource, getname, _wrap, likely_import -from dill.source import getimportable +from dill.source import getsource, getname, _wrap, getimport +from dill.source import importable from dill._dill import IS_PYPY import sys @@ -55,31 +55,31 @@ # test itself def test_itself(): - assert likely_import(likely_import)=='from dill.source import likely_import\n' + assert getimport(getimport)=='from dill.source import getimport\n' # builtin functions and objects def test_builtin(): - assert likely_import(pow) == 'pow\n' - assert likely_import(100) == '100\n' - assert likely_import(True) == 'True\n' - assert likely_import(pow, explicit=True) == 'from builtins import pow\n' - assert likely_import(100, explicit=True) == '100\n' - assert likely_import(True, explicit=True) == 'True\n' + assert getimport(pow) == 'pow\n' + assert getimport(100) == '100\n' + assert getimport(True) == 'True\n' + assert getimport(pow, builtin=True) == 'from builtins import pow\n' + assert getimport(100, builtin=True) == '100\n' + assert getimport(True, builtin=True) == 'True\n' # this is kinda BS... you can't import a None - assert likely_import(None) == 'None\n' - assert likely_import(None, explicit=True) == 'None\n' + assert getimport(None) == 'None\n' + assert getimport(None, builtin=True) == 'None\n' # other imported functions def test_imported(): from math import sin - assert likely_import(sin) == 'from math import sin\n' + assert getimport(sin) == 'from math import sin\n' # interactively defined functions def test_dynamic(): - assert likely_import(add) == 'from %s import add\n' % __name__ + assert getimport(add) == 'from %s import add\n' % __name__ # interactive lambdas - assert likely_import(squared) == 'from %s import squared\n' % __name__ + assert getimport(squared) == 'from %s import squared\n' % __name__ # classes and class instances def test_classes(): @@ -88,59 +88,78 @@ x = y if (IS_PYPY or sys.hexversion >= PY310b) else "from io import BytesIO\n" s = StringIO() - assert likely_import(StringIO) == x - assert likely_import(s) == y + assert getimport(StringIO) == x + assert getimport(s) == y # interactively defined classes and class instances - assert likely_import(Foo) == 'from %s import Foo\n' % __name__ - assert likely_import(_foo) == 'from %s import Foo\n' % __name__ + assert getimport(Foo) == 'from %s import Foo\n' % __name__ + assert getimport(_foo) == 'from %s import Foo\n' % __name__ -# test getimportable +# test importable def test_importable(): - assert getimportable(add) == 'from %s import add\n' % __name__ - assert getimportable(squared) == 'from %s import squared\n' % __name__ - assert getimportable(Foo) == 'from %s import Foo\n' % __name__ - assert getimportable(Foo.bar) == 'from %s import bar\n' % __name__ - assert getimportable(_foo.bar) == 'from %s import bar\n' % __name__ - assert getimportable(None) == 'None\n' - assert getimportable(100) == '100\n' - - assert getimportable(add, byname=False) == 'def add(x,y):\n return x+y\n' - assert getimportable(squared, byname=False) == 'squared = lambda x:x**2\n' - assert getimportable(None, byname=False) == 'None\n' - assert getimportable(Bar, byname=False) == 'class Bar:\n pass\n' - assert getimportable(Foo, byname=False) == 'class Foo(object):\n def bar(self, x):\n return x*x+x\n' - assert getimportable(Foo.bar, byname=False) == 'def bar(self, x):\n return x*x+x\n' - assert getimportable(Foo.bar, byname=True) == 'from %s import bar\n' % __name__ - assert getimportable(Foo.bar, alias='memo', byname=True) == 'from %s import bar as memo\n' % __name__ - assert getimportable(Foo, alias='memo', byname=True) == 'from %s import Foo as memo\n' % __name__ - assert getimportable(squared, alias='memo', byname=True) == 'from %s import squared as memo\n' % __name__ - assert getimportable(squared, alias='memo', byname=False) == 'memo = squared = lambda x:x**2\n' - assert getimportable(add, alias='memo', byname=False) == 'def add(x,y):\n return x+y\n\nmemo = add\n' - assert getimportable(None, alias='memo', byname=False) == 'memo = None\n' - assert getimportable(100, alias='memo', byname=False) == 'memo = 100\n' - assert getimportable(add, explicit=True) == 'from %s import add\n' % __name__ - assert getimportable(squared, explicit=True) == 'from %s import squared\n' % __name__ - assert getimportable(Foo, explicit=True) == 'from %s import Foo\n' % __name__ - assert getimportable(Foo.bar, explicit=True) == 'from %s import bar\n' % __name__ - assert getimportable(_foo.bar, explicit=True) == 'from %s import bar\n' % __name__ - assert getimportable(None, explicit=True) == 'None\n' - assert getimportable(100, explicit=True) == '100\n' + assert importable(add, source=False) == 'from %s import add\n' % __name__ + assert importable(squared, source=False) == 'from %s import squared\n' % __name__ + assert importable(Foo, source=False) == 'from %s import Foo\n' % __name__ + assert importable(Foo.bar, source=False) == 'from %s import bar\n' % __name__ + assert importable(_foo.bar, source=False) == 'from %s import bar\n' % __name__ + assert importable(None, source=False) == 'None\n' + assert importable(100, source=False) == '100\n' + + assert importable(add, source=True) == 'def add(x,y):\n return x+y\n' + assert importable(squared, source=True) == 'squared = lambda x:x**2\n' + assert importable(None, source=True) == 'None\n' + assert importable(Bar, source=True) == 'class Bar:\n pass\n' + assert importable(Foo, source=True) == 'class Foo(object):\n def bar(self, x):\n return x*x+x\n' + assert importable(Foo.bar, source=True) == 'def bar(self, x):\n return x*x+x\n' + assert importable(Foo.bar, source=False) == 'from %s import bar\n' % __name__ + assert importable(Foo.bar, alias='memo', source=False) == 'from %s import bar as memo\n' % __name__ + assert importable(Foo, alias='memo', source=False) == 'from %s import Foo as memo\n' % __name__ + assert importable(squared, alias='memo', source=False) == 'from %s import squared as memo\n' % __name__ + assert importable(squared, alias='memo', source=True) == 'memo = squared = lambda x:x**2\n' + assert importable(add, alias='memo', source=True) == 'def add(x,y):\n return x+y\n\nmemo = add\n' + assert importable(None, alias='memo', source=True) == 'memo = None\n' + assert importable(100, alias='memo', source=True) == 'memo = 100\n' + assert importable(add, builtin=True, source=False) == 'from %s import add\n' % __name__ + assert importable(squared, builtin=True, source=False) == 'from %s import squared\n' % __name__ + assert importable(Foo, builtin=True, source=False) == 'from %s import Foo\n' % __name__ + assert importable(Foo.bar, builtin=True, source=False) == 'from %s import bar\n' % __name__ + assert importable(_foo.bar, builtin=True, source=False) == 'from %s import bar\n' % __name__ + assert importable(None, builtin=True, source=False) == 'None\n' + assert importable(100, builtin=True, source=False) == '100\n' def test_numpy(): try: - from numpy import array - x = array([1,2,3]) - assert getimportable(x) == 'from numpy import array\narray([1, 2, 3])\n' - assert getimportable(array) == 'from %s import array\n' % array.__module__ - assert getimportable(x, byname=False) == 'from numpy import array\narray([1, 2, 3])\n' - assert getimportable(array, byname=False) == 'from %s import array\n' % array.__module__ + import numpy as np + y = np.array + x = y([1,2,3]) + assert importable(x, source=False) == 'from numpy import array\narray([1, 2, 3])\n' + assert importable(y, source=False) == 'from %s import array\n' % y.__module__ + assert importable(x, source=True) == 'from numpy import array\narray([1, 2, 3])\n' + assert importable(y, source=True) == 'from %s import array\n' % y.__module__ + y = np.int64 + x = y(0) + assert importable(x, source=False) == 'from numpy import int64\nint64(0)\n' + assert importable(y, source=False) == 'from %s import int64\n' % y.__module__ + assert importable(x, source=True) == 'from numpy import int64\nint64(0)\n' + assert importable(y, source=True) == 'from %s import int64\n' % y.__module__ + y = np.bool_ + x = y(0) + import warnings + with warnings.catch_warnings(): + warnings.filterwarnings('ignore', category=FutureWarning) + warnings.filterwarnings('ignore', category=DeprecationWarning) + if hasattr(np, 'bool'): b = 'bool_' if np.bool is bool else 'bool' + else: b = 'bool_' + assert importable(x, source=False) == 'from numpy import %s\n%s(False)\n' % (b,b) + assert importable(y, source=False) == 'from %s import %s\n' % (y.__module__,b) + assert importable(x, source=True) == 'from numpy import %s\n%s(False)\n' % (b,b) + assert importable(y, source=True) == 'from %s import %s\n' % (y.__module__,b) except ImportError: pass -#NOTE: if before likely_import(pow), will cause pow to throw AssertionError +#NOTE: if before getimport(pow), will cause pow to throw AssertionError def test_foo(): - assert getimportable(_foo, byname=False).startswith("import dill\nclass Foo(object):\n def bar(self, x):\n return x*x+x\ndill.loads(") + assert importable(_foo, source=True).startswith("import dill\nclass Foo(object):\n def bar(self, x):\n return x*x+x\ndill.loads(") if __name__ == '__main__': test_getsource() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dill-0.3.8/dill/tests/test_sources.py new/dill-0.3.9/dill/tests/test_sources.py --- old/dill-0.3.8/dill/tests/test_sources.py 1970-01-01 01:00:00.000000000 +0100 +++ new/dill-0.3.9/dill/tests/test_sources.py 2024-09-29 02:04:07.000000000 +0200 @@ -0,0 +1,190 @@ +#!/usr/bin/env python +# +# Author: Mike McKerns (mmckerns @uqfoundation) +# Copyright (c) 2024 The Uncertainty Quantification Foundation. +# License: 3-clause BSD. The full license text is available at: +# - https://github.com/uqfoundation/dill/blob/master/LICENSE +""" +check that dill.source performs as expected with changes to locals in 3.13.0b1 +see: https://github.com/python/cpython/issues/118888 +""" +# repeat functions from test_source.py +f = lambda x: x**2 +def g(x): return f(x) - x + +def h(x): + def g(x): return x + return g(x) - x + +class Foo(object): + def bar(self, x): + return x*x+x +_foo = Foo() + +def add(x,y): + return x+y + +squared = lambda x:x**2 + +class Bar: + pass +_bar = Bar() + +# repeat, but from test_source.py +import test_source as ts + +# test objects created in other test modules +import test_mixins as tm + +import dill.source as ds + + +def test_isfrommain(): + assert ds.isfrommain(add) == True + assert ds.isfrommain(squared) == True + assert ds.isfrommain(Bar) == True + assert ds.isfrommain(_bar) == True + assert ds.isfrommain(ts.add) == False + assert ds.isfrommain(ts.squared) == False + assert ds.isfrommain(ts.Bar) == False + assert ds.isfrommain(ts._bar) == False + assert ds.isfrommain(tm.quad) == False + assert ds.isfrommain(tm.double_add) == False + assert ds.isfrommain(tm.quadratic) == False + assert ds.isdynamic(add) == False + assert ds.isdynamic(squared) == False + assert ds.isdynamic(ts.add) == False + assert ds.isdynamic(ts.squared) == False + assert ds.isdynamic(tm.double_add) == False + assert ds.isdynamic(tm.quadratic) == False + + +def test_matchlambda(): + assert ds._matchlambda(f, 'f = lambda x: x**2\n') + assert ds._matchlambda(squared, 'squared = lambda x:x**2\n') + assert ds._matchlambda(ts.f, 'f = lambda x: x**2\n') + assert ds._matchlambda(ts.squared, 'squared = lambda x:x**2\n') + + +def test_findsource(): + lines, lineno = ds.findsource(add) + assert lines[lineno] == 'def add(x,y):\n' + lines, lineno = ds.findsource(ts.add) + assert lines[lineno] == 'def add(x,y):\n' + lines, lineno = ds.findsource(squared) + assert lines[lineno] == 'squared = lambda x:x**2\n' + lines, lineno = ds.findsource(ts.squared) + assert lines[lineno] == 'squared = lambda x:x**2\n' + lines, lineno = ds.findsource(Bar) + assert lines[lineno] == 'class Bar:\n' + lines, lineno = ds.findsource(ts.Bar) + assert lines[lineno] == 'class Bar:\n' + lines, lineno = ds.findsource(_bar) + assert lines[lineno] == 'class Bar:\n' + lines, lineno = ds.findsource(ts._bar) + assert lines[lineno] == 'class Bar:\n' + lines, lineno = ds.findsource(tm.quad) + assert lines[lineno] == 'def quad(a=1, b=1, c=0):\n' + lines, lineno = ds.findsource(tm.double_add) + assert lines[lineno] == ' def func(*args, **kwds):\n' + lines, lineno = ds.findsource(tm.quadratic) + assert lines[lineno] == ' def dec(f):\n' + + +def test_getsourcelines(): + assert ''.join(ds.getsourcelines(add)[0]) == 'def add(x,y):\n return x+y\n' + assert ''.join(ds.getsourcelines(ts.add)[0]) == 'def add(x,y):\n return x+y\n' + assert ''.join(ds.getsourcelines(squared)[0]) == 'squared = lambda x:x**2\n' + assert ''.join(ds.getsourcelines(ts.squared)[0]) == 'squared = lambda x:x**2\n' + assert ''.join(ds.getsourcelines(Bar)[0]) == 'class Bar:\n pass\n' + assert ''.join(ds.getsourcelines(ts.Bar)[0]) == 'class Bar:\n pass\n' + assert ''.join(ds.getsourcelines(_bar)[0]) == 'class Bar:\n pass\n' #XXX: ? + assert ''.join(ds.getsourcelines(ts._bar)[0]) == 'class Bar:\n pass\n' #XXX: ? + assert ''.join(ds.getsourcelines(tm.quad)[0]) == 'def quad(a=1, b=1, c=0):\n inverted = [False]\n def invert():\n inverted[0] = not inverted[0]\n def dec(f):\n def func(*args, **kwds):\n x = f(*args, **kwds)\n if inverted[0]: x = -x\n return a*x**2 + b*x + c\n func.__wrapped__ = f\n func.invert = invert\n func.inverted = inverted\n return func\n return dec\n' + assert ''.join(ds.getsourcelines(tm.quadratic)[0]) == ' def dec(f):\n def func(*args,**kwds):\n fx = f(*args,**kwds)\n return a*fx**2 + b*fx + c\n return func\n' + assert ''.join(ds.getsourcelines(tm.quadratic, lstrip=True)[0]) == 'def dec(f):\n def func(*args,**kwds):\n fx = f(*args,**kwds)\n return a*fx**2 + b*fx + c\n return func\n' + assert ''.join(ds.getsourcelines(tm.quadratic, enclosing=True)[0]) == 'def quad_factory(a=1,b=1,c=0):\n def dec(f):\n def func(*args,**kwds):\n fx = f(*args,**kwds)\n return a*fx**2 + b*fx + c\n return func\n return dec\n' + assert ''.join(ds.getsourcelines(tm.double_add)[0]) == ' def func(*args, **kwds):\n x = f(*args, **kwds)\n if inverted[0]: x = -x\n return a*x**2 + b*x + c\n' + assert ''.join(ds.getsourcelines(tm.double_add, enclosing=True)[0]) == 'def quad(a=1, b=1, c=0):\n inverted = [False]\n def invert():\n inverted[0] = not inverted[0]\n def dec(f):\n def func(*args, **kwds):\n x = f(*args, **kwds)\n if inverted[0]: x = -x\n return a*x**2 + b*x + c\n func.__wrapped__ = f\n func.invert = invert\n func.inverted = inverted\n return func\n return dec\n' + + +def test_indent(): + assert ds.outdent(''.join(ds.getsourcelines(tm.quadratic)[0])) == ''.join(ds.getsourcelines(tm.quadratic, lstrip=True)[0]) + assert ds.indent(''.join(ds.getsourcelines(tm.quadratic, lstrip=True)[0]), 2) == ''.join(ds.getsourcelines(tm.quadratic)[0]) + + +def test_dumpsource(): + local = {} + exec(ds.dumpsource(add, alias='raw'), {}, local) + exec(ds.dumpsource(ts.add, alias='mod'), {}, local) + assert local['raw'](1,2) == local['mod'](1,2) + exec(ds.dumpsource(squared, alias='raw'), {}, local) + exec(ds.dumpsource(ts.squared, alias='mod'), {}, local) + assert local['raw'](3) == local['mod'](3) + assert ds._wrap(add)(1,2) == ds._wrap(ts.add)(1,2) + assert ds._wrap(squared)(3) == ds._wrap(ts.squared)(3) + + +def test_name(): + assert ds._namespace(add) == ds.getname(add, fqn=True).split('.') + assert ds._namespace(ts.add) == ds.getname(ts.add, fqn=True).split('.') + assert ds._namespace(squared) == ds.getname(squared, fqn=True).split('.') + assert ds._namespace(ts.squared) == ds.getname(ts.squared, fqn=True).split('.') + assert ds._namespace(Bar) == ds.getname(Bar, fqn=True).split('.') + assert ds._namespace(ts.Bar) == ds.getname(ts.Bar, fqn=True).split('.') + assert ds._namespace(tm.quad) == ds.getname(tm.quad, fqn=True).split('.') + #XXX: the following also works, however behavior may be wrong for nested functions + #assert ds._namespace(tm.double_add) == ds.getname(tm.double_add, fqn=True).split('.') + #assert ds._namespace(tm.quadratic) == ds.getname(tm.quadratic, fqn=True).split('.') + assert ds.getname(add) == 'add' + assert ds.getname(ts.add) == 'add' + assert ds.getname(squared) == 'squared' + assert ds.getname(ts.squared) == 'squared' + assert ds.getname(Bar) == 'Bar' + assert ds.getname(ts.Bar) == 'Bar' + assert ds.getname(tm.quad) == 'quad' + assert ds.getname(tm.double_add) == 'func' #XXX: ? + assert ds.getname(tm.quadratic) == 'dec' #XXX: ? + + +def test_getimport(): + local = {} + exec(ds.getimport(add, alias='raw'), {}, local) + exec(ds.getimport(ts.add, alias='mod'), {}, local) + assert local['raw'](1,2) == local['mod'](1,2) + exec(ds.getimport(squared, alias='raw'), {}, local) + exec(ds.getimport(ts.squared, alias='mod'), {}, local) + assert local['raw'](3) == local['mod'](3) + exec(ds.getimport(Bar, alias='raw'), {}, local) + exec(ds.getimport(ts.Bar, alias='mod'), {}, local) + assert ds.getname(local['raw']) == ds.getname(local['mod']) + exec(ds.getimport(tm.quad, alias='mod'), {}, local) + assert local['mod']()(sum)([1,2,3]) == tm.quad()(sum)([1,2,3]) + #FIXME: wrong results for nested functions (e.g. tm.double_add, tm.quadratic) + + +def test_importable(): + assert ds.importable(add, source=False) == ds.getimport(add) + assert ds.importable(add) == ds.getsource(add) + assert ds.importable(squared, source=False) == ds.getimport(squared) + assert ds.importable(squared) == ds.getsource(squared) + assert ds.importable(Bar, source=False) == ds.getimport(Bar) + assert ds.importable(Bar) == ds.getsource(Bar) + assert ds.importable(ts.add) == ds.getimport(ts.add) + assert ds.importable(ts.add, source=True) == ds.getsource(ts.add) + assert ds.importable(ts.squared) == ds.getimport(ts.squared) + assert ds.importable(ts.squared, source=True) == ds.getsource(ts.squared) + assert ds.importable(ts.Bar) == ds.getimport(ts.Bar) + assert ds.importable(ts.Bar, source=True) == ds.getsource(ts.Bar) + + +if __name__ == '__main__': + test_isfrommain() + test_matchlambda() + test_findsource() + test_getsourcelines() + test_indent() + test_dumpsource() + test_name() + test_getimport() + test_importable() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dill-0.3.8/dill/tests/test_threads.py new/dill-0.3.9/dill/tests/test_threads.py --- old/dill-0.3.8/dill/tests/test_threads.py 1970-01-01 01:00:00.000000000 +0100 +++ new/dill-0.3.9/dill/tests/test_threads.py 2024-09-29 02:04:07.000000000 +0200 @@ -0,0 +1,46 @@ +#!/usr/bin/env python +# +# Author: Mike McKerns (mmckerns @caltech and @uqfoundation) +# Copyright (c) 2024 The Uncertainty Quantification Foundation. +# License: 3-clause BSD. The full license text is available at: +# - https://github.com/uqfoundation/dill/blob/master/LICENSE + +import dill +dill.settings['recurse'] = True + + +def test_new_thread(): + import threading + t = threading.Thread() + t_ = dill.copy(t) + assert t.is_alive() == t_.is_alive() + for i in ['daemon','name','ident','native_id']: + if hasattr(t, i): + assert getattr(t, i) == getattr(t_, i) + +def test_run_thread(): + import threading + t = threading.Thread() + t.start() + t_ = dill.copy(t) + assert t.is_alive() == t_.is_alive() + for i in ['daemon','name','ident','native_id']: + if hasattr(t, i): + assert getattr(t, i) == getattr(t_, i) + +def test_join_thread(): + import threading + t = threading.Thread() + t.start() + t.join() + t_ = dill.copy(t) + assert t.is_alive() == t_.is_alive() + for i in ['daemon','name','ident','native_id']: + if hasattr(t, i): + assert getattr(t, i) == getattr(t_, i) + + +if __name__ == '__main__': + test_new_thread() + test_run_thread() + test_join_thread() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dill-0.3.8/docs/requirements.txt new/dill-0.3.9/docs/requirements.txt --- old/dill-0.3.8/docs/requirements.txt 2024-01-28 00:44:53.000000000 +0100 +++ new/dill-0.3.9/docs/requirements.txt 2024-09-29 02:04:07.000000000 +0200 @@ -1,40 +1,56 @@ # Packages required to build docs # dependencies pinned as: -# https://github.com/readthedocs/readthedocs.org/blob/4dd655eaa5a36aa2cb9eed3e98961419536f99e8/requirements/docs.txt +# https://github.com/readthedocs/readthedocs.org/blob/d3606da9907bb4cd933abcf71c7bab9eb20435cd/requirements/docs.txt -alabaster==0.7.13 -babel==2.12.1 -certifi==2023.7.22 -charset-normalizer==3.2.0 -click==8.1.6 +alabaster==0.7.16 +anyio==4.4.0 +babel==2.15.0 +certifi==2024.7.4 +charset-normalizer==3.3.2 +click==8.1.7 colorama==0.4.6 -docutils==0.18.1 -idna==3.4 +docutils==0.20.1 +exceptiongroup==1.2.1 +h11==0.14.0 +idna==3.7 imagesize==1.4.1 -jinja2==3.1.3 -livereload==2.6.3 +jinja2==3.1.4 markdown-it-py==3.0.0 -markupsafe==2.1.3 -mdit-py-plugins==0.4.0 +markupsafe==2.1.5 +mdit-py-plugins==0.4.1 mdurl==0.1.2 -myst-parser==2.0.0 -packaging==23.1 -pygments==2.16.1 +myst-parser==3.0.1 +packaging==24.0 +pygments==2.18.0 pyyaml==6.0.1 readthedocs-sphinx-search==0.3.2 -requests==2.31.0 +requests==2.32.3 six==1.16.0 +sniffio==1.3.1 snowballstemmer==2.2.0 -sphinx==6.2.1 -sphinx-autobuild==2021.3.14 +sphinx==7.3.7 +sphinx-autobuild==2024.4.16 sphinx-copybutton==0.5.2 -sphinx-design==0.5.0 -sphinx-hoverxref==1.3.0 -sphinx-intl==2.1.0 +sphinx-design==0.6.0 +sphinx-hoverxref==1.4.0 +sphinx-intl==2.2.0 sphinx-multiproject==1.0.0rc1 -sphinx-notfound-page==0.8.3 -sphinx-prompt==1.6.0 -sphinx-rtd-theme==1.2.2 -sphinx-tabs==3.4.1 -tornado==6.3.3 -urllib3==2.0.7 +sphinx-notfound-page==1.0.2 +sphinx-prompt==1.8.0 +sphinx-rtd-theme==2.0.0rc2 +sphinx-tabs==3.4.5 +sphinxcontrib-applehelp==1.0.8 +sphinxcontrib-devhelp==1.0.6 +sphinxcontrib-htmlhelp==2.0.5 +sphinxcontrib-httpdomain==1.8.1 +sphinxcontrib-jquery==4.1 +sphinxcontrib-jsmath==1.0.1 +sphinxcontrib-qthelp==1.0.7 +sphinxcontrib-serializinghtml==1.1.10 +starlette==0.37.2 +tomli==2.0.1 +typing-extensions==4.12.1 +urllib3==2.2.2 +uvicorn==0.30.0 +watchfiles==0.22.0 +websockets==12.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dill-0.3.8/setup.cfg new/dill-0.3.9/setup.cfg --- old/dill-0.3.8/setup.cfg 2024-01-28 00:44:53.000000000 +0100 +++ new/dill-0.3.9/setup.cfg 2024-09-29 02:04:07.000000000 +0200 @@ -3,7 +3,7 @@ [bdist_wheel] #python-tag = py3 -#plat-name = manylinux_2_24_x86_64 +#plat-name = manylinux_2_28_x86_64 [sdist] #formats=zip,gztar diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dill-0.3.8/setup.py new/dill-0.3.9/setup.py --- old/dill-0.3.8/setup.py 2024-01-28 00:44:53.000000000 +0100 +++ new/dill-0.3.9/setup.py 2024-09-29 02:04:07.000000000 +0200 @@ -67,6 +67,7 @@ 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3.11', 'Programming Language :: Python :: 3.12', + 'Programming Language :: Python :: 3.13', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy', 'Topic :: Scientific/Engineering', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dill-0.3.8/version.py new/dill-0.3.9/version.py --- old/dill-0.3.8/version.py 2024-01-28 00:44:53.000000000 +0100 +++ new/dill-0.3.9/version.py 2024-09-29 02:04:07.000000000 +0200 @@ -5,7 +5,7 @@ # License: 3-clause BSD. The full license text is available at: # - https://github.com/uqfoundation/dill/blob/master/LICENSE -__version__ = '0.3.8'#.dev0' +__version__ = '0.3.9'#.dev0' __author__ = 'Mike McKerns' __contact__ = '[email protected]'
