Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 83 additions & 7 deletions .github/workflows/maturin.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# This file is autogenerated by maturin v1.9.4
# This file is autogenerated by maturin v1.9.5
# To update, run
#
# maturin generate-ci github
# maturin generate-ci github --pytest -m python/Cargo.toml -o .github/workflows/pytest.yml
#
# NOTE: this file has been modified to add mypy and force installing the packages from the dist directory
#
name: Maturin

Expand Down Expand Up @@ -45,14 +47,39 @@ jobs:
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.platform.target }}
args: --release --out dist --find-interpreter -m python/Cargo.toml
args: --release --out dist --find-interpreter --manifest-path python/Cargo.toml
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
manylinux: auto
- name: Upload wheels
uses: actions/upload-artifact@v4
with:
name: wheels-linux-${{ matrix.platform.target }}
path: dist
- name: pytest
if: ${{ startsWith(matrix.platform.target, 'x86_64') }}
shell: bash
run: |
set -e
python3 -m venv .venv
source .venv/bin/activate
pip install pyfaup-rs --no-index --find-links dist --force-reinstall
pip install pytest mypy
cd python && pytest && mypy .
- name: pytest
if: ${{ !startsWith(matrix.platform.target, 'x86') && matrix.platform.target != 'ppc64' }}
uses: uraimo/run-on-arch-action@v2
with:
arch: ${{ matrix.platform.target }}
distro: ubuntu22.04
githubToken: ${{ github.token }}
install: |
apt-get update
apt-get install -y --no-install-recommends python3 python3-pip
pip3 install -U pip pytest mypy
run: |
set -e
pip3 install pyfaup-rs --no-index --find-links dist --force-reinstall
cd python && pytest && mypy .

musllinux:
runs-on: ${{ matrix.platform.runner }}
Expand All @@ -76,14 +103,44 @@ jobs:
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.platform.target }}
args: --release --out dist --find-interpreter -m python/Cargo.toml
args: --release --out dist --find-interpreter --manifest-path python/Cargo.toml
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
manylinux: musllinux_1_2
- name: Upload wheels
uses: actions/upload-artifact@v4
with:
name: wheels-musllinux-${{ matrix.platform.target }}
path: dist
- name: pytest
if: ${{ startsWith(matrix.platform.target, 'x86_64') }}
uses: addnab/docker-run-action@v3
with:
image: alpine:latest
options: -v ${{ github.workspace }}:/io -w /io
run: |
set -e
apk add py3-pip py3-virtualenv
python3 -m virtualenv .venv
source .venv/bin/activate
pip install pyfaup-rs --no-index --find-links dist --force-reinstall
pip install pytest mypy
cd python && pytest && mypy .
- name: pytest
if: ${{ !startsWith(matrix.platform.target, 'x86') }}
uses: uraimo/run-on-arch-action@v2
with:
arch: ${{ matrix.platform.target }}
distro: alpine_latest
githubToken: ${{ github.token }}
install: |
apk add py3-virtualenv
run: |
set -e
python3 -m virtualenv .venv
source .venv/bin/activate
pip install pytest mypy
pip install pyfaup-rs --no-index --find-links dist --force-reinstall
cd python && pytest && mypy .

windows:
runs-on: ${{ matrix.platform.runner }}
Expand All @@ -104,13 +161,24 @@ jobs:
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.platform.target }}
args: --release --out dist --find-interpreter -m python/Cargo.toml
args: --release --out dist --find-interpreter --manifest-path python/Cargo.toml
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
maturin-version: 1.9.4
- name: Upload wheels
uses: actions/upload-artifact@v4
with:
name: wheels-windows-${{ matrix.platform.target }}
path: dist
- name: pytest
if: ${{ !startsWith(matrix.platform.target, 'aarch64') }}
shell: bash
run: |
set -e
python3 -m venv .venv
source .venv/Scripts/activate
pip install pyfaup-rs --no-index --find-links dist --force-reinstall
pip install pytest mypy
cd python && pytest && mypy .

macos:
runs-on: ${{ matrix.platform.runner }}
Expand All @@ -130,13 +198,21 @@ jobs:
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.platform.target }}
args: --release --out dist --find-interpreter -m python/Cargo.toml
args: --release --out dist --find-interpreter --manifest-path python/Cargo.toml
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
- name: Upload wheels
uses: actions/upload-artifact@v4
with:
name: wheels-macos-${{ matrix.platform.target }}
path: dist
- name: pytest
run: |
set -e
python3 -m venv .venv
source .venv/bin/activate
pip install pyfaup-rs --no-index --find-links dist --force-reinstall
pip install pytest mypy
cd python && pytest && mypy .

sdist:
runs-on: ubuntu-latest
Expand All @@ -146,7 +222,7 @@ jobs:
uses: PyO3/maturin-action@v1
with:
command: sdist
args: --out dist -m python/Cargo.toml
args: --out dist --manifest-path python/Cargo.toml
- name: Upload sdist
uses: actions/upload-artifact@v4
with:
Expand Down
Empty file added python/py.typed
Empty file.
61 changes: 61 additions & 0 deletions python/pyfaup.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
class FaupCompat:

url: bytes

def __init__(self, url: str | None=None) -> None:
...

def decode(self, url: str) -> None:
...

def get_credential(self) -> str | None:
...

def get_domain(self) -> str | None:
...

def get_subdomain(self) -> str | None:
...

def get_fragment(self) -> str | None:
...

def get_host(self) -> str | None:
...

def get_resource_path(self) -> str | None:
...

def get_tld(self) -> str | None:
...

def get_query_string(self) -> str | None:
...

def get_scheme(self) -> str | None:
...

def get_domain_without_tld(self) -> str | None:
...

def get_port(self) -> int | None:
...


class Url:

orig: str
scheme: str
username: str | None
password: str | None
host: str
subdomain: str | None
domain: str | None
suffix: str | None
port: int | None
path: str | None
query: str | None
fragment: str | None

def __init__(self, url: str | None = None) -> None:
...
2 changes: 1 addition & 1 deletion python/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[build-system]
requires = ["maturin>=1.9,<2.0"]
requires = ["maturin (>=1.9.4,!=1.9.5,<2.0)"]
build-backend = "maturin"

[project]
Expand Down
57 changes: 57 additions & 0 deletions python/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ impl From<Error> for PyErr {
/// >>> print(url.port) # 8080
#[pyclass]
pub struct Url {
#[pyo3(get)]
pub orig: String,
#[pyo3(get)]
pub scheme: String,
#[pyo3(get)]
Expand Down Expand Up @@ -91,6 +93,7 @@ impl From<faup_rs::Url<'_>> for Url {
};

Self {
orig: value.as_str().into(),
scheme: value.scheme().into(),
username,
password,
Expand Down Expand Up @@ -140,6 +143,7 @@ impl Url {
.map(|u| u.into())
.map_err(|e| PyValueError::new_err(e.to_string()))
}

}

/// A compatibility class that mimics the FAUP (Fast URL Parser) Python API.
Expand Down Expand Up @@ -233,6 +237,59 @@ impl FaupCompat {

Ok(m)
}

fn get_credential(&self) -> Option<String> {
let url = self.url.as_ref();
url.and_then(|u| u.credentials())
}

fn get_domain(&self) -> Option<&str> {
self.url.as_ref()?.domain.as_deref()
}

fn get_subdomain(&self) -> Option<&str> {
self.url.as_ref()?.subdomain.as_deref()
}

fn get_fragment(&self) -> Option<&str> {
self.url.as_ref()?.fragment.as_deref()
}

fn get_host(&self) -> Option<&str> {
self.url.as_ref().map(|u| u.host.as_str())
}

fn get_resource_path(&self) -> Option<&str> {
self.url.as_ref()?.path.as_deref()
}

fn get_tld(&self) -> Option<&str> {
self.url.as_ref()?.suffix.as_deref()
}

fn get_query_string(&self) -> Option<&str> {
self.url.as_ref()?.query.as_deref()
}

fn get_scheme(&self) -> Option<&str> {
self.url.as_ref().map(|u| u.scheme.as_str())
}

fn get_port(&self) -> Option<u16> {
self.url.as_ref()?.port
}

fn get_domain_without_tld(&self) -> Option<&str> {
if let (Some(domain), Some(tld)) = (self.get_domain(), self.get_tld()) {
domain
.strip_suffix(tld)
.and_then(|dom| dom.strip_suffix('.'))
}
else {
None
}
}

}

/// A Python module implemented in Rust for URL parsing.
Expand Down
27 changes: 27 additions & 0 deletions python/tests/test_pyfaup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env python3

from __future__ import annotations

import unittest

from pyfaup import Url


class TestPyFaupRR(unittest.TestCase):

def test_url(self) -> None:
parsed_url = Url('https://user:pass@sub.example.com:8080/path?query=value#fragment')

self.assertEqual(parsed_url.orig, 'https://user:pass@sub.example.com:8080/path?query=value#fragment')

self.assertEqual(parsed_url.scheme, 'https')
self.assertEqual(parsed_url.username, 'user')
self.assertEqual(parsed_url.password, 'pass')
self.assertEqual(parsed_url.host, 'sub.example.com')
self.assertEqual(parsed_url.subdomain, 'sub')
self.assertEqual(parsed_url.domain, 'example.com')
self.assertEqual(parsed_url.suffix, 'com')
self.assertEqual(parsed_url.port, 8080)
self.assertEqual(parsed_url.path, '/path')
self.assertEqual(parsed_url.query, 'query=value')
self.assertEqual(parsed_url.fragment, 'fragment')
Loading