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.
Files changed (25) hide show
  1. {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/.github/workflows/CI.yml +19 -1
  2. {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/CHANGELOG.md +9 -0
  3. {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/Cargo.lock +1 -1
  4. {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/Cargo.toml +1 -1
  5. {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/MAINTAINING.md +23 -7
  6. {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/PKG-INFO +1 -1
  7. {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/pyproject.toml +1 -1
  8. {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/python/fastjsonpatch/__init__.py +1 -2
  9. {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/src/lib.rs +2 -0
  10. {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/tests/test_parity.py +35 -0
  11. {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/.gitignore +0 -0
  12. {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/BENCHMARKS.md +0 -0
  13. {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/LICENSE +0 -0
  14. {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/README.md +0 -0
  15. {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/THIRD_PARTY_LICENSES.md +0 -0
  16. {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/bench/compare.py +0 -0
  17. {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/scripts/test_linux_matrix.sh +0 -0
  18. {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/scripts/third_party_licenses.py +0 -0
  19. {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/tests/rfc6902/LICENSE-APACHE-2.0 +0 -0
  20. {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/tests/rfc6902/README.md +0 -0
  21. {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/tests/rfc6902/spec_tests.json +0 -0
  22. {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/tests/rfc6902/test_rfc6902.py +0 -0
  23. {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/tests/rfc6902/tests.json +0 -0
  24. {fastjsonpatch-0.1.3 → fastjsonpatch-0.1.4}/tests/upstream/test_upstream.py +0 -0
  25. {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
- python -m pip install --only-binary fastjsonpatch --find-links dist "fastjsonpatch[test]"
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}`,
@@ -23,7 +23,7 @@ checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600"
23
23
 
24
24
  [[package]]
25
25
  name = "fastjsonpatch"
26
- version = "0.1.3"
26
+ version = "0.1.4"
27
27
  dependencies = [
28
28
  "ahash",
29
29
  "pyo3",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "fastjsonpatch"
3
- version = "0.1.3"
3
+ version = "0.1.4"
4
4
  edition = "2024"
5
5
  description = "Rust core of the fastjsonpatch Python package"
6
6
  license = "BSD-3-Clause"
@@ -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 # ~1570 tests, a few seconds
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 lives only in `pyproject.toml` (`[project] version`);
50
- `fastjsonpatch.__version__` reads it from the installed package. `Cargo.toml` is not
51
- published and can stay at 0.1.0.
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. Update the version in `pyproject.toml` and `CHANGELOG.md`; merge to `main` with green CI.
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 that the tag equals the
61
- version, builds every wheel and the sdist, and publishes to PyPI.
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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastjsonpatch
3
- Version: 0.1.3
3
+ Version: 0.1.4
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: Operating System :: OS Independent
@@ -4,7 +4,7 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "fastjsonpatch"
7
- version = "0.1.3"
7
+ version = "0.1.4"
8
8
  description = "Drop-in faster jsonpatch (RFC 6902): make_patch and apply in Rust"
9
9
  readme = "README.md"
10
10
  license = "BSD-3-Clause"
@@ -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__ = importlib.metadata.version('fastjsonpatch')
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