Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: python-jsonschema/jsonschema
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v4.21.1
Choose a base ref
...
head repository: python-jsonschema/jsonschema
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: main
Choose a head ref
Loading
Showing with 4,706 additions and 1,246 deletions.
  1. +51 −34 .github/workflows/ci.yml
  2. +2 −2 .github/workflows/documentation-links.yml
  3. +0 −30 .github/workflows/fuzz.yml
  4. +35 −0 .github/workflows/zizmor.yml
  5. +6 −5 .gitignore
  6. +2 −11 .pre-commit-config.yaml
  7. +18 −0 CHANGELOG.rst
  8. +0 −2 README.rst
  9. +10 −6 docs/conf.py
  10. +2 −2 docs/errors.rst
  11. +34 −20 docs/referencing.rst
  12. +1 −1 docs/requirements.in
  13. +41 −46 docs/requirements.txt
  14. +21 −0 json/.github/workflows/annotation-tests.yml
  15. +12 −0 json/.github/workflows/pr-dependencies.yml
  16. +21 −0 json/.github/workflows/show_specification_annotations.yml
  17. +4 −1 json/README.md
  18. +116 −0 json/annotations/README.md
  19. +24 −0 json/annotations/assertion.schema.json
  20. +38 −0 json/annotations/test-case.schema.json
  21. +15 −0 json/annotations/test-suite.schema.json
  22. +16 −0 json/annotations/test.schema.json
  23. +409 −0 json/annotations/tests/applicators.json
  24. +121 −0 json/annotations/tests/content.json
  25. +30 −0 json/annotations/tests/core.json
  26. +26 −0 json/annotations/tests/format.json
  27. +150 −0 json/annotations/tests/meta-data.json
  28. +661 −0 json/annotations/tests/unevaluated.json
  29. +27 −0 json/annotations/tests/unknown.json
  30. +140 −0 json/bin/annotate-specification-links
  31. +31 −0 json/bin/annotation-tests.ts
  32. +34 −0 json/bin/specification_urls.json
  33. +1 −0 json/remotes/draft-next/format-assertion-false.json
  34. +1 −0 json/remotes/draft-next/format-assertion-true.json
  35. +1 −0 json/remotes/draft-next/metaschema-no-validation.json
  36. +1 −0 json/remotes/draft-next/metaschema-optional-vocabulary.json
  37. +1 −0 json/remotes/draft2019-09/metaschema-no-validation.json
  38. +1 −0 json/remotes/draft2019-09/metaschema-optional-vocabulary.json
  39. +1 −0 json/remotes/draft2020-12/format-assertion-false.json
  40. +1 −0 json/remotes/draft2020-12/format-assertion-true.json
  41. +1 −0 json/remotes/draft2020-12/metaschema-no-validation.json
  42. +1 −0 json/remotes/draft2020-12/metaschema-optional-vocabulary.json
  43. 0 json/remotes/{ → draft3}/subSchemas.json
  44. 0 json/remotes/{locationIndependentIdentifierDraft4.json → draft4/locationIndependentIdentifier.json}
  45. 0 json/remotes/{ → draft4}/name.json
  46. +10 −0 json/remotes/draft4/subSchemas.json
  47. 0 json/remotes/{locationIndependentIdentifierPre2019.json → draft6/locationIndependentIdentifier.json}
  48. +15 −0 json/remotes/draft6/name.json
  49. +1 −1 json/remotes/{ → draft6}/ref-and-definitions.json
  50. +10 −0 json/remotes/draft6/subSchemas.json
  51. +11 −0 json/remotes/draft7/locationIndependentIdentifier.json
  52. +15 −0 json/remotes/draft7/name.json
  53. +11 −0 json/remotes/draft7/ref-and-definitions.json
  54. +10 −0 json/remotes/draft7/subSchemas.json
  55. +63 −0 json/test-schema.json
  56. +92 −0 json/tests/draft-next/additionalProperties.json
  57. +0 −24 json/tests/draft-next/anchor.json
  58. +55 −0 json/tests/draft-next/dynamicRef.json
  59. +0 −211 json/tests/draft-next/id.json
  60. +1 −1 json/tests/draft-next/oneOf.json
  61. +56 −0 json/tests/draft-next/optional/dynamicRef.json
  62. +0 −14 json/tests/draft-next/optional/ecmascript-regex.json
  63. +5 −0 json/tests/draft-next/optional/format/duration.json
  64. +16 −0 json/tests/draft-next/optional/format/ecmascript-regex.json
  65. +10 −0 json/tests/draft-next/optional/format/hostname.json
  66. +58 −1 json/tests/draft-next/optional/format/idn-hostname.json
  67. +69 −0 json/tests/draft-next/unevaluatedProperties.json
  68. +57 −0 json/tests/draft2019-09/additionalProperties.json
  69. +0 −25 json/tests/draft2019-09/anchor.json
  70. +0 −211 json/tests/draft2019-09/id.json
  71. +151 −3 json/tests/draft2019-09/not.json
  72. +1 −1 json/tests/draft2019-09/oneOf.json
  73. +5 −0 json/tests/draft2019-09/optional/format/duration.json
  74. +10 −0 json/tests/draft2019-09/optional/format/hostname.json
  75. +58 −1 json/tests/draft2019-09/optional/format/idn-hostname.json
  76. +53 −0 json/tests/draft2019-09/propertyNames.json
  77. +39 −16 json/tests/draft2019-09/ref.json
  78. +33 −0 json/tests/draft2019-09/unevaluatedProperties.json
  79. +65 −2 json/tests/draft2020-12/additionalProperties.json
  80. +0 −25 json/tests/draft2020-12/anchor.json
  81. +55 −0 json/tests/draft2020-12/dynamicRef.json
  82. +0 −211 json/tests/draft2020-12/id.json
  83. +151 −3 json/tests/draft2020-12/not.json
  84. +1 −1 json/tests/draft2020-12/oneOf.json
  85. +56 −0 json/tests/draft2020-12/optional/dynamicRef.json
  86. +0 −14 json/tests/draft2020-12/optional/ecmascript-regex.json
  87. +5 −0 json/tests/draft2020-12/optional/format/duration.json
  88. +16 −0 json/tests/draft2020-12/optional/format/ecmascript-regex.json
  89. +10 −0 json/tests/draft2020-12/optional/format/hostname.json
  90. +58 −1 json/tests/draft2020-12/optional/format/idn-hostname.json
  91. +83 −0 json/tests/draft2020-12/propertyNames.json
  92. +0 −15 json/tests/draft2020-12/ref.json
  93. +0 −1 json/tests/draft2020-12/unevaluatedItems.json
  94. +59 −36 json/tests/draft2020-12/unevaluatedProperties.json
  95. 0 json/tests/draft3/optional/{ → format}/ecmascript-regex.json
  96. +5 −0 json/tests/draft3/optional/format/host-name.json
  97. +2 −2 json/tests/draft3/refRemote.json
  98. +62 −1 json/tests/draft4/not.json
  99. +1 −1 json/tests/draft4/oneOf.json
  100. +10 −0 json/tests/draft4/optional/format/hostname.json
  101. +4 −4 json/tests/draft4/refRemote.json
  102. +147 −5 json/tests/draft6/not.json
  103. +1 −1 json/tests/draft6/oneOf.json
  104. +10 −0 json/tests/draft6/optional/format/hostname.json
  105. +47 −0 json/tests/draft6/propertyNames.json
  106. +5 −5 json/tests/draft6/refRemote.json
  107. +147 −5 json/tests/draft7/not.json
  108. +1 −1 json/tests/draft7/oneOf.json
  109. +10 −0 json/tests/draft7/optional/format/hostname.json
  110. +55 −1 json/tests/draft7/optional/format/idn-hostname.json
  111. +47 −0 json/tests/draft7/propertyNames.json
  112. +5 −5 json/tests/draft7/refRemote.json
  113. +2 −2 jsonschema/__init__.py
  114. +15 −13 jsonschema/_format.py
  115. +11 −2 jsonschema/_types.py
  116. +3 −2 jsonschema/_typing.py
  117. +26 −19 jsonschema/_utils.py
  118. +30 −0 jsonschema/benchmarks/const_vs_enum.py
  119. +106 −0 jsonschema/benchmarks/useless_applicator_schemas.py
  120. +32 −0 jsonschema/benchmarks/useless_keywords.py
  121. +1 −5 jsonschema/cli.py
  122. +52 −38 jsonschema/exceptions.py
  123. +7 −9 jsonschema/protocols.py
  124. +44 −34 jsonschema/tests/_suite.py
  125. +4 −7 jsonschema/tests/test_cli.py
  126. +1 −1 jsonschema/tests/test_deprecations.py
  127. +85 −0 jsonschema/tests/test_exceptions.py
  128. +12 −19 jsonschema/tests/test_jsonschema_test_suite.py
  129. +14 −0 jsonschema/tests/test_utils.py
  130. +33 −10 jsonschema/validators.py
  131. +35 −17 noxfile.py
  132. +52 −59 pyproject.toml
85 changes: 51 additions & 34 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -2,44 +2,41 @@ name: CI

on:
push:
branches-ignore:
- "wip*"
tags:
- "v*"
pull_request:
release:
types: [published]
schedule:
# Daily at 3:21
- cron: "21 3 * * *"
workflow_dispatch:

env:
PIP_DISABLE_PIP_VERSION_CHECK: "1"
PIP_NO_PYTHON_VERSION_WARNING: "1"
permissions: {}

jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.x"
- uses: pre-commit/action@v3.0.0

list:
runs-on: ubuntu-latest
outputs:
noxenvs: ${{ steps.noxenvs-matrix.outputs.noxenvs }}
steps:
- uses: actions/checkout@v4
- name: Set up nox
uses: wntrblm/nox@2023.04.22
with:
persist-credentials: false
- name: Set up uv
uses: astral-sh/setup-uv@f0ec1fc3b38f5e7cd731bb6ce540c5af426746bb
with:
enable-cache: ${{ github.ref_type != 'tag' }} # zizmor: ignore[cache-poisoning]
- id: noxenvs-matrix
run: |
echo >>$GITHUB_OUTPUT noxenvs=$(
nox --list-sessions --json | jq '[.[].session]'
uvx nox --list-sessions --json | jq '[.[].session]'
)
ci:
needs: list
runs-on: ${{ matrix.os }}

strategy:
fail-fast: false
matrix:
@@ -48,12 +45,24 @@ jobs:
posargs: [""]
include:
- os: ubuntu-latest
noxenv: "tests-3.11(format)"
noxenv: "tests-3.13(format)"
posargs: coverage github
- os: ubuntu-latest
noxenv: "tests-3.11(no-extras)"
noxenv: "tests-3.13(no-extras)"
posargs: coverage github
exclude:
- os: macos-latest
noxenv: "docs(dirhtml)"
- os: macos-latest
noxenv: "docs(doctest)"
- os: macos-latest
noxenv: "docs(linkcheck)"
- os: macos-latest
noxenv: "docs(man)"
- os: macos-latest
noxenv: "docs(spelling)"
- os: macos-latest
noxenv: "docs(style)"
- os: windows-latest
noxenv: "docs(dirhtml)"
- os: windows-latest
@@ -67,6 +76,8 @@ jobs:

steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Install dependencies
run: sudo apt-get update && sudo apt-get install -y libenchant-2-dev
if: runner.os == 'Linux' && startsWith(matrix.noxenv, 'docs')
@@ -77,27 +88,32 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: |
3.8
3.9
3.10
3.11
3.12
pypy3.10
3.13
pypy3.11
allow-prereleases: true
- name: Set up nox
uses: wntrblm/nox@2023.04.22
- name: Enable UTF-8 on Windows
run: echo "PYTHONUTF8=1" >> $env:GITHUB_ENV
if: runner.os == 'Windows' && startsWith(matrix.noxenv, 'tests')

- name: Set up uv
uses: astral-sh/setup-uv@f0ec1fc3b38f5e7cd731bb6ce540c5af426746bb
with:
enable-cache: true

- name: Run nox
run: nox -s "${{ matrix.noxenv }}" -- ${{ matrix.posargs }}
run: uvx nox -s "${{ matrix.noxenv }}" -- ${{ matrix.posargs }} # zizmor: ignore[template-injection]

packaging:
needs: ci
runs-on: ubuntu-latest
environment:
name: PyPI
url: https://pypi.org/p/jsonschema

permissions:
contents: write
id-token: write
@@ -106,20 +122,21 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
persist-credentials: false
- name: Set up uv
uses: astral-sh/setup-uv@f0ec1fc3b38f5e7cd731bb6ce540c5af426746bb
with:
python-version: "3.x"
- name: Install dependencies
run: python -m pip install build
- name: Create packages
run: python -m build .
enable-cache: true

- name: Build our distributions
run: uv run --with 'build[uv]' -m build --installer=uv

- name: Publish to PyPI
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
uses: pypa/gh-action-pypi-publish@release/v1
- name: Create a Release
uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc
- name: Create a GitHub Release
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631
with:
files: |
dist/*
4 changes: 2 additions & 2 deletions .github/workflows/documentation-links.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: Read the Docs Pull Request Preview
on:
pull_request_target:
pull_request_target: # zizmor: ignore[dangerous-triggers]
types:
- opened

@@ -11,6 +11,6 @@ jobs:
documentation-links:
runs-on: ubuntu-latest
steps:
- uses: readthedocs/actions/preview@v1
- uses: readthedocs/actions/preview@b8bba1484329bda1a3abe986df7ebc80a8950333
with:
project-slug: "python-jsonschema"
30 changes: 0 additions & 30 deletions .github/workflows/fuzz.yml

This file was deleted.

35 changes: 35 additions & 0 deletions .github/workflows/zizmor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: GitHub Actions Security Analysis with zizmor 🌈

on:
push:
branches: ["main"]
pull_request:
branches: ["**"]

jobs:
zizmor:
name: Run zizmor
runs-on: ubuntu-latest
permissions:
security-events: write

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
persist-credentials: false

- name: Install uv
uses: astral-sh/setup-uv@f0ec1fc3b38f5e7cd731bb6ce540c5af426746bb

- name: Run zizmor 🌈
run: uvx zizmor --format=sarif .github > results.sarif

env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Upload SARIF file
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
category: zizmor
11 changes: 6 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
/TODO*
/dirhtml/
_cache
_static
_templates

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
@@ -150,8 +156,3 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

# User defined
_cache
_static
_templates
13 changes: 2 additions & 11 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ exclude: json/

repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
rev: v5.0.0
hooks:
- id: check-ast
- id: check-json
@@ -16,16 +16,7 @@ repos:
args: [--fix, lf]
- id: trailing-whitespace
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.1.13"
rev: "v0.11.13"
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
- repo: https://github.com/PyCQA/isort
rev: 5.13.2
hooks:
- id: isort
- repo: https://github.com/pre-commit/mirrors-prettier
rev: "v4.0.0-alpha.8"
hooks:
- id: prettier
exclude: "^jsonschema/benchmarks/issue232/issue.json$"
18 changes: 18 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
v4.24.0
=======

* Fix improper handling of ``unevaluatedProperties`` in the presence of ``additionalProperties`` (#1351).
* Support for Python 3.8 has been dropped, as it is end-of-life.

v4.23.0
=======

* Do not reorder dictionaries (schemas, instances) that are printed as part of validation errors.
* Declare support for Py3.13

v4.22.0
=======

* Improve ``best_match`` (and thereby error messages from ``jsonschema.validate``) in cases where there are multiple *sibling* errors from applying ``anyOf`` / ``allOf`` -- i.e. when multiple elements of a JSON array have errors, we now do prefer showing errors from earlier elements rather than simply showing an error for the full array (#1250).
* (Micro-)optimize equality checks when comparing for JSON Schema equality by first checking for object identity, as ``==`` would.

v4.21.1
=======

2 changes: 0 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
@@ -134,8 +134,6 @@ I'm Julian Berman.

Get in touch, via GitHub or otherwise, if you've got something to contribute, it'd be most welcome!

You can also generally find me on Libera (nick: ``Julian``) in various channels, including ``#python``.

If you feel overwhelmingly grateful, you can also `sponsor me <https://github.com/sponsors/Julian/>`_.

And for companies who appreciate ``jsonschema`` and its continued support and growth, ``jsonschema`` is also now supportable via `TideLift <https://tidelift.com/subscription/pkg/pypi-jsonschema?utm_source=pypi-jsonschema&utm_medium=referral&utm_campaign=readme>`_.
16 changes: 10 additions & 6 deletions docs/conf.py
Original file line number Diff line number Diff line change
@@ -123,19 +123,23 @@ def entire_domain(host):

autosectionlabel_prefix_document = True

# -- intersphinx --

intersphinx_mapping = {
"python": ("https://docs.python.org/3", None),
"referencing": ("https://referencing.readthedocs.io/en/stable/", None),
}

# -- extlinks --

extlinks = {
"ujs": ("https://json-schema.org/understanding-json-schema%s", None),
}
extlinks_detect_hardcoded_links = True
# -- sphinx-copybutton --

# -- intersphinx --

intersphinx_mapping = {
"python": ("https://docs.python.org/3", None),
"referencing": ("https://referencing.readthedocs.io/en/stable/", None),
}
copybutton_prompt_text = r">>> |\.\.\. |\$"
copybutton_prompt_is_regexp = True

# -- sphinxcontrib-spelling --

4 changes: 2 additions & 2 deletions docs/errors.rst
Original file line number Diff line number Diff line change
@@ -216,8 +216,8 @@ easier debugging.
3 is not valid under any of the given schemas

Failed validating 'anyOf' in schema['items']:
{'anyOf': [{'maxLength': 2, 'type': 'string'},
{'minimum': 5, 'type': 'integer'}]}
{'anyOf': [{'type': 'string', 'maxLength': 2},
{'type': 'integer', 'minimum': 5}]}

On instance[1]:
3
Loading