Skip to content

Commit 2bf5f7d

Browse files
authored
Merge pull request #394 from python-jsonschema/always-support-toml
Make TOML parsing always available
2 parents 6c7c951 + 2e57ff1 commit 2bf5f7d

File tree

9 files changed

+42
-82
lines changed

9 files changed

+42
-82
lines changed

CHANGELOG.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ Unreleased
1414
- Support the use of `orjson` for faster JSON parsing when it is installed.
1515
This makes it an optional parser which is preferred over the default
1616
`json` module when it is available.
17+
- TOML parsing is now always available (rather than an optional parser).
18+
This change adds a dependency on `tomli` on older Python versions, ensuring
19+
that TOML formatted data is always supported. Users should no longer need
20+
to install `tomli` manually in order to use TOML files.
1721

1822
0.27.4
1923
------

docs/optional_parsers.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ For example,
2828
TOML
2929
----
3030

31+
.. note::
32+
33+
In the latest versions of ``check-jsonschema``, the TOML parser is no
34+
longer optional. It is always available, using ``tomli`` or ``tomllib``
35+
depending on the environment.
36+
3137
- Supported for Instances: yes
3238
- Supported for Schemas: no
3339

setup.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ python_requires = >=3.8
1919
# reference for dependency spec: https://www.python.org/dev/peps/pep-0508/
2020
install_requires =
2121
importlib-resources>=1.4.0;python_version<"3.9"
22+
tomli>=2.0;python_version<"3.11"
2223
ruamel.yaml==0.18.5
2324
jsonschema>=4.18.0,<5.0
2425
regress>=0.4.0

src/check_jsonschema/_testing.py

Lines changed: 0 additions & 20 deletions
This file was deleted.

src/check_jsonschema/parsers/__init__.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,22 @@
99
from ..identify_filetype import path_to_type
1010
from . import json5, json_, toml, yaml
1111

12-
_PARSER_ERRORS: set[type[Exception]] = {json_.JSONDecodeError, yaml.ParseError}
12+
_PARSER_ERRORS: set[type[Exception]] = {
13+
json_.JSONDecodeError,
14+
yaml.ParseError,
15+
toml.ParseError,
16+
}
1317
DEFAULT_LOAD_FUNC_BY_TAG: dict[str, t.Callable[[t.IO[bytes]], t.Any]] = {
1418
"json": json_.load,
19+
"toml": toml.load,
1520
}
16-
SUPPORTED_FILE_FORMATS = ["json", "yaml"]
21+
SUPPORTED_FILE_FORMATS = ["json", "toml", "yaml"]
1722
if json5.ENABLED:
1823
SUPPORTED_FILE_FORMATS.append("json5")
1924
DEFAULT_LOAD_FUNC_BY_TAG["json5"] = json5.load
2025
_PARSER_ERRORS.add(json5.ParseError)
21-
if toml.ENABLED:
22-
SUPPORTED_FILE_FORMATS.append("toml")
23-
DEFAULT_LOAD_FUNC_BY_TAG["toml"] = toml.load
24-
_PARSER_ERRORS.add(toml.ParseError)
2526
MISSING_SUPPORT_MESSAGES: dict[str, str] = {
2627
"json5": json5.MISSING_SUPPORT_MESSAGE,
27-
"toml": toml.MISSING_SUPPORT_MESSAGE,
2828
}
2929
LOADING_FAILURE_ERROR_TYPES: tuple[type[Exception], ...] = tuple(_PARSER_ERRORS)
3030

src/check_jsonschema/parsers/toml.py

Lines changed: 5 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,9 @@
44
import sys
55
import typing as t
66

7-
from check_jsonschema._testing import FORCE_TOML_DISABLED
8-
97
if sys.version_info < (3, 11):
10-
try:
11-
import tomli as toml_implementation
12-
13-
has_toml = True
14-
except ImportError: # pragma: no cover
15-
has_toml = False
8+
import tomli as toml_implementation
169
else:
17-
has_toml = True
1810
import tomllib as toml_implementation
1911

2012

@@ -55,30 +47,9 @@ def _normalize(data: t.Any) -> t.Any:
5547
return data
5648

5749

58-
# present a bool for detecting that it's enabled
59-
ENABLED = has_toml and not FORCE_TOML_DISABLED
60-
61-
62-
if ENABLED:
63-
ParseError: type[Exception] = toml_implementation.TOMLDecodeError
64-
65-
def load(stream: t.IO[bytes]) -> t.Any:
66-
data = toml_implementation.load(stream)
67-
return _normalize(data)
68-
69-
else:
70-
ParseError = ValueError
71-
72-
def load(stream: t.IO[bytes]) -> t.Any:
73-
raise NotImplementedError
74-
75-
76-
MISSING_SUPPORT_MESSAGE = """
77-
check-jsonschema can only parse TOML files when a TOML parser is installed
50+
ParseError: type[Exception] = toml_implementation.TOMLDecodeError
7851

79-
If you are running check-jsonschema as an installed python package, add support with
80-
pip install tomli
8152

82-
If you are running check-jsonschema as a pre-commit hook, set
83-
additional_dependencies: ['tomli']
84-
"""
53+
def load(stream: t.IO[bytes]) -> t.Any:
54+
data = toml_implementation.load(stream)
55+
return _normalize(data)

tests/acceptance/test_example_files.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import ruamel.yaml
1010

1111
from check_jsonschema.parsers.json5 import ENABLED as JSON5_ENABLED
12-
from check_jsonschema.parsers.toml import ENABLED as TOML_ENABLED
1312

1413
yaml = ruamel.yaml.YAML(typ="safe")
1514

@@ -109,8 +108,6 @@ def test_explicit_positive_examples(case_name, run_line):
109108
def _check_file_format_skip(case_name):
110109
if case_name.endswith("json5") and not JSON5_ENABLED:
111110
pytest.skip("cannot check json5 support without json5 enabled")
112-
if case_name.endswith("toml") and not TOML_ENABLED:
113-
pytest.skip("cannot check toml support without toml enabled")
114111

115112

116113
@dataclasses.dataclass

tests/unit/test_instance_loader.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from check_jsonschema.instance_loader import InstanceLoader
44
from check_jsonschema.parsers import BadFileTypeError, FailedFileLoadError
55
from check_jsonschema.parsers.json5 import ENABLED as JSON5_ENABLED
6-
from check_jsonschema.parsers.toml import ENABLED as TOML_ENABLED
76

87

98
# handy helper for opening multiple files for InstanceLoader
@@ -70,6 +69,23 @@ def test_instanceloader_yaml_data(tmp_path, filename, default_filetype, open_wid
7069
assert data == [(str(f), {"a": {"b": [1, 2], "c": "d"}})]
7170

7271

72+
@pytest.mark.parametrize(
73+
"filename, default_filetype",
74+
[
75+
("foo.toml", "notarealfiletype"),
76+
("foo.toml", "json"),
77+
("foo.toml", "yaml"),
78+
("foo", "toml"),
79+
],
80+
)
81+
def test_instanceloader_toml_data(tmp_path, filename, default_filetype, open_wide):
82+
f = tmp_path / "foo.toml"
83+
f.write_text('[foo]\nbar = "baz"\n')
84+
loader = InstanceLoader(open_wide(f), default_filetype=default_filetype)
85+
data = list(loader.iter_files())
86+
assert data == [(str(f), {"foo": {"bar": "baz"}})]
87+
88+
7389
def test_instanceloader_unknown_type_nonjson_content(tmp_path, open_wide):
7490
f = tmp_path / "foo" # no extension here
7591
f.write_text("a:b") # non-json data (cannot be detected as JSON)
@@ -93,13 +109,6 @@ def test_instanceloader_unknown_type_nonjson_content(tmp_path, open_wide):
93109
{},
94110
"pip install json5",
95111
),
96-
(
97-
TOML_ENABLED,
98-
"toml",
99-
'[foo]\nbar = "baz"\n',
100-
{"foo": {"bar": "baz"}},
101-
"pip install tomli",
102-
),
103112
],
104113
)
105114
def test_instanceloader_optional_format_handling(
@@ -162,8 +171,6 @@ def test_instanceloader_invalid_data(
162171
):
163172
if file_format == "json5" and not JSON5_ENABLED:
164173
pytest.skip("test requires 'json5' support")
165-
if file_format == "toml" and not TOML_ENABLED:
166-
pytest.skip("test requires 'toml' support")
167174

168175
f = tmp_path / filename
169176
f.write_text(content)
@@ -211,8 +218,6 @@ def test_instanceloader_invalid_data_mixed_with_valid_data(tmp_path, open_wide):
211218
def test_instanceloader_mixed_filetypes(tmp_path, filetypes, open_wide):
212219
if not JSON5_ENABLED and "json5" in filetypes:
213220
pytest.skip("test requires json5")
214-
if not TOML_ENABLED and "toml" in filetypes:
215-
pytest.skip("test requires toml")
216221
files = {}
217222
file_order = []
218223
if "json" in filetypes:

tox.ini

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@
22
envlist =
33
mypy
44
cov_clean
5-
py38-mindeps
5+
py38-mindeps{,-format}
66
py{312,311,310,39,38}
7-
py310-{notoml,tomli-format}
8-
py{38,312}-{json5,pyjson5}
7+
py{38,312}-{json5,pyjson5}{,-format}
98
py{38,312}-{disable_orjson}
109
cov
1110
skip_missing_interpreters = true
@@ -26,10 +25,7 @@ deps =
2625
!disable_orjson: orjson
2726
json5: json5
2827
pyjson5: pyjson5
29-
tomli: tomli
3028
format: jsonschema[format]
31-
set_env =
32-
notoml: FORCE_TOML_DISABLED=1
3329
commands =
3430
coverage run -m pytest {posargs:--junitxml={envdir}/pytest.xml}
3531

0 commit comments

Comments
 (0)