diff --git a/.github/workflows/publish-to-test-pypi.yml b/.github/workflows/publish-to-test-pypi.yml index 9410aba..1c43b6b 100644 --- a/.github/workflows/publish-to-test-pypi.yml +++ b/.github/workflows/publish-to-test-pypi.yml @@ -5,13 +5,21 @@ on: branches: - 'develop' - 'release/**' + workflow_dispatch: + inputs: + publish: + description: 'Publish the validated artifacts to TestPyPI' + required: false + default: false + type: boolean permissions: contents: read + id-token: write jobs: build-n-publish: - name: Build and publish Python 🐍 distributions 📦 to TestPyPI + name: Build Python 🐍 distributions 📦 and optionally publish to TestPyPI runs-on: ubuntu-latest steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 @@ -20,11 +28,12 @@ jobs: with: python-version: '3.12' - - name: Install pypa/build + - name: Install packaging tools run: >- python -m pip install build + twine --user - name: Build a binary wheel and a source tarball run: >- @@ -35,10 +44,14 @@ jobs: --outdir dist/ . + - name: Check distribution metadata + run: python -m twine check dist/* + - name: Publish distribution 📦 to Test PyPI + if: github.event_name == 'workflow_dispatch' && inputs.publish uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0 with: user: __token__ password: ${{ secrets.TEST_PYPI_API_TOKEN }} - repository_url: https://test.pypi.org/legacy/ - skip_existing: true + repository-url: https://test.pypi.org/legacy/ + skip-existing: true diff --git a/HISTORY.rst b/HISTORY.rst index cbc356c..4f61b63 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -1,4 +1,15 @@ +6.5.0 / 2026-07-15 +================== + + * perf: reduce pure Python serializer time by 31.1% on the deterministic 5,000-record benchmark through exact native-type dispatch + * perf: release ``json2xml-rs`` 0.4.2 with hybrid SIMD/word XML escape scanning and a 6.23% benchmark reduction + * fix: preserve numeric, string, dictionary, and sequence subclass behavior across the optimized Python dispatch paths + * test: require exactly 100% statement coverage from the complete Python suite and add dense Rust XML escape scanning regression coverage + * chore: require ``json2xml-rs>=0.4.2`` from ``json2xml[fast]`` and validate release wheels before PyPI publication + * docs: add Python and Rust before/after flamegraphs, buffer-capacity measurements, and release performance notes + + 6.4.0 / 2026-07-13 ================== diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 527c6fb..8fee9d7 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,3 +1,45 @@ +# json2xml 6.5.0 + +Released 2026-07-15. + +## Highlights + +- Reduced pure Python serializer time by 31.1% on the deterministic 5,000-record workload by using exact native-type dispatch on hot paths while preserving subclass fallbacks. +- Added explicit regression coverage for `Decimal`, `Fraction`, complex, custom `Number`, string, dictionary, list, and tuple subclasses. +- Made the complete Python suite an exact 100% statement-coverage gate: 421 tests cover all 762 statements. +- Updated `json2xml[fast]` to require the published `json2xml-rs>=0.4.2` accelerator. + +## Performance + +All profiles used uv-managed CPython 3.15.0b3 and the same deterministic 5,000-record nested payload. + +| Pure Python metric | Before | After | Change | +| --- | ---: | ---: | ---: | +| Conversion time | 83.0 ms | 57.2 ms | 31.1% lower | +| 20-loop traced time | 8.311 s | 5.782 s | 30.4% lower | +| Function calls | 48.17 million | 30.13 million | 37.4% fewer | +| `isinstance` calls | 11.70 million | 2.80 million | 76.1% fewer | + +The Rust 0.4.2 accelerator released first and improved its paired release median from 6.007 ms to 5.632 ms, or 6.23%, with identical 4,093,244-byte output. Its hybrid scanner keeps dense XML escape input linear, and the measured 16 KiB streaming buffer remains unchanged. + +## Package Versions + +- Python package: `json2xml==6.5.0` +- Rust accelerator: `json2xml-rs==0.4.2` +- Fast install: `pip install "json2xml[fast]==6.5.0"` + +## Profiling Evidence + +- [Python before flamegraph](docs/flamegraphs/python315-before.svg) +- [Python after flamegraph](docs/flamegraphs/python315-after.svg) +- [Rust before flamegraph](docs/flamegraphs/rust-before.svg) +- [Rust after flamegraph](docs/flamegraphs/rust-after.svg) + +## Verification + +The release passed the full cross-platform Python matrix, Rust formatting and Clippy checks, 48 Rust unit tests, 421 Python tests with exactly 100% statement coverage, and install tests against the published Rust 0.4.2 wheels. + + # json2xml_rs 0.4.2 Released 2026-07-15. diff --git a/json2xml/__init__.py b/json2xml/__init__.py index e5a66f3..e2726ba 100644 --- a/json2xml/__init__.py +++ b/json2xml/__init__.py @@ -2,4 +2,4 @@ __author__ = """Vinit Kumar""" __email__ = "mail@vinitkumar.me" -__version__ = "6.4.0" +__version__ = "6.5.0" diff --git a/lat.md/architecture.md b/lat.md/architecture.md index 802c111..b33f30e 100644 --- a/lat.md/architecture.md +++ b/lat.md/architecture.md @@ -72,7 +72,7 @@ Runtime dependencies are declared in `pyproject.toml` and mirrored by `uv.lock`; GitHub Actions workflows run with read-only tokens by default and use full SHA pins so third-party action updates are explicit. -The `.github/workflows/` files declare the minimum `permissions:` scopes needed by each workflow, with CodeQL retaining `security-events: write` for result upload. Action references are pinned to immutable commits with the upstream tag retained in comments for reviewability, and `.github/dependabot.yml` checks the `github-actions` ecosystem weekly so those pins do not silently age. The Python test matrix pins its PyPy 3.11 job to an explicit PyPy release so CI keeps exercising the intended CPython 3.11.15-compatible runtime instead of silently drifting with runner cache updates. It also exercises regular CPython 3.15.0b3 while leaving that beta's free-threaded builds out of CI until the runner support is less brittle. +The `.github/workflows/` files declare the minimum `permissions:` scopes needed by each workflow, with CodeQL retaining `security-events: write` for result upload and TestPyPI retaining `id-token: write` for explicit trusted-publishing runs. Release-branch pushes build distributions and run Twine checks; TestPyPI upload is a manual opt-in because that external registry requires separate publisher configuration. Action references are pinned to immutable commits with the upstream tag retained in comments for reviewability, and `.github/dependabot.yml` checks the `github-actions` ecosystem weekly so those pins do not silently age. The Python test matrix pins its PyPy 3.11 job to an explicit PyPy release so CI keeps exercising the intended CPython 3.11.15-compatible runtime instead of silently drifting with runner cache updates. It also exercises regular CPython 3.15.0b3 while leaving that beta's free-threaded builds out of CI until the runner support is less brittle. Rust extension CI triggers on Rust sources, Rust integration tests, and Python fast-path files such as [[json2xml/backend_selector.py]] and [[json2xml/dicttoxml_fast.py]]. That keeps native backend tests attached to the Python dispatch code that decides whether the accelerator is used. diff --git a/pyproject.toml b/pyproject.toml index 1a8aba8..9ed17e8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "json2xml" -version = "6.4.0" +version = "6.5.0" description = "Simple Python Library to convert JSON to XML" readme = "README.rst" requires-python = ">=3.10" @@ -50,7 +50,7 @@ dev = [ "pygments>=2.20.0", "xmltodict>=0.12.0", ] -fast = ["json2xml-rs>=0.4.1"] +fast = ["json2xml-rs>=0.4.2"] [tool.pytest.ini_options] testpaths = ["tests"] diff --git a/uv.lock b/uv.lock index e089a7c..3985cc1 100644 --- a/uv.lock +++ b/uv.lock @@ -147,7 +147,7 @@ wheels = [ [[package]] name = "json2xml" -version = "6.4.0" +version = "6.5.0" source = { editable = "." } dependencies = [ { name = "defusedxml" }, @@ -171,7 +171,7 @@ fast = [ requires-dist = [ { name = "coverage", marker = "extra == 'dev'" }, { name = "defusedxml" }, - { name = "json2xml-rs", marker = "extra == 'fast'", specifier = ">=0.4.1" }, + { name = "json2xml-rs", marker = "extra == 'fast'", specifier = ">=0.4.2" }, { name = "pygments", marker = "extra == 'dev'", specifier = ">=2.20.0" }, { name = "pytest", marker = "extra == 'dev'", specifier = ">=8.4.1" }, { name = "pytest-cov", marker = "extra == 'dev'" }, @@ -183,39 +183,41 @@ provides-extras = ["dev", "fast"] [[package]] name = "json2xml-rs" -version = "0.4.1" +version = "0.4.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/9b/48/bfce5499488c57a1d2dc07c35ade98edd0b4f385828e537132e220a703ab/json2xml_rs-0.4.1.tar.gz", hash = "sha256:dbf19cfe93cee3c245cffa64668fde9380d85a33da716bfbd43a9b41bc2c7e6e", size = 8914, upload-time = "2026-07-13T17:06:28.075Z" } +sdist = { url = "https://files.pythonhosted.org/packages/4b/df/24550bb7664ef8aba5e6ea8aa6f6f29dffa4bcab8a4415d492cf9130c499/json2xml_rs-0.4.2.tar.gz", hash = "sha256:be63b26a8885002dcdd2d11d8685251224370cc1a45073ff226a5a6ecf15d508", size = 9860, upload-time = "2026-07-15T19:29:16.138Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ac/37/0585f1b0fae8a4e0c82d5312e52f41a0bb1d09a33dbf08f94a384105a7ed/json2xml_rs-0.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa4d185d6786aca2f7458eaa4ce52594c05902d0f9676b1566e862962ea75e11", size = 229081, upload-time = "2026-07-13T17:05:40.019Z" }, - { url = "https://files.pythonhosted.org/packages/1f/a4/a2394e43e7e861b4b14784b70ecc229d8a06a1dede555a172105d2bf45b2/json2xml_rs-0.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d7bce8bb920e942f6a4283d44c81a168e65fc7ab9575a9b2435ef22a0d60b8d", size = 230950, upload-time = "2026-07-13T17:05:41.934Z" }, - { url = "https://files.pythonhosted.org/packages/a6/11/4ad4e7f031baa699cc56e536e33a9d8840e65008bb93f25ca61dcd942a37/json2xml_rs-0.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:90824b0754f9a2e6f252b867848605973ebdcf6ffc0e697aa4d670cc991e7323", size = 117686, upload-time = "2026-07-13T17:05:43.422Z" }, - { url = "https://files.pythonhosted.org/packages/56/73/d82523fcd6f61878d86f87f8101cf3943c9e0e3c964634f1d13126088f97/json2xml_rs-0.4.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:74984dd97a1048984e396013afdc13c1110c506f5fd4f2d29f694290572a3f0d", size = 222412, upload-time = "2026-07-13T17:05:45.008Z" }, - { url = "https://files.pythonhosted.org/packages/1c/d8/3dd97f1da5898d30b2ed58caf4e5d99f45d7b8888914e8f61e0819ea3dc1/json2xml_rs-0.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c4b315c5d2c24b2897f136bb1dda8f91e2ab764312ac534a3af34e50d2b2fadc", size = 213292, upload-time = "2026-07-13T17:05:46.726Z" }, - { url = "https://files.pythonhosted.org/packages/68/9e/c7363a6042bde846d8947312cfa8877a01e83a6977fa43fd80f4eb29f0cf/json2xml_rs-0.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2880d03274cd67564d9699c46615e79efea1a6e0bf9f06c5b4e6f57fbfc61ff6", size = 228754, upload-time = "2026-07-13T17:05:48.192Z" }, - { url = "https://files.pythonhosted.org/packages/95/5a/9c0a539bb55c55d089e3d70e59fe04628333017d792681e82b35e9fe902d/json2xml_rs-0.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5084cbb7ba964e3cb0a16eba2e84caba72d73fcc17c53cc9f5ab2491bc4960a5", size = 230828, upload-time = "2026-07-13T17:05:49.699Z" }, - { url = "https://files.pythonhosted.org/packages/20/d9/31276b02aaecdd57b8a25c4e645575e1645e12fee13329a42d5daf339dbf/json2xml_rs-0.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:7b6e57ee8877472d20c788a271f2432b0ae4728eeced6ff935945e71c24f2a34", size = 117578, upload-time = "2026-07-13T17:05:51.202Z" }, - { url = "https://files.pythonhosted.org/packages/37/c2/83e72a246053a4cd0491c698f8767d339e0296c06bcd177fac3d371ea3b6/json2xml_rs-0.4.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:cfc9e004f4e68b68baec94ba4cb3992c41559cd87de2043191752cf485dee365", size = 221538, upload-time = "2026-07-13T17:05:52.614Z" }, - { url = "https://files.pythonhosted.org/packages/e1/92/334cb874cfdfe6be0a116f390deb98a18bd5a2b1bbc21e2f8260284f0401/json2xml_rs-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fb985dc9c85c8827fd0fa41461d1911b3d8727c7af89a8ad4fe75add962f9a1c", size = 212626, upload-time = "2026-07-13T17:05:54.253Z" }, - { url = "https://files.pythonhosted.org/packages/f6/69/57f2f2a5fcd9ff0868e51722c3af23f598d9c8f56c71a77e6e5938eae178/json2xml_rs-0.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:216e92edd74eed0fd23afc031d45f2c2d923601ad8ced8cc22716e4b2a9284d3", size = 228511, upload-time = "2026-07-13T17:05:55.739Z" }, - { url = "https://files.pythonhosted.org/packages/eb/eb/7b45931346c862b65ec5076dcccb77f4b2f90bb42e72d13a3f108fddbc95/json2xml_rs-0.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b5483f085e0b99b0cd540c61bf3cc226d2e650fcf48dccdee98fb7d5ea72de5", size = 230760, upload-time = "2026-07-13T17:05:57.802Z" }, - { url = "https://files.pythonhosted.org/packages/b6/a0/a75b82cff8fcd5054b5f0f7a95c77f3a002650b8ef4bbc77b52aa98f97f4/json2xml_rs-0.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:c25d6ecd31e3457ad0046023242be1443ede4fc0061dabfa06b9a161b047af51", size = 116141, upload-time = "2026-07-13T17:05:59.223Z" }, - { url = "https://files.pythonhosted.org/packages/11/db/5adff090727f864c37d113ab47d8000e5e1978efe06a905fca0239ba9490/json2xml_rs-0.4.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:bdfe8c44dfe7745ef3dbb0eb73db92daf65621392f2343fac73e07bad68eaa22", size = 221748, upload-time = "2026-07-13T17:06:00.698Z" }, - { url = "https://files.pythonhosted.org/packages/ab/ec/8c69c2604d8a2c11421b75ff6c8e91b0ded55d6acf9553ffcb333df828ab/json2xml_rs-0.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4f05dfb166ca6743d6cd4831f012f37ba9935b19c43df7e4d229bbb83f6751dd", size = 212755, upload-time = "2026-07-13T17:06:02.326Z" }, - { url = "https://files.pythonhosted.org/packages/c8/e3/e317794dfdb40c28b9bda7d9bb1d96fdedc072b217ab3d56a0ee3877ab2a/json2xml_rs-0.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a8c4dac06e64ba0fed8c25256a56de1fcec6a96f9a556f7718b0ee474fa177b8", size = 228452, upload-time = "2026-07-13T17:06:04.012Z" }, - { url = "https://files.pythonhosted.org/packages/4a/7b/4c55143bf8c14390fe9f4ab89e4c25ada1aca73392e5c6d9c1836722ec29/json2xml_rs-0.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d12d81cf4f062f5c00d35e2df9850bed5658dba346951e48a7bbef3b345d7ce", size = 230860, upload-time = "2026-07-13T17:06:05.419Z" }, - { url = "https://files.pythonhosted.org/packages/93/16/c154da9ad023d3442bd4cc9aa190d5893ba704220546060c9fcaeb9f86b8/json2xml_rs-0.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:1cbf1ce9e18d6a72c0d39e211e21534358e32f37e63a1a8a894850f1cdd690c6", size = 116324, upload-time = "2026-07-13T17:06:07.05Z" }, - { url = "https://files.pythonhosted.org/packages/5b/3f/a7a67c3a153eb0365a745164dda65878f829ccdb4938b5c03ee2896dd4d2/json2xml_rs-0.4.1-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:e7875b727f5cc610530189b4f89530dd167d27c67c9b69945e52fc3e8ab51889", size = 221559, upload-time = "2026-07-13T17:06:08.411Z" }, - { url = "https://files.pythonhosted.org/packages/fb/d1/a6875d15decdfa0ae99f9343620681303c0acfcaf143f65a33df373b2864/json2xml_rs-0.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9ea5f30c8975dcc3707679fe604b0a942865e586320972b38d7d2be1de606c63", size = 212526, upload-time = "2026-07-13T17:06:10.003Z" }, - { url = "https://files.pythonhosted.org/packages/8f/67/78cda0d6327eb070df0c73463f70a1e3d7e3c146a8b2e086b1954890a0a5/json2xml_rs-0.4.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df3a0574823d32d723ed9859e37ebe5214698fb7e44c064d0d981c61bb049c85", size = 228134, upload-time = "2026-07-13T17:06:11.435Z" }, - { url = "https://files.pythonhosted.org/packages/c6/77/49c4753c215b957e11b6ef09203208f8f89d63c6aeebdc12c11869070c1f/json2xml_rs-0.4.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b0c102cd456ef0e8df86866036b8c8ad8e8f9c849e3e4888d04ce84a1d74af87", size = 230656, upload-time = "2026-07-13T17:06:12.998Z" }, - { url = "https://files.pythonhosted.org/packages/c7/ea/04a244cab81d45eab1dd1390216a3b9eb7dc4e13dd35c725a23d9731faeb/json2xml_rs-0.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:3d00c5494ef307b4c30e0db38e7c4c06d62f79325292b9a7d7500a4d278fbfac", size = 116198, upload-time = "2026-07-13T17:06:14.474Z" }, - { url = "https://files.pythonhosted.org/packages/f9/c7/bb4504020a56f4261b4ab1c154fc6c1d2ecd12f3efc80b266801a7fb8fd2/json2xml_rs-0.4.1-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88b38b46d51402d2c84de2dade3f1f22fe734d150888459b94c98592215468bd", size = 227103, upload-time = "2026-07-13T17:06:15.855Z" }, - { url = "https://files.pythonhosted.org/packages/3c/5f/ebaa62c9638bd9d24deca908b1669b7a8116f8bdc15ac9af7cd3c85531fc/json2xml_rs-0.4.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a617ce050a24429b620c830a9c63696c495c49c850e3e3f285a1db4ec3c15c4b", size = 229906, upload-time = "2026-07-13T17:06:17.278Z" }, - { url = "https://files.pythonhosted.org/packages/5e/61/399bfd831209e8048ebcf682fbb5dfe77d54a88cc2101eb482c4d09ee87e/json2xml_rs-0.4.1-cp315-cp315-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad559dd9a5347c737ae836e6ec099ae4809de3047f966f29cbb8057912e71c8a", size = 230209, upload-time = "2026-07-13T17:06:18.768Z" }, - { url = "https://files.pythonhosted.org/packages/5d/b6/029a61bda8b99acdb55f9b9fe20bd8fe3aea640c188441314619fc8d57bf/json2xml_rs-0.4.1-cp315-cp315t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7cc455557f2513b16180d62f0d9e7beec0c1443aa8002ed24e1a991068de0ae4", size = 229388, upload-time = "2026-07-13T17:06:20.397Z" }, - { url = "https://files.pythonhosted.org/packages/00/2b/c35ad343890bafa34e23679036e3359f3ed926a654b2ffa8a6710708ca66/json2xml_rs-0.4.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e20248aff6da25605614cb79ea101397a06adbcbdcdfa2086ac96776e397f9a9", size = 230599, upload-time = "2026-07-13T17:06:25.287Z" }, - { url = "https://files.pythonhosted.org/packages/81/a2/9e04945abd24b1b864818cd493e013f0f27e13b44d26be592e0c9e9ecc4d/json2xml_rs-0.4.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9552062589e85bb8ead1b68355d481e431bb95954e121abf9675465257f81bc", size = 232677, upload-time = "2026-07-13T17:06:26.809Z" }, + { url = "https://files.pythonhosted.org/packages/44/71/5d1bbf681d61a86232396568e9b117d4b399b6fd85f4242022e01953640e/json2xml_rs-0.4.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:7ad92712ed0c61da1287d8af1ed0ea7d29b1db5677cfee962b81b89161a7d3d5", size = 228754, upload-time = "2026-07-15T19:28:30.647Z" }, + { url = "https://files.pythonhosted.org/packages/8d/22/f5c4809a28861783162ab2379237330dc7238c6aefb58126fe7da9a7f520/json2xml_rs-0.4.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ff28b3c5ae09e0d716604b5fad0cd202b907f06cd801d1ae5fff505b5d898c64", size = 216101, upload-time = "2026-07-15T19:28:32.063Z" }, + { url = "https://files.pythonhosted.org/packages/02/6b/180d0fe7e544ad8e80730bc8f9e2b0036be5d7c494ad6cf3b4592bdaa685/json2xml_rs-0.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84f88fac51361577cdbaedc00869524a2d52cf31d8ca3a725ffa9cd5e03503b8", size = 232071, upload-time = "2026-07-15T19:28:33.324Z" }, + { url = "https://files.pythonhosted.org/packages/81/19/f76b390ea40d5ca49e3bae3a1ba237e644bf675c0970ccf45385f7d28b4e/json2xml_rs-0.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7335ca3eda98f64f55afc5341105aecb5280f76ade5801f46c587b2ec5a18e26", size = 236773, upload-time = "2026-07-15T19:28:34.596Z" }, + { url = "https://files.pythonhosted.org/packages/a8/0b/44c03dc291ad98340c506ea818be397cf1737b6f00453da7c3805cc88aa9/json2xml_rs-0.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:8d9aa18496e198a3dd4040d038b1fd5141419a474ccdd58ab6480980b70447cd", size = 122693, upload-time = "2026-07-15T19:28:36.051Z" }, + { url = "https://files.pythonhosted.org/packages/1d/a8/fea4fcd7c24679f76cbebbbddef33d48e96b069bb4864ed9bb08be9d922c/json2xml_rs-0.4.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:cf0e15a6125bd5898a5df4e58b3931bbdf30f6e2c1bd3a7c068372bed50a4734", size = 228456, upload-time = "2026-07-15T19:28:37.474Z" }, + { url = "https://files.pythonhosted.org/packages/eb/53/963029983dadaa9ddffd623abe667f79c0f547b7fb62127df9208bbeb3a1/json2xml_rs-0.4.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bff5ad506356af0ff3d8bf2677918c00d9c94f06891c871f16f71f0fc257025e", size = 215993, upload-time = "2026-07-15T19:28:38.994Z" }, + { url = "https://files.pythonhosted.org/packages/fe/4e/039c16db1400e5196accb8be1bf55e5f0c36ff8b0d056d0ce235a2972179/json2xml_rs-0.4.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:570bcd5708adda2bc49731776ee6a638a7aab39b53937afcc15a53ef3a795edd", size = 231705, upload-time = "2026-07-15T19:28:40.424Z" }, + { url = "https://files.pythonhosted.org/packages/da/1c/33e64336547a93998f6dac21795495a1c3571de4dadcbcaaf37b103c691a/json2xml_rs-0.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59dee86ddf29793b8abd409244d04f99f46686f4e74214869e90322f826b5d3d", size = 236573, upload-time = "2026-07-15T19:28:41.908Z" }, + { url = "https://files.pythonhosted.org/packages/46/7e/4d8eb642839f5f930ea0dfa1dffbbcc8da1161e66da41c054bd217e5b252/json2xml_rs-0.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:a56cce17b6d7844aa34cab93ecab5e8eeb38d07d31c55b530a5825a2c89e4f04", size = 122676, upload-time = "2026-07-15T19:28:43.313Z" }, + { url = "https://files.pythonhosted.org/packages/9f/03/4e4150adf7ba5cf2ea87bc9767113840407041b158283bbdacf5c7983d56/json2xml_rs-0.4.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:b8ae72d10ef65d938d04f7e86ef3c09ffb033c0646a9dbba298db8908147ccfd", size = 227337, upload-time = "2026-07-15T19:28:44.471Z" }, + { url = "https://files.pythonhosted.org/packages/08/2b/7b0489f5a0a656ad53c3ef2771a9ccca13d26e18b70d1fa93a7ab98b5a4c/json2xml_rs-0.4.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8da6b104093281da9a83ed3de14738c4a4b344a9fc929b04d227a109de119cae", size = 215399, upload-time = "2026-07-15T19:28:45.731Z" }, + { url = "https://files.pythonhosted.org/packages/ab/13/8f21655528e7e53c2bcad443520a9b205877871d43681a33953ed3d2e750/json2xml_rs-0.4.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e0d6d250c7934a98cdddf50470a96409929567bfa58cd77b3f141bce887a85d8", size = 231336, upload-time = "2026-07-15T19:28:47.248Z" }, + { url = "https://files.pythonhosted.org/packages/b2/fb/f7966a2d48b1c5d5a25b036ba8e7ed3ccc410630ec12e40d9ca0b5f0fb65/json2xml_rs-0.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d7b8a46e0011621d380079d32f63c5cc37fa87832587752c2ba0f2b36524242", size = 236633, upload-time = "2026-07-15T19:28:48.557Z" }, + { url = "https://files.pythonhosted.org/packages/74/59/6e52737b557fb81974fcf1b5454d9344c56db5d25948e0aac8efe2e1c502/json2xml_rs-0.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:168b875b2bd8b57952907b042e68802b82fca67124abe9447133fc55c95cc2dd", size = 121111, upload-time = "2026-07-15T19:28:49.915Z" }, + { url = "https://files.pythonhosted.org/packages/04/28/f5f108b1e54a086463d3ea512b748d86f116a3d098b51772c2e278e452c1/json2xml_rs-0.4.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:953620b10c9f5a1e8e72c51c3083d8afacb4be1d31450329ba225068f8276edc", size = 227522, upload-time = "2026-07-15T19:28:51.197Z" }, + { url = "https://files.pythonhosted.org/packages/98/df/d22d3c95ccfa59b7836b676fbc43a82ef7457cefa32673a2052048368c0f/json2xml_rs-0.4.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bf71582f53627e815f796bdac6ec571089508ec2b0fb1945fff88ca30eb3c8ea", size = 215557, upload-time = "2026-07-15T19:28:52.518Z" }, + { url = "https://files.pythonhosted.org/packages/56/14/cbbd821e1abaa682255540563f589a723eb4a6701a5eb2b7ee889a9a64f1/json2xml_rs-0.4.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b049f77c4299ee911f467d9e3b3a557500373a614e8d3d882ec825d9b2ae058e", size = 231366, upload-time = "2026-07-15T19:28:53.816Z" }, + { url = "https://files.pythonhosted.org/packages/75/fa/0b8d7e4e929550294af87f074eec265102c5095106bec924a698437deb79/json2xml_rs-0.4.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c191f9f3480aa83ef265034f51802def53ab59dc9fd17b071c0bb67d4493a8e", size = 236723, upload-time = "2026-07-15T19:28:55.302Z" }, + { url = "https://files.pythonhosted.org/packages/92/85/13a730c16684e43abad6613573e560fbc26eb84009f9f67f9fe7d1227f71/json2xml_rs-0.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:72ab02d5cc23ad2539d8d3ab14af8d58c3179bb2e6f7843a82206e615664f031", size = 121314, upload-time = "2026-07-15T19:28:56.595Z" }, + { url = "https://files.pythonhosted.org/packages/72/6f/01af728bb5003b7960a4f9e427fc893ef976e189e674fb55bda25c9f71e8/json2xml_rs-0.4.2-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:fe2ee5d59fb7c5d805692dce80cde4aa21a535e64eb71979806b5d981af3e417", size = 227266, upload-time = "2026-07-15T19:28:57.776Z" }, + { url = "https://files.pythonhosted.org/packages/90/32/e339f6dc9a727e6f50208e0f5e083677f9fab96b3e5ba8cb8a9a48b460eb/json2xml_rs-0.4.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:8f9a99f05fda5844ae3e5858d412e947c714b10881431e777ed826a7ca503c46", size = 215275, upload-time = "2026-07-15T19:28:59.389Z" }, + { url = "https://files.pythonhosted.org/packages/bc/e1/145fe6dbb4312bfb867d28db44d61afe5f785ca8fbb5ee586c91eab3069d/json2xml_rs-0.4.2-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0eb17ed09d57c47e725321321fd93e91b9a29b3e84ee5b32d9e8ca67ce154d4", size = 231013, upload-time = "2026-07-15T19:29:00.744Z" }, + { url = "https://files.pythonhosted.org/packages/41/b2/2e5b6714e6de31e9eba0df50a5fee154ccf5359fd7022b2cf55b7c824a89/json2xml_rs-0.4.2-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e50cbe379830783504fe862ebc9ee44f5ca9eb41fd0d611f6b99dc166bff8560", size = 236491, upload-time = "2026-07-15T19:29:02.143Z" }, + { url = "https://files.pythonhosted.org/packages/ca/b4/77cc6deb8a26f9b837bc1b4d358ff03317e2e98796ba0b742d6de7fd8063/json2xml_rs-0.4.2-cp314-cp314-win_amd64.whl", hash = "sha256:c8472e19f6506fe8e98872136fc6aca062853d03ada8e601343b5c7afbd2ec04", size = 121118, upload-time = "2026-07-15T19:29:03.657Z" }, + { url = "https://files.pythonhosted.org/packages/9b/a3/184a57d724c31db0fa6beffe2fb1eb64d37814e595ea3a1eed4f21cb6cd7/json2xml_rs-0.4.2-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c4d86932ede1ce290724f48f9ac1bbb2413d766b70d0c824257be094c582734", size = 230020, upload-time = "2026-07-15T19:29:05.087Z" }, + { url = "https://files.pythonhosted.org/packages/1b/93/0f162a8b214c9818fa207bb7f5b92677a33f7f5eb445b0195bd17f2bd855/json2xml_rs-0.4.2-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:329447da89fd6af6047604a5f121f243ac8a88ea8f094472732c317f552d9d20", size = 235688, upload-time = "2026-07-15T19:29:06.456Z" }, + { url = "https://files.pythonhosted.org/packages/6c/2f/3014c23537830778357dde18adcc0fa28dfee1fe3a54b82833cbdaf5e05b/json2xml_rs-0.4.2-cp315-cp315-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:30275441b6be1a591948195e5e3fc1130bf9b0a7cf49d8d9fb44290706eff8be", size = 235884, upload-time = "2026-07-15T19:29:07.916Z" }, + { url = "https://files.pythonhosted.org/packages/9c/85/bf705b01d3d1b1fbaeafb9e7b93fe6394d8114ded6a73bf3d36f1355e64d/json2xml_rs-0.4.2-cp315-cp315t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b67c1199080bdba5d7c7a2bbd13e26a1aa990d3af19bcd1ea3d891e5ebf327f", size = 235147, upload-time = "2026-07-15T19:29:09.328Z" }, + { url = "https://files.pythonhosted.org/packages/11/b8/2b6539769b8253c103de8e643dcf351f90faa473be1a3026aa868f2122b0/json2xml_rs-0.4.2-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78c08daa09f46556282603d8ee480062a6d1111d52f3baedd5e7262195de217e", size = 233522, upload-time = "2026-07-15T19:29:13.55Z" }, + { url = "https://files.pythonhosted.org/packages/65/18/cb9b4dba617c8b292dd34674bb8a9a2968e5168e533d64e45d491676f50c/json2xml_rs-0.4.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:826bd78c84b57d0990d1e117b0057b1e47349f4aa25168db7f3c5d6668a33176", size = 238401, upload-time = "2026-07-15T19:29:14.989Z" }, ] [[package]]