Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-unicode-segmentation-rs for 
openSUSE:Factory checked in at 2026-04-28 11:53:25
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-unicode-segmentation-rs (Old)
 and      /work/SRC/openSUSE:Factory/.python-unicode-segmentation-rs.new.11940 
(New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-unicode-segmentation-rs"

Tue Apr 28 11:53:25 2026 rev:2 rq:1349282 version:0.2.4

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-unicode-segmentation-rs/python-unicode-segmentation-rs.changes
    2026-01-13 21:37:31.207345169 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-unicode-segmentation-rs.new.11940/python-unicode-segmentation-rs.changes
 2026-04-28 11:53:36.746637518 +0200
@@ -1,0 +2,11 @@
+Sat Apr 25 20:35:12 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 0.2.4:
+  * fix(ci): publish wheels compatible with more Python versions
+  * fix(deps): update rust crate pyo3 to 0.28.3
+- update to 0.2.3:
+  * feat: structure release notes
+  * Fix README module name and add automated example verification
+  * fix(deps): update rust crate pyo3 to 0.28.2
+
+-------------------------------------------------------------------

Old:
----
  unicode_segmentation_rs-0.2.1.tar.gz

New:
----
  unicode_segmentation_rs-0.2.4.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-unicode-segmentation-rs.spec ++++++
--- /var/tmp/diff_new_pack.gdn6eK/_old  2026-04-28 11:53:38.946728365 +0200
+++ /var/tmp/diff_new_pack.gdn6eK/_new  2026-04-28 11:53:38.946728365 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-unicode-segmentation-rs
 #
-# Copyright (c) 2026 SUSE LLC
+# 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
@@ -17,24 +17,27 @@
 
 
 Name:           python-unicode-segmentation-rs
-Version:        0.2.1
+Version:        0.2.4
 Release:        0
 Summary:        Unicode segmentation and width for Python using Rust
-License:        MIT AND CC0-1.0
-URL:            https://weblate.org/
+License:        CC0-1.0 AND MIT
+URL:            https://github.com/WeblateOrg/unicode-segmentation-rs
 Source:         
https://files.pythonhosted.org/packages/source/u/unicode-segmentation-rs/unicode_segmentation_rs-%{version}.tar.gz
 Source1:        vendor.tar.zst
-BuildRequires:  python-rpm-macros
 BuildRequires:  %{python_module maturin >= 1.10.0}
 BuildRequires:  %{python_module pip}
 BuildRequires:  %{python_module pytest}
 BuildRequires:  cargo
 BuildRequires:  fdupes
+BuildRequires:  python-rpm-macros
 BuildRequires:  zstd
 %python_subpackages
 
 %description
-Python bindings for the Rust 
[unicode-segmentation](https://docs.rs/unicode-segmentation/) and 
[unicode-width](https://docs.rs/unicode-width/) crates, providing Unicode text 
segmentation and width calculation according to Unicode standards.
+Python bindings for the Rust
+[unicode-segmentation](https://docs.rs/unicode-segmentation/) and
+[unicode-width](https://docs.rs/unicode-width/) crates, providing Unicode text
+segmentation and width calculation according to Unicode standards.
 
 %prep
 %autosetup -a1 -p1 -n unicode_segmentation_rs-%{version}

++++++ _service ++++++
--- /var/tmp/diff_new_pack.gdn6eK/_old  2026-04-28 11:53:39.002730678 +0200
+++ /var/tmp/diff_new_pack.gdn6eK/_new  2026-04-28 11:53:39.014731173 +0200
@@ -1,6 +1,6 @@
 <services>
   <service name="download_files" mode="manual"/>
-  <service name="cargo_vendor" mode="disabled">
+  <service name="cargo_vendor" mode="manual">
     <param name="srctar">unicode_segmentation_rs-*.tar.gz</param>
     <param name="compression">zst</param>
     <param name="filter">true</param>

++++++ unicode_segmentation_rs-0.2.1.tar.gz -> 
unicode_segmentation_rs-0.2.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unicode_segmentation_rs-0.2.1/.editorconfig 
new/unicode_segmentation_rs-0.2.4/.editorconfig
--- old/unicode_segmentation_rs-0.2.1/.editorconfig     1970-01-01 
01:00:00.000000000 +0100
+++ new/unicode_segmentation_rs-0.2.4/.editorconfig     2006-07-24 
03:21:28.000000000 +0200
@@ -0,0 +1,43 @@
+# Copyright © Michal Čihař <[email protected]>
+#
+# SPDX-License-Identifier: CC0-1.0
+
+# This file is maintained in https://github.com/WeblateOrg/meta/
+
+root = true
+
+[*]
+indent_style = space
+indent_size = 2
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+spaces_around_operators = true
+
+[*.bat]
+end_of_line = crlf
+
+[*.html]
+indent_size = 2
+
+[*.py]
+indent_size = 4
+
+[*.rst]
+indent_size = 3
+
+[*.js]
+quote_type = double
+
+[*.{markdown,md}]
+trim_trailing_whitespace = false
+
+[[shell]]
+indent_style = space
+indent_size = 4
+space_redirects = true
+simplify = true
+
+[*.{kt,kts}]
+indent_size = 4
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unicode_segmentation_rs-0.2.1/.github/release.yml 
new/unicode_segmentation_rs-0.2.4/.github/release.yml
--- old/unicode_segmentation_rs-0.2.1/.github/release.yml       1970-01-01 
01:00:00.000000000 +0100
+++ new/unicode_segmentation_rs-0.2.4/.github/release.yml       2006-07-24 
03:21:28.000000000 +0200
@@ -0,0 +1,22 @@
+# Copyright © Michal Čihař <[email protected]>
+#
+# SPDX-License-Identifier: CC0-1.0
+
+# This file is maintained in https://github.com/WeblateOrg/meta/
+
+changelog:
+  categories:
+  - title: Changes and improvements
+    labels:
+    - '*'
+    exclude:
+      labels:
+      - dependencies
+      authors:
+      - weblate
+  - title: Dependency updates
+    labels:
+    - dependencies
+  - title: Translation updates
+    authors:
+    - weblate
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/unicode_segmentation_rs-0.2.1/.github/workflows/ci.yml 
new/unicode_segmentation_rs-0.2.4/.github/workflows/ci.yml
--- old/unicode_segmentation_rs-0.2.1/.github/workflows/ci.yml  2006-07-24 
03:21:28.000000000 +0200
+++ new/unicode_segmentation_rs-0.2.4/.github/workflows/ci.yml  2006-07-24 
03:21:28.000000000 +0200
@@ -38,23 +38,24 @@
           python-version: '3.14'
     name: Tests, Python ${{ matrix.python-version }}, ${{ matrix.os }}
     steps:
-    - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
       with:
         persist-credentials: false
     - name: Set up Python ${{ matrix.python-version }}
-      uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # 
v6.1.0
+      uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # 
v6.2.0
       id: setup_python
       with:
         python-version: ${{ matrix.python-version }}
-    - uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # 
v7.1.6 # zizmor: ignore[cache-poisoning]
+    - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # 
v8.0.0 # zizmor: ignore[cache-poisoning]
       # The cache is stored only on main branch and not used for publishing
       with:
         save-cache: ${{ github.ref == 'refs/heads/main' }}
         cache-suffix: ${{ steps.setup_python.outputs.python-version }}
-        version: 0.9.17
+        version: 0.11.6
         activate-environment: 'true'
     - run: uv sync
-    - run: pytest
+    - name: Run tests
+      run: pytest
 
 
   linux:
@@ -76,35 +77,33 @@
         - runner: ubuntu-latest
           target: ppc64le
     steps:
-    - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
       with:
         persist-credentials: false
-    - uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # 
v6.1.0
-      with:
-        python-version: 3.x
     - name: Build wheels
-      uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # 
v1.49.4
+      uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # 
v1.51.0
       with:
         target: ${{ matrix.platform.target }}
-        args: --release --out dist
+        # Build the stable-ABI wheel against CPython 3.10 so it is tagged 
cp310-abi3 everywhere.
+        args: --release --out dist -i python3.10
         sccache: false
         manylinux: auto
     - name: Build free-threaded wheels
-      uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # 
v1.49.4
+      uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # 
v1.51.0
       with:
         target: ${{ matrix.platform.target }}
         args: --release --out dist -i python3.14t
         sccache: false
         manylinux: auto
     - name: Build free-threaded wheels
-      uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # 
v1.49.4
+      uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # 
v1.51.0
       with:
         target: ${{ matrix.platform.target }}
         args: --release --out dist -i python3.13t
         sccache: false
         manylinux: auto
     - name: Upload wheels
-      uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # 
v6.0.0
+      uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # 
v7.0.0
       with:
         name: wheels-linux-${{ matrix.platform.target }}
         path: dist
@@ -124,21 +123,18 @@
         - runner: ubuntu-latest
           target: armv7
     steps:
-    - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
       with:
         persist-credentials: false
-    - uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # 
v6.1.0
-      with:
-        python-version: 3.x
     - name: Build wheels
-      uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # 
v1.49.4
+      uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # 
v1.51.0
       with:
         target: ${{ matrix.platform.target }}
-        args: --release --out dist
+        args: --release --out dist -i python3.10
         sccache: false
         manylinux: musllinux_1_2
     - name: Build free-threaded wheels
-      uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # 
v1.49.4
+      uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # 
v1.51.0
       with:
         target: ${{ matrix.platform.target }}
         args: --release --out dist -i python3.13t
@@ -146,7 +142,7 @@
         sccache: false
         manylinux: musllinux_1_2
     - name: Build free-threaded wheels
-      uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # 
v1.49.4
+      uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # 
v1.51.0
       with:
         target: ${{ matrix.platform.target }}
         args: --release --out dist -i python3.14t
@@ -154,7 +150,7 @@
         sccache: false
         manylinux: musllinux_1_2
     - name: Upload wheels
-      uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # 
v6.0.0
+      uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # 
v7.0.0
       with:
         name: wheels-musllinux-${{ matrix.platform.target }}
         path: dist
@@ -170,37 +166,37 @@
         - runner: windows-latest
           target: x86
     steps:
-    - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
       with:
         persist-credentials: false
-    - uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # 
v6.1.0
+    - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # 
v6.2.0
       with:
-        python-version: 3.x
+        python-version: '3.10'
         architecture: ${{ matrix.platform.target }}
     - name: Build wheels
-      uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # 
v1.49.4
+      uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # 
v1.51.0
       with:
         target: ${{ matrix.platform.target }}
-        args: --release --out dist
+        args: --release --out dist -i python
         sccache: false
-    - uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # 
v6.1.0
+    - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # 
v6.2.0
       with:
         python-version: 3.13t
         architecture: ${{ matrix.platform.target }}
     - name: Build free-threaded wheels
-      uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # 
v1.49.4
+      uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # 
v1.51.0
       with:
         target: ${{ matrix.platform.target }}
         args: --release --out dist -i python3.13t
         sccache: false
     - name: Build free-threaded wheels
-      uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # 
v1.49.4
+      uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # 
v1.51.0
       with:
         target: ${{ matrix.platform.target }}
         args: --release --out dist -i python3.14t
         sccache: false
     - name: Upload wheels
-      uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # 
v6.0.0
+      uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # 
v7.0.0
       with:
         name: wheels-windows-${{ matrix.platform.target }}
         path: dist
@@ -216,52 +212,52 @@
         - runner: macos-15
           target: aarch64
     steps:
-    - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
       with:
         persist-credentials: false
-    - uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # 
v6.1.0
+    - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # 
v6.2.0
       with:
-        python-version: 3.x
+        python-version: '3.10'
     - name: Build wheels
-      uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # 
v1.49.4
+      uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # 
v1.51.0
       with:
         target: ${{ matrix.platform.target }}
-        args: --release --out dist
+        args: --release --out dist -i python
         sccache: false
     - name: Build free-threaded wheels
-      uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # 
v1.49.4
+      uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # 
v1.51.0
       with:
         target: ${{ matrix.platform.target }}
         args: --release --out dist -i python3.13t
 
         sccache: false
     - name: Build free-threaded wheels
-      uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # 
v1.49.4
+      uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # 
v1.51.0
       with:
         target: ${{ matrix.platform.target }}
         args: --release --out dist -i python3.14t
 
         sccache: false
     - name: Upload wheels
-      uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # 
v6.0.0
+      uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # 
v7.0.0
       with:
         name: wheels-macos-${{ matrix.platform.target }}
         path: dist
 
   sdist:
-    runs-on: ubuntu-latest
+    runs-on: ubuntu-24.04
     name: Package sdist
     steps:
-    - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
       with:
         persist-credentials: false
     - name: Build sdist
-      uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # 
v1.49.4
+      uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # 
v1.51.0
       with:
         command: sdist
         args: --out dist
     - name: Upload sdist
-      uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # 
v6.0.0
+      uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # 
v7.0.0
       with:
         name: wheels-sdist
         path: dist
@@ -281,7 +277,7 @@
 
   release:
     name: Release
-    runs-on: ubuntu-latest
+    runs-on: ubuntu-24.04
     if: ${{ startsWith(github.ref, 'refs/tags/') || github.event_name == 
'workflow_dispatch' }}
     needs: all-tests
     permissions:
@@ -292,31 +288,35 @@
       # Used to generate artifact attestation
       attestations: write
     steps:
-    - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
       with:
         persist-credentials: false
-    - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 
# v7.0.0
+    - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c 
# v8.0.1
     - name: Generate artifact attestation
-      uses: 
actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # 
v3.0.0
+      uses: 
actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # 
v4.1.0
       with:
         subject-path: wheels-*/*
     - name: Publish to PyPI
       if: ${{ startsWith(github.ref, 'refs/tags/') }}
-      uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # 
v1.49.4
+      uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # 
v1.51.0
       with:
         command: upload
         args: --non-interactive --skip-existing wheels-*/*
 
   release_github:
-    runs-on: ubuntu-latest
+    runs-on: ubuntu-24.04
     name: Create release on GitHub
     permissions:
       contents: write
     needs: all-tests
     if: ${{ startsWith(github.ref, 'refs/tags/') || github.event_name == 
'workflow_dispatch' }}
     steps:
-    - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 
# v7.0.0
-    - uses: ncipollo/release-action@b7eabc95ff50cbeeedec83973935c8f306dfcd0b # 
v1.20.0
+    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
       with:
-        generateReleaseNotes: true
-        artifacts: wheels-*/*
+        persist-credentials: false
+    - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c 
# v8.0.1
+    - env:
+        VERSION: ${{ github.ref_name }}
+        GH_TOKEN: ${{ github.token }}
+      run: |
+        gh release create "$VERSION" --verify-tag --generate-notes wheels-*/*
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/unicode_segmentation_rs-0.2.1/.github/workflows/dependency-review.yml 
new/unicode_segmentation_rs-0.2.4/.github/workflows/dependency-review.yml
--- old/unicode_segmentation_rs-0.2.1/.github/workflows/dependency-review.yml   
1970-01-01 01:00:00.000000000 +0100
+++ new/unicode_segmentation_rs-0.2.4/.github/workflows/dependency-review.yml   
2006-07-24 03:21:28.000000000 +0200
@@ -0,0 +1,22 @@
+# Copyright © Michal Čihař <[email protected]>
+#
+# SPDX-License-Identifier: CC0-1.0
+
+# This file is maintained in https://github.com/WeblateOrg/meta/
+name: Dependency Review
+on:
+  pull_request:
+
+permissions:
+  contents: read
+
+jobs:
+  dependency-review:
+    runs-on: ubuntu-slim
+    steps:
+    - name: Checkout Repository
+      uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd   # 
v6.0.2
+      with:
+        persist-credentials: false
+    - name: Dependency Review
+      uses: 
actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48   # 
v4.9.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/unicode_segmentation_rs-0.2.1/.github/workflows/pre-commit.yml 
new/unicode_segmentation_rs-0.2.4/.github/workflows/pre-commit.yml
--- old/unicode_segmentation_rs-0.2.1/.github/workflows/pre-commit.yml  
2006-07-24 03:21:28.000000000 +0200
+++ new/unicode_segmentation_rs-0.2.4/.github/workflows/pre-commit.yml  
2006-07-24 03:21:28.000000000 +0200
@@ -10,6 +10,7 @@
     branches-ignore:
     - renovate/**
     - weblate
+    - dependabot/**
   pull_request:
 
 permissions:
@@ -20,30 +21,24 @@
     runs-on: ubuntu-24.04
 
     steps:
-    - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
       with:
         persist-credentials: false
-    - name: Get cache tag
-      id: get-date
-      run: |
-        echo "cache_tag=$(/bin/date --utc '+%Y%m')" >> "$GITHUB_OUTPUT"
-        echo "previous_cache_tag=$(/bin/date --date='1 month ago' --utc 
'+%Y%m')" >> "$GITHUB_OUTPUT"
-      shell: bash
-    - uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1
-      id: pre-commit-cache
+    - uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
       with:
-        path: ~/.cache/pre-commit
-        key: ${{ runner.os }}-pre-commit-${{ steps.get-date.outputs.cache_tag 
}}-${{ hashFiles('.pre-commit-config.yaml') }}
+        path: |
+          ~/.cache/prek
+          ~/.cache/kingfisher
+        key: ${{ runner.os }}-prek-${{ hashFiles('.pre-commit-config.yaml') }}
         restore-keys: |
-          ${{ runner.os }}-pre-commit-${{ steps.get-date.outputs.cache_tag }}
-          ${{ runner.os }}-pre-commit-${{ 
steps.get-date.outputs.previous_cache_tag }}
-          ${{ runner.os }}-pre-commit-
+          ${{ runner.os }}-prek-
     - name: Setup Python
-      uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # 
v6.1.0
+      uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # 
v6.2.0
       with:
         python-version: '3.14'
-    - uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # 
v7.1.6
+    - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # 
v8.0.0
       with:
+        version: 0.11.6
         enable-cache: false
     - name: detect method
       id: detect
@@ -52,16 +47,14 @@
           echo "method=requirements" >> "$GITHUB_OUTPUT"
         elif test -f pyproject.toml && grep -q dependency-groups 
pyproject.toml ; then
           echo "method=pep735" >> "$GITHUB_OUTPUT"
-        elif test -f pyproject.toml && grep -q dependency-groups 
pyproject.toml ; then
-          echo "method=pyproject" >> "$GITHUB_OUTPUT"
         else
           echo "method=uvx" >> "$GITHUB_OUTPUT"
         fi
     - name: pre-commit (PEP 735)
       if: steps.detect.outputs.method == 'pep735'
       run: |
-        uv run --only-group pre-commit pre-commit run --all 
--show-diff-on-failure
-        uv run --only-group pre-commit pre-commit gc
+        uv run --only-group pre-commit prek run --all-files 
--show-diff-on-failure
+        uv run --only-group pre-commit prek cache gc
       env:
         RUFF_OUTPUT_FORMAT: github
         REUSE_OUTPUT_FORMAT: github
@@ -69,23 +62,18 @@
     - name: pre-commit (uvx)
       if: steps.detect.outputs.method == 'uvx'
       run: |
-        uvx pre-commit run --all --show-diff-on-failure
-        uvx pre-commit gc
+        uvx prek run --all-files --show-diff-on-failure
+        uvx prek cache gc
       env:
         RUFF_OUTPUT_FORMAT: github
         REUSE_OUTPUT_FORMAT: github
         GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-    - name: Install dependencies
+    - name: pre-commit (requirements)
       if: steps.detect.outputs.method == 'requirements'
-      run: uv pip install --system -r requirements-lint.txt
-    - name: Install dependencies
-      if: steps.detect.outputs.method == 'pyproject'
-      run: uv pip install --system "$(sed -n 
's/.*"\(pre-commit==\([^"]*\)\)".*/\1/p' pyproject.toml)"
-    - name: pre-commit (installed)
-      if: steps.detect.outputs.method == 'requirements' || 
steps.detect.outputs.method == 'pyproject'
       run: |
-        pre-commit run --all --show-diff-on-failure
-        pre-commit gc
+        uv pip install --system -r requirements-lint.txt
+        prek run --all-files --show-diff-on-failure
+        prek cache gc
       env:
         RUFF_OUTPUT_FORMAT: github
         REUSE_OUTPUT_FORMAT: github
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/unicode_segmentation_rs-0.2.1/.github/workflows/pull_requests.yaml 
new/unicode_segmentation_rs-0.2.4/.github/workflows/pull_requests.yaml
--- old/unicode_segmentation_rs-0.2.1/.github/workflows/pull_requests.yaml      
1970-01-01 01:00:00.000000000 +0100
+++ new/unicode_segmentation_rs-0.2.4/.github/workflows/pull_requests.yaml      
2006-07-24 03:21:28.000000000 +0200
@@ -0,0 +1,28 @@
+# Copyright © Michal Čihař <[email protected]>
+#
+# SPDX-License-Identifier: CC0-1.0
+
+# This file is maintained in https://github.com/WeblateOrg/meta/
+
+name: Pull request automation
+
+on: # zizmor: ignore[dangerous-triggers]
+  pull_request_target:
+    types: opened
+
+permissions:
+  contents: read
+
+jobs:
+  weblate_automerge:
+    runs-on: ubuntu-slim
+    name: Weblate automerge
+    if: github.actor == 'weblate'
+    steps:
+    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+      with:
+        persist-credentials: false
+    - name: Enable Pull Request Automerge
+      run: gh pr merge --rebase --auto "${{ github.event.pull_request.number 
}}"
+      env:
+        GH_TOKEN: ${{ secrets.WEBLATE_CI_TOKEN }} # zizmor: 
ignore[secrets-outside-env]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/unicode_segmentation_rs-0.2.1/.pre-commit-config.yaml 
new/unicode_segmentation_rs-0.2.4/.pre-commit-config.yaml
--- old/unicode_segmentation_rs-0.2.1/.pre-commit-config.yaml   2006-07-24 
03:21:28.000000000 +0200
+++ new/unicode_segmentation_rs-0.2.4/.pre-commit-config.yaml   2006-07-24 
03:21:28.000000000 +0200
@@ -10,17 +10,16 @@
   - id: check-toml
   - id: check-merge-conflict
   - id: check-json
-  - id: debug-statements
   - id: mixed-line-ending
     args: [--fix=lf]
   - id: pretty-format-json
     args: [--no-sort-keys, --autofix]
 - repo: https://github.com/adrienverge/yamllint
-  rev: v1.37.1
+  rev: v1.38.0
   hooks:
   - id: yamllint
 - repo: https://github.com/astral-sh/ruff-pre-commit
-  rev: v0.14.9
+  rev: v0.15.10
   hooks:
   - id: ruff-check
     args:
@@ -32,7 +31,7 @@
   - id: check-hooks-apply
   - id: check-useless-excludes
 - repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks
-  rev: v2.15.0
+  rev: v2.16.0
   hooks:
   - id: pretty-format-yaml
     args: [--autofix, --indent, '2']
@@ -45,7 +44,7 @@
     additional_dependencies:
     - mdformat-gfm==1.0.0
 - repo: https://github.com/igorshubovych/markdownlint-cli
-  rev: v0.47.0
+  rev: v0.48.0
   hooks:
   - id: markdownlint
 - repo: https://github.com/fsfe/reuse-tool
@@ -53,16 +52,19 @@
   hooks:
   - id: reuse
 - repo: https://github.com/rhysd/actionlint
-  rev: v1.7.9
+  rev: v1.7.12
   hooks:
   - id: actionlint
 - repo: https://github.com/zizmorcore/zizmor-pre-commit
-  rev: v1.18.0
+  rev: v1.23.1
   hooks:
   - id: zizmor
-- repo: https://github.com/gitleaks/gitleaks
-  rev: v8.30.0
+- repo: https://github.com/mongodb/kingfisher
+  rev: v1.95.0
   hooks:
-  - id: gitleaks
+  - id: kingfisher-auto
 ci:
   autoupdate_schedule: quarterly
+  skip:
+  - reuse
+  - kingfisher-auto
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unicode_segmentation_rs-0.2.1/Cargo.lock 
new/unicode_segmentation_rs-0.2.4/Cargo.lock
--- old/unicode_segmentation_rs-0.2.1/Cargo.lock        2006-07-24 
03:21:28.000000000 +0200
+++ new/unicode_segmentation_rs-0.2.4/Cargo.lock        2006-07-24 
03:21:28.000000000 +0200
@@ -3,16 +3,10 @@
 version = 4
 
 [[package]]
-name = "autocfg"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
-
-[[package]]
 name = "cc"
-version = "1.2.49"
+version = "1.2.60"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "90583009037521a116abf44494efecd645ba48b6622457080f080b85544e2215"
+checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20"
 dependencies = [
  "find-msvc-tools",
  "shlex",
@@ -20,9 +14,9 @@
 
 [[package]]
 name = "find-msvc-tools"
-version = "0.1.5"
+version = "0.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844"
+checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
 
 [[package]]
 name = "heck"
@@ -31,72 +25,51 @@
 checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
 
 [[package]]
-name = "indoc"
-version = "2.0.7"
-source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706"
-dependencies = [
- "rustversion",
-]
-
-[[package]]
 name = "libc"
-version = "0.2.178"
+version = "0.2.184"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091"
-
-[[package]]
-name = "memoffset"
-version = "0.9.1"
-source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
-dependencies = [
- "autocfg",
-]
+checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af"
 
 [[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 = "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 = "proc-macro2"
-version = "1.0.103"
+version = "1.0.106"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
+checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
 dependencies = [
  "unicode-ident",
 ]
 
 [[package]]
 name = "pyo3"
-version = "0.27.2"
+version = "0.28.3"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "ab53c047fcd1a1d2a8820fe84f05d6be69e9526be40cb03b73f86b6b03e6d87d"
+checksum = "91fd8e38a3b50ed1167fb981cd6fd60147e091784c427b8f7183a7ee32c31c12"
 dependencies = [
- "indoc",
  "libc",
- "memoffset",
  "once_cell",
  "portable-atomic",
  "pyo3-build-config",
  "pyo3-ffi",
  "pyo3-macros",
- "unindent",
 ]
 
 [[package]]
 name = "pyo3-build-config"
-version = "0.27.2"
+version = "0.28.3"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "b455933107de8642b4487ed26d912c2d899dec6114884214a0b3bb3be9261ea6"
+checksum = "e368e7ddfdeb98c9bca7f8383be1648fd84ab466bf2bc015e94008db6d35611e"
 dependencies = [
  "python3-dll-a",
  "target-lexicon",
@@ -104,9 +77,9 @@
 
 [[package]]
 name = "pyo3-ffi"
-version = "0.27.2"
+version = "0.28.3"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "1c85c9cbfaddf651b1221594209aed57e9e5cff63c4d11d1feead529b872a089"
+checksum = "7f29e10af80b1f7ccaf7f69eace800a03ecd13e883acfacc1e5d0988605f651e"
 dependencies = [
  "libc",
  "pyo3-build-config",
@@ -114,9 +87,9 @@
 
 [[package]]
 name = "pyo3-macros"
-version = "0.27.2"
+version = "0.28.3"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "0a5b10c9bf9888125d917fb4d2ca2d25c8df94c7ab5a52e13313a07e050a3b02"
+checksum = "df6e520eff47c45997d2fc7dd8214b25dd1310918bbb2642156ef66a67f29813"
 dependencies = [
  "proc-macro2",
  "pyo3-macros-backend",
@@ -126,9 +99,9 @@
 
 [[package]]
 name = "pyo3-macros-backend"
-version = "0.27.2"
+version = "0.28.3"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "03b51720d314836e53327f5871d4c0cfb4fb37cc2c4a11cc71907a86342c40f9"
+checksum = "c4cdc218d835738f81c2338f822078af45b4afdf8b2e33cbb5916f108b813acb"
 dependencies = [
  "heck",
  "proc-macro2",
@@ -139,29 +112,23 @@
 
 [[package]]
 name = "python3-dll-a"
-version = "0.2.14"
+version = "0.2.15"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "d381ef313ae70b4da5f95f8a4de773c6aa5cd28f73adec4b4a31df70b66780d8"
+checksum = "d80ba7540edb18890d444c5aa8e1f1f99b1bdf26fb26ae383135325f4a36042b"
 dependencies = [
  "cc",
 ]
 
 [[package]]
 name = "quote"
-version = "1.0.42"
+version = "1.0.45"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f"
+checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
 dependencies = [
  "proc-macro2",
 ]
 
 [[package]]
-name = "rustversion"
-version = "1.0.22"
-source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
-
-[[package]]
 name = "shlex"
 version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
@@ -169,9 +136,9 @@
 
 [[package]]
 name = "syn"
-version = "2.0.111"
+version = "2.0.117"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87"
+checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -180,25 +147,25 @@
 
 [[package]]
 name = "target-lexicon"
-version = "0.13.3"
+version = "0.13.5"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "df7f62577c25e07834649fc3b39fafdc597c0a3527dc1c60129201ccfcbaa50c"
+checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
 
 [[package]]
 name = "unicode-ident"
-version = "1.0.22"
+version = "1.0.24"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
+checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
 
 [[package]]
 name = "unicode-segmentation"
-version = "1.12.0"
+version = "1.13.2"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
+checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c"
 
 [[package]]
 name = "unicode-segmentation-rs"
-version = "0.2.1"
+version = "0.2.4"
 dependencies = [
  "pyo3",
  "unicode-segmentation",
@@ -210,9 +177,3 @@
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
-
-[[package]]
-name = "unindent"
-version = "0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unicode_segmentation_rs-0.2.1/Cargo.toml 
new/unicode_segmentation_rs-0.2.4/Cargo.toml
--- old/unicode_segmentation_rs-0.2.1/Cargo.toml        2006-07-24 
03:21:28.000000000 +0200
+++ new/unicode_segmentation_rs-0.2.4/Cargo.toml        2006-07-24 
03:21:28.000000000 +0200
@@ -1,6 +1,6 @@
 [dependencies]
-pyo3 = {version = "0.27.1", features = ["extension-module", "abi3-py310", 
"generate-import-lib"]}
-unicode-segmentation = "1.12.0"
+pyo3 = {version = "0.28.3", features = ["extension-module", "abi3-py310", 
"generate-import-lib"]}
+unicode-segmentation = "1.13.2"
 unicode-width = "0.2.2"
 
 [lib]
@@ -15,4 +15,4 @@
 name = "unicode-segmentation-rs"
 readme = "README.md"
 repository = "https://github.com/WeblateOrg/unicode-segmentation-rs";
-version = "0.2.1"
+version = "0.2.4"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unicode_segmentation_rs-0.2.1/PKG-INFO 
new/unicode_segmentation_rs-0.2.4/PKG-INFO
--- old/unicode_segmentation_rs-0.2.1/PKG-INFO  2006-07-24 03:21:28.000000000 
+0200
+++ new/unicode_segmentation_rs-0.2.4/PKG-INFO  2006-07-24 03:21:28.000000000 
+0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: unicode-segmentation-rs
-Version: 0.2.1
+Version: 0.2.4
 Classifier: Programming Language :: Rust
 Classifier: Programming Language :: Python :: Implementation :: CPython
 Classifier: Programming Language :: Python :: Implementation :: PyPy
@@ -56,40 +56,40 @@
 
 # Grapheme clusters (user-perceived characters)
 text = "Hello 👨‍👩‍👧‍👦 World"
-clusters = unicode_segmentation_py.graphemes(text, is_extended=True)
+clusters = unicode_segmentation_rs.graphemes(text, is_extended=True)
 print(clusters)  # ['H', 'e', 'l', 'l', 'o', ' ', '👨‍👩‍👧‍👦', ' ', 'W', 'o', 
'r', 'l', 'd']
 
 # Get grapheme clusters with their byte indices
-indices = unicode_segmentation_py.grapheme_indices(text, is_extended=True)
+indices = unicode_segmentation_rs.grapheme_indices(text, is_extended=True)
 print(indices)  # [(0, 'H'), (1, 'e'), ...]
 
 # Word boundaries (includes punctuation and whitespace)
 text = "Hello, world!"
-words = unicode_segmentation_py.split_word_bounds(text)
+words = unicode_segmentation_rs.split_word_bounds(text)
 print(words)  # ['Hello', ',', ' ', 'world', '!']
 
 # Unicode words (excludes punctuation and whitespace)
-words = unicode_segmentation_py.unicode_words(text)
+words = unicode_segmentation_rs.unicode_words(text)
 print(words)  # ['Hello', 'world']
 
 # Word indices
-indices = unicode_segmentation_py.split_word_bound_indices(text)
+indices = unicode_segmentation_rs.split_word_bound_indices(text)
 print(indices)  # [(0, 'Hello'), (5, ','), ...]
 
 # Sentence segmentation
 text = "Hello world. How are you? I'm fine."
-sentences = unicode_segmentation_py.unicode_sentences(text)
+sentences = unicode_segmentation_rs.unicode_sentences(text)
 print(sentences)  # ['Hello world. ', 'How are you? ', "I'm fine."]
 
 # Display width calculation
 text = "Hello 世界"
-width = unicode_segmentation_py.text_width(text)
+width = unicode_segmentation_rs.text_width(text)
 print(width)  # 10 (Hello=5, space=1, 世=2, 界=2, but depends on terminal)
 
 # Character width
-print(unicode_segmentation_py.text_width('A'))    # Some(1)
-print(unicode_segmentation_py.text_width('世'))   # Some(2)
-print(unicode_segmentation_py.text_width('\t'))   # None (control character)
+print(unicode_segmentation_rs.text_width('A'))    # 1
+print(unicode_segmentation_rs.text_width('世'))   # 2
+print(unicode_segmentation_rs.text_width('\t'))   # 1
 ```
 
 ## Examples
@@ -102,13 +102,13 @@
 # Complex emojis and combining characters
 text = "Hello 👨‍👩‍👧‍👦 नमस्ते"
 print(f"Text: {text}")
-print(f"Graphemes: {unicode_segmentation_py.graphemes(text, 
is_extended=True)}")
-print(f"Length (graphemes): {len(unicode_segmentation_py.graphemes(text, 
is_extended=True))}")
+print(f"Graphemes: {unicode_segmentation_rs.graphemes(text, 
is_extended=True)}")
+print(f"Length (graphemes): {len(unicode_segmentation_rs.graphemes(text, 
is_extended=True))}")
 print(f"Length (chars): {len(text)}")
 
 # With indices
 print("Grapheme indices:")
-for idx, cluster in unicode_segmentation_py.grapheme_indices(text, 
is_extended=True):
+for idx, cluster in unicode_segmentation_rs.grapheme_indices(text, 
is_extended=True):
     print(f"  {idx:3d}: {cluster!r}")
 ```
 
@@ -117,12 +117,12 @@
 ```python
 text = "Hello, world! How are you?"
 print(f"Text: {text}")
-print(f"Word bounds: {unicode_segmentation_py.split_word_bounds(text)}")
-print(f"Unicode words: {unicode_segmentation_py.unicode_words(text)}")
+print(f"Word bounds: {unicode_segmentation_rs.split_word_bounds(text)}")
+print(f"Unicode words: {unicode_segmentation_rs.unicode_words(text)}")
 
 # With indices
 print("Word boundary indices:")
-for idx, word in unicode_segmentation_py.split_word_bound_indices(text):
+for idx, word in unicode_segmentation_rs.split_word_bound_indices(text):
     print(f"  {idx:3d}: {word!r}")
 ```
 
@@ -131,7 +131,7 @@
 ```python
 text = "Hello world. How are you? I'm fine, thanks! What about you?"
 print(f"Text: {text}")
-sentences = unicode_segmentation_py.unicode_sentences(text)
+sentences = unicode_segmentation_rs.unicode_sentences(text)
 print("Sentences:")
 for i, sentence in enumerate(sentences, 1):
     print(f"  {i}. {sentence!r}")
@@ -143,17 +143,17 @@
 # Arabic
 arabic = "مرحبا بك. كيف حالك؟"
 print(f"Arabic: {arabic}")
-print(f"Sentences: {unicode_segmentation_py.unicode_sentences(arabic)}")
+print(f"Sentences: {unicode_segmentation_rs.unicode_sentences(arabic)}")
 
 # Japanese
 japanese = "こんにちは。お元気ですか?"
 print(f"Japanese: {japanese}")
-print(f"Sentences: {unicode_segmentation_py.unicode_sentences(japanese)}")
+print(f"Sentences: {unicode_segmentation_rs.unicode_sentences(japanese)}")
 
 # Mixed languages
 mixed = "Hello世界! This is a test文章."
 print(f"Mixed: {mixed}")
-print(f"Words: {unicode_segmentation_py.unicode_words(mixed)}")
+print(f"Words: {unicode_segmentation_rs.unicode_words(mixed)}")
 ```
 
 ### Display Width Calculation
@@ -169,18 +169,14 @@
 ]
 
 for text in examples:
-    width = unicode_segmentation_py.text_width(text)
-    width_cjk = unicode_segmentation_py.text_width_cjk(text)
-    print(f"Text: {text!r:20} Width: {width:2} CJK: {width_cjk:2} Chars: 
{len(text):2}")
+    width = unicode_segmentation_rs.text_width(text)
+    print(f"Text: {text!r:20} Width: {width:2} Chars: {len(text):2}")
 
 # Character widths
 chars = ['a', 'A', '1', ' ', '世', '界', 'あ', '🎉', '\t', '\n']
 for c in chars:
-    w = unicode_segmentation_py.text_width(c)
-    w_cjk = unicode_segmentation_py.text_width_cjk(c)
-    w_str = str(w) if w is not None else "None"
-    w_cjk_str = str(w_cjk) if w_cjk is not None else "None"
-    print(f"  {c!r:6} width: {w_str:4} cjk: {w_cjk_str:4}")
+    w = unicode_segmentation_rs.text_width(c)
+    print(f"  {c!r:6} width: {w:2}")
 ```
 
 ### Gettext PO File Wrapping
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unicode_segmentation_rs-0.2.1/README.md 
new/unicode_segmentation_rs-0.2.4/README.md
--- old/unicode_segmentation_rs-0.2.1/README.md 2006-07-24 03:21:28.000000000 
+0200
+++ new/unicode_segmentation_rs-0.2.4/README.md 2006-07-24 03:21:28.000000000 
+0200
@@ -35,40 +35,40 @@
 
 # Grapheme clusters (user-perceived characters)
 text = "Hello 👨‍👩‍👧‍👦 World"
-clusters = unicode_segmentation_py.graphemes(text, is_extended=True)
+clusters = unicode_segmentation_rs.graphemes(text, is_extended=True)
 print(clusters)  # ['H', 'e', 'l', 'l', 'o', ' ', '👨‍👩‍👧‍👦', ' ', 'W', 'o', 
'r', 'l', 'd']
 
 # Get grapheme clusters with their byte indices
-indices = unicode_segmentation_py.grapheme_indices(text, is_extended=True)
+indices = unicode_segmentation_rs.grapheme_indices(text, is_extended=True)
 print(indices)  # [(0, 'H'), (1, 'e'), ...]
 
 # Word boundaries (includes punctuation and whitespace)
 text = "Hello, world!"
-words = unicode_segmentation_py.split_word_bounds(text)
+words = unicode_segmentation_rs.split_word_bounds(text)
 print(words)  # ['Hello', ',', ' ', 'world', '!']
 
 # Unicode words (excludes punctuation and whitespace)
-words = unicode_segmentation_py.unicode_words(text)
+words = unicode_segmentation_rs.unicode_words(text)
 print(words)  # ['Hello', 'world']
 
 # Word indices
-indices = unicode_segmentation_py.split_word_bound_indices(text)
+indices = unicode_segmentation_rs.split_word_bound_indices(text)
 print(indices)  # [(0, 'Hello'), (5, ','), ...]
 
 # Sentence segmentation
 text = "Hello world. How are you? I'm fine."
-sentences = unicode_segmentation_py.unicode_sentences(text)
+sentences = unicode_segmentation_rs.unicode_sentences(text)
 print(sentences)  # ['Hello world. ', 'How are you? ', "I'm fine."]
 
 # Display width calculation
 text = "Hello 世界"
-width = unicode_segmentation_py.text_width(text)
+width = unicode_segmentation_rs.text_width(text)
 print(width)  # 10 (Hello=5, space=1, 世=2, 界=2, but depends on terminal)
 
 # Character width
-print(unicode_segmentation_py.text_width('A'))    # Some(1)
-print(unicode_segmentation_py.text_width('世'))   # Some(2)
-print(unicode_segmentation_py.text_width('\t'))   # None (control character)
+print(unicode_segmentation_rs.text_width('A'))    # 1
+print(unicode_segmentation_rs.text_width('世'))   # 2
+print(unicode_segmentation_rs.text_width('\t'))   # 1
 ```
 
 ## Examples
@@ -81,13 +81,13 @@
 # Complex emojis and combining characters
 text = "Hello 👨‍👩‍👧‍👦 नमस्ते"
 print(f"Text: {text}")
-print(f"Graphemes: {unicode_segmentation_py.graphemes(text, 
is_extended=True)}")
-print(f"Length (graphemes): {len(unicode_segmentation_py.graphemes(text, 
is_extended=True))}")
+print(f"Graphemes: {unicode_segmentation_rs.graphemes(text, 
is_extended=True)}")
+print(f"Length (graphemes): {len(unicode_segmentation_rs.graphemes(text, 
is_extended=True))}")
 print(f"Length (chars): {len(text)}")
 
 # With indices
 print("Grapheme indices:")
-for idx, cluster in unicode_segmentation_py.grapheme_indices(text, 
is_extended=True):
+for idx, cluster in unicode_segmentation_rs.grapheme_indices(text, 
is_extended=True):
     print(f"  {idx:3d}: {cluster!r}")
 ```
 
@@ -96,12 +96,12 @@
 ```python
 text = "Hello, world! How are you?"
 print(f"Text: {text}")
-print(f"Word bounds: {unicode_segmentation_py.split_word_bounds(text)}")
-print(f"Unicode words: {unicode_segmentation_py.unicode_words(text)}")
+print(f"Word bounds: {unicode_segmentation_rs.split_word_bounds(text)}")
+print(f"Unicode words: {unicode_segmentation_rs.unicode_words(text)}")
 
 # With indices
 print("Word boundary indices:")
-for idx, word in unicode_segmentation_py.split_word_bound_indices(text):
+for idx, word in unicode_segmentation_rs.split_word_bound_indices(text):
     print(f"  {idx:3d}: {word!r}")
 ```
 
@@ -110,7 +110,7 @@
 ```python
 text = "Hello world. How are you? I'm fine, thanks! What about you?"
 print(f"Text: {text}")
-sentences = unicode_segmentation_py.unicode_sentences(text)
+sentences = unicode_segmentation_rs.unicode_sentences(text)
 print("Sentences:")
 for i, sentence in enumerate(sentences, 1):
     print(f"  {i}. {sentence!r}")
@@ -122,17 +122,17 @@
 # Arabic
 arabic = "مرحبا بك. كيف حالك؟"
 print(f"Arabic: {arabic}")
-print(f"Sentences: {unicode_segmentation_py.unicode_sentences(arabic)}")
+print(f"Sentences: {unicode_segmentation_rs.unicode_sentences(arabic)}")
 
 # Japanese
 japanese = "こんにちは。お元気ですか?"
 print(f"Japanese: {japanese}")
-print(f"Sentences: {unicode_segmentation_py.unicode_sentences(japanese)}")
+print(f"Sentences: {unicode_segmentation_rs.unicode_sentences(japanese)}")
 
 # Mixed languages
 mixed = "Hello世界! This is a test文章."
 print(f"Mixed: {mixed}")
-print(f"Words: {unicode_segmentation_py.unicode_words(mixed)}")
+print(f"Words: {unicode_segmentation_rs.unicode_words(mixed)}")
 ```
 
 ### Display Width Calculation
@@ -148,18 +148,14 @@
 ]
 
 for text in examples:
-    width = unicode_segmentation_py.text_width(text)
-    width_cjk = unicode_segmentation_py.text_width_cjk(text)
-    print(f"Text: {text!r:20} Width: {width:2} CJK: {width_cjk:2} Chars: 
{len(text):2}")
+    width = unicode_segmentation_rs.text_width(text)
+    print(f"Text: {text!r:20} Width: {width:2} Chars: {len(text):2}")
 
 # Character widths
 chars = ['a', 'A', '1', ' ', '世', '界', 'あ', '🎉', '\t', '\n']
 for c in chars:
-    w = unicode_segmentation_py.text_width(c)
-    w_cjk = unicode_segmentation_py.text_width_cjk(c)
-    w_str = str(w) if w is not None else "None"
-    w_cjk_str = str(w_cjk) if w_cjk is not None else "None"
-    print(f"  {c!r:6} width: {w_str:4} cjk: {w_cjk_str:4}")
+    w = unicode_segmentation_rs.text_width(c)
+    print(f"  {c!r:6} width: {w:2}")
 ```
 
 ### Gettext PO File Wrapping
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unicode_segmentation_rs-0.2.1/SECURITY.md 
new/unicode_segmentation_rs-0.2.4/SECURITY.md
--- old/unicode_segmentation_rs-0.2.1/SECURITY.md       1970-01-01 
01:00:00.000000000 +0100
+++ new/unicode_segmentation_rs-0.2.4/SECURITY.md       2006-07-24 
03:21:28.000000000 +0200
@@ -0,0 +1,29 @@
+<!--
+Copyright © Michal Čihař <[email protected]>
+
+SPDX-License-Identifier: CC0-1.0
+
+This file is maintained in https://github.com/WeblateOrg/meta/
+-->
+
+# Weblate security
+
+The Weblate team takes security and related transparency very seriously.
+We welcome any peer review of our 100% open-source code to ensure nobody's 
Weblate
+is ever compromised or hacked.
+
+If you think you have identified a security issue with a Weblate project, **do
+not open a public issue**.
+
+To responsibly report a security issue, please navigate to the Security tab for
+the repository and click “Report a vulnerability”.
+
+Be sure to include as much detail as necessary in your report. As with
+reporting normal issues, a minimal reproducible example will help the
+maintainers address the issue faster.
+
+More information about practices for reporting and fixing security issues is
+described in [our documentation][1]. This ensures all vulnerabilities are
+solved securely, quickly, and transparently.
+
+[1]: https://docs.weblate.org/en/latest/security/issues.html
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unicode_segmentation_rs-0.2.1/pyproject.toml 
new/unicode_segmentation_rs-0.2.4/pyproject.toml
--- old/unicode_segmentation_rs-0.2.1/pyproject.toml    2006-07-24 
03:21:28.000000000 +0200
+++ new/unicode_segmentation_rs-0.2.4/pyproject.toml    2006-07-24 
03:21:28.000000000 +0200
@@ -4,7 +4,7 @@
 
 [dependency-groups]
 build = [
-  "maturin==1.10.2"
+  "maturin==1.13.1"
 ]
 dev = [
   {include-group = "build"},
@@ -12,11 +12,11 @@
   {include-group = "pre-commit"}
 ]
 pre-commit = [
-  "pre-commit==4.5.0"
+  "prek==0.3.8"
 ]
 test = [
-  "pytest-github-actions-annotate-failures==0.3.0",
-  "pytest==9.0.2"
+  "pytest-github-actions-annotate-failures==0.4.0",
+  "pytest==9.0.3"
 ]
 
 [project]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/unicode_segmentation_rs-0.2.1/tests/test_gettext_wrap.py 
new/unicode_segmentation_rs-0.2.4/tests/test_gettext_wrap.py
--- old/unicode_segmentation_rs-0.2.1/tests/test_gettext_wrap.py        
2006-07-24 03:21:28.000000000 +0200
+++ new/unicode_segmentation_rs-0.2.4/tests/test_gettext_wrap.py        
2006-07-24 03:21:28.000000000 +0200
@@ -45,6 +45,21 @@
         result = unicode_segmentation_rs.gettext_wrap(text, 11)
         assert result == ["This has \\n", " escape ", "sequences ", "\\t in 
it"]
 
+    def test_wrap_with_carriage_return_escape(self):
+        text = r"foo\rbar baz"
+        result = unicode_segmentation_rs.gettext_wrap(text, 5)
+        assert result == [r"foo\r", "bar ", "baz"]
+
+    def test_wrap_with_consecutive_escape_sequences(self):
+        text = r"abc\n\nxyz"
+        result = unicode_segmentation_rs.gettext_wrap(text, 10)
+        assert result == [r"abc\n", r"\n", "xyz"]
+
+    def test_wrap_with_doubled_backslash_before_escape(self):
+        text = r"foo\\nbar"
+        result = unicode_segmentation_rs.gettext_wrap(text, 5)
+        assert result == [r"foo\\n", "bar"]
+
     def test_wrap_long_word(self):
         # Long words that don't fit should still be included
         text = "Supercalifragilisticexpialidocious"
@@ -112,6 +127,26 @@
             "告は、PostGIS開発者がそれを再現できるようにすることで、それの引き金となったス",
         ]
 
+    def test_wrap_combining_character_sequence(self):
+        text = "Cafe\u0301 society"
+        result = unicode_segmentation_rs.gettext_wrap(text, 5)
+        assert result == ["Cafe\u0301 ", "society"]
+
+    def test_wrap_standalone_combining_mark(self):
+        text = "\u0301x"
+        result = unicode_segmentation_rs.gettext_wrap(text, 1)
+        assert result == [text]
+
+    def test_wrap_fullwidth_punctuation_behavior(self):
+        text = "你好,世界你好,世界"
+        result = unicode_segmentation_rs.gettext_wrap(text, 8)
+        assert result == ["你好,世", "界你好,", "世界"]
+
+    def test_wrap_fullwidth_parentheses_behavior(self):
+        text = "foo(bar)bazfoo(bar)baz"
+        result = unicode_segmentation_rs.gettext_wrap(text, 12)
+        assert result == ["foo(bar)", "bazfoo(bar", ")baz"]
+
     def test_wrap_emoji(self):
         text = 'print(ts.string_get_word_breaks("Test ❤️‍🔥 Test")) # Prints 
[1, 2, 3, 4, 5, '
         result = unicode_segmentation_rs.gettext_wrap(text, 77)
@@ -243,3 +278,26 @@
             "在 C# 中,请注意 ``_Process()`` 所采用的 ``delta`` 参数类型是 ``double``\\\\ ",
             "。 故当我们将其应用于旋转时,需要将其转换为 ``float`` \\\\。",
         ]
+
+    def test_wrap_round_trip_invariant(self):
+        samples = [
+            r"abc\n\nxyz",
+            r"foo\rbar baz",
+            r"foo\\nbar",
+            "Cafe\u0301 society",
+            "你好,世界你好,世界",
+            "foo(bar)bazfoo(bar)baz",
+        ]
+        for text in samples:
+            assert "".join(unicode_segmentation_rs.gettext_wrap(text, 8)) == 
text
+
+    def test_wrap_width_invariant(self):
+        samples = [
+            ("This is a simple test string", 20),
+            (r"abc\n\nxyz", 10),
+            (r"foo\rbar baz", 5),
+            ("你好,世界你好,世界", 8),
+        ]
+        for text, width in samples:
+            for line in unicode_segmentation_rs.gettext_wrap(text, width):
+                assert unicode_segmentation_rs.text_width(line) <= width
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/unicode_segmentation_rs-0.2.1/tests/test_readme_examples.py 
new/unicode_segmentation_rs-0.2.4/tests/test_readme_examples.py
--- old/unicode_segmentation_rs-0.2.1/tests/test_readme_examples.py     
1970-01-01 01:00:00.000000000 +0100
+++ new/unicode_segmentation_rs-0.2.4/tests/test_readme_examples.py     
2006-07-24 03:21:28.000000000 +0200
@@ -0,0 +1,207 @@
+# Copyright © Michal Čihař <[email protected]>
+#
+# SPDX-License-Identifier: MIT
+
+"""Test that all code examples in README.md work correctly"""
+
+import unicode_segmentation_rs
+
+
+class TestReadmeBasicUsage:
+    """Tests for basic usage section of README"""
+
+    def test_grapheme_clusters(self):
+        """Test grapheme cluster example from README"""
+        text = "Hello 👨‍👩‍👧‍👦 World"
+        clusters = unicode_segmentation_rs.graphemes(text, is_extended=True)
+        # Verify it works
+        assert isinstance(clusters, list)
+        assert len(clusters) > 0
+
+    def test_grapheme_indices(self):
+        """Test grapheme indices example from README"""
+        text = "Hello 👨‍👩‍👧‍👦 World"
+        indices = unicode_segmentation_rs.grapheme_indices(text, 
is_extended=True)
+        # Verify it works
+        assert isinstance(indices, list)
+        assert len(indices) > 0
+        assert isinstance(indices[0], tuple)
+
+    def test_word_boundaries(self):
+        """Test word boundaries example from README"""
+        text = "Hello, world!"
+        words = unicode_segmentation_rs.split_word_bounds(text)
+        assert words == ["Hello", ",", " ", "world", "!"]
+
+    def test_unicode_words(self):
+        """Test unicode words example from README"""
+        text = "Hello, world!"
+        words = unicode_segmentation_rs.unicode_words(text)
+        assert words == ["Hello", "world"]
+
+    def test_word_indices(self):
+        """Test word indices example from README"""
+        text = "Hello, world!"
+        indices = unicode_segmentation_rs.split_word_bound_indices(text)
+        assert isinstance(indices, list)
+        assert len(indices) > 0
+
+    def test_sentence_segmentation(self):
+        """Test sentence segmentation example from README"""
+        text = "Hello world. How are you? I'm fine."
+        sentences = unicode_segmentation_rs.unicode_sentences(text)
+        assert isinstance(sentences, list)
+        assert len(sentences) == 3
+
+    def test_display_width(self):
+        """Test display width example from README"""
+        text = "Hello 世界"
+        width = unicode_segmentation_rs.text_width(text)
+        assert width == 10  # Hello=5, space=1, 世=2, 界=2
+
+    def test_character_width(self):
+        """Test character width examples from README"""
+        assert unicode_segmentation_rs.text_width("A") == 1
+        assert unicode_segmentation_rs.text_width("世") == 2
+        assert unicode_segmentation_rs.text_width("\t") == 1
+
+
+class TestReadmeGraphemeExamples:
+    """Tests for grapheme cluster segmentation examples section"""
+
+    def test_complex_emojis_combining_chars(self):
+        """Test complex emoji and combining characters example"""
+        text = "Hello 👨‍👩‍👧‍👦 नमस्ते"
+        graphemes = unicode_segmentation_rs.graphemes(text, is_extended=True)
+        assert isinstance(graphemes, list)
+        assert len(graphemes) > 0
+        assert len(graphemes) < len(text)  # Should be fewer graphemes than 
chars
+
+    def test_grapheme_indices_complex(self):
+        """Test grapheme indices with complex text"""
+        text = "Hello 👨‍👩‍👧‍👦 नमस्ते"
+        indices = unicode_segmentation_rs.grapheme_indices(text, 
is_extended=True)
+        assert isinstance(indices, list)
+        for idx, cluster in indices:
+            assert isinstance(idx, int)
+            assert isinstance(cluster, str)
+
+
+class TestReadmeWordExamples:
+    """Tests for word segmentation examples section"""
+
+    def test_word_bounds_with_punctuation(self):
+        """Test word boundaries with punctuation"""
+        text = "Hello, world! How are you?"
+        bounds = unicode_segmentation_rs.split_word_bounds(text)
+        assert isinstance(bounds, list)
+        assert len(bounds) > 0
+
+    def test_unicode_words_extraction(self):
+        """Test unicode words extraction"""
+        text = "Hello, world! How are you?"
+        words = unicode_segmentation_rs.unicode_words(text)
+        assert isinstance(words, list)
+        assert "Hello" in words
+        assert "world" in words
+
+    def test_word_boundary_indices(self):
+        """Test word boundary indices"""
+        text = "Hello, world! How are you?"
+        indices = unicode_segmentation_rs.split_word_bound_indices(text)
+        assert isinstance(indices, list)
+        for idx, word in indices:
+            assert isinstance(idx, int)
+            assert isinstance(word, str)
+
+
+class TestReadmeSentenceExamples:
+    """Tests for sentence segmentation examples section"""
+
+    def test_sentence_segmentation_multiple(self):
+        """Test sentence segmentation with multiple sentences"""
+        text = "Hello world. How are you? I'm fine, thanks! What about you?"
+        sentences = unicode_segmentation_rs.unicode_sentences(text)
+        assert isinstance(sentences, list)
+        assert len(sentences) >= 3
+
+
+class TestReadmeMultilingualExamples:
+    """Tests for multilingual examples section"""
+
+    def test_arabic_sentences(self):
+        """Test Arabic sentence segmentation"""
+        arabic = "مرحبا بك. كيف حالك؟"
+        sentences = unicode_segmentation_rs.unicode_sentences(arabic)
+        assert isinstance(sentences, list)
+        assert len(sentences) > 0
+
+    def test_japanese_sentences(self):
+        """Test Japanese sentence segmentation"""
+        japanese = "こんにちは。お元気ですか?"
+        sentences = unicode_segmentation_rs.unicode_sentences(japanese)
+        assert isinstance(sentences, list)
+        assert len(sentences) > 0
+
+    def test_mixed_language_words(self):
+        """Test mixed language word segmentation"""
+        mixed = "Hello世界! This is a test文章."
+        words = unicode_segmentation_rs.unicode_words(mixed)
+        assert isinstance(words, list)
+        assert len(words) > 0
+
+
+class TestReadmeDisplayWidthExamples:
+    """Tests for display width calculation examples section"""
+
+    def test_various_text_widths(self):
+        """Test width calculation for various texts"""
+        examples = [
+            "Hello",
+            "世界",
+            "Hello 世界",
+            "こんにちは",
+            "🎉🎊",
+            "Tab\there",
+        ]
+
+        for text in examples:
+            width = unicode_segmentation_rs.text_width(text)
+            assert isinstance(width, int)
+
+    def test_character_widths_various(self):
+        """Test character width for various characters"""
+        chars = ["a", "A", "1", " ", "世", "界", "あ", "🎉", "\t", "\n"]
+        for c in chars:
+            w = unicode_segmentation_rs.text_width(c)
+            assert isinstance(w, int)
+
+
+class TestReadmeGettextWrapExamples:
+    """Tests for gettext PO file wrapping examples section"""
+
+    def test_basic_gettext_wrap(self):
+        """Test basic gettext wrapping"""
+        text = "This is a long translation string that needs to be wrapped 
appropriately for a gettext PO file"
+        lines = unicode_segmentation_rs.gettext_wrap(text, 77)
+        assert isinstance(lines, list)
+        assert len(lines) > 0
+
+    def test_gettext_wrap_cjk(self):
+        """Test gettext wrapping with CJK characters"""
+        text = "This translation contains 中文字符 (Chinese characters) and should 
wrap correctly"
+        lines = unicode_segmentation_rs.gettext_wrap(text, 40)
+        assert isinstance(lines, list)
+        assert len(lines) > 0
+        for line in lines:
+            width = unicode_segmentation_rs.text_width(line)
+            assert isinstance(width, int)
+
+    def test_gettext_wrap_escape_sequences(self):
+        """Test gettext wrapping preserves escape sequences"""
+        text = "This has\\nline breaks\\tand tabs"
+        lines = unicode_segmentation_rs.gettext_wrap(text, 20)
+        assert isinstance(lines, list)
+        # Verify escape sequences are preserved
+        full_text = "".join(lines)
+        assert "\\n" in full_text or "\\t" in full_text

++++++ vendor.tar.zst ++++++
++++ 834230 lines of diff (skipped)

Reply via email to