Skip to content

Commit a4d7bb1

Browse files
committed
PyPy support
1 parent 2312ec3 commit a4d7bb1

File tree

3 files changed

+43
-26
lines changed

3 files changed

+43
-26
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@ jobs:
2626
runs-on: ubuntu-latest
2727
strategy:
2828
matrix:
29-
python-version: [3.6, 3.7, 3.8, 3.9]
29+
python-version: [3.6, 3.7, 3.8, 3.9, "pypy-3.6", "pypy-3.7"]
3030
fail-fast: false
3131
steps:
3232
- uses: actions/checkout@v2
3333
- name: Set up Python ${{ matrix.python-version }}
34-
uses: actions/setup-python@v1
34+
uses: actions/setup-python@v2
3535
with:
3636
python-version: ${{ matrix.python-version }}
3737
- name: Install dependencies

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Changelog
22

3+
- PyPy support (#77)
4+
35
#### 0.19.0 - 2021-01-06
46
- Generate empty lists when `maxItems > 0` but no elements are allowed (#75)
57
- Correct handling of regex patterns which are invalid in Python (#75)

src/hypothesis_jsonschema/_encode.py

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,53 @@
11
"""Canonical encoding for the JSONSchema semantics, where 1 == 1.0."""
22
import json
33
import math
4-
from json.encoder import _make_iterencode, encode_basestring_ascii # type: ignore
4+
import platform
55
from typing import Any, Dict, Tuple, Union
66

77
# Mypy does not (yet!) support recursive type definitions.
88
# (and writing a few steps by hand is a DoS attack on the AST walker in Pytest)
9+
PYTHON_IMPLEMENTATION = platform.python_implementation()
910
JSONType = Union[None, bool, float, str, list, Dict[str, Any]]
1011

12+
if PYTHON_IMPLEMENTATION != "PyPy":
13+
from json.encoder import _make_iterencode, encode_basestring_ascii # type: ignore
14+
else:
15+
_make_iterencode = None
16+
encode_basestring_ascii = None
17+
18+
19+
def _floatstr(o: float) -> str:
20+
# This is the bit we're overriding - integer-valued floats are
21+
# encoded as integers, to support JSONschemas's uniqueness.
22+
assert math.isfinite(o)
23+
if o == int(o):
24+
return repr(int(o))
25+
return repr(o)
26+
1127

1228
class CanonicalisingJsonEncoder(json.JSONEncoder):
13-
def iterencode(self, o: Any, _one_shot: bool = False) -> Any:
14-
"""Replace a stdlib method, so we encode integer-valued floats as ints."""
15-
16-
def floatstr(o: float) -> str:
17-
# This is the bit we're overriding - integer-valued floats are
18-
# encoded as integers, to support JSONschemas's uniqueness.
19-
assert math.isfinite(o)
20-
if o == int(o):
21-
return repr(int(o))
22-
return repr(o)
23-
24-
return _make_iterencode(
25-
{},
26-
self.default,
27-
encode_basestring_ascii,
28-
self.indent,
29-
floatstr,
30-
self.key_separator,
31-
self.item_separator,
32-
self.sort_keys,
33-
self.skipkeys,
34-
_one_shot,
35-
)(o, 0)
29+
30+
if PYTHON_IMPLEMENTATION == "PyPy":
31+
32+
def _JSONEncoder__floatstr(self, o: float) -> str: # noqa: N802
33+
return _floatstr(o)
34+
35+
else:
36+
37+
def iterencode(self, o: Any, _one_shot: bool = False) -> Any:
38+
"""Replace a stdlib method, so we encode integer-valued floats as ints."""
39+
return _make_iterencode(
40+
{},
41+
self.default,
42+
encode_basestring_ascii,
43+
self.indent,
44+
_floatstr,
45+
self.key_separator,
46+
self.item_separator,
47+
self.sort_keys,
48+
self.skipkeys,
49+
_one_shot,
50+
)(o, 0)
3651

3752

3853
def encode_canonical_json(value: JSONType) -> str:

0 commit comments

Comments
 (0)