fastjsonpatch 0.1.3__tar.gz → 0.1.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/.github/workflows/CI.yml +19 -1
- {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/CHANGELOG.md +9 -0
- {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/Cargo.lock +1 -1
- {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/Cargo.toml +1 -1
- {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/MAINTAINING.md +23 -7
- {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/PKG-INFO +1 -1
- {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/pyproject.toml +1 -1
- {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/python/fastjsonpatch/__init__.py +1 -2
- {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/src/lib.rs +2 -0
- {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/tests/test_parity.py +35 -0
- {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/.gitignore +0 -0
- {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/BENCHMARKS.md +0 -0
- {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/LICENSE +0 -0
- {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/README.md +0 -0
- {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/THIRD_PARTY_LICENSES.md +0 -0
- {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/bench/compare.py +0 -0
- {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/scripts/test_linux_matrix.sh +0 -0
- {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/scripts/third_party_licenses.py +0 -0
- {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/tests/rfc6902/LICENSE-APACHE-2.0 +0 -0
- {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/tests/rfc6902/README.md +0 -0
- {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/tests/rfc6902/spec_tests.json +0 -0
- {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/tests/rfc6902/test_rfc6902.py +0 -0
- {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/tests/rfc6902/tests.json +0 -0
- {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/tests/upstream/test_upstream.py +0 -0
- {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/tests/upstream/tests.js +0 -0
|
@@ -44,7 +44,10 @@ jobs:
|
|
|
44
44
|
run: |
|
|
45
45
|
python -m pip install --upgrade pip maturin
|
|
46
46
|
maturin build --release --out dist
|
|
47
|
-
|
|
47
|
+
# Install the wheel just built by its path: with --find-links, pip prefers a
|
|
48
|
+
# PyPI wheel of the same version and platform tag over the local one.
|
|
49
|
+
wheel=$(ls dist/*.whl)
|
|
50
|
+
python -m pip install "${wheel}[test]"
|
|
48
51
|
- name: Tests (parity with jsonpatch, upstream suite, RFC 6902 suite)
|
|
49
52
|
shell: bash
|
|
50
53
|
run: |
|
|
@@ -127,6 +130,21 @@ jobs:
|
|
|
127
130
|
name: sdist
|
|
128
131
|
path: dist
|
|
129
132
|
|
|
133
|
+
# One check for branch protection to require: fails unless every test, wheel and
|
|
134
|
+
# sdist job succeeded.
|
|
135
|
+
ci-ok:
|
|
136
|
+
name: ci-ok
|
|
137
|
+
needs: [test, wheels, sdist]
|
|
138
|
+
if: always()
|
|
139
|
+
runs-on: ubuntu-latest
|
|
140
|
+
steps:
|
|
141
|
+
- name: All required jobs succeeded
|
|
142
|
+
run: |
|
|
143
|
+
echo 'test=${{ needs.test.result }} wheels=${{ needs.wheels.result }} sdist=${{ needs.sdist.result }}'
|
|
144
|
+
test '${{ needs.test.result }}' = success
|
|
145
|
+
test '${{ needs.wheels.result }}' = success
|
|
146
|
+
test '${{ needs.sdist.result }}' = success
|
|
147
|
+
|
|
130
148
|
publish:
|
|
131
149
|
name: publish to ${{ startsWith(github.ref, 'refs/tags/v') && 'PyPI' || 'TestPyPI' }}
|
|
132
150
|
needs: [test, wheels, sdist]
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.4 (2026-10-12)
|
|
4
|
+
|
|
5
|
+
- `import fastjsonpatch` takes about 11 ms instead of about 53 ms: `__version__` now
|
|
6
|
+
comes from the Rust module instead of `importlib.metadata`, which is no longer
|
|
7
|
+
imported. (jsonpatch 1.34 takes about 11 ms.)
|
|
8
|
+
- CI: the macOS and Windows test jobs installed the wheel from PyPI instead of the
|
|
9
|
+
one built in the job whenever both had the same version; they now install the
|
|
10
|
+
built wheel by path. No change to the package.
|
|
11
|
+
|
|
3
12
|
## 0.1.3 (2026-10-12)
|
|
4
13
|
|
|
5
14
|
- Fix: `replace` with a path ending in `-` that names a dict key (`{"-": 1}`,
|
|
@@ -19,7 +19,7 @@ jsonpatch 1.34. A behaviour difference is a bug, unless it is listed in the READ
|
|
|
19
19
|
```sh
|
|
20
20
|
maturin develop --release
|
|
21
21
|
pip install "jsonpatch==1.34" pytest
|
|
22
|
-
pytest tests # ~
|
|
22
|
+
pytest tests # ~1580 tests, a few seconds
|
|
23
23
|
python bench/compare.py # speed vs jsonpatch
|
|
24
24
|
```
|
|
25
25
|
|
|
@@ -33,6 +33,19 @@ python bench/compare.py # speed vs jsonpatch
|
|
|
33
33
|
CI runs the tests and the speed comparison on Linux x86_64/arm64, macOS arm64/x86_64
|
|
34
34
|
and Windows for Python 3.12, 3.13 and 3.14; the run's summary page has the table.
|
|
35
35
|
|
|
36
|
+
## Making changes
|
|
37
|
+
|
|
38
|
+
Every change goes through a pull request; nothing is pushed to `main` directly.
|
|
39
|
+
|
|
40
|
+
1. Branch from `main` (`fix/...`, `feat/...`, `chore/...`), commit, push the branch.
|
|
41
|
+
2. Open a pull request. CI runs on it; the `ci-ok` check passes only when every
|
|
42
|
+
test, wheel and sdist job passed.
|
|
43
|
+
3. Review the diff on the pull request page, then merge (squash or merge commit).
|
|
44
|
+
|
|
45
|
+
`main` has a branch rule that requires a pull request and the `ci-ok` check. It does
|
|
46
|
+
not require an approving review: GitHub does not let the author approve their own
|
|
47
|
+
pull request, and the maintainer pushes with their own account.
|
|
48
|
+
|
|
36
49
|
## Versions
|
|
37
50
|
|
|
38
51
|
[Semantic versioning](https://semver.org): `MAJOR.MINOR.PATCH`.
|
|
@@ -46,19 +59,22 @@ and Windows for Python 3.12, 3.13 and 3.14; the run's summary page has the table
|
|
|
46
59
|
While on 0.x the API may still change between minor versions. Go to 1.0 once the
|
|
47
60
|
package has had real-world use without behaviour bugs.
|
|
48
61
|
|
|
49
|
-
The version
|
|
50
|
-
`fastjsonpatch.__version__` reads it from the installed package. `Cargo.toml`
|
|
51
|
-
|
|
62
|
+
The published version comes from `pyproject.toml` (`[project] version`);
|
|
63
|
+
`fastjsonpatch.__version__` reads it from the installed package. Keep `Cargo.toml`
|
|
64
|
+
and `Cargo.lock` at the same version (they ship in the sdist).
|
|
52
65
|
|
|
53
66
|
## Releasing
|
|
54
67
|
|
|
55
|
-
1.
|
|
68
|
+
1. In a pull request, update the version in `pyproject.toml`, `Cargo.toml` (and
|
|
69
|
+
`Cargo.lock`) and `CHANGELOG.md`; merge it with a green `ci-ok`.
|
|
56
70
|
2. Optional dry run: Actions → CI → "Run workflow" with target `testpypi`, then
|
|
57
71
|
`pip install -i https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ fastjsonpatch`.
|
|
58
72
|
A version number can be uploaded to TestPyPI only once as well, so use a dev
|
|
59
73
|
version (e.g. `0.1.1.dev1`) for dry runs.
|
|
60
|
-
3. `git tag v0.1.1 && git push origin v0.1.1`. CI checks
|
|
61
|
-
version
|
|
74
|
+
3. On the merged `main` commit: `git tag v0.1.1 && git push origin v0.1.1`. CI checks
|
|
75
|
+
that the tag equals the version and builds every wheel and the sdist; the publish
|
|
76
|
+
job then waits for approval in the `pypi` environment (Actions → the run →
|
|
77
|
+
Review deployments) and uploads to PyPI.
|
|
62
78
|
|
|
63
79
|
A version uploaded to PyPI can be yanked (hidden from new installs) but its number can
|
|
64
80
|
never be reused. Fix mistakes with a new PATCH release.
|
|
@@ -50,7 +50,6 @@ Custom pointer classes, custom ``operations`` and subclasses that override
|
|
|
50
50
|
import collections
|
|
51
51
|
import copy
|
|
52
52
|
import functools
|
|
53
|
-
import importlib.metadata
|
|
54
53
|
import json
|
|
55
54
|
from collections.abc import MutableMapping, MutableSequence, Sequence
|
|
56
55
|
from types import MappingProxyType
|
|
@@ -64,7 +63,7 @@ _ST_ADD = 0
|
|
|
64
63
|
_ST_REMOVE = 1
|
|
65
64
|
|
|
66
65
|
|
|
67
|
-
__version__ =
|
|
66
|
+
__version__ = _core.__version__
|
|
68
67
|
__license__ = 'BSD-3-Clause'
|
|
69
68
|
# Version of jsonpatch whose behaviour this module reproduces.
|
|
70
69
|
__jsonpatch_version__ = '1.34'
|
|
@@ -965,5 +965,7 @@ fn _core(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
|
|
965
965
|
m.add_function(wrap_pyfunction!(apply, m)?)?;
|
|
966
966
|
m.add_function(wrap_pyfunction!(validate, m)?)?;
|
|
967
967
|
m.add_function(wrap_pyfunction!(py_deepcopy, m)?)?;
|
|
968
|
+
// The package version, so `fastjsonpatch.__version__` needs no importlib.metadata.
|
|
969
|
+
m.add("__version__", env!("CARGO_PKG_VERSION"))?;
|
|
968
970
|
Ok(())
|
|
969
971
|
}
|
|
@@ -207,6 +207,41 @@ def test_standalone_does_not_import_jsonpatch():
|
|
|
207
207
|
assert out.stdout.strip() == "False"
|
|
208
208
|
|
|
209
209
|
|
|
210
|
+
def test_version_matches_the_installed_package():
|
|
211
|
+
# __version__ comes from Cargo.toml; the wheel's version from pyproject.toml.
|
|
212
|
+
import importlib.metadata
|
|
213
|
+
assert fastjsonpatch.__version__ == importlib.metadata.version("fastjsonpatch")
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
_SPY_IMPORTLIB_METADATA = """
|
|
217
|
+
import sys, traceback
|
|
218
|
+
preloaded = "importlib.metadata" in sys.modules
|
|
219
|
+
for name in [m for m in sys.modules if m == "importlib.metadata" or m.startswith("importlib.metadata.")]:
|
|
220
|
+
del sys.modules[name]
|
|
221
|
+
importers = []
|
|
222
|
+
|
|
223
|
+
class Spy:
|
|
224
|
+
def find_spec(self, name, path=None, target=None):
|
|
225
|
+
if name == "importlib.metadata":
|
|
226
|
+
importers.append("".join(traceback.format_stack(limit=15)))
|
|
227
|
+
|
|
228
|
+
sys.meta_path.insert(0, Spy())
|
|
229
|
+
import fastjsonpatch
|
|
230
|
+
print("preloaded:", preloaded)
|
|
231
|
+
print(importers[0] if importers else "")
|
|
232
|
+
"""
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def test_import_does_not_load_importlib_metadata():
|
|
236
|
+
# importlib.metadata alone used to add ~30 ms to `import fastjsonpatch`. Drop it
|
|
237
|
+
# from sys.modules first, in case the interpreter loaded it at startup, and
|
|
238
|
+
# record who imports it again.
|
|
239
|
+
out = subprocess.run([sys.executable, "-I", "-c", _SPY_IMPORTLIB_METADATA],
|
|
240
|
+
capture_output=True, text=True, check=True)
|
|
241
|
+
preloaded, _, importer = out.stdout.partition("\n")
|
|
242
|
+
assert not importer.strip(), f"{preloaded}; importlib.metadata imported by:\n{importer}"
|
|
243
|
+
|
|
244
|
+
|
|
210
245
|
def test_aliasing_preserved_like_deepcopy():
|
|
211
246
|
shared = [1, 2]
|
|
212
247
|
doc = {"a": shared, "b": shared}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|