Skip to content

Commit

Permalink
Merge pull request #541 from davvid/compat
Browse files Browse the repository at this point in the history
* davvid/compat:
  api: inline PRIMITIVES and NUMERIC_TYPES
  api: the jsonpickle.compat module has been deprecated
  tree-wide: replace compat.numeric_types with util.NUMERIC_TYPES
  util: stop using compat.iterator_types
  util: stop using compat.abc_iterator and compat.class_types
  tree-wide: stop using compat.string_types
  tree-wide: stop using compat.ustr
  handlers: stop using compat.queue
  • Loading branch information
davvid committed Nov 21, 2024
2 parents 5be928f + 126f598 commit 3bfba5f
Show file tree
Hide file tree
Showing 8 changed files with 39 additions and 41 deletions.
2 changes: 2 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ Upcoming
========
* The unpickler is now more resilient to malformed "py/set" input data.
* The test suite was updated to leverage more pytest features.
* The ``jsonpickle.compat`` module is no longer used. It is still provided
for backwards compatibility but it may be removed in a future version.

v4.0.0
======
Expand Down
5 changes: 1 addition & 4 deletions jsonpickle/backend.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
from .compat import string_types


class JSONBackend:
"""Manages encoding and decoding using various backends.
Expand Down Expand Up @@ -172,7 +169,7 @@ def load_backend(self, name, dumps='dumps', loads='loads', loads_exc=ValueError)
):
return False

if isinstance(loads_exc, string_types):
if isinstance(loads_exc, str):
# This backend's decoder exception is part of the backend
if not self._store(self._decoder_exceptions, name, mod, loads_exc):
return False
Expand Down
3 changes: 2 additions & 1 deletion jsonpickle/compat.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""jsonpickle.compat is a deprecated private module and will be removed in the future"""

import queue # noqa
import sys
from collections.abc import Iterator as abc_iterator # noqa
Expand All @@ -13,5 +15,4 @@


def iterator(class_):
# TODO: Replace all instances of this
return class_
6 changes: 2 additions & 4 deletions jsonpickle/ext/numpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@

import numpy as np

from .. import compat
from ..compat import numeric_types
from ..handlers import BaseHandler, register, unregister
from ..util import b64decode, b64encode

Expand All @@ -27,7 +25,7 @@ def flatten_dtype(self, dtype, data):
if hasattr(dtype, 'tostring'):
data['dtype'] = dtype.tostring()
else:
dtype = compat.ustr(dtype)
dtype = str(dtype)
prefix = '(numpy.record, '
if dtype.startswith(prefix):
dtype = dtype[len(prefix) : -1]
Expand Down Expand Up @@ -191,7 +189,7 @@ def restore(self, data):
if isinstance(values, list):
# decode text representation
arr = super().restore(data)
elif isinstance(values, numeric_types):
elif isinstance(values, (int, float)):
# single-value array
arr = np.array([values], dtype=self.restore_dtype(data))
else:
Expand Down
9 changes: 5 additions & 4 deletions jsonpickle/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@
import copy
import datetime
import io
import queue
import re
import threading
import uuid

from . import compat, util
from . import util


class Registry:
Expand Down Expand Up @@ -174,7 +175,7 @@ def flatten(self, obj, data):
if hasattr(obj, 'isoformat'):
result = obj.isoformat()
else:
result = compat.ustr(obj)
result = str(obj)
return result
cls, args = obj.__reduce__()
flatten = pickler.flatten
Expand Down Expand Up @@ -224,10 +225,10 @@ def flatten(self, obj, data):
return data

def restore(self, data):
return compat.queue.Queue()
return queue.Queue()


QueueHandler.handles(compat.queue.Queue)
QueueHandler.handles(queue.Queue)


class CloneFactory:
Expand Down
27 changes: 13 additions & 14 deletions jsonpickle/pickler.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@
import warnings
from itertools import chain, islice

from . import compat, handlers, tags, util
from . import handlers, tags, util
from .backend import json
from .compat import numeric_types, string_types


def encode(
Expand Down Expand Up @@ -188,7 +187,7 @@ def _mktyperef(obj):

def _wrap_string_slot(string):
"""Converts __slots__ = 'a' into __slots__ = ('a',)"""
if isinstance(string, string_types):
if isinstance(string, str):
return (string,)
return string

Expand Down Expand Up @@ -377,7 +376,7 @@ def _flatten_impl(self, obj):
return self._flatten_bytestring(obj)

# Decimal is a primitive when use_decimal is True
if type(obj) in util.PRIMITIVES or (
if type(obj) in (str, bool, int, float, type(None)) or (
self._use_decimal and isinstance(obj, decimal.Decimal)
):
return obj
Expand Down Expand Up @@ -456,13 +455,13 @@ def _flatten_key_value_pair(self, k, v, data):
if k is None:
k = 'null' # for compatibility with common json encoders

if self.numeric_keys and isinstance(k, numeric_types):
if self.numeric_keys and isinstance(k, (int, float)):
pass
elif not isinstance(k, string_types):
elif not isinstance(k, str):
try:
k = repr(k)
except Exception:
k = compat.ustr(k)
k = str(k)

data[k] = self._flatten(v)
return data
Expand Down Expand Up @@ -593,7 +592,7 @@ def _flatten_obj_instance(self, obj):
# we ignore those
pass

if reduce_val and isinstance(reduce_val, string_types):
if reduce_val and isinstance(reduce_val, str):
try:
varpath = iter(reduce_val.split('.'))
# curmod will be transformed by the
Expand Down Expand Up @@ -673,7 +672,7 @@ def _flatten_obj_instance(self, obj):
if self.unpicklable:
data[tags.MODULE] = '{name}/{name}'.format(name=obj.__name__)
else:
data = compat.ustr(obj)
data = str(obj)
return data

if util.is_dictionary_subclass(obj):
Expand Down Expand Up @@ -743,7 +742,7 @@ def _flatten_non_string_key_value_pair(self, k, v, data):
"""Flatten only non-string key/value pairs"""
if not util.is_picklable(k, v):
return data
if self.keys and not isinstance(k, string_types):
if self.keys and not isinstance(k, str):
k = self._escape_key(k)
data[k] = self._flatten(v)
return data
Expand All @@ -753,21 +752,21 @@ def _flatten_string_key_value_pair(self, k, v, data):
if not util.is_picklable(k, v):
return data
if self.keys:
if not isinstance(k, string_types):
if not isinstance(k, str):
return data
elif k.startswith(tags.JSON_KEY):
k = self._escape_key(k)
else:
if k is None:
k = 'null' # for compatibility with common json encoders

if self.numeric_keys and isinstance(k, numeric_types):
if self.numeric_keys and isinstance(k, (int, float)):
pass
elif not isinstance(k, string_types):
elif not isinstance(k, str):
try:
k = repr(k)
except Exception:
k = compat.ustr(k)
k = str(k)

data[k] = self._flatten(v)
return data
Expand Down
11 changes: 5 additions & 6 deletions jsonpickle/unpickler.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@
import sys
import warnings

from . import compat, errors, handlers, tags, util
from . import errors, handlers, tags, util
from .backend import json
from .compat import numeric_types


def decode(
Expand Down Expand Up @@ -115,7 +114,7 @@ def _safe_hasattr(obj, attr):

def _is_json_key(key):
"""Has this key a special object that has been encoded to JSON?"""
return isinstance(key, compat.string_types) and key.startswith(tags.JSON_KEY)
return isinstance(key, str) and key.startswith(tags.JSON_KEY)


class _Proxy:
Expand Down Expand Up @@ -653,7 +652,7 @@ def _restore_from_dict(
# ignore the reserved attribute
if ignorereserved and k in tags.RESERVED:
continue
if isinstance(k, numeric_types):
if isinstance(k, (int, float)):
str_k = k.__str__()
else:
str_k = k
Expand Down Expand Up @@ -868,7 +867,7 @@ def _restore_dict(self, obj):
for k, v in util.items(obj):
if _is_json_key(k):
continue
if isinstance(k, numeric_types):
if isinstance(k, (int, float)):
str_k = k.__str__()
else:
str_k = k
Expand All @@ -893,7 +892,7 @@ def _restore_dict(self, obj):
else:
# No special keys, thus we don't need to restore the keys either.
for k, v in util.items(obj):
if isinstance(k, numeric_types):
if isinstance(k, (int, float)):
str_k = k.__str__()
else:
str_k = k
Expand Down
17 changes: 9 additions & 8 deletions jsonpickle/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@
import sys
import time
import types
from collections.abc import Iterator as abc_iterator

from . import compat, tags
from .compat import abc_iterator, class_types, iterator_types, numeric_types
from . import tags

_ITERATOR_TYPE = type(iter(''))
SEQUENCES = (list, set, tuple)
SEQUENCES_SET = {list, set, tuple}
PRIMITIVES = {compat.ustr, bool, type(None)} | set(numeric_types)
PRIMITIVES = {str, bool, int, float, type(None)}
FUNCTION_TYPES = {
types.FunctionType,
types.MethodType,
Expand Down Expand Up @@ -65,7 +66,7 @@ def is_type(obj):
True
"""
# use "isinstance" and not "is" to allow for metaclasses
return isinstance(obj, class_types)
return isinstance(obj, type)


def has_method(obj, name):
Expand Down Expand Up @@ -205,8 +206,8 @@ def is_bytes(obj):


def is_unicode(obj):
"""Helper method to see if the object is a unicode string"""
return type(obj) is compat.ustr
"""DEPRECATED: Helper method to see if the object is a unicode string"""
return type(obj) is str


def is_tuple(obj):
Expand Down Expand Up @@ -380,7 +381,7 @@ def is_reducible(obj):
# Condensing it into one line seems to save the parser a lot of time.
# fmt: off
# pylint: disable=line-too-long
if type(obj) in NON_REDUCIBLE_TYPES or obj is object or is_dictionary_subclass(obj) or isinstance(obj, types.ModuleType) or is_reducible_sequence_subclass(obj) or is_list_like(obj) or isinstance(getattr(obj, '__slots__', None), iterator_types) or (is_type(obj) and obj.__module__ == 'datetime'): # noqa: E501
if type(obj) in NON_REDUCIBLE_TYPES or obj is object or is_dictionary_subclass(obj) or isinstance(obj, types.ModuleType) or is_reducible_sequence_subclass(obj) or is_list_like(obj) or isinstance(getattr(obj, '__slots__', None), _ITERATOR_TYPE) or (is_type(obj) and obj.__module__ == 'datetime'): # noqa: E501
return False
# fmt: on
return True
Expand Down Expand Up @@ -574,7 +575,7 @@ def b85decode(payload):


def itemgetter(obj, getter=operator.itemgetter(0)):
return compat.ustr(getter(obj))
return str(getter(obj))


def items(obj, exclude=()):
Expand Down

0 comments on commit 3bfba5f

Please sign in to comment.