Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-nh3 for openSUSE:Factory checked in at 2026-04-08 17:13:40 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-nh3 (Old) and /work/SRC/openSUSE:Factory/.python-nh3.new.21863 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-nh3" Wed Apr 8 17:13:40 2026 rev:7 rq:1344941 version:0.3.4 Changes: -------- --- /work/SRC/openSUSE:Factory/python-nh3/python-nh3.changes 2025-10-07 18:25:50.671059009 +0200 +++ /work/SRC/openSUSE:Factory/.python-nh3.new.21863/python-nh3.changes 2026-04-08 17:13:53.903401616 +0200 @@ -1,0 +2,24 @@ +Sun Apr 5 13:57:40 UTC 2026 - ecsos <[email protected]> + +- Update to 0.3.4 + - Bump pyo3 from 0.28.1 to 0.28.2 in #114 + - Validate rel attribute conflict with link_rel in #117 + - Expose default clean_content_tags as module constant in #118 + - Accept frozenset and Mapping in type stubs in #119 +- Changes from 0.3.3 + - Bump pyo3 from 0.27.1 to 0.27.2 in #106 + - Bump actions/checkout from 5 to 6 in the github-actions group in #105 + - Bump the github-actions group with 2 updates in #108 + - Add riscv64 build, and make target list more explicit #110 + - Bump pyo3 from 0.27.2 to 0.28.0 in #111 +- Changes from 0.3.2 + - Upgrade GitHub Actions in #94 + - GitHub Actions: Stop reinstalling Rust on windows-11-arm in #95 + - Add README reference in pyproject.toml in #97 + - Keep GitHub Actions up to date with GitHub's Dependabot in #96 + - Build wheels for Python 3.14 free-threaded in #100 +- Changes from 0.3.1 + - Bump ammonia from 4.1.1 to 4.1.2 in #93 + - Bump pyo3 from 0.25.1 to 0.26.0 in #92 + +------------------------------------------------------------------- Old: ---- nh3-0.3.0.tar.gz New: ---- nh3-0.3.4.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-nh3.spec ++++++ --- /var/tmp/diff_new_pack.z6DcbE/_old 2026-04-08 17:13:54.847440429 +0200 +++ /var/tmp/diff_new_pack.z6DcbE/_new 2026-04-08 17:13:54.851440594 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-nh3 # -# Copyright (c) 2025 SUSE LLC and contributors +# Copyright (c) 2026 SUSE LLC and contributors # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,7 +18,7 @@ %{?sle15_python_module_pythons} Name: python-nh3 -Version: 0.3.0 +Version: 0.3.4 Release: 0 Summary: Ammonia HTML sanitizer Python binding License: MIT @@ -28,7 +28,7 @@ BuildRequires: %{python_module maturin >= 1.0} BuildRequires: %{python_module pip} BuildRequires: %{python_module pytest} -BuildRequires: cargo +BuildRequires: cargo-packaging BuildRequires: fdupes BuildRequires: python-rpm-macros BuildRequires: zstd ++++++ _service ++++++ --- /var/tmp/diff_new_pack.z6DcbE/_old 2026-04-08 17:13:54.887442074 +0200 +++ /var/tmp/diff_new_pack.z6DcbE/_new 2026-04-08 17:13:54.895442403 +0200 @@ -1,10 +1,8 @@ <services> <service name="download_files" mode="manual"/> <service name="cargo_vendor" mode="manual"> - <param name="srcdir">nh3-0.3.0</param> + <param name="src">nh3-0.3.4.tar.gz</param> <param name="compression">zst</param> </service> - <service name="cargo_audit" mode="manual"> - </service> </services> ++++++ nh3-0.3.0.tar.gz -> nh3-0.3.4.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nh3-0.3.0/.github/dependabot.yml new/nh3-0.3.4/.github/dependabot.yml --- old/nh3-0.3.0/.github/dependabot.yml 2025-07-17 16:38:00.000000000 +0200 +++ new/nh3-0.3.4/.github/dependabot.yml 2006-07-24 03:21:28.000000000 +0200 @@ -9,3 +9,11 @@ directory: "/" # Location of package manifests schedule: interval: "weekly" + - package-ecosystem: "github-actions" + directory: "/" + groups: + github-actions: + patterns: + - "*" # Group all Actions updates into a single larger pull request + schedule: + interval: "weekly" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nh3-0.3.0/.github/workflows/CI.yml new/nh3-0.3.4/.github/workflows/CI.yml --- old/nh3-0.3.0/.github/workflows/CI.yml 2025-07-17 16:38:00.000000000 +0200 +++ new/nh3-0.3.4/.github/workflows/CI.yml 2006-07-24 03:21:28.000000000 +0200 @@ -11,8 +11,8 @@ macos: runs-on: macos-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v6 + - uses: actions/setup-python@v6 with: python-version: 3.12 architecture: x64 @@ -27,7 +27,7 @@ uses: pyo3/maturin-action@v1 with: target: universal2-apple-darwin - args: --release --out dist -i python3.13t + args: --release --out dist -i python3.14t sccache: true - name: Install built wheel run: | @@ -35,7 +35,7 @@ pip install pytest cd tests && pytest - name: Upload wheels - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: wheels-macos path: dist @@ -46,8 +46,8 @@ matrix: target: [x64, x86] steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v6 + - uses: actions/setup-python@v6 with: python-version: 3.12 architecture: ${{ matrix.target }} @@ -61,14 +61,14 @@ uses: pyo3/maturin-action@v1 with: target: ${{ matrix.target }} - args: --release --out dist -i python3.13t + args: --release --out dist -i python3.14t - name: Install built wheel run: | pip install nh3 --no-index --find-links dist --force-reinstall pip install pytest cd tests && pytest - name: Upload wheels - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: wheels-windows-${{ matrix.target }} path: dist @@ -79,18 +79,11 @@ matrix: target: [aarch64-pc-windows-msvc] steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v6 + - uses: actions/setup-python@v6 with: python-version: 3.12 architecture: arm64 - # rust toolchain is not currently installed on windopws arm64 images https://github.com/actions/partner-runner-images/issues/77 - - name: Setup rust - id: setup-rust - run: | - Invoke-WebRequest https://static.rust-lang.org/rustup/dist/aarch64-pc-windows-msvc/rustup-init.exe -OutFile .\rustup-init.exe - .\rustup-init.exe -y - Add-Content $env:GITHUB_PATH "$env:USERPROFILE\.cargo\bin" - name: Build wheels uses: pyo3/maturin-action@v1 with: @@ -100,14 +93,14 @@ uses: pyo3/maturin-action@v1 with: target: ${{ matrix.target }} - args: --release --out dist -i python3.13t + args: --release --out dist -i python3.14t - name: Install built wheel run: | pip install nh3 --no-index --find-links dist --force-reinstall pip install pytest cd tests && pytest - name: Upload wheels - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: wheels-windows-arm-${{ matrix.target }} path: dist @@ -118,8 +111,8 @@ matrix: target: [x86_64, i686] steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v6 + - uses: actions/setup-python@v6 with: python-version: 3.12 architecture: x64 @@ -138,7 +131,7 @@ rust-toolchain: nightly target: ${{ matrix.target }} manylinux: auto - args: --release --out dist -i python3.13t + args: --release --out dist -i python3.14t sccache: true before-script-linux: yum install -y libatomic - name: Install built wheel @@ -148,7 +141,7 @@ pip install pytest cd tests && pytest - name: Upload wheels - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: wheels-linux-${{ matrix.target }} path: dist @@ -157,17 +150,29 @@ runs-on: ubuntu-latest strategy: matrix: - target: [aarch64, armv7, s390x, ppc64le, ppc64] + platform: + - target: aarch64-unknown-linux-gnu + arch: aarch64 + - target: armv7-unknown-linux-gnueabihf + arch: armv7 + - target: s390x-unknown-linux-gnu + arch: s390x + - target: powerpc64le-unknown-linux-gnu + arch: ppc64le + - target: powerpc64-unknown-linux-gnu + arch: ppc64 + - target: riscv64gc-unknown-linux-gnu + arch: riscv64 steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v6 + - uses: actions/setup-python@v6 with: python-version: 3.12 - name: Build wheels uses: pyo3/maturin-action@v1 with: rust-toolchain: nightly - target: ${{ matrix.target }} + target: ${{ matrix.platform.target }} manylinux: auto args: --release --out dist sccache: true @@ -175,15 +180,15 @@ uses: pyo3/maturin-action@v1 with: rust-toolchain: nightly - target: ${{ matrix.target }} + target: ${{ matrix.platform.target }} manylinux: auto args: --release --out dist -i python3.13 sccache: true - - uses: uraimo/[email protected] - if: matrix.target != 'ppc64' + - uses: uraimo/[email protected] + if: matrix.platform.arch != 'ppc64' name: Install built wheel with: - arch: ${{ matrix.target }} + arch: ${{ matrix.platform.arch }} distro: ubuntu22.04 githubToken: ${{ github.token }} install: | @@ -194,9 +199,9 @@ pip3 install nh3 --no-index --find-links dist/ --force-reinstall cd tests && pytest - name: Upload wheels - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: - name: wheels-linux-${{ matrix.target }} + name: wheels-linux-${{ matrix.platform.arch }} path: dist musllinux: @@ -207,8 +212,8 @@ - x86_64-unknown-linux-musl - i686-unknown-linux-musl steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v6 + - uses: actions/setup-python@v6 with: python-version: 3.12 architecture: x64 @@ -224,23 +229,21 @@ with: target: ${{ matrix.target }} manylinux: musllinux_1_2 - args: --release --out dist -i python3.13t + args: --release --out dist -i python3.14t sccache: true - name: Install built wheel if: matrix.target == 'x86_64-unknown-linux-musl' - uses: addnab/docker-run-action@v3 - with: - image: alpine:latest - options: -v ${{ github.workspace }}:/io -w /io - run: | + run: | + docker run --rm -v ${{ github.workspace }}:/io -w /io alpine:latest sh -c ' apk add py3-virtualenv python3 -m virtualenv .venv source .venv/bin/activate pip install -U pip pytest pip install nh3 --no-index --find-links /io/dist/ --force-reinstall cd tests && python3 -m pytest + ' - name: Upload wheels - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: wheels-${{ matrix.target }} path: dist @@ -255,8 +258,8 @@ - target: armv7-unknown-linux-musleabihf arch: armv7 steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v6 + - uses: actions/setup-python@v6 with: python-version: 3.12 - name: Build wheels @@ -271,9 +274,9 @@ with: target: ${{ matrix.platform.target }} manylinux: musllinux_1_2 - args: --release --out dist -i python3.13t + args: --release --out dist -i python3.14t sccache: true - - uses: uraimo/[email protected] + - uses: uraimo/[email protected] name: Install built wheel with: arch: ${{ matrix.platform.arch }} @@ -288,16 +291,16 @@ pip install nh3 --no-index --find-links dist/ --force-reinstall cd tests && python3 -m pytest - name: Upload wheels - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: - name: wheels-${{ matrix.platform.target }} + name: wheels-${{ matrix.platform.arch }} path: dist sdist: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v6 + - uses: actions/setup-python@v6 with: python-version: 3.12 architecture: x64 @@ -307,7 +310,7 @@ command: sdist args: --out dist - name: Upload sdist - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: wheels-sdist path: dist @@ -319,11 +322,11 @@ needs: [macos, windows, windows-arm, linux, linux-cross, musllinux, musllinux-cross, sdist] steps: - - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@v8 with: pattern: wheels-* merge-multiple: true - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v6 with: python-version: 3.12 - name: Publish to PyPI diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nh3-0.3.0/.readthedocs.yml new/nh3-0.3.4/.readthedocs.yml --- old/nh3-0.3.0/.readthedocs.yml 2025-07-17 16:38:00.000000000 +0200 +++ new/nh3-0.3.4/.readthedocs.yml 2006-07-24 03:21:28.000000000 +0200 @@ -9,8 +9,8 @@ build: os: "ubuntu-22.04" tools: - python: "3.12" - rust: "1.82" + python: "3.14" + rust: "latest" python: install: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nh3-0.3.0/Cargo.lock new/nh3-0.3.4/Cargo.lock --- old/nh3-0.3.0/Cargo.lock 2025-07-17 16:38:00.000000000 +0200 +++ new/nh3-0.3.4/Cargo.lock 2006-07-24 03:21:28.000000000 +0200 @@ -10,9 +10,9 @@ [[package]] name = "ammonia" -version = "4.1.1" +version = "4.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6b346764dd0814805de8abf899fe03065bcee69bb1a4771c785817e39f3978f" +checksum = "17e913097e1a2124b46746c980134e8c954bc17a6a59bb3fde96f088d126dde6" dependencies = [ "cssparser", "html5ever", @@ -22,31 +22,26 @@ ] [[package]] -name = "autocfg" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" - -[[package]] name = "bitflags" -version = "2.9.1" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" [[package]] name = "cc" -version = "1.2.29" +version = "1.2.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c1599538de2394445747c8cf7935946e3cc27e9625f889d979bfb2aaf569362" +checksum = "7a0dd1ca384932ff3641c8718a02769f1698e7563dc6974ffd03346116310423" dependencies = [ + "find-msvc-tools", "shlex", ] [[package]] name = "cfg-if" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cssparser" @@ -84,9 +79,9 @@ [[package]] name = "dtoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6add3b8cff394282be81f3fc1a0605db594ed69890078ca6e2cab1c408bcf04" +checksum = "4c3cf4824e2d5f025c7b531afcb2325364084a16806f6d47fbc1f5fbd9960590" [[package]] name = "dtoa-short" @@ -98,10 +93,16 @@ ] [[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] name = "form_urlencoded" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] @@ -141,9 +142,9 @@ [[package]] name = "icu_collections" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" dependencies = [ "displaydoc", "potential_utf", @@ -154,9 +155,9 @@ [[package]] name = "icu_locale_core" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" dependencies = [ "displaydoc", "litemap", @@ -167,11 +168,10 @@ [[package]] name = "icu_normalizer" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" dependencies = [ - "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", @@ -182,42 +182,38 @@ [[package]] name = "icu_normalizer_data" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" [[package]] name = "icu_properties" -version = "2.0.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" dependencies = [ - "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", "icu_provider", - "potential_utf", "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "2.0.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" [[package]] name = "icu_provider" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" dependencies = [ "displaydoc", "icu_locale_core", - "stable_deref_trait", - "tinystr", "writeable", "yoke", "zerofrom", @@ -227,9 +223,9 @@ [[package]] name = "idna" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ "idna_adapter", "smallvec", @@ -247,44 +243,37 @@ ] [[package]] -name = "indoc" -version = "2.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd" - -[[package]] name = "itoa" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "libc" -version = "0.2.174" +version = "0.2.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" +checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" [[package]] name = "litemap" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] name = "lock_api" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.27" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "mac" @@ -321,15 +310,6 @@ ] [[package]] -name = "memoffset" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" -dependencies = [ - "autocfg", -] - -[[package]] name = "new_debug_unreachable" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -337,7 +317,7 @@ [[package]] name = "nh3" -version = "0.3.0" +version = "0.3.4" dependencies = [ "ammonia", "ouroboros", @@ -346,9 +326,9 @@ [[package]] name = "once_cell" -version = "1.21.3" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "ouroboros" @@ -376,9 +356,9 @@ [[package]] name = "parking_lot" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -386,22 +366,22 @@ [[package]] name = "parking_lot_core" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-link", ] [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "phf" @@ -457,15 +437,15 @@ [[package]] name = "portable-atomic" -version = "1.11.1" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" [[package]] name = "potential_utf" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" dependencies = [ "zerovec", ] @@ -478,9 +458,9 @@ [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] @@ -500,37 +480,33 @@ [[package]] name = "pyo3" -version = "0.25.1" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8970a78afe0628a3e3430376fc5fd76b6b45c4d43360ffd6cdd40bdde72b682a" +checksum = "cf85e27e86080aafd5a22eae58a162e133a589551542b3e5cee4beb27e54f8e1" dependencies = [ - "indoc", "libc", - "memoffset", "once_cell", "portable-atomic", "pyo3-build-config", "pyo3-ffi", "pyo3-macros", - "unindent", ] [[package]] name = "pyo3-build-config" -version = "0.25.1" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "458eb0c55e7ece017adeba38f2248ff3ac615e53660d7c71a238d7d2a01c7598" +checksum = "8bf94ee265674bf76c09fa430b0e99c26e319c945d96ca0d5a8215f31bf81cf7" dependencies = [ - "once_cell", "python3-dll-a", "target-lexicon", ] [[package]] name = "pyo3-ffi" -version = "0.25.1" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7114fe5457c61b276ab77c5055f206295b812608083644a5c5b2640c3102565c" +checksum = "491aa5fc66d8059dd44a75f4580a2962c1862a1c2945359db36f6c2818b748dc" dependencies = [ "libc", "pyo3-build-config", @@ -538,9 +514,9 @@ [[package]] name = "pyo3-macros" -version = "0.25.1" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8725c0a622b374d6cb051d11a0983786448f7785336139c3c94f5aa6bef7e50" +checksum = "f5d671734e9d7a43449f8480f8b38115df67bef8d21f76837fa75ee7aaa5e52e" dependencies = [ "proc-macro2", "pyo3-macros-backend", @@ -550,9 +526,9 @@ [[package]] name = "pyo3-macros-backend" -version = "0.25.1" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4109984c22491085343c05b0dbc54ddc405c3cf7b4374fc533f5c3313a572ccc" +checksum = "22faaa1ce6c430a1f71658760497291065e6450d7b5dc2bcf254d49f66ee700a" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -572,9 +548,9 @@ [[package]] name = "quote" -version = "1.0.40" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] @@ -596,9 +572,9 @@ [[package]] name = "redox_syscall" -version = "0.5.13" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ "bitflags", ] @@ -611,18 +587,27 @@ [[package]] name = "serde" -version = "1.0.219" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", @@ -637,9 +622,9 @@ [[package]] name = "siphasher" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" +checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" [[package]] name = "smallvec" @@ -649,9 +634,9 @@ [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "static_assertions" @@ -686,9 +671,9 @@ [[package]] name = "syn" -version = "2.0.104" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -708,9 +693,9 @@ [[package]] name = "target-lexicon" -version = "0.13.2" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e502f78cdbb8ba4718f566c418c52bc729126ffd16baee5baa718cf25dd5a69a" +checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca" [[package]] name = "tendril" @@ -725,9 +710,9 @@ [[package]] name = "tinystr" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" dependencies = [ "displaydoc", "zerovec", @@ -735,25 +720,20 @@ [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" - -[[package]] -name = "unindent" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "url" -version = "2.5.4" +version = "2.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] [[package]] @@ -787,74 +767,16 @@ ] [[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" +name = "windows-link" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "writeable" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] name = "yansi" @@ -864,11 +786,10 @@ [[package]] name = "yoke" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" dependencies = [ - "serde", "stable_deref_trait", "yoke-derive", "zerofrom", @@ -876,9 +797,9 @@ [[package]] name = "yoke-derive" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", @@ -909,9 +830,9 @@ [[package]] name = "zerotrie" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" dependencies = [ "displaydoc", "yoke", @@ -920,9 +841,9 @@ [[package]] name = "zerovec" -version = "0.11.2" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" dependencies = [ "yoke", "zerofrom", @@ -931,9 +852,9 @@ [[package]] name = "zerovec-derive" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nh3-0.3.0/Cargo.toml new/nh3-0.3.4/Cargo.toml --- old/nh3-0.3.0/Cargo.toml 1970-01-01 01:00:00.000000000 +0100 +++ new/nh3-0.3.4/Cargo.toml 2006-07-24 03:21:28.000000000 +0200 @@ -1,8 +1,8 @@ [package] name = "nh3" -version = "0.3.0" +version = "0.3.4" authors = ["messense <[email protected]>"] -edition = "2021" +edition = "2024" description = "Python bindings to the ammonia HTML sanitization library." license = "MIT" repository = "https://github.com/messense/nh3" @@ -14,6 +14,6 @@ crate-type = ["cdylib"] [dependencies] -ammonia = "4.1.1" -pyo3 = { version = "0.25.1", features = ["abi3-py38", "generate-import-lib"] } +ammonia = "4.1.2" +pyo3 = { version = "0.28.2", features = ["abi3-py38", "generate-import-lib"] } ouroboros = "0.18" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nh3-0.3.0/PKG-INFO new/nh3-0.3.4/PKG-INFO --- old/nh3-0.3.0/PKG-INFO 1970-01-01 01:00:00.000000000 +0100 +++ new/nh3-0.3.4/PKG-INFO 2006-07-24 03:21:28.000000000 +0200 @@ -1,13 +1,12 @@ Metadata-Version: 2.4 Name: nh3 -Version: 0.3.0 +Version: 0.3.4 Classifier: Programming Language :: Rust Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Topic :: Software Development :: Libraries :: Python Modules License-File: LICENSE Summary: Python binding to Ammonia HTML sanitizer Rust crate -Author: messense <[email protected]> Author-email: messense <[email protected]> License: MIT Requires-Python: >=3.8 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nh3-0.3.0/nh3.pyi new/nh3-0.3.4/nh3.pyi --- old/nh3-0.3.0/nh3.pyi 2025-07-17 16:38:00.000000000 +0200 +++ new/nh3-0.3.4/nh3.pyi 2006-07-24 03:21:28.000000000 +0200 @@ -1,41 +1,42 @@ -from typing import Callable, Dict, Optional, Set +from typing import AbstractSet, Callable, Dict, Mapping, Optional, Set ALLOWED_TAGS: Set[str] ALLOWED_ATTRIBUTES: Dict[str, Set[str]] ALLOWED_URL_SCHEMES: Set[str] +CLEAN_CONTENT_TAGS: Set[str] class Cleaner: def __init__( self, - tags: Optional[Set[str]] = None, - clean_content_tags: Optional[Set[str]] = None, - attributes: Optional[Dict[str, Set[str]]] = None, + tags: Optional[AbstractSet[str]] = None, + clean_content_tags: Optional[AbstractSet[str]] = None, + attributes: Optional[Mapping[str, AbstractSet[str]]] = None, attribute_filter: Optional[Callable[[str, str, str], Optional[str]]] = None, strip_comments: bool = True, link_rel: Optional[str] = "noopener noreferrer", - generic_attribute_prefixes: Optional[Set[str]] = None, - tag_attribute_values: Optional[Dict[str, Dict[str, Set[str]]]] = None, - set_tag_attribute_values: Optional[Dict[str, Dict[str, str]]] = None, - url_schemes: Optional[Set[str]] = None, - allowed_classes: Optional[Dict[str, Set[str]]] = None, - filter_style_properties: Optional[Set[str]] = None, + generic_attribute_prefixes: Optional[AbstractSet[str]] = None, + tag_attribute_values: Optional[Mapping[str, Mapping[str, AbstractSet[str]]]] = None, + set_tag_attribute_values: Optional[Mapping[str, Mapping[str, str]]] = None, + url_schemes: Optional[AbstractSet[str]] = None, + allowed_classes: Optional[Mapping[str, AbstractSet[str]]] = None, + filter_style_properties: Optional[AbstractSet[str]] = None, ) -> None: ... def clean(self, html: str) -> str: ... def clean( html: str, - tags: Optional[Set[str]] = None, - clean_content_tags: Optional[Set[str]] = None, - attributes: Optional[Dict[str, Set[str]]] = None, + tags: Optional[AbstractSet[str]] = None, + clean_content_tags: Optional[AbstractSet[str]] = None, + attributes: Optional[Mapping[str, AbstractSet[str]]] = None, attribute_filter: Optional[Callable[[str, str, str], Optional[str]]] = None, strip_comments: bool = True, link_rel: Optional[str] = "noopener noreferrer", - generic_attribute_prefixes: Optional[Set[str]] = None, - tag_attribute_values: Optional[Dict[str, Dict[str, Set[str]]]] = None, - set_tag_attribute_values: Optional[Dict[str, Dict[str, str]]] = None, - url_schemes: Optional[Set[str]] = None, - allowed_classes: Optional[Dict[str, Set[str]]] = None, - filter_style_properties: Optional[Set[str]] = None, + generic_attribute_prefixes: Optional[AbstractSet[str]] = None, + tag_attribute_values: Optional[Mapping[str, Mapping[str, AbstractSet[str]]]] = None, + set_tag_attribute_values: Optional[Mapping[str, Mapping[str, str]]] = None, + url_schemes: Optional[AbstractSet[str]] = None, + allowed_classes: Optional[Mapping[str, AbstractSet[str]]] = None, + filter_style_properties: Optional[AbstractSet[str]] = None, ) -> str: ... def clean_text(html: str) -> str: ... def is_html(html: str) -> bool: ... diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nh3-0.3.0/pyproject.toml new/nh3-0.3.4/pyproject.toml --- old/nh3-0.3.0/pyproject.toml 2025-07-17 16:38:00.000000000 +0200 +++ new/nh3-0.3.4/pyproject.toml 2006-07-24 03:21:28.000000000 +0200 @@ -6,6 +6,7 @@ name = "nh3" description = "Python binding to Ammonia HTML sanitizer Rust crate" authors = [{ name = "messense", email = "[email protected]" }] +readme = "README.md" requires-python = ">=3.8" license = {text = "MIT"} classifiers = [ @@ -14,7 +15,7 @@ "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Software Development :: Libraries :: Python Modules", ] -dynamic = ["version"] +dynamic = ["urls", "version"] [tool.maturin] features = ["pyo3/extension-module"] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nh3-0.3.0/src/lib.rs new/nh3-0.3.4/src/lib.rs --- old/nh3-0.3.0/src/lib.rs 2025-07-17 16:38:00.000000000 +0200 +++ new/nh3-0.3.4/src/lib.rs 2006-07-24 03:21:28.000000000 +0200 @@ -2,7 +2,7 @@ use std::collections::{HashMap, HashSet}; use ouroboros::self_referencing; -use pyo3::exceptions::PyTypeError; +use pyo3::exceptions::{PyTypeError, PyValueError}; use pyo3::prelude::*; use pyo3::types::{PyString, PyTuple}; @@ -10,7 +10,7 @@ tags: Option<HashSet<String>>, clean_content_tags: Option<HashSet<String>>, attributes: Option<HashMap<String, HashSet<String>>>, - attribute_filter: Option<PyObject>, + attribute_filter: Option<Py<PyAny>>, strip_comments: bool, link_rel: Option<String>, generic_attribute_prefixes: Option<HashSet<String>>, @@ -48,6 +48,51 @@ builder: ammonia::Builder<'this>, } +/// Create a reusable sanitizer according to the given options. +/// +/// :param tags: Sets the tags that are allowed. +/// :type tags: ``set[str]``, optional +/// :param clean_content_tags: Sets the tags whose contents will be completely removed from the output. +/// :type clean_content_tags: ``set[str]``, optional +/// :param attributes: Sets the HTML attributes that are allowed on specific tags, +/// ``*`` key means the attributes are allowed on any tag. +/// :type attributes: ``dict[str, set[str]]``, optional +/// :param attribute_filter: Allows rewriting of all attributes using a callback. +/// The callback takes name of the element, attribute and its value. +/// Returns ``None`` to remove the attribute, or a value to use. +/// :type attribute_filter: ``Callable[[str, str, str], str | None]``, optional +/// :param strip_comments: Configures the handling of HTML comments, defaults to ``True``. +/// :type strip_comments: ``bool`` +/// :param link_rel: Configures a ``rel`` attribute that will be added on links, defaults to ``noopener noreferrer``. +/// To turn on rel-insertion, pass a space-separated list. +/// If ``rel`` is in the generic or tag attributes, this must be set to ``None``. Common ``rel`` values to include: +/// +/// - ``noopener``: This prevents a particular type of XSS attack, and should usually be turned on for untrusted HTML. +/// - ``noreferrer``: This prevents the browser from sending the source URL to the website that is linked to. +/// - ``nofollow``: This prevents search engines from using this link for ranking, which disincentivizes spammers. +/// :type link_rel: ``str`` +/// :param generic_attribute_prefixes: Sets the prefix of attributes that are allowed on any tag. +/// :type generic_attribute_prefixes: ``set[str]``, optional +/// :param tag_attribute_values: Sets the values of HTML attributes that are allowed on specific tags. +/// The value is structured as a map from tag names to a map from attribute names to a set of attribute values. +/// If a tag is not itself whitelisted, adding entries to this map will do nothing. +/// :type tag_attribute_values: ``dict[str, dict[str, set[str]]]``, optional +/// :param set_tag_attribute_values: Sets the values of HTML attributes that are to be set on specific tags. +/// The value is structured as a map from tag names to a map from attribute names to an attribute value. +/// If a tag is not itself whitelisted, adding entries to this map will do nothing. +/// :type set_tag_attribute_values: ``dict[str, dict[str, str]]``, optional +/// :param url_schemes: Sets the URL schemes permitted on ``href`` and ``src`` attributes. +/// :type url_schemes: ``set[str]``, optional +/// :param allowed_classes: Sets the CSS classes that are allowed on specific tags. +/// The values is structured as a map from tag names to a set of class names. +/// The `class` attribute itself should not be whitelisted if this parameter is used. +/// :type allowed_classes: ``dict[str, set[str]]``, optional +/// :param filter_style_properties: Only allows the specified properties in `style` attributes. +/// Irrelevant if `style` is not an allowed attribute. +/// Note that if style filtering is enabled style properties will be normalised e.g. +/// invalid declarations and @rules will be removed, with only syntactically valid +/// declarations kept. +/// :type filter_style_properties: ``set[str]``, optional #[pyclass] pub struct Cleaner { inner: Inner, @@ -122,10 +167,10 @@ let attribute_filter = config .attribute_filter .as_ref() - .map(|f| Python::with_gil(|py| f.clone_ref(py))); + .map(|f| Python::attach(|py| f.clone_ref(py))); if let Some(callback) = attribute_filter { builder.attribute_filter(move |element, attribute, value| { - Python::with_gil(|py| { + Python::attach(|py| { let res = callback.call( py, PyTuple::new( @@ -143,12 +188,15 @@ Ok(val) => { if val.is_none(py) { return None; - } else if let Ok(s) = val.extract::<String>(py) { - return Some(Cow::<str>::Owned(s)); } else { - PyTypeError::new_err( - "expected attribute_filter to return str or None", - ) + match val.extract::<String>(py) { + Ok(s) => { + return Some(Cow::<str>::Owned(s)); + } + _ => PyTypeError::new_err( + "expected attribute_filter to return str or None", + ), + } } } Err(err) => err, @@ -207,51 +255,6 @@ #[pymethods] impl Cleaner { - /// Create a reusable sanitizer according to the given options. - /// - /// :param tags: Sets the tags that are allowed. - /// :type tags: ``set[str]``, optional - /// :param clean_content_tags: Sets the tags whose contents will be completely removed from the output. - /// :type clean_content_tags: ``set[str]``, optional - /// :param attributes: Sets the HTML attributes that are allowed on specific tags, - /// ``*`` key means the attributes are allowed on any tag. - /// :type attributes: ``dict[str, set[str]]``, optional - /// :param attribute_filter: Allows rewriting of all attributes using a callback. - /// The callback takes name of the element, attribute and its value. - /// Returns ``None`` to remove the attribute, or a value to use. - /// :type attribute_filter: ``Callable[[str, str, str], str | None]``, optional - /// :param strip_comments: Configures the handling of HTML comments, defaults to ``True``. - /// :type strip_comments: ``bool`` - /// :param link_rel: Configures a ``rel`` attribute that will be added on links, defaults to ``noopener noreferrer``. - /// To turn on rel-insertion, pass a space-separated list. - /// If ``rel`` is in the generic or tag attributes, this must be set to ``None``. Common ``rel`` values to include: - /// - /// - ``noopener``: This prevents a particular type of XSS attack, and should usually be turned on for untrusted HTML. - /// - ``noreferrer``: This prevents the browser from sending the source URL to the website that is linked to. - /// - ``nofollow``: This prevents search engines from using this link for ranking, which disincentivizes spammers. - /// :type link_rel: ``str`` - /// :param generic_attribute_prefixes: Sets the prefix of attributes that are allowed on any tag. - /// :type generic_attribute_prefixes: ``set[str]``, optional - /// :param tag_attribute_values: Sets the values of HTML attributes that are allowed on specific tags. - /// The value is structured as a map from tag names to a map from attribute names to a set of attribute values. - /// If a tag is not itself whitelisted, adding entries to this map will do nothing. - /// :type tag_attribute_values: ``dict[str, dict[str, set[str]]]``, optional - /// :param set_tag_attribute_values: Sets the values of HTML attributes that are to be set on specific tags. - /// The value is structured as a map from tag names to a map from attribute names to an attribute value. - /// If a tag is not itself whitelisted, adding entries to this map will do nothing. - /// :type set_tag_attribute_values: ``dict[str, dict[str, str]]``, optional - /// :param url_schemes: Sets the URL schemes permitted on ``href`` and ``src`` attributes. - /// :type url_schemes: ``set[str]``, optional - /// :param allowed_classes: Sets the CSS classes that are allowed on specific tags. - /// The values is structured as a map from tag names to a set of class names. - /// The `class` attribute itself should not be whitelisted if this parameter is used. - /// :type allowed_classes: ``dict[str, set[str]]``, optional - /// :param filter_style_properties: Only allows the specified properties in `style` attributes. - /// Irrelevant if `style` is not an allowed attribute. - /// Note that if style filtering is enabled style properties will be normalised e.g. - /// invalid declarations and @rules will be removed, with only syntactically valid - /// declarations kept. - /// :type filter_style_properties: ``set[str]``, optional #[new] #[pyo3(signature = ( tags = None, @@ -272,7 +275,7 @@ tags: Option<HashSet<String>>, clean_content_tags: Option<HashSet<String>>, attributes: Option<HashMap<String, HashSet<String>>>, - attribute_filter: Option<PyObject>, + attribute_filter: Option<Py<PyAny>>, strip_comments: bool, link_rel: Option<&str>, generic_attribute_prefixes: Option<HashSet<String>>, @@ -287,6 +290,19 @@ return Err(PyTypeError::new_err("attribute_filter must be callable")); } } + if link_rel.is_some() { + if let Some(ref attrs) = attributes { + for (tag, attr_set) in attrs.iter() { + if attr_set.contains("rel") { + return Err(PyValueError::new_err(format!( + "\"rel\" attribute is not allowed for tag \"{}\" when link_rel is set; \ + pass link_rel=None to manage the \"rel\" attribute directly", + tag + ))); + } + } + } + } let config = Config { tags, clean_content_tags, @@ -307,7 +323,7 @@ /// Sanitize an HTML fragment #[pyo3(name = "clean")] fn py_clean(&self, py: Python, html: &str) -> PyResult<String> { - Ok(py.allow_threads(|| self.clean(html))) + Ok(py.detach(|| self.clean(html))) } } @@ -380,7 +396,7 @@ tags: Option<HashSet<String>>, clean_content_tags: Option<HashSet<String>>, attributes: Option<HashMap<String, HashSet<String>>>, - attribute_filter: Option<PyObject>, + attribute_filter: Option<Py<PyAny>>, strip_comments: bool, link_rel: Option<&str>, generic_attribute_prefixes: Option<HashSet<String>>, @@ -405,7 +421,7 @@ allowed_classes, filter_style_properties, )?; - Ok(py.allow_threads(|| cleaner.clean(html))) + Ok(py.detach(|| cleaner.clean(html))) } /// Turn an arbitrary string into unformatted HTML. @@ -428,7 +444,7 @@ /// 'Robert"); abuse();//' #[pyfunction] fn clean_text(py: Python, html: &str) -> String { - py.allow_threads(|| ammonia::clean_text(html)) + py.detach(|| ammonia::clean_text(html)) } /// Determine if a given string contains HTML. @@ -452,7 +468,7 @@ /// True #[pyfunction] fn is_html(py: Python, html: &str) -> bool { - py.allow_threads(|| ammonia::is_html(html)) + py.detach(|| ammonia::is_html(html)) } /// Python bindings to the ammonia HTML sanitization library ( https://github.com/rust-ammonia/ammonia ). @@ -468,5 +484,6 @@ m.add("ALLOWED_TAGS", a.clone_tags())?; m.add("ALLOWED_ATTRIBUTES", a.clone_tag_attributes())?; m.add("ALLOWED_URL_SCHEMES", a.clone_url_schemes())?; + m.add("CLEAN_CONTENT_TAGS", a.clone_clean_content_tags())?; Ok(()) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nh3-0.3.0/tests/test_nh3.py new/nh3-0.3.4/tests/test_nh3.py --- old/nh3-0.3.0/tests/test_nh3.py 2025-07-17 16:38:00.000000000 +0200 +++ new/nh3-0.3.4/tests/test_nh3.py 2006-07-24 03:21:28.000000000 +0200 @@ -88,11 +88,76 @@ nh3.clean(html, attribute_filter=lambda _element, _attribute, _value: True) +def test_clean_rel_attribute_conflict(): + with pytest.raises(ValueError, match="link_rel is set"): + nh3.clean( + "<a href='http://example.com'>test</a>", + tags={"a"}, + attributes={"a": {"href", "rel"}}, + ) + + # No error when link_rel=None + result = nh3.clean( + "<a href='http://example.com' rel='nofollow'>test</a>", + tags={"a"}, + attributes={"a": {"href", "rel"}}, + link_rel=None, + ) + assert result == '<a href="http://example.com" rel="nofollow">test</a>' + + # No error when rel is not in attributes + nh3.clean( + "<a href='http://example.com'>test</a>", + tags={"a"}, + attributes={"a": {"href"}}, + ) + + +def test_cleaner_rel_attribute_conflict(): + with pytest.raises(ValueError, match="link_rel is set"): + nh3.Cleaner( + tags={"a"}, + attributes={"a": {"href", "rel"}}, + ) + + # No error when link_rel=None + cleaner = nh3.Cleaner( + tags={"a"}, + attributes={"a": {"href", "rel"}}, + link_rel=None, + ) + result = cleaner.clean("<a href='http://example.com' rel='nofollow'>test</a>") + assert result == '<a href="http://example.com" rel="nofollow">test</a>' + + def test_clean_text(): res = nh3.clean_text('Robert"); abuse();//') assert res == "Robert"); abuse();//" +def test_clean_content_tags_constant(): + assert isinstance(nh3.CLEAN_CONTENT_TAGS, set) + assert "script" in nh3.CLEAN_CONTENT_TAGS + assert "style" in nh3.CLEAN_CONTENT_TAGS + + +def test_frozenset_args(): + html = "<b><img src='x'>hello</b>" + assert nh3.clean(html, tags=frozenset({"b"})) == "<b>hello</b>" + assert ( + nh3.clean(html, tags=frozenset({"img"}), attributes={"img": frozenset({"src"})}) + == '<img src="x">hello' + ) + + +def test_cleaner_frozenset_args(): + cleaner = nh3.Cleaner( + tags=frozenset({"b", "img"}), + attributes={"img": frozenset({"src"})}, + ) + assert cleaner.clean("<b><img src='x'>hi</b>") == '<b><img src="x">hi</b>' + + def test_is_html(): assert not nh3.is_html("plain text") assert nh3.is_html("<p>html!</p>") ++++++ vendor.tar.zst ++++++ /work/SRC/openSUSE:Factory/python-nh3/vendor.tar.zst /work/SRC/openSUSE:Factory/.python-nh3.new.21863/vendor.tar.zst differ: char 7, line 1
