diff options
author | Colin Watson <cjwatson@debian.org> | 2024-04-30 10:54:43 +0100 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2024-04-30 10:54:43 +0100 |
commit | feed4abac8c218ea828bb60e5595a5512294c271 (patch) | |
tree | e1c806ed3b8fdf272f11183f167b37063ab5a5ff | |
parent | 5ed72213c2a573c62dddb0dd4e99571b8cfc3c08 (diff) |
New upstream version 3.0.4+dfsg
38 files changed, 303 insertions, 494 deletions
@@ -7,6 +7,7 @@ /env* /htmlcov /tags +/pages /.pytest_cache /.tox /.idea diff --git a/CHANGES.rst b/CHANGES.rst index 5fdf89c..a9d69a1 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,13 @@ +v3.0.4 +====== + * Fixed an issue with django.SafeString and other classes inheriting from + str having read-only attribute errors (#478) (+481) + * The test suite was made compatible with `pytest-ruff>=0.3.0`. (+482) + * A `garden.yaml` file was added for use with the + `garden <https://crates.io/crates/garden-tools>_` command runner. (+486) + * The test suite was updated to avoid deprecated SQLALchemy APIs. + * The `jaraco.packaging.sphinx` documentation dependency was removed. + v3.0.3 ====== * Compatibilty with Pandas and Cython 3.0 was added. (#460) (+477) @@ -5,7 +15,8 @@ v3.0.3 could return a ``None`` module. (#447) * Fixed a bug where unpickling a missing class would return a different object instead of ``None``. (+471) - * Fixed the handling of missing classes when setting ``on_missing`` to ``warn`` or ``error``. (+471) + * Fixed the handling of missing classes when setting ``on_missing`` to ``warn`` + or ``error``. (+471) * The test suite was made compatible with Python 3.12. * The tox configuration was updated to generate code coverage reports. * The suite now uses ``ruff`` to validate python code. @@ -336,7 +347,7 @@ v0.7.1 ====== * Added support for Python 3.4. - * Added support for :class:`posix.stat_result`. + * Added support for `posix.stat_result`. v0.7.0 ====== @@ -365,7 +376,7 @@ v0.6.0 * Python 3 support! * :class:`time.struct_time` is now serialized using the built-in - :class:`jsonpickle.handlers.SimpleReduceHandler`. + `jsonpickle.handlers.SimpleReduceHandler`. v0.5.0 ====== @@ -35,7 +35,7 @@ JOB_COUNT := $(shell printf '%s' "$(JOB_FLAGS)" | sed -e 's/-j//') DASH_J := $(shell echo -- $(JOB_FLAGS) -j$(nproc) | grep -o -e '-j[0-9]\+' | head -n 1) NUM_JOBS := $(shell printf %s "$(DASH_J)" | sed -e 's/-j//') -TESTCMD ?= $(PYTEST) -p no:cacheprovier +TESTCMD ?= $(PYTEST) BENCHMARKCMD ?= $(BENCHMARK) TOXCMD ?= $(TOX) run-parallel --parallel-live ifdef V @@ -68,7 +68,7 @@ help:: .PHONY: help test:: - $(TESTCMD) $(flags) + $(TESTCMD) jsonpickle tests $(flags) .PHONY: test tox:: @@ -1,7 +1,7 @@ Metadata-Version: 2.1 Name: jsonpickle -Version: 3.0.3 -Summary: Python library for serializing any arbitrary object graph into JSON +Version: 3.0.4 +Summary: Serialize any Python object to JSON Home-page: https://github.com/jsonpickle/jsonpickle Author: David Aguilar Author-email: davvid@gmail.com @@ -18,162 +18,14 @@ Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 Classifier: Programming Language :: JavaScript Classifier: Operating System :: OS Independent Classifier: Topic :: Software Development :: Libraries :: Python Modules Requires-Python: >=3.7 Provides-Extra: docs +Provides-Extra: packaging Provides-Extra: testing License-File: LICENSE -.. image:: https://img.shields.io/pypi/v/jsonpickle.svg - :target: `PyPI link`_ - -.. image:: https://img.shields.io/pypi/pyversions/jsonpickle.svg - :target: `PyPI link`_ - -.. _PyPI link: https://pypi.org/project/jsonpickle - -.. image:: https://readthedocs.org/projects/jsonpickle/badge/?version=latest - :target: https://jsonpickle.readthedocs.io/en/latest/?badge=latest - -.. image:: https://github.com/jsonpickle/jsonpickle/actions/workflows/test.yml/badge.svg - :target: https://github.com/jsonpickle/jsonpickle/actions - :alt: Github Actions - -.. image:: https://img.shields.io/badge/License-BSD%203--Clause-blue.svg - :target: https://github.com/jsonpickle/jsonpickle/blob/main/COPYING - :alt: BSD - - -jsonpickle -========== -jsonpickle is a library for the two-way conversion of complex Python objects -and `JSON <http://json.org/>`_. jsonpickle builds upon the existing JSON -encoders, such as simplejson, json, and ujson. - -.. warning:: - - jsonpickle can execute arbitrary Python code. - - Please see the Security section for more details. - - -For complete documentation, please visit the -`jsonpickle documentation <http://jsonpickle.readthedocs.io/>`_. - -Bug reports and merge requests are encouraged at the -`jsonpickle repository on github <https://github.com/jsonpickle/jsonpickle>`_. - -Why jsonpickle? -=============== -Data serialized with python's pickle (or cPickle or dill) is not easily readable outside of python. Using the json format, jsonpickle allows simple data types to be stored in a human-readable format, and more complex data types such as numpy arrays and pandas dataframes, to be machine-readable on any platform that supports json. E.g., unlike pickled data, jsonpickled data stored in an Amazon S3 bucket is indexible by Amazon's Athena. - -Security -======== - -jsonpickle should be treated the same as the -`Python stdlib pickle module <https://docs.python.org/3/library/pickle.html>`_ -from a security perspective. - -.. warning:: - - The jsonpickle module **is not secure**. Only unpickle data you trust. - - It is possible to construct malicious pickle data which will **execute - arbitrary code during unpickling**. Never unpickle data that could have come - from an untrusted source, or that could have been tampered with. - - Consider signing data with an HMAC if you need to ensure that it has not - been tampered with. - - Safer deserialization approaches, such as reading JSON directly, - may be more appropriate if you are processing untrusted data. - - -Install -======= - -Install from pip for the latest stable release: - -:: - - pip install jsonpickle - -Install from github for the latest changes: - -:: - - pip install git+https://github.com/jsonpickle/jsonpickle.git - -If you have the files checked out for development: - -:: - - git clone https://github.com/jsonpickle/jsonpickle.git - cd jsonpickle - python setup.py develop - - -Numpy Support -============= -jsonpickle includes a built-in numpy extension. If would like to encode -sklearn models, numpy arrays, and other numpy-based data then you must -enable the numpy extension by registering its handlers:: - - >>> import jsonpickle.ext.numpy as jsonpickle_numpy - >>> jsonpickle_numpy.register_handlers() - -Pandas Support -============== -jsonpickle includes a built-in pandas extension. If would like to encode -pandas DataFrame or Series objects then you must enable the pandas extension -by registering its handlers:: - - >>> import jsonpickle.ext.pandas as jsonpickle_pandas - >>> jsonpickle_pandas.register_handlers() - -Development -=========== - -Use `make` to run the unit tests:: - - make test - -`pytest` is used to run unit tests internally. - -A `tox` target is provided to run tests using all installed and supported Python versions:: - - make tox - -`jsonpickle` itself has no dependencies beyond the Python stdlib. -`tox` is required for testing when using the `tox` test runner only. - -The testing requirements are specified in `requirements-dev.txt`. -It is recommended to create a virtualenv and run tests from within the -virtualenv, or use a tool such as `vx <https://github.com/davvid/vx/>`_ -to activate the virtualenv without polluting the shell environment:: - - python3 -mvenv env3x - vx env3x pip install --requirement requirements-dev.txt - vx env3x make test - -`jsonpickle` supports multiple Python versions, so using a combination of -multiple virtualenvs and `tox` is useful in order to catch compatibility -issues when developing. - -GPG Signing -=========== -Releases before v3.0.0 are signed with `davvid's key <https://keys.openpgp.org/vks/v1/by-fingerprint/FA41BF59C1B48E8C5F3DA61C8CE26BF4A9F606B0>`_. v3.0.0 and after are likely signed by `Theelx's key <https://github.com/Theelx.gpg>`_. All upcoming releases should be signed by one of these two keys, usually Theelx's key. - -jsonpickleJS -============ -`jsonpickleJS <https://github.com/cuthbertLab/jsonpickleJS>`_ -is a javascript implementation of jsonpickle by Michael Scott Cuthbert. -jsonpickleJS can be extremely useful for projects that have parallel data -structures between Python and Javascript. - -License -======= -Licensed under the BSD License. See COPYING for details. -See jsonpickleJS/LICENSE for details about the jsonpickleJS license. +Python library for serializing arbitrary object graphs into JSON @@ -21,7 +21,7 @@ jsonpickle ========== jsonpickle is a library for the two-way conversion of complex Python objects -and `JSON <http://json.org/>`_. jsonpickle builds upon the existing JSON +and `JSON <http://json.org/>`_. jsonpickle builds upon existing JSON encoders, such as simplejson, json, and ujson. .. warning:: @@ -78,31 +78,17 @@ Install from github for the latest changes: pip install git+https://github.com/jsonpickle/jsonpickle.git -If you have the files checked out for development: -:: - - git clone https://github.com/jsonpickle/jsonpickle.git - cd jsonpickle - python setup.py develop - - -Numpy Support +Numpy/Pandas Support ============= -jsonpickle includes a built-in numpy extension. If would like to encode -sklearn models, numpy arrays, and other numpy-based data then you must -enable the numpy extension by registering its handlers:: +jsonpickle includes built-in numpy and pandas extensions. If you would +like to encode sklearn models, numpy arrays, pandas DataFrames, and other +numpy/pandas-based data, then you must enable the numpy and/or pandas +extensions by registering their handlers:: >>> import jsonpickle.ext.numpy as jsonpickle_numpy - >>> jsonpickle_numpy.register_handlers() - -Pandas Support -============== -jsonpickle includes a built-in pandas extension. If would like to encode -pandas DataFrame or Series objects then you must enable the pandas extension -by registering its handlers:: - >>> import jsonpickle.ext.pandas as jsonpickle_pandas + >>> jsonpickle_numpy.register_handlers() >>> jsonpickle_pandas.register_handlers() Development @@ -136,16 +122,8 @@ issues when developing. GPG Signing =========== -Releases before v3.0.0 are signed with `davvid's key <https://keys.openpgp.org/vks/v1/by-fingerprint/FA41BF59C1B48E8C5F3DA61C8CE26BF4A9F606B0>`_. v3.0.0 and after are likely signed by `Theelx's key <https://github.com/Theelx.gpg>`_. All upcoming releases should be signed by one of these two keys, usually Theelx's key. - -jsonpickleJS -============ -`jsonpickleJS <https://github.com/cuthbertLab/jsonpickleJS>`_ -is a javascript implementation of jsonpickle by Michael Scott Cuthbert. -jsonpickleJS can be extremely useful for projects that have parallel data -structures between Python and Javascript. +Unfortunately, while versions of jsonpickle before 3.0.1 should still be signed, GPG signing support was removed from PyPi (https://blog.pypi.org/posts/2023-05-23-removing-pgp/) back in May 2023. License ======= Licensed under the BSD License. See COPYING for details. -See jsonpickleJS/LICENSE for details about the jsonpickleJS license. diff --git a/contrib/pyqt-reduce-handler.py b/contrib/pyqt-reduce-handler.py index 287505b..387380d 100644 --- a/contrib/pyqt-reduce-handler.py +++ b/contrib/pyqt-reduce-handler.py @@ -1,13 +1,13 @@ """ This example demonstrates how to add a custom handler to serialize -Qt's QPointF class jsonpickle using PyQt4. +Qt's QPointF class jsonpickle using qtpy. """ import sys import unittest -from PyQt4 import QtCore +from qtpy import QtCore import jsonpickle from jsonpickle import handlers diff --git a/docs/conf.py b/docs/conf.py index ccd44a7..a82ded7 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -6,10 +6,6 @@ try: except ImportError: furo = None try: - import jaraco.packaging.sphinx as jaraco_packaging_sphinx -except ImportError: - jaraco_packaging_sphinx = None -try: import rst.linker as rst_linker except ImportError: rst_linker = None @@ -23,9 +19,8 @@ extensions = [ 'sphinx.ext.todo', 'sphinx.ext.coverage', ] -if jaraco_packaging_sphinx is not None: - extensions += ['jaraco.packaging.sphinx'] +project = 'jsonpickle' master_doc = 'index' if furo is not None: @@ -34,17 +29,19 @@ if furo is not None: # Link dates and other references in the changelog if rst_linker is not None: extensions += ['rst.linker'] + +package_url = 'https://github.com/jsonpickle/jsonpickle' link_files = { '../CHANGES.rst': dict( using=dict(GH='https://github.com'), replace=[ dict( pattern=r'(Issue #|\B#)(?P<issue>\d+)', - url='{package_url}/issues/{issue}', + url=package_url + '/issues/{issue}', ), dict( pattern=r'\B\+(?P<pull>\d+)', - url='{package_url}/pull/{pull}', + url=package_url + '/pull/{pull}', ), dict( pattern=r'(?m:^((?P<scm_version>v?\d+(\.\d+){1,2}))\n[-=]+\n)', diff --git a/garden.yaml b/garden.yaml new file mode 100644 index 0000000..0e6707f --- /dev/null +++ b/garden.yaml @@ -0,0 +1,61 @@ +# Use "cargo install garden-tools" to install garden https://gitlab.com/garden-rs/garden +# +# # Usage +# garden doc # Build the jsonpickle.github.io documentation +# garden fmt # Apply code formatting +# garden test # Run tests +# garden tox # Run tests using "tox" +# garden bench # Run benchmarks +trees: + jsonpickle: + description: Two-way conversion of complex Python objects into JSON. + path: ${GARDEN_CONFIG_DIR} + url: git@github.com:jsonpickle/jsonpickle.git + remotes: + Theelx: git@github.com:Theelx/jsonpickle.git + davvid: git@github.com:davvid/jsonpickle.git + commands: + bench: | + python3 -m pytest \ + --benchmark-verbose \ + --benchmark-only \ + --benchmark-histogram=./images/benchmark-${timestamp} \ + ./jsonpickle_benchmarks.py + check>: + - test + - check/fmt + - doc + check/fmt: garden ${GARDEN_CMD_VERBOSE} fmt -- --check + clean: | + rm -fr build dist jsonpickle.egg-info + find . -type d -name __pycache__ -print0 | xargs -0 rm -fr + doc: | + test -d pages || garden grow pages + ${activate} python3 -m sphinx docs pages + fmt: | + ${activate} + black --skip-string-normalization --target-version py37 "$@" jsonpickle tests + isort --profile=black "$@" jsonpickle tests + setup: | + python3 -m venv env3 + garden ${GARDEN_CMD_VERBOSE} setup/dev + setup/dev: ${activate} pip install --editable '.[dev,docs]' + setup/packaging: ${activate} pip install --editable '.[packaging]' + test: ${activate} python3 -m pytest ${GARDEN_CMD_VERBOSE} "$@" jsonpickle tests + tox: tox run-parallel --parallel-live "$@" ${GARDEN_CMD_VERBOSE} + wheel: | + ${activate} + python3 -m build -n . + publish: | + ${activate} + twine upload dist/*.whl dist/*.tar.gz + pages: + description: The jsonpickle.github.io website. + url: git@github.com:jsonpickle/jsonpickle.github.io.git + +variables: + activate: | + test -n "$VIRTUAL_ENV" || + test ! -d env3 || + source env3/bin/activate + timestamp: $ date +%Y-%m-%dT%T%z diff --git a/jsonpickle.egg-info/PKG-INFO b/jsonpickle.egg-info/PKG-INFO index cfaca35..bed22d5 100644 --- a/jsonpickle.egg-info/PKG-INFO +++ b/jsonpickle.egg-info/PKG-INFO @@ -1,7 +1,7 @@ Metadata-Version: 2.1 Name: jsonpickle -Version: 3.0.3 -Summary: Python library for serializing any arbitrary object graph into JSON +Version: 3.0.4 +Summary: Serialize any Python object to JSON Home-page: https://github.com/jsonpickle/jsonpickle Author: David Aguilar Author-email: davvid@gmail.com @@ -18,162 +18,14 @@ Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 Classifier: Programming Language :: JavaScript Classifier: Operating System :: OS Independent Classifier: Topic :: Software Development :: Libraries :: Python Modules Requires-Python: >=3.7 Provides-Extra: docs +Provides-Extra: packaging Provides-Extra: testing License-File: LICENSE -.. image:: https://img.shields.io/pypi/v/jsonpickle.svg - :target: `PyPI link`_ - -.. image:: https://img.shields.io/pypi/pyversions/jsonpickle.svg - :target: `PyPI link`_ - -.. _PyPI link: https://pypi.org/project/jsonpickle - -.. image:: https://readthedocs.org/projects/jsonpickle/badge/?version=latest - :target: https://jsonpickle.readthedocs.io/en/latest/?badge=latest - -.. image:: https://github.com/jsonpickle/jsonpickle/actions/workflows/test.yml/badge.svg - :target: https://github.com/jsonpickle/jsonpickle/actions - :alt: Github Actions - -.. image:: https://img.shields.io/badge/License-BSD%203--Clause-blue.svg - :target: https://github.com/jsonpickle/jsonpickle/blob/main/COPYING - :alt: BSD - - -jsonpickle -========== -jsonpickle is a library for the two-way conversion of complex Python objects -and `JSON <http://json.org/>`_. jsonpickle builds upon the existing JSON -encoders, such as simplejson, json, and ujson. - -.. warning:: - - jsonpickle can execute arbitrary Python code. - - Please see the Security section for more details. - - -For complete documentation, please visit the -`jsonpickle documentation <http://jsonpickle.readthedocs.io/>`_. - -Bug reports and merge requests are encouraged at the -`jsonpickle repository on github <https://github.com/jsonpickle/jsonpickle>`_. - -Why jsonpickle? -=============== -Data serialized with python's pickle (or cPickle or dill) is not easily readable outside of python. Using the json format, jsonpickle allows simple data types to be stored in a human-readable format, and more complex data types such as numpy arrays and pandas dataframes, to be machine-readable on any platform that supports json. E.g., unlike pickled data, jsonpickled data stored in an Amazon S3 bucket is indexible by Amazon's Athena. - -Security -======== - -jsonpickle should be treated the same as the -`Python stdlib pickle module <https://docs.python.org/3/library/pickle.html>`_ -from a security perspective. - -.. warning:: - - The jsonpickle module **is not secure**. Only unpickle data you trust. - - It is possible to construct malicious pickle data which will **execute - arbitrary code during unpickling**. Never unpickle data that could have come - from an untrusted source, or that could have been tampered with. - - Consider signing data with an HMAC if you need to ensure that it has not - been tampered with. - - Safer deserialization approaches, such as reading JSON directly, - may be more appropriate if you are processing untrusted data. - - -Install -======= - -Install from pip for the latest stable release: - -:: - - pip install jsonpickle - -Install from github for the latest changes: - -:: - - pip install git+https://github.com/jsonpickle/jsonpickle.git - -If you have the files checked out for development: - -:: - - git clone https://github.com/jsonpickle/jsonpickle.git - cd jsonpickle - python setup.py develop - - -Numpy Support -============= -jsonpickle includes a built-in numpy extension. If would like to encode -sklearn models, numpy arrays, and other numpy-based data then you must -enable the numpy extension by registering its handlers:: - - >>> import jsonpickle.ext.numpy as jsonpickle_numpy - >>> jsonpickle_numpy.register_handlers() - -Pandas Support -============== -jsonpickle includes a built-in pandas extension. If would like to encode -pandas DataFrame or Series objects then you must enable the pandas extension -by registering its handlers:: - - >>> import jsonpickle.ext.pandas as jsonpickle_pandas - >>> jsonpickle_pandas.register_handlers() - -Development -=========== - -Use `make` to run the unit tests:: - - make test - -`pytest` is used to run unit tests internally. - -A `tox` target is provided to run tests using all installed and supported Python versions:: - - make tox - -`jsonpickle` itself has no dependencies beyond the Python stdlib. -`tox` is required for testing when using the `tox` test runner only. - -The testing requirements are specified in `requirements-dev.txt`. -It is recommended to create a virtualenv and run tests from within the -virtualenv, or use a tool such as `vx <https://github.com/davvid/vx/>`_ -to activate the virtualenv without polluting the shell environment:: - - python3 -mvenv env3x - vx env3x pip install --requirement requirements-dev.txt - vx env3x make test - -`jsonpickle` supports multiple Python versions, so using a combination of -multiple virtualenvs and `tox` is useful in order to catch compatibility -issues when developing. - -GPG Signing -=========== -Releases before v3.0.0 are signed with `davvid's key <https://keys.openpgp.org/vks/v1/by-fingerprint/FA41BF59C1B48E8C5F3DA61C8CE26BF4A9F606B0>`_. v3.0.0 and after are likely signed by `Theelx's key <https://github.com/Theelx.gpg>`_. All upcoming releases should be signed by one of these two keys, usually Theelx's key. - -jsonpickleJS -============ -`jsonpickleJS <https://github.com/cuthbertLab/jsonpickleJS>`_ -is a javascript implementation of jsonpickle by Michael Scott Cuthbert. -jsonpickleJS can be extremely useful for projects that have parallel data -structures between Python and Javascript. - -License -======= -Licensed under the BSD License. See COPYING for details. -See jsonpickleJS/LICENSE for details about the jsonpickleJS license. +Python library for serializing arbitrary object graphs into JSON diff --git a/jsonpickle.egg-info/SOURCES.txt b/jsonpickle.egg-info/SOURCES.txt index 670e895..74d0613 100644 --- a/jsonpickle.egg-info/SOURCES.txt +++ b/jsonpickle.egg-info/SOURCES.txt @@ -11,12 +11,11 @@ README.rst appveyor.yml azure-pipelines.yml conftest.py +garden.yaml jsonpickle_benchmarks.py pyproject.toml pytest.ini -requirements-dev.txt setup.cfg -setup.py skeleton.md tox.ini .github/FUNDING.yml diff --git a/jsonpickle.egg-info/requires.txt b/jsonpickle.egg-info/requires.txt index 8e94eb9..be11eb1 100644 --- a/jsonpickle.egg-info/requires.txt +++ b/jsonpickle.egg-info/requires.txt @@ -4,21 +4,27 @@ importlib_metadata [docs] furo -jaraco.packaging>=9 rst.linker>=1.9 sphinx +[packaging] +build +twine + [testing] +bson ecdsa feedparser numpy pandas pymongo pytest!=3.7.3,>=3.5 +pytest-benchmark +pytest-benchmark[histogram] pytest-checkdocs>=1.2.3 pytest-cov pytest-enabler>=1.0.1 -pytest-ruff +pytest-ruff>=0.2.1 scikit-learn simplejson sqlalchemy @@ -26,3 +32,9 @@ ujson [testing:python_version < "3.12"] gmpy2 + +[testing:python_version <= "3.10"] +scipy + +[testing:python_version > "3.10"] +scipy>=1.9.3 diff --git a/jsonpickle/__init__.py b/jsonpickle/__init__.py index a41f7ac..54af6b5 100644 --- a/jsonpickle/__init__.py +++ b/jsonpickle/__init__.py @@ -67,8 +67,6 @@ added to JSON:: that contain non-string dictionary keys. """ -from __future__ import absolute_import, division, unicode_literals - # Export other names not in __all__ from .backend import JSONBackend # noqa: F401 from .backend import json diff --git a/jsonpickle/backend.py b/jsonpickle/backend.py index 1faa13f..2e9ebb9 100644 --- a/jsonpickle/backend.py +++ b/jsonpickle/backend.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import, division, unicode_literals - from .compat import string_types diff --git a/jsonpickle/compat.py b/jsonpickle/compat.py index 320c64d..e971aeb 100644 --- a/jsonpickle/compat.py +++ b/jsonpickle/compat.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import, division, unicode_literals - import queue # noqa import sys from collections.abc import Iterator as abc_iterator # noqa diff --git a/jsonpickle/ext/numpy.py b/jsonpickle/ext/numpy.py index af2bf71..fd321d3 100644 --- a/jsonpickle/ext/numpy.py +++ b/jsonpickle/ext/numpy.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import ast import json import sys diff --git a/jsonpickle/ext/pandas.py b/jsonpickle/ext/pandas.py index c49b86b..475b77e 100644 --- a/jsonpickle/ext/pandas.py +++ b/jsonpickle/ext/pandas.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import zlib from io import StringIO diff --git a/jsonpickle/handlers.py b/jsonpickle/handlers.py index 6a5162a..2109f6b 100644 --- a/jsonpickle/handlers.py +++ b/jsonpickle/handlers.py @@ -8,8 +8,6 @@ A handler can be bound to other types by calling """ -from __future__ import absolute_import, division, unicode_literals - import array import copy import datetime diff --git a/jsonpickle/pickler.py b/jsonpickle/pickler.py index 7b37e57..d95f792 100644 --- a/jsonpickle/pickler.py +++ b/jsonpickle/pickler.py @@ -1,11 +1,9 @@ # Copyright (C) 2008 John Paulett (john -at- paulett.org) -# Copyright (C) 2009-2018 David Aguilar (davvid -at- gmail.com) +# Copyright (C) 2009-2024 David Aguilar (davvid -at- gmail.com) # All rights reserved. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. -from __future__ import absolute_import, division, unicode_literals - import decimal import inspect import itertools @@ -36,6 +34,7 @@ def encode( indent=None, separators=None, include_properties=False, + handle_readonly=False, ): """Return a JSON formatted representation of value, a Python object. @@ -54,10 +53,6 @@ def encode( ) before your pickling code. - :param max_depth: If set to a non-negative integer then jsonpickle will - not recurse deeper than 'max_depth' steps into the object. Anything - deeper than 'max_depth' is represented using a Python repr() of the - object. :param make_refs: If set to False jsonpickle's referencing support is disabled. Objects that are id()-identical won't be preserved across encode()/decode(), but the resulting JSON stream will be conceptually @@ -67,15 +62,25 @@ def encode( dictionary keys instead of coercing them into strings via `repr()`. This is typically what you want if you need to support Integer or objects as dictionary keys. - :param numeric_keys: Only use this option if the backend supports integer - dict keys natively. This flag tells jsonpickle to leave numeric keys - as-is rather than conforming them to json-friendly strings. - Using ``keys=True`` is the typical solution for integer keys, so only - use this if you have a specific use case where you want to allow the - backend to handle serialization of numeric dict keys. + :param max_depth: If set to a non-negative integer then jsonpickle will + not recurse deeper than 'max_depth' steps into the object. Anything + deeper than 'max_depth' is represented using a Python repr() of the + object. + :param reset: Custom pickle handlers that use the `Pickler.flatten` method or + `jsonpickle.encode` function must call `encode` with `reset=False` + in order to retain object references during pickling. + This flag is not typically used outside of a custom handler or + `__getstate__` implementation. + :param backend: If set to an instance of jsonpickle.backend.JSONBackend, + jsonpickle will use that backend for deserialization. :param warn: If set to True then jsonpickle will warn when it returns None for an object which it cannot pickle (e.g. file descriptors). + :param context: Supply a pre-built Pickler or Unpickler object to the + `jsonpickle.encode` and `jsonpickle.decode` machinery instead + of creating a new instance. The `context` represents the currently + active Pickler and Unpickler objects when custom handlers are + invoked by jsonpickle. :param max_iter: If set to a non-negative integer then jsonpickle will consume at most `max_iter` items when pickling iterators. :param use_decimal: If set to True jsonpickle will allow Decimal @@ -91,6 +96,12 @@ def encode( NOTE: A side-effect of the above settings is that float values will be converted to Decimal when converting to json. + :param numeric_keys: Only use this option if the backend supports integer + dict keys natively. This flag tells jsonpickle to leave numeric keys + as-is rather than conforming them to json-friendly strings. + Using ``keys=True`` is the typical solution for integer keys, so only + use this if you have a specific use case where you want to allow the + backend to handle serialization of numeric dict keys. :param use_base85: If possible, use base85 to encode binary data. Base85 bloats binary data by 1/4 as opposed to base64, which expands it by 1/3. This argument is @@ -118,6 +129,11 @@ def encode( meant to be used if processing the json outside of Python. Certain types such as sets will not pickle due to not having a native-json equivalent. Defaults to ``False``. + :param handle_readonly: + Handle objects with readonly methods, such as Django's SafeString. This + basically prevents jsonpickle from raising an exception for such objects. + You MUST set ``handle_readonly=True`` for the decoding if you encode with + this flag set to ``True``. >>> encode('my string') == '"my string"' True @@ -143,6 +159,8 @@ def encode( use_base85=use_base85, fail_safe=fail_safe, include_properties=include_properties, + handle_readonly=handle_readonly, + original_object=value, ) return backend.encode( context.flatten(value, reset=reset), indent=indent, separators=separators @@ -190,6 +208,8 @@ class Pickler(object): use_base85=False, fail_safe=None, include_properties=False, + handle_readonly=False, + original_object=None, ): self.unpicklable = unpicklable self.make_refs = make_refs @@ -212,6 +232,8 @@ class Pickler(object): self._use_decimal = use_decimal # A cache of objects that have already been flattened. self._flattened = {} + # Used for util.is_readonly, see +483 + self.handle_readonly = handle_readonly if self.use_base85: self._bytes_tag = tags.B85 @@ -224,6 +246,8 @@ class Pickler(object): self.fail_safe = fail_safe self.include_properties = include_properties + self._original_object = original_object + def _determine_sort_keys(self): for _, options in getattr(self.backend, '_encoder_options', {}).values(): if options.get("sort_keys", False): @@ -293,9 +317,11 @@ class Pickler(object): return pretend_new or is_new def _getref(self, obj): + """Return a "py/id" entry for the specified object""" return {tags.ID: self._objs.get(id(obj))} def _flatten(self, obj): + """Flatten an object and its guts into a json-safe representation""" if self.unpicklable and self.make_refs: result = self._flatten_impl(obj) else: @@ -417,6 +443,13 @@ class Pickler(object): """Flatten a key/value pair into the passed-in dictionary.""" if not util.is_picklable(k, v): return data + # TODO: use inspect.getmembers_static on 3.11+ because it avoids dynamic attribute lookups + if ( + self.handle_readonly + and k in {attr for attr, val in inspect.getmembers(self._original_object)} + and util.is_readonly(self._original_object, k, v) + ): + return data if k is None: k = 'null' # for compatibility with common json encoders @@ -458,7 +491,7 @@ class Pickler(object): # i don't like lambdas def valid_property(x): - return not x[0].startswith("__") and x[0] not in allslots_set + return not x[0].startswith('__') and x[0] not in allslots_set properties = [ x[0] for x in inspect.getmembers(obj.__class__) if valid_property(x) @@ -611,7 +644,9 @@ class Pickler(object): data[tags.OBJECT] = class_name if has_getnewargs_ex: - data[tags.NEWARGSEX] = list(map(self._flatten, obj.__getnewargs_ex__())) + data[tags.NEWARGSEX] = [ + self._flatten(arg) for arg in obj.__getnewargs_ex__() + ] if has_getnewargs and not has_getnewargs_ex: data[tags.NEWARGS] = self._flatten(obj.__getnewargs__()) diff --git a/jsonpickle/tags.py b/jsonpickle/tags.py index 62c80a2..9f2bb22 100644 --- a/jsonpickle/tags.py +++ b/jsonpickle/tags.py @@ -7,8 +7,6 @@ these custom key names to identify dictionaries that need to be specially handled. """ -from __future__ import absolute_import, division, unicode_literals - BYTES = 'py/bytes' B64 = 'py/b64' B85 = 'py/b85' diff --git a/jsonpickle/unpickler.py b/jsonpickle/unpickler.py index 21afb07..ec1e9dc 100644 --- a/jsonpickle/unpickler.py +++ b/jsonpickle/unpickler.py @@ -1,11 +1,9 @@ # Copyright (C) 2008 John Paulett (john -at- paulett.org) -# Copyright (C) 2009-2018 David Aguilar (davvid -at- gmail.com) +# Copyright (C) 2009-2024 David Aguilar (davvid -at- gmail.com) # All rights reserved. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. -from __future__ import absolute_import, division, unicode_literals - import dataclasses import sys import warnings @@ -25,42 +23,53 @@ def decode( classes=None, v1_decode=False, on_missing="ignore", + handle_readonly=False, ): """Convert a JSON string into a Python object. - The keyword argument 'keys' defaults to False. - If set to True then jsonpickle will decode non-string dictionary keys - into python objects via the jsonpickle protocol. - - The keyword argument 'classes' defaults to None. - If set to a single class, or a sequence (list, set, tuple) of classes, - then the classes will be made available when constructing objects. - If set to a dictionary of class names to class objects, the class object - will be provided to jsonpickle to deserialize the class name into. - This can be used to give jsonpickle access to local classes that are not - available through the global module import scope, and the dict method can - be used to deserialize encoded objects into a new class. - - The keyword argument 'safe' defaults to False. - If set to True, eval() is avoided, but backwards-compatible - (pre-0.7.0) deserialization of repr-serialized objects is disabled. - - The keyword argument 'backend' defaults to None. - If set to an instance of jsonpickle.backend.JSONBackend, jsonpickle - will use that backend for deserialization. - - The keyword argument 'v1_decode' defaults to False. - If set to True it enables you to decode objects serialized in jsonpickle v1. - Please do not attempt to re-encode the objects in the v1 format! Version 2's - format fixes issue #255, and allows dictionary identity to be preserved - through an encode/decode cycle. - - The keyword argument 'on_missing' defaults to 'ignore'. - If set to 'error', it will raise an error if the class it's decoding is not - found. If set to 'warn', it will warn you in said case. If set to a - non-awaitable function, it will call said callback function with the class - name (a string) as the only parameter. Strings passed to on_missing are - lowercased automatically. + :param backend: If set to an instance of jsonpickle.backend.JSONBackend, jsonpickle + will use that backend for deserialization. + + :param context: Supply a pre-built Pickler or Unpickler object to the + `jsonpickle.encode` and `jsonpickle.decode` machinery instead + of creating a new instance. The `context` represents the currently + active Pickler and Unpickler objects when custom handlers are + invoked by jsonpickle. + + :param keys: If set to True then jsonpickle will decode non-string dictionary keys + into python objects via the jsonpickle protocol. + + :param reset: Custom pickle handlers that use the `Pickler.flatten` method or + `jsonpickle.encode` function must call `encode` with `reset=False` + in order to retain object references during pickling. + This flag is not typically used outside of a custom handler or + `__getstate__` implementation. + + :param safe: If set to True, eval() is avoided, but backwards-compatible + (pre-0.7.0) deserialization of repr-serialized objects is disabled. + + :param classes: If set to a single class, or a sequence (list, set, tuple) of classes, + then the classes will be made available when constructing objects. + If set to a dictionary of class names to class objects, the class object + will be provided to jsonpickle to deserialize the class name into. + This can be used to give jsonpickle access to local classes that are not + available through the global module import scope, and the dict method can + be used to deserialize encoded objects into a new class. + + :param v1_decode: If set to True it enables you to decode objects serialized in jsonpickle v1. + Please do not attempt to re-encode the objects in the v1 format! Version 2's + format fixes issue #255, and allows dictionary identity to be preserved + through an encode/decode cycle. + + :param on_missing: If set to 'error', it will raise an error if the class it's decoding is not + found. If set to 'warn', it will warn you in said case. If set to a + non-awaitable function, it will call said callback function with the class + name (a string) as the only parameter. Strings passed to on_missing are + lowercased automatically. + + :param handle_readonly: If set to True, the Unpickler will handle objects encoded with + 'handle_readonly' properly. Do not set this flag for objects not encoded + with 'handle_readonly' set to True. >>> decode('"my string"') == 'my string' @@ -83,6 +92,7 @@ def decode( safe=safe, v1_decode=v1_decode, on_missing=on_missing, + handle_readonly=handle_readonly, ) data = backend.decode(string) return context.restore(data, reset=reset, classes=classes) @@ -151,10 +161,12 @@ class _IDProxy(_Proxy): def _obj_setattr(obj, attr, proxy): + """Use setattr to update a proxy entry""" setattr(obj, attr, proxy.get()) def _obj_setvalue(obj, idx, proxy): + """Use obj[key] assignments to update a proxy entry""" obj[idx] = proxy.get() @@ -296,13 +308,20 @@ def has_tag_dict(obj, tag): class Unpickler(object): def __init__( - self, backend=None, keys=False, safe=False, v1_decode=False, on_missing="ignore" + self, + backend=None, + keys=False, + safe=False, + v1_decode=False, + on_missing='ignore', + handle_readonly=False, ): self.backend = backend or json self.keys = keys self.safe = safe self.v1_decode = v1_decode self.on_missing = on_missing + self.handle_readonly = handle_readonly self.reset() @@ -409,7 +428,7 @@ class Unpickler(object): def _mkref(self, obj): obj_id = id(obj) try: - self._obj_to_idx[obj_id] + _ = self._obj_to_idx[obj_id] except KeyError: self._obj_to_idx[obj_id] = len(self._objs) self._objs.append(obj) @@ -626,11 +645,14 @@ class Unpickler(object): # i think this is the only way to set frozen dataclass attrs object.__setattr__(instance, k, value) except AttributeError as e: - # some objects may raise this for read-only attributes (#422) + # some objects may raise this for read-only attributes (#422) (#478) if ( hasattr(instance, "__slots__") and not len(instance.__slots__) and issubclass(instance.__class__, int) + and self.handle_readonly + # we have to handle this separately because of +483 + and issubclass(instance.__class__, str) ): continue raise e @@ -697,7 +719,7 @@ class Unpickler(object): return instance - def _restore_object_instance(self, obj, cls, class_name=""): + def _restore_object_instance(self, obj, cls, class_name=''): # This is a placeholder proxy object which allows child objects to # reference the parent object before it has been instantiated. proxy = _Proxy() @@ -719,7 +741,7 @@ class Unpickler(object): is_oldstyle = not (isinstance(cls, type) or getattr(cls, '__meta__', None)) try: - if (not is_oldstyle) and hasattr(cls, '__new__'): + if not is_oldstyle and hasattr(cls, '__new__'): # new style classes if factory: instance = cls.__new__(cls, factory, *args, **kwargs) @@ -832,6 +854,7 @@ class Unpickler(object): return tuple([self._restore(v) for v in obj[tags.TUPLE]]) def _restore_tags(self, obj): + """Return the restoration function for the specified object""" try: if not tags.RESERVED <= set(obj) and type(obj) not in (list, dict): diff --git a/jsonpickle/util.py b/jsonpickle/util.py index eadbcc1..6b3f551 100644 --- a/jsonpickle/util.py +++ b/jsonpickle/util.py @@ -8,8 +8,6 @@ """Helper functions for pickling and unpickling. Most functions assist in determining the type of an object. """ -from __future__ import absolute_import, division, unicode_literals - import base64 import collections import inspect @@ -397,6 +395,20 @@ def is_cython_function(obj): ) +def is_readonly(obj, attr, value): + # CPython 3.11+ has 0-cost try/except, please use up-to-date versions! + try: + setattr(obj, attr, value) + return False + except AttributeError: + # this is okay, it means the attribute couldn't be set + return True + except TypeError: + # this should only be happening when obj is a dict + # as these errors happen when attr isn't a str + return True + + def in_dict(obj, key, default=False): """ Returns true if key exists in obj.__dict__; false if not in. diff --git a/requirements-dev.txt b/requirements-dev.txt deleted file mode 100644 index bac9bad..0000000 --- a/requirements-dev.txt +++ /dev/null @@ -1,20 +0,0 @@ -bson -coverage -ecdsa -feedparser -gmpy2; python_version<"3.12" -numpy -pandas -pymongo -pytest -pytest-cov -pytest-enabler -pytest-benchmark -pytest-benchmark[histogram] -pytest-ruff -scikit-learn -scipy>=1.9.3; python_version>"3.10" -scipy; python_version<="3.10" -simplejson -sqlalchemy>=1.2.19 -ujson @@ -3,8 +3,8 @@ license_file = LICENSE name = jsonpickle author = David Aguilar author_email = davvid@gmail.com -description = Python library for serializing any arbitrary object graph into JSON -long_description = file:README.rst +description = Serialize any Python object to JSON +long_description = Python library for serializing arbitrary object graphs into JSON url = https://github.com/jsonpickle/jsonpickle classifiers = Development Status :: 5 - Production/Stable @@ -17,6 +17,7 @@ classifiers = Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 + Programming Language :: Python :: 3.12 Programming Language :: JavaScript Operating System :: OS Independent Topic :: Software Development :: Libraries :: Python Modules @@ -45,25 +46,30 @@ testing = pytest-checkdocs >= 1.2.3 pytest-cov pytest-enabler >= 1.0.1 - pytest-ruff + pytest-ruff >= 0.2.1 + bson ecdsa feedparser gmpy2; python_version<"3.12" numpy pandas pymongo + pytest-benchmark + pytest-benchmark[histogram] scikit-learn + scipy>=1.9.3; python_version>"3.10" + scipy; python_version<="3.10" simplejson sqlalchemy ujson docs = sphinx - jaraco.packaging >= 9 rst.linker >= 1.9 furo - -[options.entry_points] +packaging = + build + twine [egg_info] tag_build = diff --git a/setup.py b/setup.py deleted file mode 100644 index bac24a4..0000000 --- a/setup.py +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env python - -import setuptools - -if __name__ == "__main__": - setuptools.setup() diff --git a/tests/backend_test.py b/tests/backend_test.py index 80bb1f4..bfb388e 100644 --- a/tests/backend_test.py +++ b/tests/backend_test.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import, division, unicode_literals - import decimal import unittest from hashlib import md5 @@ -54,7 +52,7 @@ class BackendBase(SkippableTest): # always reset to default backend jsonpickle.set_preferred_backend('json') - def assertEncodeDecode(self, json_input): + def assert_roundtrip(self, json_input): expect = SAMPLE_DATA actual = jsonpickle.decode(json_input) self.assertEqual(expect['things'][0].name, actual['things'][0].name) @@ -95,7 +93,7 @@ class JsonTestCase(BackendBase): '"child": null} ' ']}' ) - self.assertEncodeDecode(expected_pickled) + self.assert_roundtrip(expected_pickled) class SimpleJsonTestCase(BackendBase): @@ -110,7 +108,7 @@ class SimpleJsonTestCase(BackendBase): '"child": null}' ']}' ) - self.assertEncodeDecode(expected_pickled) + self.assert_roundtrip(expected_pickled) def test_decimal(self): # Default behavior: Decimal is preserved @@ -170,7 +168,7 @@ class UJsonTestCase(BackendBase): '"name":"data","child":null}' ']}' ) - self.assertEncodeDecode(expected_pickled) + self.assert_roundtrip(expected_pickled) def suite(): diff --git a/tests/collections_test.py b/tests/collections_test.py index e522097..a1ebce9 100644 --- a/tests/collections_test.py +++ b/tests/collections_test.py @@ -33,8 +33,6 @@ """ Unit tests for collections """ -from __future__ import absolute_import, division, print_function, unicode_literals - import sys from collections import OrderedDict, defaultdict diff --git a/tests/datetime_test.py b/tests/datetime_test.py index 06f96ae..e51cc11 100644 --- a/tests/datetime_test.py +++ b/tests/datetime_test.py @@ -179,10 +179,10 @@ class DateTimeSimpleTestCase(unittest.TestCase): now = datetime.datetime.now() SaoPaulo = ZoneInfo('America/Sao_Paulo') - USEastern = ZoneInfo('US/Eastern') + NewYork = ZoneInfo('America/New_York') now_sp = now.replace(tzinfo=SaoPaulo) - now_us = now.replace(tzinfo=USEastern) + now_us = now.replace(tzinfo=NewYork) self._roundtrip(now_sp) self._roundtrip(now_us) diff --git a/tests/ecdsa_test.py b/tests/ecdsa_test.py index 4ae4fe2..b8d5937 100644 --- a/tests/ecdsa_test.py +++ b/tests/ecdsa_test.py @@ -1,7 +1,5 @@ """Test serializing ecdsa keys""" -from __future__ import absolute_import, division, unicode_literals - import unittest import pytest diff --git a/tests/jsonpickle_test.py b/tests/jsonpickle_test.py index 3a98a4d..bf7ff74 100644 --- a/tests/jsonpickle_test.py +++ b/tests/jsonpickle_test.py @@ -1,11 +1,9 @@ # Copyright (C) 2008 John Paulett (john -at- paulett.org) -# Copyright (C) 2009-2021 David Aguilar (davvid -at- gmail.com) +# Copyright (C) 2009-2024 David Aguilar (davvid -at- gmail.com) # All rights reserved. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. -from __future__ import absolute_import, division, unicode_literals - import collections import os import unittest @@ -51,6 +49,9 @@ class Capture: self.args = args self.kwargs = kwargs + def __repr__(self): + return object.__repr__(self) + ('(%r, %r)' % (self.args, self.kwargs)) + class ThingWithProps: def _get_identity(self): @@ -164,6 +165,15 @@ class MyPropertiesDict: ) +# see issue #478 +class SafeData: + __slots__ = () + + +class SafeString(str, SafeData): + __slots__ = () + + def on_missing_callback(class_name): # not actually a runtime problem but it doesn't matter warnings.warn("The unpickler couldn't find %s" % class_name, RuntimeWarning) @@ -194,13 +204,13 @@ class PicklingTestCase(unittest.TestCase): self.assertEqual({tags.B64: encoded}, self.pickler.flatten(data)) def test_decode_base85(self): - pickled = {tags.B85: 'P{Y4;Xv4O{u^=-c'} - expected = u'P\u00ffth\u00f6\u00f1 3!'.encode('utf-8') + expected = 'Pÿthöñ 3!'.encode('utf-8') + pickled = {tags.B85: util.b85encode(expected)} self.assertEqual(expected, self.unpickler.restore(pickled)) def test_base85_still_handles_base64(self): - pickled = {tags.B64: 'UMO/dGjDtsOxIDMh'} - expected = u'P\u00ffth\u00f6\u00f1 3!'.encode('utf-8') + expected = 'Pÿthöñ 3!'.encode('utf-8') + pickled = {tags.B64: util.b64encode(expected)} self.assertEqual(expected, self.unpickler.restore(pickled)) def test_string(self): @@ -990,6 +1000,17 @@ class JSONPickleTestCase(SkippableTest): pickler.flatten([liszt, liszt, liszt, liszt, liszt]) self.assertEqual(pickler._depth, -1) + def test_readonly_attrs(self): + s = SafeString("test") + pickled = jsonpickle.encode(s, handle_readonly=True) + pickled_json_dict = jsonpickle.backend.json.loads(pickled) + # make sure it's giving concise output by erroring if it includes + # a default method which is unnecessary + self.assertTrue("join" not in pickled_json_dict) + unpickled = jsonpickle.decode(pickled) + self.assertEqual(unpickled.__class__, SafeString) + self.assertEqual(unpickled, s) + class PicklableNamedTuple(object): """ diff --git a/tests/numpy_test.py b/tests/numpy_test.py index 580e81f..694f21f 100644 --- a/tests/numpy_test.py +++ b/tests/numpy_test.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import, division, unicode_literals - import datetime import warnings diff --git a/tests/object_test.py b/tests/object_test.py index beb7b23..2434057 100644 --- a/tests/object_test.py +++ b/tests/object_test.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import, division, unicode_literals - import array import collections import datetime diff --git a/tests/pandas_test.py b/tests/pandas_test.py index 530449f..532563f 100644 --- a/tests/pandas_test.py +++ b/tests/pandas_test.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import, division, unicode_literals - import datetime import pytest diff --git a/tests/sklearn_test.py b/tests/sklearn_test.py index 210e098..853cc79 100644 --- a/tests/sklearn_test.py +++ b/tests/sklearn_test.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import, division, unicode_literals - import pytest try: diff --git a/tests/sqlalchemy_test.py b/tests/sqlalchemy_test.py index 381812e..002b5a9 100644 --- a/tests/sqlalchemy_test.py +++ b/tests/sqlalchemy_test.py @@ -8,6 +8,7 @@ import jsonpickle try: import sqlalchemy as sqa + from sqlalchemy import orm from sqlalchemy.ext import declarative from sqlalchemy.orm import Session @@ -16,7 +17,12 @@ except ImportError: HAS_SQA = False if HAS_SQA: - Base = declarative.declarative_base() + # sqlalchemy.ext.declarative.declarative_base() was deprecated in SQLAlchemy 2.0 + # and replaced by sqlalchemy.orm.declarative_base(). + if hasattr(orm, 'declarative_base'): + Base = orm.declarative_base() + else: + Base = declarative.declarative_base() class Table(Base): __tablename__ = 'table' diff --git a/tests/util_test.py b/tests/util_test.py index 4d8da07..8456631 100644 --- a/tests/util_test.py +++ b/tests/util_test.py @@ -4,9 +4,6 @@ # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. - -from __future__ import absolute_import, division, unicode_literals - import doctest import io import time diff --git a/tests/wizard_test.py b/tests/wizard_test.py index ef3014e..b303d43 100644 --- a/tests/wizard_test.py +++ b/tests/wizard_test.py @@ -6,8 +6,6 @@ Includes functionality to assist with adding compatibility to jsonpickle. """ -from __future__ import absolute_import, division, unicode_literals - import collections import unittest diff --git a/tests/zoneinfo_test.py b/tests/zoneinfo_test.py index 5c7f3db..3d87c15 100644 --- a/tests/zoneinfo_test.py +++ b/tests/zoneinfo_test.py @@ -20,7 +20,7 @@ if sys.version_info >= (3, 9): """ jsonpickle should pickle a zoneinfo object """ - self._roundtrip(ZoneInfo("Australia/Queensland")) + self._roundtrip(ZoneInfo("Australia/Brisbane")) def suite(): suite = unittest.TestSuite() @@ -4,10 +4,12 @@ envlist = clean,py36,py37,py38,py39,py310,py311,py312,report skip_missing_interpreters = true [testenv] +allowlist_externals = + ruff passenv = FORCE_COLOR commands = - python3 -m pytest -p no:cacheprovider --cov --cov-append --cov-report=term-missing jsonpickle tests {posargs} + python3 -m pytest --cov --cov-append --cov-report=term-missing jsonpickle tests {posargs} depends = {py36,py37,py38,py39,py310,py311,py312}: clean report: py36,py37,py38,py39,py310,py311,py312 |