Skip to content

Commit

Permalink
Merge pull request #75 from mverleg/deprecate_ign_cmts
Browse files Browse the repository at this point in the history
Deprecation warning ignore_comments
  • Loading branch information
mverleg authored Apr 9, 2020
2 parents cf3e10d + 00050bf commit 4b3ca4c
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 9 deletions.
2 changes: 2 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,8 @@ As a note on performance_, both dicts and OrderedDicts have the same scaling for
Comments
+++++++++++++++++++++++++++++++++++++++

*Warning: in the next major version, comment parsing will be opt-in, not default anymore (for performance reasons). Update your code now to pass `ignore_comments=True` explicitly if you want comment parsing.*

This package uses ``#`` and ``//`` for comments, which seem to be the most common conventions, though only the latter is valid javascript.

For example, you could call ``loads`` on the following string::
Expand Down
2 changes: 1 addition & 1 deletion json_tricks/_version.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@

VERSION = '3.15.0'
VERSION = '3.15.1'

20 changes: 14 additions & 6 deletions json_tricks/nonp.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@

import warnings
from json import loads as json_loads
from os import fsync
from sys import exc_info

from json_tricks.utils import is_py3, dict_default, gzip_compress, gzip_decompress
from json_tricks.utils import is_py3, dict_default, gzip_compress, gzip_decompress, JsonTricksDeprecation
from .utils import str_type, NoNumpyException # keep 'unused' imports
from .comment import strip_comments # keep 'unused' imports
#TODO @mark: imports removed?
Expand Down Expand Up @@ -176,7 +176,7 @@ def dump(obj, fp, sort_keys=None, cls=TricksEncoder, obj_encoders=DEFAULT_ENCODE
return txt


def loads(string, preserve_order=True, ignore_comments=True, decompression=None, obj_pairs_hooks=DEFAULT_HOOKS,
def loads(string, preserve_order=True, ignore_comments=None, decompression=None, obj_pairs_hooks=DEFAULT_HOOKS,
extra_obj_pairs_hooks=(), cls_lookup_map=None, allow_duplicates=True, conv_str_byte=False, **jsonkwargs):
"""
Convert a nested data structure to a json string.
Expand Down Expand Up @@ -212,8 +212,16 @@ def loads(string, preserve_order=True, ignore_comments=True, decompression=None,
'for example bytevar.encode("utf-8") if utf-8 is the encoding. Alternatively you can '
'force an attempt by passing conv_str_byte=True, but this may cause decoding issues.')
.format(type(string)))
if ignore_comments:
string = strip_comments(string)
if ignore_comments or ignore_comments is None:
new_string = strip_comments(string)
if ignore_comments is None and not getattr(loads, '_ignore_comments_warned', False) and string != new_string:
warnings.warn('`json_tricks.load(s)` stripped some comments, but `ignore_comments` was '
'not passed; in the next major release, the behaviour when `ignore_comments` is not '
'passed will change; it is recommended to explicitly pass `ignore_comments=True` if '
'you want to strip comments; see https://github.com/mverleg/pyjson_tricks/issues/74',
JsonTricksDeprecation)
loads._ignore_comments_warned = True
string = new_string
obj_pairs_hooks = tuple(obj_pairs_hooks)
_cih_instance.cls_lookup_map = cls_lookup_map or {}
_eih_instance.cls_lookup_map = cls_lookup_map or {}
Expand All @@ -222,7 +230,7 @@ def loads(string, preserve_order=True, ignore_comments=True, decompression=None,
return json_loads(string, object_pairs_hook=hook, **jsonkwargs)


def load(fp, preserve_order=True, ignore_comments=True, decompression=None, obj_pairs_hooks=DEFAULT_HOOKS,
def load(fp, preserve_order=True, ignore_comments=None, decompression=None, obj_pairs_hooks=DEFAULT_HOOKS,
extra_obj_pairs_hooks=(), cls_lookup_map=None, allow_duplicates=True, conv_str_byte=False, **jsonkwargs):
"""
Convert a nested data structure to a json string.
Expand Down
48 changes: 47 additions & 1 deletion tests/test_bare.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@
from os.path import join
from tempfile import mkdtemp

from _pytest.recwarn import warns
from pytest import raises, fail

from json_tricks import fallback_ignore_unknown, DuplicateJsonKeyException
from json_tricks.nonp import strip_comments, dump, dumps, load, loads, \
ENCODING
from json_tricks.utils import is_py3, gzip_compress
from json_tricks.utils import is_py3, gzip_compress, JsonTricksDeprecation
from .test_class import MyTestCls, CustomEncodeCls, SubClass, SuperClass, SlotsBase, SlotsDictABC, SlotsStr, \
SlotsABCDict, SlotsABC

Expand Down Expand Up @@ -143,6 +144,12 @@ def test_file_path():
}
"""

test_object_for_comment_strings = {
"hello": "Wor#d", "Bye": "\"M#rk\"", "yes\\\"": 5,
"quote": "\"th#t's\" what she said",
"list": [1, 1, "#", "\"", "\\", 8], "dict": {"q": 7}
}

test_json_duplicates = """{"test": 42, "test": 37}"""


Expand All @@ -153,6 +160,45 @@ def test_strip_comments():
assert valid == test_json_without_comments.replace('#', '//')


def test_ignore_comments_deprecation():
# https://github.com/mverleg/pyjson_tricks/issues/74

# First time should have deprecation warning
loads._ignore_comments_warned_ = False
with warns(JsonTricksDeprecation):
loads(test_json_with_comments)

# Second time there should be no warning
# noinspection PyTypeChecker
with warns(None) as captured:
loaded = loads(test_json_with_comments)
assert len(captured) == 0
assert loaded == test_object_for_comment_strings

# Passing a string without comments should not have a warning
loads._ignore_comments_warned_ = False
# noinspection PyTypeChecker
with warns(None) as captured:
loaded = loads(test_json_without_comments)
assert len(captured) == 0

# Passing True for argument explicitly should not have a warning
loads._ignore_comments_warned_ = False
# noinspection PyTypeChecker
with warns(None) as captured:
loaded = loads(test_json_with_comments, ignore_comments=True)
assert len(captured) == 0
assert loaded == test_object_for_comment_strings

# Passing False for argument explicitly should not have a warning
loads._ignore_comments_warned_ = False
# noinspection PyTypeChecker
with warns(None) as captured:
loaded = loads(test_json_without_comments, ignore_comments=False)
assert len(captured) == 0
assert loaded == test_object_for_comment_strings


ordered_map = OrderedDict((
('elephant', None),
('chicken', None),
Expand Down
1 change: 0 additions & 1 deletion tests/test_np.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
float16, float32, float64, complex64, complex128, zeros, ndindex
from numpy.core.umath import exp
from numpy.testing import assert_equal
from pytest import raises

from json_tricks import numpy_encode
from json_tricks.np import dump, dumps, load, loads
Expand Down

0 comments on commit 4b3ca4c

Please sign in to comment.