Skip to content

Commit 8cc6b58

Browse files
committed
Transform to Python (PyO3) package - fast_unidecode
1 parent 9d814c2 commit 8cc6b58

19 files changed

Lines changed: 683 additions & 64 deletions
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: Test build & install
2+
3+
# see: https://help.github.com/en/actions/reference/events-that-trigger-workflows
4+
on: # Trigger the workflow on push or pull request, but only for the master branch
5+
push:
6+
branches: [pyo3]
7+
pull_request:
8+
branches: [pyo3]
9+
10+
jobs:
11+
pkg-install:
12+
runs-on: ${{ matrix.os }}
13+
strategy:
14+
matrix:
15+
os: [ubuntu-24.04, macOS-13]
16+
python-version: ["3.10", "3.13"]
17+
timeout-minutes: 5
18+
19+
steps:
20+
- uses: actions/checkout@v4
21+
- uses: actions/setup-python@v5
22+
with:
23+
python-version: ${{ matrix.python-version }}
24+
- uses: messense/maturin-action@v1
25+
26+
- name: Build package with maturin
27+
run: maturin build --release
28+
29+
- name: Install | Uninstall package
30+
working-directory: target/wheels/
31+
run: |
32+
python -m pip install *.whl
33+
python -c "import fast_unidecode"
34+
python -m pip uninstall -y fast_unidecode

.github/workflows/pre-commit.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
name: Pre-commit
2+
3+
# see: https://help.github.com/en/actions/reference/events-that-trigger-workflows
4+
on: # Trigger the workflow on push or pull request, but only for the master branch
5+
push:
6+
branches: [pyo3]
7+
pull_request:
8+
branches: [pyo3]
9+
10+
jobs:
11+
pre-commit:
12+
runs-on: ubuntu-24.04
13+
steps:
14+
- uses: actions/checkout@v4
15+
- uses: actions/setup-python@v5
16+
with:
17+
python-version: 3.13
18+
- name: Install dependencies
19+
run: |
20+
pip install pre-commit
21+
shell: bash
22+
- name: pre-commit
23+
run: |
24+
pre-commit run --all-files

.github/workflows/release-pypi.yml

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
name: PyPI Release
2+
3+
# https://help.github.com/en/actions/reference/events-that-trigger-workflows
4+
on:
5+
push:
6+
branches:
7+
- pyo3
8+
release:
9+
types: [published]
10+
11+
jobs:
12+
build-wheels-manylinux:
13+
runs-on: ubuntu-24.04
14+
name: Build wheels for manylinux
15+
container: quay.io/pypa/manylinux_2_28_x86_64
16+
17+
steps:
18+
- uses: actions/checkout@v1
19+
20+
- name: Install Maturin and Build manylinux2014 packages
21+
run: sh build_manylinux_wheels.sh
22+
23+
- name: Upload wheels
24+
uses: actions/upload-artifact@v4
25+
with:
26+
name: manylinux-wheels
27+
path: ./target/wheels/*whl
28+
29+
build-wheels-macos:
30+
runs-on: ${{ matrix.os }}
31+
name: Build wheels for MacOS
32+
strategy:
33+
matrix:
34+
os: [macOS-13]
35+
python: ["3.10", "3.11", "3.12", "3.13"]
36+
37+
steps:
38+
- uses: actions/checkout@v4
39+
- uses: actions/setup-python@v5
40+
with:
41+
python-version: ${{ matrix.python }}
42+
architecture: x64
43+
44+
- name: Install Rust
45+
uses: actions-rs/toolchain@v1
46+
with:
47+
toolchain: stable
48+
override: true
49+
50+
- uses: messense/maturin-action@v1
51+
52+
- name: Build ${{ matrix.os }} package on 64bit (${{ matrix.python-version }})
53+
run: maturin build --release
54+
55+
- name: Upload wheels
56+
uses: actions/upload-artifact@v4
57+
with:
58+
name: macos-wheels-${{ matrix.os }}-${{ matrix.python }}
59+
path: ./target/wheels/*whl
60+
61+
publish-to-pypi:
62+
name: Publish to PyPI
63+
runs-on: ubuntu-24.04
64+
needs: [build-wheels-manylinux, build-wheels-macos]
65+
if: github.event_name == 'release' && github.event.action == 'published'
66+
67+
steps:
68+
- name: Download all wheels
69+
uses: actions/download-artifact@v4
70+
with:
71+
path: dist/
72+
73+
- name: Prepare wheels for publishing
74+
run: |
75+
# The download-artifact action creates sub-directories for each artifact.
76+
# We need to move the wheels from the sub-directories to the top-level dist/ directory
77+
# and then remove the empty sub-directories.
78+
find dist -type f -name "*.whl" -exec mv -t dist/ {} +
79+
find dist -mindepth 1 -maxdepth 1 -type d -exec rm -r {} +
80+
81+
- name: List downloaded wheels
82+
run: ls -R dist
83+
84+
- name: Publish to PyPI
85+
uses: pypa/gh-action-pypi-publish@release/v1
86+
with:
87+
password: ${{ secrets.PYPI_API_TOKEN }}

.github/workflows/tests.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: Python tests
2+
3+
# see: https://help.github.com/en/actions/reference/events-that-trigger-workflows
4+
on: # Trigger the workflow on push or pull request, but only for the master branch
5+
push:
6+
branches: [pyo3]
7+
pull_request:
8+
branches: [pyo3]
9+
10+
jobs:
11+
pytest:
12+
runs-on: ubuntu-24.04
13+
timeout-minutes: 5
14+
15+
steps:
16+
- uses: actions/checkout@master
17+
- uses: actions/setup-python@v5
18+
with:
19+
python-version: "3.13"
20+
- uses: messense/maturin-action@v1
21+
22+
- name: Build package with maturin
23+
run: maturin build --release
24+
25+
- name: Install package and dependencies
26+
run: |
27+
python -m pip install target/wheels/*.whl
28+
python -m pip install -r constraints.txt
29+
30+
- name: test-pkg
31+
run: python -m pytest tests

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
target
22
Cargo.lock
3+
__pycache__/

.pre-commit-config.yaml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
---
2+
repos:
3+
- repo: https://github.com/pre-commit/pre-commit-hooks
4+
rev: v5.0.0
5+
hooks:
6+
- id: check-added-large-files
7+
- id: check-ast
8+
- id: check-docstring-first
9+
- id: debug-statements
10+
- id: end-of-file-fixer
11+
- id: mixed-line-ending
12+
args: [--fix=lf]
13+
- id: trailing-whitespace
14+
- repo: https://github.com/astral-sh/ruff-pre-commit
15+
rev: v0.12.1
16+
hooks:
17+
- id: ruff
18+
args: [--fix, --exit-non-zero-on-fix]
19+
- id: ruff-format

CHANGELOG.md

Lines changed: 2 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,5 @@
11
# Changelog
22

3-
## 0.3.0 (2016-12-25)
3+
## Unreleased (YYYY-MM-DD)
44

5-
- Updated mappings from Text::Unidecode version 1.30.
6-
7-
## 0.2.0 (2015-07-01)
8-
9-
- Switched from phf map to lookup table for speed increase
10-
11-
## 0.1.10 (2015-07-01)
12-
13-
- Added `unidecode_char()` function
14-
15-
## 0.1.9 (2015-04-14)
16-
17-
- Fixed incorrect visibility modifier
18-
19-
## 0.1.8 (2015-04-12)
20-
21-
- Replaced `phf_macros` usage with `phf_codegen`, which works on stable Rust
22-
23-
## 0.1.7 (2015-03-26)
24-
25-
- Updated dependencies
26-
27-
## 0.1.6 (2015-03-22)
28-
29-
- Updated dependencies
30-
31-
## 0.1.5 (2015-03-20)
32-
33-
- Updated dependencies
34-
35-
## 0.1.4 (2015-03-18)
36-
37-
- Fixed typos
38-
39-
## 0.1.3 (2015-03-17)
40-
41-
- Changed badges in README to use shields.io
42-
43-
## 0.1.2 (2015-03-17)
44-
45-
- Added version badge to README
46-
47-
## 0.1.1 (2015-03-17)
48-
49-
- Added link to documentation in the README
50-
51-
## 0.1.0 (2015-03-17)
52-
53-
- Initial release
54-
- Entire `Text::Unidecode` data set exported into a Rust code file
5+
- Ported `rust-unidecode` 0.3.0 to PyO3 package

Cargo.toml

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
[package]
2-
name = "unidecode"
3-
version = "0.3.0"
4-
authors = ["Amit Chowdhury <amitc97@gmail.com>"]
2+
name = "fast_unidecode"
3+
version = "1.0.0"
4+
edition = "2024"
5+
authors = ["Daniel Stancl <daniel.stancl@gmail.com>", "Amit Chowdhury <amitc97@gmail.com>"]
56
description = "Provides pure ASCII transliterations of Unicode strings."
6-
documentation = "https://chowdhurya.github.io/rust-unidecode/unidecode/"
7-
homepage = "https://github.com/chowdhurya/rust-unidecode/"
8-
repository = "https://github.com/chowdhurya/rust-unidecode/"
7+
homepage = "https://github.com/stancld/rust-unidecode/"
8+
repository = "https://github.com/stancld/rust-unidecode/"
99
readme = "README.md"
1010
keywords = [
1111
"unidecode",
@@ -14,4 +14,21 @@ keywords = [
1414
"ASCII",
1515
"transliteration"
1616
]
17+
classifiers = [
18+
"Programming Language :: Python",
19+
"Programming Language :: Python :: 3.10",
20+
"Programming Language :: Python :: 3.11",
21+
"Programming Language :: Python :: 3.12",
22+
"Programming Language :: Python :: 3.13"
23+
]
1724
license = "BSD-3-Clause"
25+
26+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.htmlAdd commentMore actions
27+
[lib]
28+
name = "fast_unidecode"
29+
path = "src/lib.rs"
30+
crate-type = ["cdylib"]
31+
32+
[dependencies.pyo3]
33+
version = "0.25.1"
34+
features = ["extension-module"]

LICENSE

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
# `fast_unidecode`
2+
3+
This project is a Python package providing bindings for the `rust-unidecode` library.
4+
5+
The original `rust-unidecode` library is licensed under the BSD 3-Clause License. Its full text is included below.
6+
7+
All new code added specifically for the Python bindings is licensed under the MIT License. Its full text is also included below.
8+
9+
---
10+
11+
## BSD 3-Clause License (for the original rust-unidecode code)
12+
113
Copyright (c) 2015, Amit Chowdhury
214
All rights reserved.
315

@@ -23,3 +35,27 @@ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
2335
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2436
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2537
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38+
39+
---
40+
41+
## MIT License (fast_unidecode)
42+
43+
Copyright (c) 2025 Daniel Stancl
44+
45+
Permission is hereby granted, free of charge, to any person obtaining a copy
46+
of this software and associated documentation files (the "Software"), to deal
47+
in the Software without restriction, including without limitation the rights
48+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
49+
copies of the Software, and to permit persons to whom the Software is
50+
furnished to do so, subject to the following conditions:
51+
52+
The above copyright notice and this permission notice shall be included in all
53+
copies or substantial portions of the "Software".
54+
55+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
56+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
57+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
58+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
59+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
60+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
61+
SOFTWARE.

0 commit comments

Comments
 (0)