From 16e008daf4d358f1121b35d390702e67abe1a36a Mon Sep 17 00:00:00 2001 From: Jacob Coffee Date: Sat, 7 Oct 2023 15:07:24 -0500 Subject: [PATCH 1/9] infra: pdm - chore: update deps --- .github/{dependabot.yaml => dependabot.yml} | 0 .github/workflows/{ci.yaml => ci.yml} | 46 +-- .../workflows/{publish.yaml => publish.yml} | 33 ++ .gitignore | 6 + .pre-commit-config.yaml | 12 +- .sourcery.yaml | 42 +++ CODE_OF_CONDUCT.md | 123 ------- Cargo.lock | 54 +-- Cargo.toml | 2 +- LICENSE | 2 +- Makefile | 148 ++++++++ README.md | 13 +- SECURITY.md | 5 - benchmarks.py | 17 +- fast_query_parsers.pyi | 2 +- pdm.lock | 324 ++++++++++++++++++ poetry.lock | 173 ---------- pyproject.toml | 106 ++---- tests/test_parse_qs.py | 4 +- tests/test_parse_qsl.py | 36 +- 20 files changed, 672 insertions(+), 476 deletions(-) rename .github/{dependabot.yaml => dependabot.yml} (100%) rename .github/workflows/{ci.yaml => ci.yml} (78%) rename .github/workflows/{publish.yaml => publish.yml} (99%) create mode 100644 .sourcery.yaml delete mode 100644 CODE_OF_CONDUCT.md create mode 100644 Makefile delete mode 100644 SECURITY.md create mode 100644 pdm.lock delete mode 100644 poetry.lock diff --git a/.github/dependabot.yaml b/.github/dependabot.yml similarity index 100% rename from .github/dependabot.yaml rename to .github/dependabot.yml diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yml similarity index 78% rename from .github/workflows/ci.yaml rename to .github/workflows/ci.yml index 581b90b..aeb789e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yml @@ -13,20 +13,18 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 + - name: Setup Python 3.11 uses: actions/setup-python@v4 with: python-version: "3.11" + - name: Install Pre-Commit run: python -m pip install pre-commit && pre-commit install - - name: Load cached Pre-Commit Dependencies - id: cached-poetry-dependencies - uses: actions/cache@v3 - with: - path: ~/.cache/pre-commit/ - key: pre-commit-4|${{ env.pythonLocation }}|${{ hashFiles('.pre-commit-config.yaml') }} + - name: Execute Pre-Commit run: pre-commit run --show-diff-on-failure --color=always --all-files + pyton_tests: name: "Python Tests" runs-on: ubuntu-latest @@ -37,36 +35,36 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 + - name: Setup Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - - name: Install Poetry - uses: snok/install-poetry@v1 - with: - virtualenvs-create: true - virtualenvs-in-project: true - installer-parallel: true - - name: Load Cached Venv - id: cached-poetry-dependencies - uses: actions/cache@v3 + + - uses: pdm-project/setup-pdm@v3 + name: Set up PDM with: - path: .venv - key: v1-venv-${{ runner.os }}-${{ matrix.python-version }}-${{ hashFiles('**/poetry.lock') }} + python-version: ${{ matrix.python-version }} + - name: Install Python Dependencies - run: poetry install --no-interaction --no-root + run: pdm install + - name: Set pythonpath run: echo "PYTHONPATH=$PWD" >> $GITHUB_ENV + - name: Install library - run: poetry run maturin develop + run: pdm run maturin develop + - name: Test - run: poetry run pytest + run: pdm run pytest + rust_tests: name: "Rust Tests" runs-on: ubuntu-latest steps: - name: Checkout Repository uses: actions/checkout@v4 + - name: Install Rust uses: actions-rs/toolchain@v1 with: @@ -74,19 +72,24 @@ jobs: override: true target: x86_64-unknown-linux-musl components: llvm-tools-preview + - name: Download grcov run: | mkdir -p "${HOME}/.local/bin" curl -sL https://github.com/mozilla/grcov/releases/download/v0.8.10/grcov-x86_64-unknown-linux-gnu.tar.bz2 | tar jxf - -C "${HOME}/.local/bin" echo "$HOME/.local/bin" >> $GITHUB_PATH + - name: Test with Coverage run: CARGO_INCREMENTAL=0 RUSTFLAGS='-Cinstrument-coverage' LLVM_PROFILE_FILE='cargo-test-%p-%m.profraw' cargo test + - name: Generate Coverage Report run: mkdir coverage && grcov . --binary-path ./target/debug/deps/ -s . -t lcov --branch --ignore-not-existing --ignore '../*' --ignore "/*" -o coverage.lcov + - uses: actions/upload-artifact@v3 with: name: coverage-lcov path: coverage.lcov + sonar: name: "Sonar" needs: @@ -98,12 +101,15 @@ jobs: steps: - name: Check out repository uses: actions/checkout@v4 + - name: Download Artifacts uses: actions/download-artifact@v3 with: name: coverage-lcov + - name: Fix coverage file for sonarcloud run: sed -i "s/home\/runner\/work\/http_utils\/src/github\/workspace/g" coverage.lcov + - name: SonarCloud Scan uses: sonarsource/sonarcloud-github-action@master env: diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yml similarity index 99% rename from .github/workflows/publish.yaml rename to .github/workflows/publish.yml index 22d9442..361291e 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yml @@ -17,35 +17,42 @@ jobs: runs-on: macos-latest steps: - uses: actions/checkout@v4 + - uses: actions/setup-python@v4 with: python-version: ${{ env.PYTHON_VERSION }} architecture: x64 + - name: Install Rust toolchain uses: actions-rs/toolchain@v1 with: toolchain: stable profile: minimal default: true + - name: Build wheels - x86_64 uses: messense/maturin-action@v1 with: target: x86_64 args: --release --out dist --sdist + - name: Install built wheel - x86_64 run: | pip install dist/${{ env.PACKAGE_NAME }}-*.whl --force-reinstall pip install pytest pytest -v + - name: Build wheels - universal2 uses: messense/maturin-action@v1 with: args: --release --universal2 --out dist + - name: Install built wheel - universal2 run: | pip install dist/${{ env.PACKAGE_NAME }}-*universal2.whl --force-reinstall pip install pytest pytest -v + - name: Upload wheels uses: actions/upload-artifact@v3 with: @@ -59,27 +66,32 @@ jobs: target: [x64, x86] steps: - uses: actions/checkout@v4 + - uses: actions/setup-python@v4 with: python-version: ${{ env.PYTHON_VERSION }} architecture: ${{ matrix.target }} + - name: Install Rust toolchain uses: actions-rs/toolchain@v1 with: toolchain: stable profile: minimal default: true + - name: Build wheels uses: messense/maturin-action@v1 with: target: ${{ matrix.target }} args: --release --out dist + - name: Install built wheel shell: bash run: | python -m pip install dist/${{ env.PACKAGE_NAME }}-*.whl --force-reinstall pip install pytest python -m pytest -v + - name: Upload wheels uses: actions/upload-artifact@v3 with: @@ -93,22 +105,26 @@ jobs: target: [x86_64, i686] steps: - uses: actions/checkout@v4 + - uses: actions/setup-python@v4 with: python-version: ${{ env.PYTHON_VERSION }} architecture: x64 + - name: Build wheels uses: messense/maturin-action@v1 with: target: ${{ matrix.target }} manylinux: auto args: --release --out dist + - name: Install built wheel if: matrix.target == 'x86_64' run: | pip install dist/${{ env.PACKAGE_NAME }}-*.whl --force-reinstall pip install pytest pytest -v + - name: Upload wheels uses: actions/upload-artifact@v3 with: @@ -122,15 +138,18 @@ jobs: target: [aarch64, armv7, s390x, ppc64le, ppc64] steps: - uses: actions/checkout@v4 + - uses: actions/setup-python@v4 with: python-version: ${{ env.PYTHON_VERSION }} + - name: Build wheels uses: messense/maturin-action@v1 with: target: ${{ matrix.target }} manylinux: auto args: --release --out dist + - uses: uraimo/run-on-arch-action@v2.5.1 if: matrix.target != 'ppc64' name: Install built wheel @@ -146,6 +165,7 @@ jobs: pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links dist/ --force-reinstall pip install pytest pytest -v + - name: Upload wheels uses: actions/upload-artifact@v3 with: @@ -161,16 +181,20 @@ jobs: - i686-unknown-linux-musl steps: - uses: actions/checkout@v4 + - uses: actions/setup-python@v4 + with: python-version: ${{ env.PYTHON_VERSION }} architecture: x64 + - name: Build wheels uses: messense/maturin-action@v1 with: target: ${{ matrix.target }} manylinux: musllinux_1_2 args: --release --out dist + - name: Install built wheel if: matrix.target == 'x86_64-unknown-linux-musl' uses: addnab/docker-run-action@v3 @@ -182,6 +206,7 @@ jobs: pip3 install -U pip pytest pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links /io/dist/ --force-reinstall python3 -m pytest + - name: Upload wheels uses: actions/upload-artifact@v3 with: @@ -199,15 +224,18 @@ jobs: arch: armv7 steps: - uses: actions/checkout@v4 + - uses: actions/setup-python@v4 with: python-version: ${{ env.PYTHON_VERSION }} + - name: Build wheels uses: messense/maturin-action@v1 with: target: ${{ matrix.platform.target }} manylinux: musllinux_1_2 args: --release --out dist + - uses: uraimo/run-on-arch-action@v2.5.1 name: Install built wheel with: @@ -220,11 +248,13 @@ jobs: run: | pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links dist/ --force-reinstall python3 -m pytest + - name: Upload wheels uses: actions/upload-artifact@v3 with: name: wheels path: dist + publish: name: Publish runs-on: ubuntu-latest @@ -235,11 +265,14 @@ jobs: - linux-cross - musllinux - musllinux-cross + steps: - uses: actions/download-artifact@v3 with: name: wheels + - uses: actions/setup-python@v4 + - name: Publish to PyPi env: TWINE_USERNAME: __token__ diff --git a/.gitignore b/.gitignore index 1608640..a14b14a 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,9 @@ __pycache__/ .idea *.profraw coverage* +.venv/ + +# pdm +.pdm-python +.pdm.toml +__pypackages__/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 71a8dea..e8b1d3e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,21 +16,17 @@ repos: - id: mixed-line-ending - id: trailing-whitespace - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: "v0.0.285" + rev: "v0.0.292" hooks: - id: ruff args: ["--fix"] - - repo: https://github.com/psf/black - rev: 23.7.0 - hooks: - - id: black - args: [--config=./pyproject.toml] + - id: ruff-format - repo: https://github.com/codespell-project/codespell - rev: v2.2.5 + rev: v2.2.6 hooks: - id: codespell - repo: https://github.com/pre-commit/mirrors-prettier - rev: "v3.0.2" + rev: "v3.0.3" hooks: - id: prettier - repo: https://github.com/doublify/pre-commit-rust diff --git a/.sourcery.yaml b/.sourcery.yaml new file mode 100644 index 0000000..0e7be06 --- /dev/null +++ b/.sourcery.yaml @@ -0,0 +1,42 @@ +ignore: + - .tox/ + - .venv/ + - dist/ + - docs/_build/ + - docs/_static/ + - node_modules/ + - vendor/ + - venv/ + +rule_settings: + enable: [default] + disable: [dont-import-test-modules] + rule_types: + - refactoring + - suggestion + - comment + python_version: "3.8" + +rules: [] + +metrics: + quality_threshold: 25.0 + +github: + ignore_labels: + - sourcery-ignore + - docs + labels: + - build-ignore + request_review: + origin: owner + forked: author + sourcery_branch: sourcery/{base_branch} + +clone_detection: + min_lines: 3 + min_duplicates: 2 + identical_clones_only: false + +proxy: + no_ssl_verify: false diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index 526b19e..0000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,123 +0,0 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -We as members, contributors, and leaders pledge to make participation in our -community a harassment-free experience for everyone, regardless of age, body -size, visible or invisible disability, ethnicity, sex characteristics, gender -identity and expression, level of experience, education, socioeconomic status, -nationality, personal appearance, race, religion, or sexual identity -and orientation. - -We pledge to act and interact in ways that contribute to an open, welcoming, -diverse, inclusive, and healthy community. - -## Our Standards - -Examples of behavior that contributes to a positive environment for our -community include: - -- Demonstrating empathy and kindness toward other people -- Being respectful of differing opinions, viewpoints, and experiences -- Giving and gracefully accepting constructive feedback -- Accepting responsibility and apologizing to those affected by our mistakes, - and learning from the experience -- Focusing on what is best not just for us as individuals, but for the - overall community - -Examples of unacceptable behavior include: - -- The use of sexualized language or imagery, and sexual attention or - advances of any kind -- Trolling, insulting or derogatory comments, and personal or political attacks -- Public or private harassment -- Publishing others' private information, such as a physical or email - address, without their explicit permission -- Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Enforcement Responsibilities - -Community leaders are responsible for clarifying and enforcing our standards of -acceptable behavior and will take appropriate and fair corrective action in -response to any behavior that they deem inappropriate, threatening, offensive, -or harmful. - -Community leaders have the right and responsibility to remove, edit, or reject -comments, commits, code, wiki edits, issues, and other contributions that are -not aligned to this Code of Conduct, and will communicate reasons for moderation -decisions when appropriate. - -## Scope - -This Code of Conduct applies within all community spaces, and also applies when -an individual is officially representing the community in public spaces. -Examples of representing our community include using an official e-mail address, -posting via an official social media account, or acting as an appointed -representative at an online or offline event. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported to the community leaders responsible for enforcement at -. -All complaints will be reviewed and investigated promptly and fairly. - -All community leaders are obligated to respect the privacy and security of the -reporter of any incident. - -## Enforcement Guidelines - -Community leaders will follow these Community Impact Guidelines in determining -the consequences for any action they deem in violation of this Code of Conduct: - -### 1. Correction - -**Community Impact**: Use of inappropriate language or other behavior deemed -unprofessional or unwelcome in the community. - -**Consequence**: A private, written warning from community leaders, providing -clarity around the nature of the violation and an explanation of why the -behavior was inappropriate. A public apology may be requested. - -### 2. Warning - -**Community Impact**: A violation through a single incident or series -of actions. - -**Consequence**: A warning with consequences for continued behavior. No -interaction with the people involved, including unsolicited interaction with -those enforcing the Code of Conduct, for a specified period of time. This -includes avoiding interactions in community spaces as well as external channels -like social media. Violating these terms may lead to a temporary or -permanent ban. - -### 3. Temporary Ban - -**Community Impact**: A serious violation of community standards, including -sustained inappropriate behavior. - -**Consequence**: A temporary ban from any sort of interaction or public -communication with the community for a specified period of time. No public or -private interaction with the people involved, including unsolicited interaction -with those enforcing the Code of Conduct, is allowed during this period. -Violating these terms may lead to a permanent ban. - -### 4. Permanent Ban - -**Community Impact**: Demonstrating a pattern of violation of community -standards, including sustained inappropriate behavior, harassment of an -individual, or aggression toward or disparagement of classes of individuals. - -**Consequence**: A permanent ban from any sort of public interaction within -the community. - -## Attribution - -This Code of Conduct is adapted from -the [Contributor Covenant version 2.0](https://www.contributor-covenant.org/version/2/0/code_of_conduct.html). - -Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity). - -For answers to common questions about this code of conduct, see [the FAQ](https://www.contributor-covenant.org/faq) -and [translations](https://www.contributor-covenant.org/translations). diff --git a/Cargo.lock b/Cargo.lock index f45a24d..0957809 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "aho-corasick" -version = "1.0.4" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6748e8def348ed4d14996fa801f4122cd763fff530258cdc03f64b25f89d3a5a" +checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab" dependencies = [ "memchr", ] @@ -62,9 +62,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.147" +version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" [[package]] name = "lock_api" @@ -78,9 +78,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "memoffset" @@ -122,9 +122,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "5b1106fec09662ec6dd98ccac0f81cef56984d0b49f75c92d8cbad76e20c005c" dependencies = [ "unicode-ident", ] @@ -219,9 +219,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.9.3" +version = "1.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" +checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff" dependencies = [ "aho-corasick", "memchr", @@ -231,9 +231,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.6" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" +checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" dependencies = [ "aho-corasick", "memchr", @@ -242,9 +242,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" [[package]] name = "rustc-hash" @@ -266,29 +266,29 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.186" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f5db24220c009de9bd45e69fb2938f4b6d2df856aa9304ce377b3180f83b7c1" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.186" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ad697f7e0b65af4983a4ce8f56ed5b357e8d3c36651bf6a7e13639c17b8e670" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.38", ] [[package]] name = "serde_json" -version = "1.0.105" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" dependencies = [ "itoa", "ryu", @@ -297,9 +297,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" [[package]] name = "syn" @@ -314,9 +314,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.29" +version = "2.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" +checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" dependencies = [ "proc-macro2", "quote", @@ -331,9 +331,9 @@ checksum = "9d0e916b1148c8e263850e1ebcbd046f333e0683c724876bb0da63ea4373dc8a" [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unindent" diff --git a/Cargo.toml b/Cargo.toml index 03b8687..1b348bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ authors = ["Na'aman Hirschfeld "] description = "Ultra-fast query string and url-encoded form-data parsers" readme = "README.md" license-file = "LICENSE" -repository = "https://github.com/starlite-api/fast-query-parsers" +repository = "https://github.com/litestar-org/fast-query-parsers" version = "1.0.3" edition = "2021" diff --git a/LICENSE b/LICENSE index 419898b..c7d8c9b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2022, 2023 Starlite-API +Copyright (c) 2023 Litestar Organization Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0db855c --- /dev/null +++ b/Makefile @@ -0,0 +1,148 @@ +SHELL := /bin/bash +# ============================================================================= +# Variables +# ============================================================================= + +.DEFAULT_GOAL:=help +.ONESHELL: +USING_PDM = $(shell grep "tool.pdm" pyproject.toml && echo "yes") +USING_CARGO = $(shell stat Cargo.toml > /dev/null && echo "yes") +ENV_PREFIX := $(shell if [ -d .venv ]; then echo ".venv/bin/"; fi) +VENV_EXISTS := $(shell if [ -d .venv ]; then echo "yes"; fi) +PDM_OPTS ?= +PDM ?= pdm $(PDM_OPTS) +CARGO_OPTS ?= +CARGO ?= cargo $(CARGO_OPTS) + +.EXPORT_ALL_VARIABLES: + +.PHONY: help +help: ## Display this help text for Makefile + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z0-9_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) + +.PHONY: upgrade +upgrade: ## Upgrade all dependencies to the latest stable versions + @echo "=> Updating all dependencies" + @if [ "$(USING_PDM)" ]; then $(PDM) update; fi + @if [ "$(USING_CARGO)" ]; then $(CARGO) update; fi + @echo "=> Dependencies Updated" + @$(ENV_PREFIX)pre-commit autoupdate + @echo "=> Updated Pre-commit" + +# ============================================================================= +# Developer Utils +# ============================================================================= +.PHONY: install-pdm +install-pdm: ## Install latest version of PDM + @curl -sSLO https://pdm.fming.dev/install-pdm.py && \ + @curl -sSL https://pdm.fming.dev/install-pdm.py.sha256 | shasum -a 256 -c - && \ + python3 install-pdm.py + +.PHONE: install-rust +install-rust: ## Install Rust + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + +.PHONY: install +install: ## Install the project, dependencies, and pre-commit for local development + @if ! $(PDM) --version > /dev/null; then echo '=> Installing PDM'; $(MAKE) install-pdm; fi + @if ! $(CARGO) --version > /dev/null; then echo '=> Installing Rust'; $(MAKE) install-rust; fi + @if [ "$(VENV_EXISTS)" ]; then echo "=> Removing existing virtual environment"; fi + @if [ "$(VENV_EXISTS)" ]; then $(MAKE) destroy; fi + @if [ "$(VENV_EXISTS)" ]; then $(MAKE) clean; fi + @if [ "$(USING_PDM)" ]; then $(PDM) config venv.in_project true && python3 -m venv --copies .venv && . $(ENV_PREFIX)/activate && $(ENV_PREFIX)/pip install --quiet -U wheel setuptools cython pip; fi + @if [ "$(USING_PDM)" ]; then $(PDM) install -G:all; fi + @if [ "$(USING_CARGO)" ]; then $(CARGO) build; fi + @echo "=> Install complete! Note: If you want to re-install re-run 'make install'" + +.PHONY: clean +clean: ## Cleanup temporary build artifacts + @echo "=> Cleaning working directory" + @rm -rf .pytest_cache .ruff_cache .hypothesis build/ -rf dist/ .eggs/ target/ + @find . -name '*.egg-info' -exec rm -rf {} + + @find . -name '*.egg' -exec rm -f {} + + @find . -name '*.pyc' -exec rm -f {} + + @find . -name '*.pyo' -exec rm -f {} + + @find . -name '*~' -exec rm -f {} + + @find . -name '__pycache__' -exec rm -rf {} + + @find . -name '.ipynb_checkpoints' -exec rm -rf {} + + @rm -rf .coverage coverage.xml coverage.json htmlcov/ .pytest_cache tests/.pytest_cache tests/**/.pytest_cache .mypy_cache + $(MAKE) docs-clean + +.PHONY: destroy +destroy: ## Destroy the virtual environment + @echo "=> Destroying virtual environment" + @rm -rf .venv + +.PHONY: lock-refresh +lock-refresh: ## Sync lockfiles with requirements files. + @echo "=> Refreshing lockfiles" + @pdm update --update-reuse --group :all + @cargo update + @echo "=> 🔒 Lockfiles refreshed" + +.PHONY: lock +lock: ## Rebuild lockfiles from scratch, updating all dependencies + @echo "=> Rebuilding lockfiles" + @pdm update --update-eager --group :all + @cargo generate-lockfile + @echo "=> 🔒 Lockfiles built" + +.PHONE: build +build: ## Install a release wheel for testing and benchmarking + @echo "WARN: This currently does not work. Please run 'pdm run maturin develop --release --strip' manually." + @#pdm run pd + +# ============================================================================= +# Tests, Linting, Coverage, Benchmarking +# ============================================================================= +.PHONY: lint +lint: ## Runs pre-commit hooks; includes ruff linting, codespell, black + @echo "=> Running pre-commit process" + @$(ENV_PREFIX)pre-commit run --all-files + @echo "=> Linting complete" + +.PHONY: coverage +coverage: ## Run the tests and generate coverage report + @echo "=> Running tests with coverage" + @$(ENV_PREFIX)pytest tests --cov=fast_query_parsers.pyi + @$(ENV_PREFIX)coverage html + @$(ENV_PREFIX)coverage xml + @echo "=> Coverage report generated" + +.PHONY: test +test: ## Run the tests + @echo "=> Running test cases" + @$(ENV_PREFIX)pytest tests + @echo "=> Tests complete" + +.PHONY: test-all +test-all: test ## Run all tests + +.PHONY: check-all +check-all: lint test-all coverage ## Run all linting, tests, and coverage checks + +.PHONE: benchmark +benchmark: ## Run the benchmarks + @pdm run python benchmarks.py + +# ============================================================================= +# Docs +# ============================================================================= +.PHONY: docs-install +docs-install: ## Install docs dependencies + @echo "=> Installing documentation dependencies" + @$(PDM) install --group docs + @echo "=> Installed documentation dependencies" + +docs-clean: ## Dump the existing built docs + @echo "=> Cleaning documentation build assets" + @rm -rf docs/_build + @echo "=> Removed existing documentation build assets" + +docs-serve: docs-clean ## Serve the docs locally + @echo "=> Serving documentation" + $(ENV_PREFIX)sphinx-autobuild docs docs/_build/ -j auto --watch fast_query_parser.pyi --watch docs --watch tests --watch CONTRIBUTING.rst --port 8002 + +docs: docs-clean ## Dump the existing built docs and rebuild them + @echo "=> Building documentation" + @$(ENV_PREFIX)sphinx-build -M html docs docs/_build/ -E -a -j auto --keep-going diff --git a/README.md b/README.md index 9b3c158..325d73f 100644 --- a/README.md +++ b/README.md @@ -24,11 +24,6 @@ This library includes ultra-fast Rust based query string and urlencoded parsers. These parsers are used by [`Litestar`](https://github.com/litestar-org/litestar), but are developed separately - and can of course be used separately. -> [!IMPORTANT]\ -> [**_Starlite has been renamed to Litestar_**](https://litestar.dev/about/organization.html#litestar-and-starlite) - - - ## Installation ```shell @@ -107,7 +102,7 @@ does not nest all values inside lists. Note: the second argument passed to `parse_url_encoded_dict` dictates whether numbers should be parsed. If `True`, the value will be parsed into an int or float as appropriate, otherwise it will be kept as a string. -By default the value of this arg is `True`. +By default, the value of this arg is `True`. #### Benchmarks @@ -153,14 +148,14 @@ All contributions are of course welcome! ### Repository Setup -1. Run `cargo install` to setup the rust dependencies and `poetry install` to setup the python dependencies. +1. Run `cargo build` to set up the rust dependencies and `pdm install` to set up the python dependencies. 2. Install the pre-commit hooks with `pre-commit install` (requires [pre-commit](https://pre-commit.com/)). ### Building -Run `poetry run maturin develop --release --strip` to install a release wheel (without debugging info). This wheel can be +Run `pdm run maturin develop --release --strip` to install a release wheel (without debugging info). This wheel can be used in tests and benchmarks. ### Benchmarking -There are basic benchmarks using pyperf in place. To run these execute `poetry run python benchrmarks.py`. +There are basic benchmarks using pyperf in place. To run these execute `pdm run python benchmarks.py`. diff --git a/SECURITY.md b/SECURITY.md deleted file mode 100644 index c575f84..0000000 --- a/SECURITY.md +++ /dev/null @@ -1,5 +0,0 @@ -# Security Policy - -## Reporting a Vulnerability - -To report a vulnerability either create an issue on GitHub or tag "@maintainer" on our discord server diff --git a/benchmarks.py b/benchmarks.py index 03920df..e2e8a01 100644 --- a/benchmarks.py +++ b/benchmarks.py @@ -1,7 +1,9 @@ +from __future__ import annotations + from collections import defaultdict from contextlib import suppress from json import JSONDecodeError, loads -from typing import Any, DefaultDict, Dict, List +from typing import Any from urllib.parse import parse_qs as stdlib_parse_qs from urllib.parse import parse_qsl as stdlib_parse_qsl from urllib.parse import urlencode @@ -18,11 +20,11 @@ ("calories", "122.53"), ("healthy", True), ("polluting", False), - ] + ], ).encode() -def parse_url_encoded_form_data(encoded_data: bytes) -> Dict[str, Any]: +def parse_url_encoded_form_data(encoded_data: bytes) -> dict[str, Any]: """Parse an url encoded form data dict. Args: @@ -33,7 +35,7 @@ def parse_url_encoded_form_data(encoded_data: bytes) -> Dict[str, Any]: ------- A parsed dict. """ - decoded_dict: DefaultDict[str, List[Any]] = defaultdict(list) + decoded_dict: defaultdict[str, list[Any]] = defaultdict(list) for k, v in stdlib_parse_qsl(encoded_data.decode(), keep_blank_values=True): with suppress(JSONDecodeError): v = loads(v) if isinstance(v, str) else v # noqa: PLW2901 @@ -41,7 +43,7 @@ def parse_url_encoded_form_data(encoded_data: bytes) -> Dict[str, Any]: return {k: v if len(v) > 1 else v[0] for k, v in decoded_dict.items()} -def bench_qsl(runner: pyperf.Runner): +def bench_qsl(runner: pyperf.Runner) -> None: runner.bench_func( "stdlib parse_qsl parsing query string", lambda: stdlib_parse_qsl(b"key=1&key=2&key=3&another=a&zorg=5=".decode(), keep_blank_values=True), @@ -57,7 +59,7 @@ def bench_qsl(runner: pyperf.Runner): runner.bench_func("parse_query_string urlencoded query string", lambda: parse_query_string(url_encoded_query, "&")) -def bench_qs(runner: pyperf.Runner): +def bench_qs(runner: pyperf.Runner) -> None: runner.bench_func( "stdlib parse_qs parsing url-encoded values into dict", lambda: stdlib_parse_qs(url_encoded_query.decode()), @@ -67,7 +69,8 @@ def bench_qs(runner: pyperf.Runner): lambda: parse_url_encoded_form_data(url_encoded_query), ) runner.bench_func( - "parse_url_encoded_dict parsing url-encoded values into dict", lambda: parse_url_encoded_dict(url_encoded_query) + "parse_url_encoded_dict parsing url-encoded values into dict", + lambda: parse_url_encoded_dict(url_encoded_query), ) diff --git a/fast_query_parsers.pyi b/fast_query_parsers.pyi index 57ab360..1401b66 100644 --- a/fast_query_parsers.pyi +++ b/fast_query_parsers.pyi @@ -12,7 +12,7 @@ Returns: A list of string/string tuples. """ -def parse_url_encoded_dict(qs: bytes, parse_numbers: bool = False) -> dict[str, Any]: ... +def parse_url_encoded_dict(qs: bytes, *, parse_numbers: bool = False) -> dict[str, Any]: ... """Parse a query string into a dictionary of values. diff --git a/pdm.lock b/pdm.lock new file mode 100644 index 0000000..8334c4a --- /dev/null +++ b/pdm.lock @@ -0,0 +1,324 @@ +# This file is @generated by PDM. +# It is not intended for manual editing. + +[metadata] +groups = ["default", "dev", "sourcery"] +cross_platform = true +static_urls = false +lock_version = "4.3" +content_hash = "sha256:7a51d1b3582a6314e67cf3d38a4574bb545b78d355936e4e37814edb073fe88c" + +[[package]] +name = "cfgv" +version = "3.4.0" +requires_python = ">=3.8" +summary = "Validate configuration and produce human readable error messages." +files = [ + {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, + {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, +] + +[[package]] +name = "colorama" +version = "0.4.6" +requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +summary = "Cross-platform colored terminal text." +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "distlib" +version = "0.3.7" +summary = "Distribution utilities" +files = [ + {file = "distlib-0.3.7-py2.py3-none-any.whl", hash = "sha256:2e24928bc811348f0feb63014e97aaae3037f2cf48712d51ae61df7fd6075057"}, + {file = "distlib-0.3.7.tar.gz", hash = "sha256:9dafe54b34a028eafd95039d5e5d4851a13734540f1331060d31c9916e7147a8"}, +] + +[[package]] +name = "exceptiongroup" +version = "1.1.3" +requires_python = ">=3.7" +summary = "Backport of PEP 654 (exception groups)" +files = [ + {file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"}, + {file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"}, +] + +[[package]] +name = "filelock" +version = "3.12.4" +requires_python = ">=3.8" +summary = "A platform independent file lock." +files = [ + {file = "filelock-3.12.4-py3-none-any.whl", hash = "sha256:08c21d87ded6e2b9da6728c3dff51baf1dcecf973b768ef35bcbc3447edb9ad4"}, + {file = "filelock-3.12.4.tar.gz", hash = "sha256:2e6f249f1f3654291606e046b09f1fd5eac39b360664c27f5aad072012f8bcbd"}, +] + +[[package]] +name = "identify" +version = "2.5.30" +requires_python = ">=3.8" +summary = "File identification library for Python" +files = [ + {file = "identify-2.5.30-py2.py3-none-any.whl", hash = "sha256:afe67f26ae29bab007ec21b03d4114f41316ab9dd15aa8736a167481e108da54"}, + {file = "identify-2.5.30.tar.gz", hash = "sha256:f302a4256a15c849b91cfcdcec052a8ce914634b2f77ae87dad29cd749f2d88d"}, +] + +[[package]] +name = "iniconfig" +version = "2.0.0" +requires_python = ">=3.7" +summary = "brain-dead simple config-ini parsing" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] + +[[package]] +name = "maturin" +version = "1.3.0" +requires_python = ">=3.7" +summary = "Build and publish crates with pyo3, rust-cpython and cffi bindings as well as rust binaries as python packages" +dependencies = [ + "tomli>=1.1.0; python_version < \"3.11\"", +] +files = [ + {file = "maturin-1.3.0-py3-none-linux_armv6l.whl", hash = "sha256:dcc292547986fa93254b07d6d9f01a417b46a3fa55d5c45db65e71b285922f26"}, + {file = "maturin-1.3.0-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:d612878b75bb60946a45e9534bfd9e759e84d68cc6afe8d46c572d0c3b17bb4e"}, + {file = "maturin-1.3.0-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:f319b89025632099b197a686251f25def39f982f44474b8ba66c6d5f7e6abcde"}, + {file = "maturin-1.3.0-py3-none-manylinux_2_12_i686.manylinux2010_i686.musllinux_1_1_i686.whl", hash = "sha256:f2dfe86b37f7747712f3a910e3321e955efabe2c0e1de19563cea8d05bbee5b6"}, + {file = "maturin-1.3.0-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64.whl", hash = "sha256:2686f747980c9ef4a278542b209504b03c7576487b13b9655a6cbd40f3b98a73"}, + {file = "maturin-1.3.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:91ab057ae8d8992ad3a4312e8f379cbe1a8a3289f7d2a58969407e94355bfccc"}, + {file = "maturin-1.3.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:05639678b78a0df1abb4542925ee3eb5fc91ff3846878d584db8c7a6dbf2f54f"}, + {file = "maturin-1.3.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.musllinux_1_1_ppc64le.whl", hash = "sha256:416b0a48b8785555c5060d6fec97f69545c92ffe24df074c8a716d83fa8ab66b"}, + {file = "maturin-1.3.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:329820228baa9158d69c8e36e2fd3d7df3163a66df8ae739caa6cb5289955646"}, + {file = "maturin-1.3.0-py3-none-win32.whl", hash = "sha256:1b6b3a4d28c168a7a4773a406effb71c6245400e3d1fb08db3ebc5706669c706"}, + {file = "maturin-1.3.0-py3-none-win_amd64.whl", hash = "sha256:84d9136cd241868a8c57116f6bc20e4560b70e96c60fefc3bcbc7ad15dbb7eb7"}, + {file = "maturin-1.3.0-py3-none-win_arm64.whl", hash = "sha256:777bd6b5a6b6fdafcef69168c3938f35efba6e8ca3e7657940dfca4fa077920f"}, + {file = "maturin-1.3.0.tar.gz", hash = "sha256:f6c69bc7ae147a5effd55587447b35cab1ceb726ba244d08698bc7518b8688ac"}, +] + +[[package]] +name = "nodeenv" +version = "1.8.0" +requires_python = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" +summary = "Node.js virtual environment builder" +dependencies = [ + "setuptools", +] +files = [ + {file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"}, + {file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"}, +] + +[[package]] +name = "packaging" +version = "23.2" +requires_python = ">=3.7" +summary = "Core utilities for Python packages" +files = [ + {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, + {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, +] + +[[package]] +name = "platformdirs" +version = "3.11.0" +requires_python = ">=3.7" +summary = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +files = [ + {file = "platformdirs-3.11.0-py3-none-any.whl", hash = "sha256:e9d171d00af68be50e9202731309c4e658fd8bc76f55c11c7dd760d023bda68e"}, + {file = "platformdirs-3.11.0.tar.gz", hash = "sha256:cf8ee52a3afdb965072dcc652433e0c7e3e40cf5ea1477cd4b3b1d2eb75495b3"}, +] + +[[package]] +name = "pluggy" +version = "1.3.0" +requires_python = ">=3.8" +summary = "plugin and hook calling mechanisms for python" +files = [ + {file = "pluggy-1.3.0-py3-none-any.whl", hash = "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"}, + {file = "pluggy-1.3.0.tar.gz", hash = "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12"}, +] + +[[package]] +name = "pre-commit" +version = "3.4.0" +requires_python = ">=3.8" +summary = "A framework for managing and maintaining multi-language pre-commit hooks." +dependencies = [ + "cfgv>=2.0.0", + "identify>=1.0.0", + "nodeenv>=0.11.1", + "pyyaml>=5.1", + "virtualenv>=20.10.0", +] +files = [ + {file = "pre_commit-3.4.0-py2.py3-none-any.whl", hash = "sha256:96d529a951f8b677f730a7212442027e8ba53f9b04d217c4c67dc56c393ad945"}, + {file = "pre_commit-3.4.0.tar.gz", hash = "sha256:6bbd5129a64cad4c0dfaeeb12cd8f7ea7e15b77028d985341478c8af3c759522"}, +] + +[[package]] +name = "psutil" +version = "5.9.5" +requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +summary = "Cross-platform lib for process and system monitoring in Python." +files = [ + {file = "psutil-5.9.5-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:3c6f686f4225553615612f6d9bc21f1c0e305f75d7d8454f9b46e901778e7217"}, + {file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a7dd9997128a0d928ed4fb2c2d57e5102bb6089027939f3b722f3a210f9a8da"}, + {file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89518112647f1276b03ca97b65cc7f64ca587b1eb0278383017c2a0dcc26cbe4"}, + {file = "psutil-5.9.5-cp36-abi3-win32.whl", hash = "sha256:104a5cc0e31baa2bcf67900be36acde157756b9c44017b86b2c049f11957887d"}, + {file = "psutil-5.9.5-cp36-abi3-win_amd64.whl", hash = "sha256:b258c0c1c9d145a1d5ceffab1134441c4c5113b2417fafff7315a917a026c3c9"}, + {file = "psutil-5.9.5-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:c607bb3b57dc779d55e1554846352b4e358c10fff3abf3514a7a6601beebdb30"}, + {file = "psutil-5.9.5.tar.gz", hash = "sha256:5410638e4df39c54d957fc51ce03048acd8e6d60abc0f5107af51e5fb566eb3c"}, +] + +[[package]] +name = "pyperf" +version = "2.6.1" +requires_python = ">=3.7" +summary = "Python module to run and analyze benchmarks" +dependencies = [ + "psutil>=5.9.0", +] +files = [ + {file = "pyperf-2.6.1-py3-none-any.whl", hash = "sha256:9f81bf78335428ddf9845f1388dfb56181e744a69e93d8506697a56dc67b6d5f"}, + {file = "pyperf-2.6.1.tar.gz", hash = "sha256:171aea69b8efde61210e512166d8764e7765a9c7678b768052174b01f349f247"}, +] + +[[package]] +name = "pytest" +version = "7.4.2" +requires_python = ">=3.7" +summary = "pytest: simple powerful testing with Python" +dependencies = [ + "colorama; sys_platform == \"win32\"", + "exceptiongroup>=1.0.0rc8; python_version < \"3.11\"", + "iniconfig", + "packaging", + "pluggy<2.0,>=0.12", + "tomli>=1.0.0; python_version < \"3.11\"", +] +files = [ + {file = "pytest-7.4.2-py3-none-any.whl", hash = "sha256:1d881c6124e08ff0a1bb75ba3ec0bfd8b5354a01c194ddd5a0a870a48d99b002"}, + {file = "pytest-7.4.2.tar.gz", hash = "sha256:a766259cfab564a2ad52cb1aae1b881a75c3eb7e34ca3779697c23ed47c47069"}, +] + +[[package]] +name = "pyyaml" +version = "6.0.1" +requires_python = ">=3.6" +summary = "YAML parser and emitter for Python" +files = [ + {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, + {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, + {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, + {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, + {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, + {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, + {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, + {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, + {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, + {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, +] + +[[package]] +name = "ruff" +version = "0.0.292" +requires_python = ">=3.7" +summary = "An extremely fast Python linter, written in Rust." +files = [ + {file = "ruff-0.0.292-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:02f29db018c9d474270c704e6c6b13b18ed0ecac82761e4fcf0faa3728430c96"}, + {file = "ruff-0.0.292-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:69654e564342f507edfa09ee6897883ca76e331d4bbc3676d8a8403838e9fade"}, + {file = "ruff-0.0.292-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c3c91859a9b845c33778f11902e7b26440d64b9d5110edd4e4fa1726c41e0a4"}, + {file = "ruff-0.0.292-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f4476f1243af2d8c29da5f235c13dca52177117935e1f9393f9d90f9833f69e4"}, + {file = "ruff-0.0.292-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be8eb50eaf8648070b8e58ece8e69c9322d34afe367eec4210fdee9a555e4ca7"}, + {file = "ruff-0.0.292-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:9889bac18a0c07018aac75ef6c1e6511d8411724d67cb879103b01758e110a81"}, + {file = "ruff-0.0.292-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6bdfabd4334684a4418b99b3118793f2c13bb67bf1540a769d7816410402a205"}, + {file = "ruff-0.0.292-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aa7c77c53bfcd75dbcd4d1f42d6cabf2485d2e1ee0678da850f08e1ab13081a8"}, + {file = "ruff-0.0.292-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e087b24d0d849c5c81516ec740bf4fd48bf363cfb104545464e0fca749b6af9"}, + {file = "ruff-0.0.292-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f160b5ec26be32362d0774964e218f3fcf0a7da299f7e220ef45ae9e3e67101a"}, + {file = "ruff-0.0.292-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:ac153eee6dd4444501c4bb92bff866491d4bfb01ce26dd2fff7ca472c8df9ad0"}, + {file = "ruff-0.0.292-py3-none-musllinux_1_2_i686.whl", hash = "sha256:87616771e72820800b8faea82edd858324b29bb99a920d6aa3d3949dd3f88fb0"}, + {file = "ruff-0.0.292-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b76deb3bdbea2ef97db286cf953488745dd6424c122d275f05836c53f62d4016"}, + {file = "ruff-0.0.292-py3-none-win32.whl", hash = "sha256:e854b05408f7a8033a027e4b1c7f9889563dd2aca545d13d06711e5c39c3d003"}, + {file = "ruff-0.0.292-py3-none-win_amd64.whl", hash = "sha256:f27282bedfd04d4c3492e5c3398360c9d86a295be00eccc63914438b4ac8a83c"}, + {file = "ruff-0.0.292-py3-none-win_arm64.whl", hash = "sha256:7f67a69c8f12fbc8daf6ae6d36705037bde315abf8b82b6e1f4c9e74eb750f68"}, + {file = "ruff-0.0.292.tar.gz", hash = "sha256:1093449e37dd1e9b813798f6ad70932b57cf614e5c2b5c51005bf67d55db33ac"}, +] + +[[package]] +name = "setuptools" +version = "68.2.2" +requires_python = ">=3.8" +summary = "Easily download, build, install, upgrade, and uninstall Python packages" +files = [ + {file = "setuptools-68.2.2-py3-none-any.whl", hash = "sha256:b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a"}, + {file = "setuptools-68.2.2.tar.gz", hash = "sha256:4ac1475276d2f1c48684874089fefcd83bd7162ddaafb81fac866ba0db282a87"}, +] + +[[package]] +name = "sourcery" +version = "1.10.1" +summary = "Magically refactor Python" +files = [ + {file = "sourcery-1.10.1-py2.py3-none-macosx_10_9_universal2.whl", hash = "sha256:ab5cb4e5681cd6b6093cfdfba782703578f879fbe0f46b07451386386fb285d3"}, + {file = "sourcery-1.10.1-py2.py3-none-manylinux1_x86_64.whl", hash = "sha256:7588811152c6bc846ed57fbbf6df74160f80883c6b2a55b6c1fa0029a0ea33dd"}, + {file = "sourcery-1.10.1-py2.py3-none-win_amd64.whl", hash = "sha256:c5adfd268dcff47c155e8765d78a71de8eef9331281ab127eae28d9581b1e775"}, +] + +[[package]] +name = "tomli" +version = "2.0.1" +requires_python = ">=3.7" +summary = "A lil' TOML parser" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] + +[[package]] +name = "virtualenv" +version = "20.24.5" +requires_python = ">=3.7" +summary = "Virtual Python Environment builder" +dependencies = [ + "distlib<1,>=0.3.7", + "filelock<4,>=3.12.2", + "platformdirs<4,>=3.9.1", +] +files = [ + {file = "virtualenv-20.24.5-py3-none-any.whl", hash = "sha256:b80039f280f4919c77b30f1c23294ae357c4c8701042086e3fc005963e4e537b"}, + {file = "virtualenv-20.24.5.tar.gz", hash = "sha256:e8361967f6da6fbdf1426483bfe9fca8287c242ac0bc30429905721cefbff752"}, +] diff --git a/poetry.lock b/poetry.lock deleted file mode 100644 index 13880ea..0000000 --- a/poetry.lock +++ /dev/null @@ -1,173 +0,0 @@ -# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] - -[[package]] -name = "exceptiongroup" -version = "1.1.3" -description = "Backport of PEP 654 (exception groups)" -optional = false -python-versions = ">=3.7" -files = [ - {file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"}, - {file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"}, -] - -[package.extras] -test = ["pytest (>=6)"] - -[[package]] -name = "iniconfig" -version = "2.0.0" -description = "brain-dead simple config-ini parsing" -optional = false -python-versions = ">=3.7" -files = [ - {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, - {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, -] - -[[package]] -name = "maturin" -version = "1.2.3" -description = "Build and publish crates with pyo3, rust-cpython and cffi bindings as well as rust binaries as python packages" -optional = false -python-versions = ">=3.7" -files = [ - {file = "maturin-1.2.3-py3-none-linux_armv6l.whl", hash = "sha256:7b6484d7c94d6d6188ccf4ed8a6167cb8f1e98f13c653bfa715c9ee9eac4be0c"}, - {file = "maturin-1.2.3-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:b44fb4d1d116d69ce7c713c22b322debd5fc222db09eb1cdfa0e1c1b7f3e2e9c"}, - {file = "maturin-1.2.3-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:735375559c8c75bdc910c377f6dcc9197637ee2a312a60e361ef0e08fb31fcb5"}, - {file = "maturin-1.2.3-py3-none-manylinux_2_12_i686.manylinux2010_i686.musllinux_1_1_i686.whl", hash = "sha256:619f4f7b7e3a842a4f6cbae1d138a71d67aeba460f6217b38f2150ad53bb4dc1"}, - {file = "maturin-1.2.3-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64.whl", hash = "sha256:4e1035c102f87aa3e6733d28c2248b7303afa11f93a21f2ac88636e0430b0258"}, - {file = "maturin-1.2.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:aef8ddb9e775dd3781e6f56e10cc3d26f648735723ab5c47ce938542b9b5bbb6"}, - {file = "maturin-1.2.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:23c6fdc5750b96fd10d28c125dd795e9b75cd5cd768c8a403dc91dfde641243a"}, - {file = "maturin-1.2.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.musllinux_1_1_ppc64le.whl", hash = "sha256:40b4d69f9e5be5eacedd80ae496fae67cfd71d386b5604f7ce2e9ac9d34d0460"}, - {file = "maturin-1.2.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:826e90533789ff6dd3f3f0541fbe46c3549ec985d19edceff7913f9bdf9c3131"}, - {file = "maturin-1.2.3-py3-none-win32.whl", hash = "sha256:e414e56896d904c255e80190ac81fa8299b1d7df52f7e2e3f10df33f92784fd8"}, - {file = "maturin-1.2.3-py3-none-win_amd64.whl", hash = "sha256:1f5516dbe68491bf4bf7e047caf139596a3cd9d4a5ec8bb43034980e3710e550"}, - {file = "maturin-1.2.3-py3-none-win_arm64.whl", hash = "sha256:7d47e9a0fe56d25de98a2bed7d1c75975516e3a25fa5b552b2ee61fb1add41c0"}, - {file = "maturin-1.2.3.tar.gz", hash = "sha256:ef3f42af453d64f233b99543c3001bee645019a9c2022c7972210a9cacb5301f"}, -] - -[package.dependencies] -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} - -[package.extras] -patchelf = ["patchelf"] -zig = ["ziglang (>=0.10.0,<0.11.0)"] - -[[package]] -name = "packaging" -version = "23.1" -description = "Core utilities for Python packages" -optional = false -python-versions = ">=3.7" -files = [ - {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"}, - {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"}, -] - -[[package]] -name = "pluggy" -version = "1.2.0" -description = "plugin and hook calling mechanisms for python" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pluggy-1.2.0-py3-none-any.whl", hash = "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849"}, - {file = "pluggy-1.2.0.tar.gz", hash = "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"}, -] - -[package.extras] -dev = ["pre-commit", "tox"] -testing = ["pytest", "pytest-benchmark"] - -[[package]] -name = "psutil" -version = "5.9.5" -description = "Cross-platform lib for process and system monitoring in Python." -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "psutil-5.9.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:be8929ce4313f9f8146caad4272f6abb8bf99fc6cf59344a3167ecd74f4f203f"}, - {file = "psutil-5.9.5-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ab8ed1a1d77c95453db1ae00a3f9c50227ebd955437bcf2a574ba8adbf6a74d5"}, - {file = "psutil-5.9.5-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:4aef137f3345082a3d3232187aeb4ac4ef959ba3d7c10c33dd73763fbc063da4"}, - {file = "psutil-5.9.5-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ea8518d152174e1249c4f2a1c89e3e6065941df2fa13a1ab45327716a23c2b48"}, - {file = "psutil-5.9.5-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:acf2aef9391710afded549ff602b5887d7a2349831ae4c26be7c807c0a39fac4"}, - {file = "psutil-5.9.5-cp27-none-win32.whl", hash = "sha256:5b9b8cb93f507e8dbaf22af6a2fd0ccbe8244bf30b1baad6b3954e935157ae3f"}, - {file = "psutil-5.9.5-cp27-none-win_amd64.whl", hash = "sha256:8c5f7c5a052d1d567db4ddd231a9d27a74e8e4a9c3f44b1032762bd7b9fdcd42"}, - {file = "psutil-5.9.5-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:3c6f686f4225553615612f6d9bc21f1c0e305f75d7d8454f9b46e901778e7217"}, - {file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a7dd9997128a0d928ed4fb2c2d57e5102bb6089027939f3b722f3a210f9a8da"}, - {file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89518112647f1276b03ca97b65cc7f64ca587b1eb0278383017c2a0dcc26cbe4"}, - {file = "psutil-5.9.5-cp36-abi3-win32.whl", hash = "sha256:104a5cc0e31baa2bcf67900be36acde157756b9c44017b86b2c049f11957887d"}, - {file = "psutil-5.9.5-cp36-abi3-win_amd64.whl", hash = "sha256:b258c0c1c9d145a1d5ceffab1134441c4c5113b2417fafff7315a917a026c3c9"}, - {file = "psutil-5.9.5-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:c607bb3b57dc779d55e1554846352b4e358c10fff3abf3514a7a6601beebdb30"}, - {file = "psutil-5.9.5.tar.gz", hash = "sha256:5410638e4df39c54d957fc51ce03048acd8e6d60abc0f5107af51e5fb566eb3c"}, -] - -[package.extras] -test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] - -[[package]] -name = "pyperf" -version = "2.6.1" -description = "Python module to run and analyze benchmarks" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pyperf-2.6.1-py3-none-any.whl", hash = "sha256:9f81bf78335428ddf9845f1388dfb56181e744a69e93d8506697a56dc67b6d5f"}, - {file = "pyperf-2.6.1.tar.gz", hash = "sha256:171aea69b8efde61210e512166d8764e7765a9c7678b768052174b01f349f247"}, -] - -[package.dependencies] -psutil = ">=5.9.0" - -[package.extras] -dev = ["importlib-metadata", "tox"] - -[[package]] -name = "pytest" -version = "7.4.0" -description = "pytest: simple powerful testing with Python" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pytest-7.4.0-py3-none-any.whl", hash = "sha256:78bf16451a2eb8c7a2ea98e32dc119fd2aa758f1d5d66dbf0a59d69a3969df32"}, - {file = "pytest-7.4.0.tar.gz", hash = "sha256:b4bf8c45bd59934ed84001ad51e11b4ee40d40a1229d2c79f9c592b0a3f6bd8a"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "sys_platform == \"win32\""} -exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} -iniconfig = "*" -packaging = "*" -pluggy = ">=0.12,<2.0" -tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} - -[package.extras] -testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] - -[[package]] -name = "tomli" -version = "2.0.1" -description = "A lil' TOML parser" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, -] - -[metadata] -lock-version = "2.0" -python-versions = ">=3.8" -content-hash = "416013a4be58672c6256a4baf4570488137269b7fade8843410de63eb2947e68" diff --git a/pyproject.toml b/pyproject.toml index 351f18a..72d39aa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,20 +1,15 @@ -[tool.poetry] -name = "fast-query-parsers" -version = "1.0.3" -description = "Ultra-fast query string and url-encoded form-data parsers" -authors = [ - "Na'aman Hirschfeld ", -] -maintainers = [ - "Na'aman Hirschfeld ", -] -license = "MIT" -readme = "README.md" -packages = [{include = "src"}] +[build-system] +requires = ["maturin>=1.0,<2.0"] +build-backend = "maturin" [project] name = "fast-query-parsers" requires-python = ">=3.8" +license = {text = "MIT"} +version = "1.0.4" +description = "Ultra-fast query string and url-encoded form-data parsers" +readme = "README.md" +dependencies = [] classifiers = [ "Development Status :: 5 - Production/Stable", "Environment :: Web Environment", @@ -33,80 +28,45 @@ classifiers = [ "Topic :: Software Development", "Typing :: Typed", ] - -homepage = "https://github.com/starlite-api/fast-query-parsers" -documentation = "https://github.com/starlite-api/fast-query-parsers/README.md" -repository = "https://github.com/starlite-api/fast-query-parsers" keywords = [ "query", - "query string", - "qs", - "query parameters", + "query-parameters", "rust", "asgi", - "starlite", - "litestar", "parser", ] +authors = [ + {name = "Na'aman Hirschfeld", email = "nhirschfeld@gmail.com"}, +] +maintainers = [ + {name = "Jacob Coffee", email = "jacob@z7x.org"}, +] -[tool.poetry.dependencies] -python = ">=3.8" - -[tool.poetry.group.dev.dependencies] -maturin = "*" -pytest = "*" -pyperf = "*" +[tool.pdm.dev-dependencies] +dev = [ + "pyperf>=2.6.1", + "maturin>=1.3.0", + "pytest>=7.4.2", + "ruff>=0.0.292", + "pre-commit>=3.4.0", + "sourcery>=1.10.1", +] -[build-system] -requires = ["maturin>=0.14,<0.15"] -build-backend = "maturin" +[tool.pdm.scripts] +lint = "pre-commit run --all-files" +test = "pytest tests" +docs-serve = "sphinx-autobuild docs docs/_build/ -j auto --watch src --watch docs --watch tests --port 8002" +ci = {composite = ["lint", "test"]} -[tool.black] -line-length = 120 -include = '\.pyi?$' +[tool.pdm.build] +includes = ["src"] [tool.maturin] sdist-include = ["Cargo.lock"] strip = true - [tool.ruff] -select = [ - "A", # flake8-builtins - "B", # flake8-bugbear - "BLE", # flake8-blind-except - "C4", # flake8-comprehensions - "D", # pydocstyle - "DJ", # flake8-django - "DTZ", # flake8-datetimez - "E", # pycodestyle errors - "ERA", # eradicate - "EXE", # flake8-executable - "F", # pyflakes - "G", # flake8-logging-format - "I", # isort - "ICN", # flake8-import-conventions - "ISC", # flake8-implicit-str-concat - "N", # pep8-naming - "PIE", # flake8-pie - "PLC", # pylint - convention - "PLE", # pylint - error - "PLW", # pylint - warning - "PTH", # flake8-use-pathlib - "Q", # flake8-quotes - "RET", # flake8-return - "RUF", # Ruff-specific rules - "S", # flake8-bandit - "SIM", # flake8-simplify - "T10", # flake8-debugger - "T20", # flake8-print - "TCH", # flake8-type-checking - "TID", # flake8-tidy-imports - "UP", # pyupgrade - "W", # pycodestyle - warning - "YTT", # flake8-2020 -] - +select = ["ALL"] ignore = [ "A003", # flake8-builtins - class attribute {name} is shadowing a python builtin "B010", # flake8-bugbear - do not call setattr with a constant attribute value @@ -119,6 +79,7 @@ ignore = [ "D106", # pydocstyle - missing docstring in public nested class "D107", # pydocstyle - missing docstring in __init__ "D202", # pydocstyle - no blank lines allowed after function docstring + "D203", # pydocstyle - 1 blank line required before class docstring "D205", # pydocstyle - 1 blank line required between summary line and description "D415", # pydocstyle - first line should end with a period, question mark, or exclamation point "E501", # pycodestyle line too long, handled by black @@ -128,6 +89,5 @@ ignore = [ "D213", # multiline summary "D417" ] - line-length = 120 target-version = "py38" diff --git a/tests/test_parse_qs.py b/tests/test_parse_qs.py index 2f74d01..6c8621c 100644 --- a/tests/test_parse_qs.py +++ b/tests/test_parse_qs.py @@ -17,7 +17,7 @@ def test_parse_urlencoded_with_parse_numbers() -> None: - result = parse_url_encoded_dict(encoded, True) + result = parse_url_encoded_dict(encoded, parse_numbers=True) assert result == { "value": [10, 12], "veggies": ["tomato", "potato", "aubergine"], @@ -30,7 +30,7 @@ def test_parse_urlencoded_with_parse_numbers() -> None: def test_parse_urlencoded_without_parse_numbers() -> None: - result = parse_url_encoded_dict(encoded, False) + result = parse_url_encoded_dict(encoded, parse_numbers=False) assert result == { "value": ["10", "12"], "veggies": ["tomato", "potato", "aubergine"], diff --git a/tests/test_parse_qsl.py b/tests/test_parse_qsl.py index e6303e2..226c2c2 100644 --- a/tests/test_parse_qsl.py +++ b/tests/test_parse_qsl.py @@ -1,4 +1,5 @@ -from typing import List, Tuple +from __future__ import annotations + from urllib.parse import parse_qsl, urlencode import pytest @@ -6,7 +7,7 @@ @pytest.mark.parametrize( - "qs, expected", + ("qs", "expected"), [ ("", []), ("&", []), @@ -18,64 +19,47 @@ ("&a=b", [("a", "b")]), ("a=a+b&b=b+c", [("a", "a b"), ("b", "b c")]), ("a=1&a=2", [("a", "1"), ("a", "2")]), - ("", []), - ("&", []), - ("&&", []), - ("=", [("", "")]), - ("=a", [("", "a")]), - ("a", [("a", "")]), - ("a=", [("a", "")]), - ("&a=b", [("a", "b")]), - ("a=a+b&b=b+c", [("a", "a b"), ("b", "b c")]), - ("a=1&a=2", [("a", "1"), ("a", "2")]), - (";a=b", [(";a", "b")]), - ("a=a+b;b=b+c", [("a", "a b;b=b c")]), (";a=b", [(";a", "b")]), ("a=a+b;b=b+c", [("a", "a b;b=b c")]), ], ) -def test_parse_qsl_standard_separator(qs: str, expected: List[Tuple[str, str]]) -> None: +def test_parse_qsl_standard_separator(qs: str, expected: list[tuple[str, str]]) -> None: result = parse_query_string(qs.encode(), "&") assert result == parse_qsl(qs, keep_blank_values=True) == expected @pytest.mark.parametrize( - "qs, expected", + ("qs", "expected"), [ (";", []), (";;", []), (";a=b", [("a", "b")]), ("a=a+b;b=b+c", [("a", "a b"), ("b", "b c")]), ("a=1;a=2", [("a", "1"), ("a", "2")]), - (";", []), - (";;", []), - (";a=b", [("a", "b")]), - ("a=a+b;b=b+c", [("a", "a b"), ("b", "b c")]), - ("a=1;a=2", [("a", "1"), ("a", "2")]), ], ) -def test_parse_qsl_semicolon_separator(qs: str, expected: List[Tuple[str, str]]) -> None: +def test_parse_qsl_semicolon_separator(qs: str, expected: list[tuple[str, str]]) -> None: result = parse_query_string(qs.encode(), ";") assert result == parse_qsl(qs, separator=";", keep_blank_values=True) == expected @pytest.mark.parametrize( "values", - ( + [ (("first", "x@test.com"), ("second", "aaa")), (("first", "&@A.ac"), ("second", "aaa")), (("first", "a@A.ac&"), ("second", "aaa")), (("first", "a@A&.ac"), ("second", "aaa")), - ), + ], ) -def test_query_parsing_of_escaped_values(values: Tuple[Tuple[str, str], Tuple[str, str]]) -> None: +def test_query_parsing_of_escaped_values(values: tuple[tuple[str, str], tuple[str, str]]) -> None: url_encoded = urlencode(values) assert parse_query_string(url_encoded.encode(), "&") == list(values) def test_parses_non_ascii_text() -> None: assert parse_query_string("arabic_text=اختبار اللغة العربية".encode(), "&") == [ - ("arabic_text", "اختبار اللغة العربية") + ("arabic_text", "اختبار اللغة العربية"), ] From 271b95acbd2e5f8776b858d2cd895a561e2f76d9 Mon Sep 17 00:00:00 2001 From: Jacob Coffee Date: Sat, 7 Oct 2023 15:14:00 -0500 Subject: [PATCH 2/9] ci(local): add cargo test - fix(ci): add pip --- Makefile | 4 +++- pdm.lock | 12 +++++++++++- pyproject.toml | 1 + 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 0db855c..0e78aca 100644 --- a/Makefile +++ b/Makefile @@ -57,7 +57,8 @@ install: ## Install the project, dependencies, and pre-commit for loca .PHONY: clean clean: ## Cleanup temporary build artifacts @echo "=> Cleaning working directory" - @rm -rf .pytest_cache .ruff_cache .hypothesis build/ -rf dist/ .eggs/ target/ + @rm -rf .pytest_cache .ruff_cache .hypothesis build/ -rf dist/ .eggs/ + @cargo clean @find . -name '*.egg-info' -exec rm -rf {} + @find . -name '*.egg' -exec rm -f {} + @find . -name '*.pyc' -exec rm -f {} + @@ -113,6 +114,7 @@ coverage: ## Run the tests and generate coverage report test: ## Run the tests @echo "=> Running test cases" @$(ENV_PREFIX)pytest tests + @cargo test @echo "=> Tests complete" .PHONY: test-all diff --git a/pdm.lock b/pdm.lock index 8334c4a..2b176be 100644 --- a/pdm.lock +++ b/pdm.lock @@ -6,7 +6,7 @@ groups = ["default", "dev", "sourcery"] cross_platform = true static_urls = false lock_version = "4.3" -content_hash = "sha256:7a51d1b3582a6314e67cf3d38a4574bb545b78d355936e4e37814edb073fe88c" +content_hash = "sha256:622b838a8f2497013a3233e71c5b8840d1e394e5b5ed41291b69424a3d660251" [[package]] name = "cfgv" @@ -124,6 +124,16 @@ files = [ {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, ] +[[package]] +name = "pip" +version = "23.2.1" +requires_python = ">=3.7" +summary = "The PyPA recommended tool for installing Python packages." +files = [ + {file = "pip-23.2.1-py3-none-any.whl", hash = "sha256:7ccf472345f20d35bdc9d1841ff5f313260c2c33fe417f48c30ac46cccabf5be"}, + {file = "pip-23.2.1.tar.gz", hash = "sha256:fb0bd5435b3200c602b5bf61d2d43c2f13c02e29c1707567ae7fbc514eb9faf2"}, +] + [[package]] name = "platformdirs" version = "3.11.0" diff --git a/pyproject.toml b/pyproject.toml index 72d39aa..296683d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,6 +50,7 @@ dev = [ "ruff>=0.0.292", "pre-commit>=3.4.0", "sourcery>=1.10.1", + "pip>=23.2.1", ] [tool.pdm.scripts] From 02f021ebeb479f144146a7e419829fda72100b1d Mon Sep 17 00:00:00 2001 From: Jacob Coffee Date: Sat, 7 Oct 2023 18:44:30 -0500 Subject: [PATCH 3/9] docs: add docs (#23) --- .github/workflows/docs-preview.yml | 72 ++ .github/workflows/docs.yml | 46 + .gitignore | 1 + CONTRIBUTING.rst | 23 + Makefile | 2 +- README.md | 161 --- README.rst | 81 ++ benchmarks.py | 12 +- docs/__init__.py | 0 docs/_static/css/custom.css | 67 ++ docs/_static/logo.svg | 31 + .../polyfactory-banner-inline-dark.svg | 1 + .../polyfactory-banner-inline-light.svg | 1 + docs/conf.py | 130 +++ docs/contributing.rst | 3 + docs/index.rst | 18 + docs/reference/index.rst | 16 + docs/reference/python/benchmarks.rst | 11 + docs/reference/python/fast-query-parsers.rst | 13 + docs/reference/rust/lib.rst | 10 + docs/reference/rust/query-string.rst | 10 + docs/usage/index.rst | 68 ++ pdm.lock | 1001 ++++++++++++++++- pyproject.toml | 41 + tools/build_docs.py | 53 + 25 files changed, 1706 insertions(+), 166 deletions(-) create mode 100644 .github/workflows/docs-preview.yml create mode 100644 .github/workflows/docs.yml create mode 100644 CONTRIBUTING.rst delete mode 100644 README.md create mode 100644 README.rst create mode 100644 docs/__init__.py create mode 100644 docs/_static/css/custom.css create mode 100644 docs/_static/logo.svg create mode 100644 docs/_static/polyfactory-banner-inline-dark.svg create mode 100644 docs/_static/polyfactory-banner-inline-light.svg create mode 100644 docs/conf.py create mode 100644 docs/contributing.rst create mode 100644 docs/index.rst create mode 100644 docs/reference/index.rst create mode 100644 docs/reference/python/benchmarks.rst create mode 100644 docs/reference/python/fast-query-parsers.rst create mode 100644 docs/reference/rust/lib.rst create mode 100644 docs/reference/rust/query-string.rst create mode 100644 docs/usage/index.rst create mode 100644 tools/build_docs.py diff --git a/.github/workflows/docs-preview.yml b/.github/workflows/docs-preview.yml new file mode 100644 index 0000000..9efc632 --- /dev/null +++ b/.github/workflows/docs-preview.yml @@ -0,0 +1,72 @@ +name: Deploy Documentation Preview + +on: + workflow_run: + workflows: [Tests And Linting] + types: [completed] + +jobs: + deploy: + if: ${{ github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'pull_request' }} + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Download artifact + uses: dawidd6/action-download-artifact@v2 + with: + workflow_conclusion: success + run_id: ${{ github.event.workflow_run.id }} + path: docs-preview + name: docs-preview + + - name: Set PR number + run: echo "PR_NUMBER=$(cat docs-preview/.pr_number)" >> $GITHUB_ENV + + - name: Deploy docs preview + uses: JamesIves/github-pages-deploy-action@v4 + with: + folder: docs-preview/docs/_build/html + token: ${{ secrets.DOCS_PREVIEW_DEPLOY_TOKEN }} + repository-name: litestar-org/fast-query-parsers-docs-preview + clean: false + target-folder: ${{ env.PR_NUMBER }} + branch: gh-pages + + - uses: actions/github-script@v6 + env: + PR_NUMBER: ${{ env.PR_NUMBER }} + with: + script: | + const issue_number = process.env.PR_NUMBER + const body = "Documentation preview will be available shortly at https://litestar-org.github.io/fast-query-parsers-docs-preview/" + issue_number + + const opts = github.rest.issues.listComments.endpoint.merge({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue_number, + }); + + const comments = await github.paginate(opts) + + for (const comment of comments) { + if (comment.user.id === 41898282 && comment.body === body) { + await github.rest.issues.deleteComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: comment.id + }) + } + } + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue_number, + body: body, + }) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..702ae68 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,46 @@ +name: Documentation Building + +on: + release: + types: [published] + push: + branches: + - main + +jobs: + docs: + permissions: + contents: write + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v4 + with: + python-version: "3.11" + + - uses: pdm-project/setup-pdm@v3 + name: Set up PDM + with: + python-version: "3.11" + allow-python-prereleases: true + cache: true + + - name: Install dependencies + run: pdm install -G:docs + + - name: Fetch gh pages + run: git fetch origin gh-pages --depth=1 + + - name: Build release docs + run: pdm run python tools/build_docs.py docs-build + if: github.event_name == 'release' + + - name: Build dev docs + run: pdm run python tools/build_docs.py docs-build + if: github.event_name == 'push' + + - name: Deploy + uses: JamesIves/github-pages-deploy-action@v4 + with: + folder: docs-build diff --git a/.gitignore b/.gitignore index a14b14a..8f849e7 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ __pycache__/ *.profraw coverage* .venv/ +/docs/_build/ # pdm .pdm-python diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst new file mode 100644 index 0000000..3cfd09e --- /dev/null +++ b/CONTRIBUTING.rst @@ -0,0 +1,23 @@ +============ +Contributing +============ + +All contributions are of course welcome! + +Repository Setup +~~~~~~~~~~~~~~~~ + +1. Run ``cargo build`` to set up the rust dependencies and ``pdm install`` to set up the python dependencies. +2. Install the pre-commit hooks with ``pre-commit install`` (requires `pre-commit `_). + +Building +~~~~~~~~ + +Run ``pdm run maturin develop --release --strip`` to install a release wheel (without debugging info). +This wheel can be used in tests and benchmarks. + +Benchmarking +~~~~~~~~~~~~ + +There are basic benchmarks using pyperf in place. +To run these execute ``pdm run python benchmarks.py``. diff --git a/Makefile b/Makefile index 0e78aca..e3b1ae1 100644 --- a/Makefile +++ b/Makefile @@ -143,7 +143,7 @@ docs-clean: ## Dump the existing built docs docs-serve: docs-clean ## Serve the docs locally @echo "=> Serving documentation" - $(ENV_PREFIX)sphinx-autobuild docs docs/_build/ -j auto --watch fast_query_parser.pyi --watch docs --watch tests --watch CONTRIBUTING.rst --port 8002 + $(ENV_PREFIX)sphinx-autobuild docs docs/_build/ -j auto --watch fast_query_parser.pyi --watch docs --watch tests --watch CONTRIBUTING.rst --watch README.rst --port 8002 docs: docs-clean ## Dump the existing built docs and rebuild them @echo "=> Building documentation" diff --git a/README.md b/README.md deleted file mode 100644 index 325d73f..0000000 --- a/README.md +++ /dev/null @@ -1,161 +0,0 @@ - -

- Litestar Logo - Light - Litestar Logo - Dark -

- - -
- - - -| Project | | Status | -|-----------|:----|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| CI/CD | | [![Publish](https://github.com/litestar-org/fast-query-parsers/actions/workflows/publish.yaml/badge.svg)](https://github.com/litestar-org/fast-query-parsers/actions/workflows/publish.yaml) [![CI](https://github.com/litestar-org/fast-query-parsers/actions/workflows/ci.yaml/badge.svg)](https://github.com/litestar-org/fast-query-parsers/actions/workflows/ci.yaml) | -| Package | | [![PyPI - Version](https://img.shields.io/pypi/v/fast-query-parsers?labelColor=202235&color=edb641&logo=python&logoColor=edb641)](https://badge.fury.io/py/litestar) ![PyPI - Support Python Versions](https://img.shields.io/pypi/pyversions/fast-query-parsers?labelColor=202235&color=edb641&logo=python&logoColor=edb641) ![PyPI - Downloads](https://img.shields.io/pypi/dm/fast-query-parsers?logo=python&label=fast-query-parsers%20downloads&labelColor=202235&color=edb641&logoColor=edb641) | -| Community | | [![Reddit](https://img.shields.io/reddit/subreddit-subscribers/litestarapi?label=r%2FLitestar&logo=reddit&labelColor=202235&color=edb641&logoColor=edb641)](https://reddit.com/r/litestarapi) [![Discord](https://img.shields.io/discord/919193495116337154?labelColor=202235&color=edb641&label=chat%20on%20discord&logo=discord&logoColor=edb641)](https://discord.gg/X3FJqy8d2j) [![Matrix](https://img.shields.io/badge/chat%20on%20Matrix-bridged-202235?labelColor=202235&color=edb641&logo=matrix&logoColor=edb641)](https://matrix.to/#/#litestar:matrix.org) [![Medium](https://img.shields.io/badge/Medium-202235?labelColor=202235&color=edb641&logo=medium&logoColor=edb641)](https://blog.litestar.dev) [![Twitter](https://img.shields.io/twitter/follow/LitestarAPI?labelColor=202235&color=edb641&logo=twitter&logoColor=edb641&style=flat)](https://twitter.com/LitestarAPI) [![Blog](https://img.shields.io/badge/Blog-litestar.dev-202235?logo=blogger&labelColor=202235&color=edb641&logoColor=edb641)](https://blog.litestar.dev) | -| Meta | | [![Litestar Project](https://img.shields.io/badge/Litestar%20Org-%E2%AD%90%20Fast%20Query%20Parsers-202235.svg?logo=python&labelColor=202235&color=edb641&logoColor=edb641)](https://github.com/litestar-org/fast-query-parsers) [![License - MIT](https://img.shields.io/badge/license-MIT-202235.svg?logo=python&labelColor=202235&color=edb641&logoColor=edb641)](https://spdx.org/licenses/) [![Litestar Sponsors](https://img.shields.io/badge/Sponsor-%E2%9D%A4-%23edb641.svg?&logo=github&logoColor=edb641&labelColor=202235)](https://github.com/sponsors/litestar-org) [![linting - Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json&labelColor=202235)](https://github.com/astral-sh/ruff) [![code style - Black](https://img.shields.io/badge/code%20style-black-000000.svg?logo=python&labelColor=202235&logoColor=edb641)](https://github.com/psf/black) | - - -
- -# Fast Query Parsers - -This library includes ultra-fast Rust based query string and urlencoded parsers. These parsers are used -by [`Litestar`](https://github.com/litestar-org/litestar), but are developed separately - and can of course be used separately. - -## Installation - -```shell -pip install fast-query-parsers -``` - -## Usage - -The library exposes two function `parse_query_string` and `parse_url_encoded_dict`. - -### `parse_query_string` - -This function is used to parse a query string into a list of key/value tuples. - -```python -from fast_query_parsers import parse_query_string - -result = parse_query_string(b"value=1&value=2&type=dollar&country=US", "&") -# [("value", "1"), ("value", "2"), ("type", "dollar"), ("country", "US")] -``` - -The first argument to this function is a byte string that includes the query string to be parsed, the second argument is -the separator used. - -#### Benchmarks - -Query string parsing is more than x5 times faster than the standard library: - -```text -stdlib parse_qsl parsing query string: Mean +- std dev: 2.86 us +- 0.03 us -..................... -parse_query_string parsing query string: Mean +- std dev: 916 ns +- 13 ns -..................... -stdlib parse_qsl parsing urlencoded query string: Mean +- std dev: 8.30 us +- 0.10 us -..................... -parse_query_string urlencoded query string: Mean +- std dev: 1.50 us +- 0.03 us -``` - -### `parse_url_encoded_dict` - -This function is used to parse a url-encoded form data dictionary and parse it into the python equivalent of JSON types. - -```python -from urllib.parse import urlencode - -from fast_query_parsers import parse_url_encoded_dict - -encoded = urlencode( - [ - ("value", "10"), - ("value", "12"), - ("veggies", '["tomato", "potato", "aubergine"]'), - ("nested", '{"some_key": "some_value"}'), - ("calories", "122.53"), - ("healthy", "true"), - ("polluting", "false"), - ("json", "null"), - ] -).encode() - -result = parse_url_encoded_dict(encoded, parse_numbers=True) - -# result == { -# "value": [10, 12], -# "veggies": ["tomato", "potato", "aubergine"], -# "nested": {"some_key": "some_value"}, -# "calories": 122.53, -# "healthy": True, -# "polluting": False, -# "json": None, -# } -``` - -This function handles type conversions correctly - unlike the standard library function `parse_qs`. Additionally, it -does not nest all values inside lists. - -Note: the second argument passed to `parse_url_encoded_dict` dictates whether numbers should be parsed. If `True`, -the value will be parsed into an int or float as appropriate, otherwise it will be kept as a string. -By default, the value of this arg is `True`. - -#### Benchmarks - -Url Encoded parsing is more than x2 times faster than the standard library, without accounting for parsing of values: - -```text -stdlib parse_qs parsing url-encoded values into dict: Mean +- std dev: 8.99 us +- 0.09 us -..................... -parse_url_encoded_dict parse url-encoded values into dict: Mean +- std dev: 3.77 us +- 0.08 us -``` - -To actually mimic the parsing done by `parse_url_encoded_dict` we will need a utility along these lines: - -```python -from collections import defaultdict -from contextlib import suppress -from json import loads, JSONDecodeError -from typing import Any, DefaultDict, Dict, List -from urllib.parse import parse_qsl - - -def parse_url_encoded_form_data(encoded_data: bytes) -> Dict[str, Any]: - """Parse an url encoded form data into dict of parsed values""" - decoded_dict: DefaultDict[str, List[Any]] = defaultdict(list) - for k, v in parse_qsl(encoded_data.decode(), keep_blank_values=True): - with suppress(JSONDecodeError): - v = loads(v) if isinstance(v, str) else v - decoded_dict[k].append(v) - return {k: v if len(v) > 1 else v[0] for k, v in decoded_dict.items()} -``` - -With the above, the benchmarks looks like so: - -```text -python parse_url_encoded_form_data parsing url-encoded values into dict: Mean +- std dev: 19.7 us +- 0.1 us -..................... -parse_url_encoded_dict parsing url-encoded values into dict: Mean +- std dev: 3.69 us +- 0.03 us -``` - -## Contributing - -All contributions are of course welcome! - -### Repository Setup - -1. Run `cargo build` to set up the rust dependencies and `pdm install` to set up the python dependencies. -2. Install the pre-commit hooks with `pre-commit install` (requires [pre-commit](https://pre-commit.com/)). - -### Building - -Run `pdm run maturin develop --release --strip` to install a release wheel (without debugging info). This wheel can be -used in tests and benchmarks. - -### Benchmarking - -There are basic benchmarks using pyperf in place. To run these execute `pdm run python benchmarks.py`. diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..246953d --- /dev/null +++ b/README.rst @@ -0,0 +1,81 @@ +.. image:: https://raw.githubusercontent.com/litestar-org/branding/473f54621e55cde9acbb6fcab7fc03036173eb3d/assets/Branding%20-%20SVG%20-%20Transparent/Logo%20-%20Banner%20-%20Inline%20-%20Light.svg#gh-light-mode-only + :align: center + +.. .. image:: https://raw.githubusercontent.com/litestar-org/branding/473f54621e55cde9acbb6fcab7fc03036173eb3d/assets/Branding%20-%20SVG%20-%20Transparent/Logo%20-%20Banner%20-%20Inline%20-%20Dark.svg#gh-dark-mode-only +.. :align: center +.. :class: dark_logo + +================== +Fast Query Parsers +================== + +This library includes ultra-fast Rust based query string and ``urlencoded`` parsers. +These parsers can be used in any project that needs to parse query strings or ``urlencoded`` data. + +Who's using this library? +------------------------- + +These parsers were initially built to used by `Litestar `_, +a high-performance Python web framework. However, these parsers can be used in any project that +needs to parse query strings or ``urlencoded`` data. + +Benchmarks +---------- + +.. code-block:: console + + stdlib parse_qs parsing url-encoded values into dict: Mean +- std dev: 8.99 us +- 0.09 us + ..................... + parse_url_encoded_dict parse url-encoded values into dict: Mean +- std dev: 3.77 us +- 0.08 us + +Contributing +------------ + +Contributions are welcome! +Please see the :doc:`contributing` for more details. + +Status +------ + ++-----------+-----+------------------------------------------------------------------------------------------------------------------+ +| Project | | Status | ++===========+=====+==================================================================================================================+ +| CI/CD | | |Publish| |CI| | ++-----------+-----+------------------------------------------------------------------------------------------------------------------+ +| Package | | |PyPI - Version| |PyPI - Support Python Versions| |PyPI - Downloads| | ++-----------+-----+------------------------------------------------------------------------------------------------------------------+ +| Community | | |Reddit| |Discord| |Matrix| |Medium| |Twitter| |Blog| | ++-----------+-----+------------------------------------------------------------------------------------------------------------------+ +| Meta | | |Litestar Project| |License - MIT| |Litestar Sponsors| |linting - Ruff| |code style - Black| | ++-----------+-----+------------------------------------------------------------------------------------------------------------------+ + +.. |Publish| image:: https://github.com/litestar-org/fast-query-parsers/actions/workflows/publish.yaml/badge.svg + :target: https://github.com/litestar-org/fast-query-parsers/actions/workflows/publish.yaml +.. |CI| image:: https://github.com/litestar-org/fast-query-parsers/actions/workflows/ci.yaml/badge.svg + :target: https://github.com/litestar-org/fast-query-parsers/actions/workflows/ci.yaml +.. |PyPI - Version| image:: https://img.shields.io/pypi/v/fast-query-parsers?labelColor=202235&color=edb641&logo=python&logoColor=edb641 + :target: https://badge.fury.io/py/litestar +.. |PyPI - Support Python Versions| image:: https://img.shields.io/pypi/pyversions/fast-query-parsers?labelColor=202235&color=edb641&logo=python&logoColor=edb641 +.. |PyPI - Downloads| image:: https://img.shields.io/pypi/dm/fast-query-parsers?logo=python&label=fast-query-parsers%20downloads&labelColor=202235&color=edb641&logoColor=edb641 +.. |Reddit| image:: https://img.shields.io/reddit/subreddit-subscribers/litestarapi?label=r%2FLitestar&logo=reddit&labelColor=202235&color=edb641&logoColor=edb641 + :target: https://reddit.com/r/litestarapi +.. |Discord| image:: https://img.shields.io/discord/919193495116337154?labelColor=202235&color=edb641&label=chat%20on%20discord&logo=discord&logoColor=edb641 + :target: https://discord.gg/X3FJqy8d2j +.. |Matrix| image:: https://img.shields.io/badge/chat%20on%20Matrix-bridged-202235?labelColor=202235&color=edb641&logo=matrix&logoColor=edb641 + :target: https://matrix.to/#/#litestar:matrix.org +.. |Medium| image:: https://img.shields.io/badge/Medium-202235?labelColor=202235&color=edb641&logo=medium&logoColor=edb641 + :target: https://blog.litestar.dev +.. |Twitter| image:: https://img.shields.io/twitter/follow/LitestarAPI?labelColor=202235&color=edb641&logo=twitter&logoColor=edb641&style=flat + :target: https://twitter.com/LitestarAPI +.. |Blog| image:: https://img.shields.io/badge/Blog-litestar.dev-202235?logo=blogger&labelColor=202235&color=edb641&logoColor=edb641 + :target: https://blog.litestar.dev +.. |Litestar Project| image:: https://img.shields.io/badge/Litestar%20Org-%E2%AD%90%20Fast%20Query%20Parsers-202235.svg?logo=python&labelColor=202235&color=edb641&logoColor=edb641 + :target: https://github.com/litestar-org/fast-query-parsers +.. |License - MIT| image:: https://img.shields.io/badge/license-MIT-202235.svg?logo=python&labelColor=202235&color=edb641&logoColor=edb641 + :target: https://spdx.org/licenses/ +.. |Litestar Sponsors| image:: https://img.shields.io/badge/Sponsor-%E2%9D%A4-%23edb641.svg?&logo=github&logoColor=edb641&labelColor=202235 + :target: https://github.com/sponsors/litestar-org +.. |linting - Ruff| image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json&labelColor=202235 + :target: https://github.com/astral-sh/ruff +.. |code style - Black| image:: https://img.shields.io/badge/code%20style-black-000000.svg?logo=python&labelColor=202235&logoColor=edb641 + :target: https://github.com/psf/black diff --git a/benchmarks.py b/benchmarks.py index e2e8a01..0013481 100644 --- a/benchmarks.py +++ b/benchmarks.py @@ -28,11 +28,9 @@ def parse_url_encoded_form_data(encoded_data: bytes) -> dict[str, Any]: """Parse an url encoded form data dict. Args: - ---- encoded_data: The encoded byte string. Returns: - ------- A parsed dict. """ decoded_dict: defaultdict[str, list[Any]] = defaultdict(list) @@ -44,6 +42,11 @@ def parse_url_encoded_form_data(encoded_data: bytes) -> dict[str, Any]: def bench_qsl(runner: pyperf.Runner) -> None: + """Benchmarks for parsing query string. + + Args: + runner: The pyperf runner. + """ runner.bench_func( "stdlib parse_qsl parsing query string", lambda: stdlib_parse_qsl(b"key=1&key=2&key=3&another=a&zorg=5=".decode(), keep_blank_values=True), @@ -60,6 +63,11 @@ def bench_qsl(runner: pyperf.Runner) -> None: def bench_qs(runner: pyperf.Runner) -> None: + """Benchmarks for parsing url-encoded values into dict. + + Args: + runner: The pyperf runner. + """ runner.bench_func( "stdlib parse_qs parsing url-encoded values into dict", lambda: stdlib_parse_qs(url_encoded_query.decode()), diff --git a/docs/__init__.py b/docs/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/docs/_static/css/custom.css b/docs/_static/css/custom.css new file mode 100644 index 0000000..69533f5 --- /dev/null +++ b/docs/_static/css/custom.css @@ -0,0 +1,67 @@ +/*brand_colors = {*/ +/* "--brand-primary": {"rgb": "0, 150, 76", "hex": "#00964c"},*/ +/* "--brand-secondary": {"rgb": "99, 99, 99", "hex": "#636363"},*/ +/* "--brand-green": {"rgb": "225, 39, 38", "hex": "#e12726"},*/ +/* "--brand-alert": {"rgb": "241, 81, 82", "hex": "#f15152"},*/ +/* "--brand-dark": {"rgb": "32, 32, 32", "hex": "#202020"},*/ +/* "--brand-light": {"rgb": "235, 235, 233", "hex": "#EBEBE9"},*/ +/*}*/ + +:root { + --brand-primary: #edb641; + --brand-primary-rgb: 237, 182, 65; + + --brand-secondary: #202235; + --brand-secondary-rgb: 32, 34, 53; + + --brand-tertiary: #ffd480; + --brand-tertiary-rgb: 255, 212, 128; + + --brand-green: #00f597; + --brand-green-rgb: 0, 245, 151; + + --brand-alert: #f36060; + --brand-alert-rgb: 243, 96, 96; + + --brand-dark: #202020; + --brand-dark-rgb: 32, 32, 32; + + --brand-light: #dcdfe4; + --brand-light-rgb: 220, 223, 228; +} + +html.dark, +html.light { + --sd-color-tabs-label-hover: var(--brand-primary); +} + +html.light { + /*--syntax-light-constant: var(--brand-primary);*/ + --syntax-light-meta: var(--brand-secondary); + /*!* --syntax-light-text: #09090a;*!*/ + /*!* --syntax-light-cap-bg: #325b76;*!*/ + --syntax-light-pre-bg: var(--brand-light); + /*--syntax-light-keyword: var(--brand-primary);*/ + /*--syntax-light-property: var(--brand-secondary);*/ +} + +html.light .yue { + /*--yue-c-code-bg: var(--brand-light) !important;*/ + /*--yue-c-code: var(--brand-primary) !important;*/ + /*--yue-c-black: #11a1ff !important;*/ +} + +html.dark { + /*--syntax-dark-keyword: var(--brand-primary);*/ + /*--syntax-dark-property: var(--brand-green);*/ + /*--syntax-dark-constant: var(--brand-primary);*/ + --syntax-dark-meta: var(--brand-primary); + --syntax-dark-pre-bg: var(--brand-secondary); + /*--yue-c-code-bg: var(--brand-alert) !important;*/ +} + +html.dark .yue { + /*--yue-c-code-bg: var(--brand-light) !important;*/ + /*--yue-c-code: var(--brand-secondary) !important;*/ + /*--yue-c-black: #11a1ff !important;*/ +} diff --git a/docs/_static/logo.svg b/docs/_static/logo.svg new file mode 100644 index 0000000..e83862f --- /dev/null +++ b/docs/_static/logo.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/polyfactory-banner-inline-dark.svg b/docs/_static/polyfactory-banner-inline-dark.svg new file mode 100644 index 0000000..718c208 --- /dev/null +++ b/docs/_static/polyfactory-banner-inline-dark.svg @@ -0,0 +1 @@ + diff --git a/docs/_static/polyfactory-banner-inline-light.svg b/docs/_static/polyfactory-banner-inline-light.svg new file mode 100644 index 0000000..c73ecfb --- /dev/null +++ b/docs/_static/polyfactory-banner-inline-light.svg @@ -0,0 +1 @@ + diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..ac4153d --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,130 @@ +from __future__ import annotations + +project = "Fast Query Parsers" +copyright = "2023, Litestar Organization" +author = "Litestar Organization" +release = "1.0.0" + +extensions = [ + "sphinx.ext.intersphinx", + "sphinx.ext.autosectionlabel", + "sphinx.ext.autodoc", + "sphinx.ext.napoleon", + "sphinx_design", + "sphinx_copybutton", + "sphinxcontrib.mermaid", + "myst_parser", +] + +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] + +intersphinx_mapping = { + "python": ("https://docs.python.org/3", None), +} + +napoleon_google_docstring = True +napoleon_include_special_with_doc = True +napoleon_use_admonition_for_examples = True +napoleon_use_admonition_for_notes = True +napoleon_use_admonition_for_references = False +napoleon_attr_annotations = True + +autoclass_content = "class" +autodoc_class_signature = "separated" +autodoc_default_options = { + "special-members": True, + "show-inheritance": True, + "members": True, + "exclude-members": "__init_subclass__,__weakref__,__subclasshook__", +} +autodoc_member_order = "bysource" +autodoc_typehints_format = "short" + +autosectionlabel_prefix_document = True + +suppress_warnings = [ + "autosectionlabel.*", + "ref.python", # TODO: remove when https://github.com/sphinx-doc/sphinx/issues/4961 is fixed +] + +html_theme = "shibuya" +html_static_path = ["_static"] +html_show_sourcelink = False +html_title = "Fast Query Parsers" + +PY_CLASS = "py:class" +PY_RE = r"py:.*" + +nitpicky = True +nitpick_ignore = [] +nitpick_ignore_regex = [] + +# -- Style configuration ----------------------------------------------------- +html_theme = "shibuya" +html_static_path = ["_static"] +html_css_files = ["css/custom.css"] +html_show_sourcelink = True +html_title = "Docs" +html_favicon = "_static/logo.png" +html_logo = "_static/logo.png" +html_context = { + "source_type": "github", + "source_user": "litestar-org", + "source_repo": "fast-query-parsers", +} + +brand_colors = { + "--brand-primary": {"rgb": "237, 182, 65", "hex": "#edb641"}, + "--brand-secondary": {"rgb": "32, 34, 53", "hex": "#202235"}, + "--brand-tertiary": {"rgb": "161, 173, 161", "hex": "#A1ADA1"}, + "--brand-green": {"rgb": "0, 245, 151", "hex": "#00f597"}, + "--brand-alert": {"rgb": "243, 96, 96", "hex": "#f36060"}, + "--brand-dark": {"rgb": "0, 0, 0", "hex": "#000000"}, + "--brand-light": {"rgb": "235, 221, 221", "hex": "#ebdddd"}, +} + +html_theme_options = { + "logo_target": "/", + "announcement": "This documentation is currently under development.", + "github_url": "https://github.com/litestar-org/fast-query-parsers", + "nav_links": [ + {"title": "Home", "url": "https://fqp.litestar.dev"}, + {"title": "Docs", "url": "https://docs.fqp.litestar.dev"}, + {"title": "Code", "url": "https://github.com/litestar-org/fast-query-parsers"}, + ], + "light_css_variables": { + # RGB + "--sy-rc-theme": brand_colors["--brand-primary"]["rgb"], + "--sy-rc-text": brand_colors["--brand-primary"]["rgb"], + "--sy-rc-invert": brand_colors["--brand-primary"]["rgb"], + # "--sy-rc-bg": brand_colors["--brand-secondary"]["rgb"], + # Hex + "--sy-c-link": brand_colors["--brand-secondary"]["hex"], + # "--sy-c-foot-bg": "#191919", + "--sy-c-foot-divider": brand_colors["--brand-primary"]["hex"], + "--sy-c-foot-text": brand_colors["--brand-dark"]["hex"], + "--sy-c-bold": brand_colors["--brand-primary"]["hex"], + "--sy-c-heading": brand_colors["--brand-primary"]["hex"], + "--sy-c-text-weak": brand_colors["--brand-primary"]["hex"], + "--sy-c-text": brand_colors["--brand-dark"]["hex"], + "--sy-c-bg-weak": brand_colors["--brand-dark"]["rgb"], + }, + "dark_css_variables": { + # RGB + "--sy-rc-theme": brand_colors["--brand-primary"]["rgb"], + "--sy-rc-text": brand_colors["--brand-primary"]["rgb"], + "--sy-rc-invert": brand_colors["--brand-primary"]["rgb"], + "--sy-rc-bg": brand_colors["--brand-dark"]["rgb"], + # Hex + "--sy-c-link": brand_colors["--brand-primary"]["hex"], + "--sy-c-foot-bg": brand_colors["--brand-dark"]["hex"], + "--sy-c-foot-divider": brand_colors["--brand-primary"]["hex"], + "--sy-c-foot-text": brand_colors["--brand-light"]["hex"], + "--sy-c-bold": brand_colors["--brand-primary"]["hex"], + "--sy-c-heading": brand_colors["--brand-primary"]["hex"], + "--sy-c-text-weak": brand_colors["--brand-primary"]["hex"], + "--sy-c-text": brand_colors["--brand-light"]["hex"], + "--sy-c-bg-weak": brand_colors["--brand-dark"]["hex"], + "--sy-c-bg": brand_colors["--brand-primary"]["hex"], + }, +} diff --git a/docs/contributing.rst b/docs/contributing.rst new file mode 100644 index 0000000..bbd440e --- /dev/null +++ b/docs/contributing.rst @@ -0,0 +1,3 @@ +:orphan: + +.. include:: ../CONTRIBUTING.rst diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..bec4bb9 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,18 @@ +:orphan: + +.. include:: ../README.rst + +.. toctree:: + :titlesonly: + :caption: Documentation + :hidden: + + usage/index.rst + reference/index.rst + +.. toctree:: + :titlesonly: + :caption: Development + :hidden: + + contributing diff --git a/docs/reference/index.rst b/docs/reference/index.rst new file mode 100644 index 0000000..c0ba271 --- /dev/null +++ b/docs/reference/index.rst @@ -0,0 +1,16 @@ +======================= +Reference Documentation +======================= + +This is the reference documentation for the `fast-query-parsers` package. + +It includes the Python binding documentation as well as the documentation for the +Rust library. + +.. toctree:: + :maxdepth: 2 + + python/fast-query-parsers + python/benchmarks + rust/lib + rust/query-string diff --git a/docs/reference/python/benchmarks.rst b/docs/reference/python/benchmarks.rst new file mode 100644 index 0000000..170f111 --- /dev/null +++ b/docs/reference/python/benchmarks.rst @@ -0,0 +1,11 @@ +================= +python/benchmarks +================= + +.. note:: This is not true reference documentation due to how the project is structured. + +.. literalinclude:: ../../../benchmarks.py + :language: python + :emphasize-lines: 27,46,62 + :linenos: + :caption: benchmarks.py diff --git a/docs/reference/python/fast-query-parsers.rst b/docs/reference/python/fast-query-parsers.rst new file mode 100644 index 0000000..068f732 --- /dev/null +++ b/docs/reference/python/fast-query-parsers.rst @@ -0,0 +1,13 @@ +========================= +python/fast_query_parsers +========================= + +.. note:: This is not true reference documentation due to how the project is structured. + Also, ``.pyi`` files are not currently supported + See `sphinx-doc/sphinx#4824 `_ for more details. + +.. literalinclude:: ../../../fast_query_parsers.pyi + :language: python + :emphasize-lines: 3, 15 + :linenos: + :caption: fast_query_parsers.pyi diff --git a/docs/reference/rust/lib.rst b/docs/reference/rust/lib.rst new file mode 100644 index 0000000..bf2db2c --- /dev/null +++ b/docs/reference/rust/lib.rst @@ -0,0 +1,10 @@ +======== +rust/lib +======== + +.. note:: This is not true reference documentation due to how the project is structured. + +.. literalinclude:: ../../../src/lib.rs + :language: rust + :linenos: + :caption: lib.rs diff --git a/docs/reference/rust/query-string.rst b/docs/reference/rust/query-string.rst new file mode 100644 index 0000000..a8e86d1 --- /dev/null +++ b/docs/reference/rust/query-string.rst @@ -0,0 +1,10 @@ +================= +rust/query-string +================= + +.. note:: This is not true reference documentation due to how the project is structured. + +.. literalinclude:: ../../../src/query_string.rs + :language: rust + :linenos: + :caption: query_string.rs diff --git a/docs/usage/index.rst b/docs/usage/index.rst new file mode 100644 index 0000000..94a2fa9 --- /dev/null +++ b/docs/usage/index.rst @@ -0,0 +1,68 @@ +===== +Usage +===== + +Installation +------------ + +.. code-block:: console + + pip install fast-query-parsers + +Usage +----- + +The library exposes two function ``parse_query_string`` and ``parse_url_encoded_dict``. + +``parse_query_string`` +~~~~~~~~~~~~~~~~~~~~~~ + +This function is used to parse a query string into a list of key/value tuples. + +.. code-block:: python + + from fast_query_parsers import parse_query_string + + result = parse_query_string(b"value=1&value=2&type=dollar&country=US", "&") + # [("value", "1"), ("value", "2"), ("type", "dollar"), ("country", "US")] + +Benchmarks +^^^^^^^^^^ + +Query string parsing is more than x5 times faster than the standard library: + +.. code-block:: console + + stdlib parse_qsl parsing query string: Mean +- std dev: 2.86 us +- 0.03 us + ..................... + parse_query_string parsing query string: Mean +- std dev: 916 ns +- 13 ns + ..................... + stdlib parse_qsl parsing urlencoded query string: Mean +- std dev: 8.30 us +- 0.10 us + ..................... + parse_query_string urlencoded query string: Mean +- std dev: 1.50 us +- 0.03 us + +``parse_url_encoded_dict`` +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This function is used to parse a url-encoded form data dictionary and parse it into the python equivalent of JSON types. + +.. code-block:: python + + from urllib.parse import urlencode + from fast_query_parsers import parse_url_encoded_dict + + encoded = urlencode( + [ + ("value", "10"), + ("value", "12"), + ("veggies", '["tomato", "potato", "aubergine"]'), + ("nested", '{"some_key": "some_value"}'), + ("calories", "122.53"), + ("healthy", "true"), + ("polluting", "false"), + ("json", "null"), + ] + ).encode() + + result = parse_url_encoded_dict(encoded, parse_numbers=True) + # result == { ... } diff --git a/pdm.lock b/pdm.lock index 2b176be..fc301b0 100644 --- a/pdm.lock +++ b/pdm.lock @@ -2,11 +2,181 @@ # It is not intended for manual editing. [metadata] -groups = ["default", "dev", "sourcery"] +groups = ["default", "dev", "sourcery", "docs"] cross_platform = true static_urls = false lock_version = "4.3" -content_hash = "sha256:622b838a8f2497013a3233e71c5b8840d1e394e5b5ed41291b69424a3d660251" +content_hash = "sha256:e9729ca0d23c75825e88725bcb8a01f794f0c08ed41885806fc82dda10519952" + +[[package]] +name = "alabaster" +version = "0.7.13" +requires_python = ">=3.6" +summary = "A configurable sidebar-enabled Sphinx theme" +files = [ + {file = "alabaster-0.7.13-py3-none-any.whl", hash = "sha256:1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3"}, + {file = "alabaster-0.7.13.tar.gz", hash = "sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2"}, +] + +[[package]] +name = "apeye" +version = "1.4.1" +requires_python = ">=3.6.1" +summary = "Handy tools for working with URLs and APIs." +dependencies = [ + "apeye-core>=1.0.0b2", + "domdf-python-tools>=2.6.0", + "platformdirs>=2.3.0", + "requests>=2.24.0", +] +files = [ + {file = "apeye-1.4.1-py3-none-any.whl", hash = "sha256:44e58a9104ec189bf42e76b3a7fe91e2b2879d96d48e9a77e5e32ff699c9204e"}, + {file = "apeye-1.4.1.tar.gz", hash = "sha256:14ea542fad689e3bfdbda2189a354a4908e90aee4bf84c15ab75d68453d76a36"}, +] + +[[package]] +name = "apeye-core" +version = "1.1.4" +requires_python = ">=3.6.1" +summary = "Core (offline) functionality for the apeye library." +dependencies = [ + "domdf-python-tools>=2.6.0", + "idna>=2.5", +] +files = [ + {file = "apeye_core-1.1.4-py3-none-any.whl", hash = "sha256:084bc696448d3ac428fece41c1f2eb08fa9d9ce1d1b2f4d43187e3def4528a60"}, + {file = "apeye_core-1.1.4.tar.gz", hash = "sha256:72bb89fed3baa647cb81aa28e1d851787edcbf9573853b5d2b5f87c02f50eaf5"}, +] + +[[package]] +name = "autodocsumm" +version = "0.2.11" +requires_python = ">=3.7" +summary = "Extended sphinx autodoc including automatic autosummaries" +dependencies = [ + "Sphinx<8.0,>=2.2", +] +files = [ + {file = "autodocsumm-0.2.11-py3-none-any.whl", hash = "sha256:f1d0a623bf1ad64d979a9e23fd360d1fb1b8f869beaf3197f711552cddc174e2"}, + {file = "autodocsumm-0.2.11.tar.gz", hash = "sha256:183212bd9e9f3b58a96bb21b7958ee4e06224107aa45b2fd894b61b83581b9a9"}, +] + +[[package]] +name = "babel" +version = "2.13.0" +requires_python = ">=3.7" +summary = "Internationalization utilities" +dependencies = [ + "pytz>=2015.7; python_version < \"3.9\"", +] +files = [ + {file = "Babel-2.13.0-py3-none-any.whl", hash = "sha256:fbfcae1575ff78e26c7449136f1abbefc3c13ce542eeb13d43d50d8b047216ec"}, + {file = "Babel-2.13.0.tar.gz", hash = "sha256:04c3e2d28d2b7681644508f836be388ae49e0cfe91465095340395b60d00f210"}, +] + +[[package]] +name = "beautifulsoup4" +version = "4.12.2" +requires_python = ">=3.6.0" +summary = "Screen-scraping library" +dependencies = [ + "soupsieve>1.2", +] +files = [ + {file = "beautifulsoup4-4.12.2-py3-none-any.whl", hash = "sha256:bd2520ca0d9d7d12694a53d44ac482d181b4ec1888909b035a3dbf40d0f57d4a"}, + {file = "beautifulsoup4-4.12.2.tar.gz", hash = "sha256:492bbc69dca35d12daac71c4db1bfff0c876c00ef4a2ffacce226d4638eb72da"}, +] + +[[package]] +name = "black" +version = "23.9.1" +requires_python = ">=3.8" +summary = "The uncompromising code formatter." +dependencies = [ + "click>=8.0.0", + "mypy-extensions>=0.4.3", + "packaging>=22.0", + "pathspec>=0.9.0", + "platformdirs>=2", + "tomli>=1.1.0; python_version < \"3.11\"", + "typing-extensions>=4.0.1; python_version < \"3.11\"", +] +files = [ + {file = "black-23.9.1-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:d6bc09188020c9ac2555a498949401ab35bb6bf76d4e0f8ee251694664df6301"}, + {file = "black-23.9.1-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:13ef033794029b85dfea8032c9d3b92b42b526f1ff4bf13b2182ce4e917f5100"}, + {file = "black-23.9.1-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:75a2dc41b183d4872d3a500d2b9c9016e67ed95738a3624f4751a0cb4818fe71"}, + {file = "black-23.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13a2e4a93bb8ca74a749b6974925c27219bb3df4d42fc45e948a5d9feb5122b7"}, + {file = "black-23.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:adc3e4442eef57f99b5590b245a328aad19c99552e0bdc7f0b04db6656debd80"}, + {file = "black-23.9.1-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:8431445bf62d2a914b541da7ab3e2b4f3bc052d2ccbf157ebad18ea126efb91f"}, + {file = "black-23.9.1-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:8fc1ddcf83f996247505db6b715294eba56ea9372e107fd54963c7553f2b6dfe"}, + {file = "black-23.9.1-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:7d30ec46de88091e4316b17ae58bbbfc12b2de05e069030f6b747dfc649ad186"}, + {file = "black-23.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:031e8c69f3d3b09e1aa471a926a1eeb0b9071f80b17689a655f7885ac9325a6f"}, + {file = "black-23.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:538efb451cd50f43aba394e9ec7ad55a37598faae3348d723b59ea8e91616300"}, + {file = "black-23.9.1-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:638619a559280de0c2aa4d76f504891c9860bb8fa214267358f0a20f27c12948"}, + {file = "black-23.9.1-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:a732b82747235e0542c03bf352c126052c0fbc458d8a239a94701175b17d4855"}, + {file = "black-23.9.1-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:cf3a4d00e4cdb6734b64bf23cd4341421e8953615cba6b3670453737a72ec204"}, + {file = "black-23.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf99f3de8b3273a8317681d8194ea222f10e0133a24a7548c73ce44ea1679377"}, + {file = "black-23.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:14f04c990259576acd093871e7e9b14918eb28f1866f91968ff5524293f9c573"}, + {file = "black-23.9.1-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:c619f063c2d68f19b2d7270f4cf3192cb81c9ec5bc5ba02df91471d0b88c4c5c"}, + {file = "black-23.9.1-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:6a3b50e4b93f43b34a9d3ef00d9b6728b4a722c997c99ab09102fd5efdb88325"}, + {file = "black-23.9.1-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:c46767e8df1b7beefb0899c4a95fb43058fa8500b6db144f4ff3ca38eb2f6393"}, + {file = "black-23.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50254ebfa56aa46a9fdd5d651f9637485068a1adf42270148cd101cdf56e0ad9"}, + {file = "black-23.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:403397c033adbc45c2bd41747da1f7fc7eaa44efbee256b53842470d4ac5a70f"}, + {file = "black-23.9.1-py3-none-any.whl", hash = "sha256:6ccd59584cc834b6d127628713e4b6b968e5f79572da66284532525a042549f9"}, + {file = "black-23.9.1.tar.gz", hash = "sha256:24b6b3ff5c6d9ea08a8888f6977eae858e1f340d7260cf56d70a49823236b62d"}, +] + +[[package]] +name = "blacken-docs" +version = "1.16.0" +requires_python = ">=3.8" +summary = "Run Black on Python code blocks in documentation files." +dependencies = [ + "black>=22.1.0", +] +files = [ + {file = "blacken_docs-1.16.0-py3-none-any.whl", hash = "sha256:b0dcb84b28ebfb352a2539202d396f50e15a54211e204a8005798f1d1edb7df8"}, + {file = "blacken_docs-1.16.0.tar.gz", hash = "sha256:b4bdc3f3d73898dfbf0166f292c6ccfe343e65fc22ddef5319c95d1a8dcc6c1c"}, +] + +[[package]] +name = "cachecontrol" +version = "0.13.1" +requires_python = ">=3.7" +summary = "httplib2 caching for requests" +dependencies = [ + "msgpack>=0.5.2", + "requests>=2.16.0", +] +files = [ + {file = "cachecontrol-0.13.1-py3-none-any.whl", hash = "sha256:95dedbec849f46dda3137866dc28b9d133fc9af55f5b805ab1291833e4457aa4"}, + {file = "cachecontrol-0.13.1.tar.gz", hash = "sha256:f012366b79d2243a6118309ce73151bf52a38d4a5dac8ea57f09bd29087e506b"}, +] + +[[package]] +name = "cachecontrol" +version = "0.13.1" +extras = ["filecache"] +requires_python = ">=3.7" +summary = "httplib2 caching for requests" +dependencies = [ + "cachecontrol==0.13.1", + "filelock>=3.8.0", +] +files = [ + {file = "cachecontrol-0.13.1-py3-none-any.whl", hash = "sha256:95dedbec849f46dda3137866dc28b9d133fc9af55f5b805ab1291833e4457aa4"}, + {file = "cachecontrol-0.13.1.tar.gz", hash = "sha256:f012366b79d2243a6118309ce73151bf52a38d4a5dac8ea57f09bd29087e506b"}, +] + +[[package]] +name = "certifi" +version = "2023.7.22" +requires_python = ">=3.6" +summary = "Python package for providing Mozilla's CA Bundle." +files = [ + {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, + {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, +] [[package]] name = "cfgv" @@ -18,6 +188,104 @@ files = [ {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, ] +[[package]] +name = "charset-normalizer" +version = "3.3.0" +requires_python = ">=3.7.0" +summary = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +files = [ + {file = "charset-normalizer-3.3.0.tar.gz", hash = "sha256:63563193aec44bce707e0c5ca64ff69fa72ed7cf34ce6e11d5127555756fd2f6"}, + {file = "charset_normalizer-3.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:effe5406c9bd748a871dbcaf3ac69167c38d72db8c9baf3ff954c344f31c4cbe"}, + {file = "charset_normalizer-3.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4162918ef3098851fcd8a628bf9b6a98d10c380725df9e04caf5ca6dd48c847a"}, + {file = "charset_normalizer-3.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0570d21da019941634a531444364f2482e8db0b3425fcd5ac0c36565a64142c8"}, + {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5707a746c6083a3a74b46b3a631d78d129edab06195a92a8ece755aac25a3f3d"}, + {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:278c296c6f96fa686d74eb449ea1697f3c03dc28b75f873b65b5201806346a69"}, + {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a4b71f4d1765639372a3b32d2638197f5cd5221b19531f9245fcc9ee62d38f56"}, + {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5969baeaea61c97efa706b9b107dcba02784b1601c74ac84f2a532ea079403e"}, + {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3f93dab657839dfa61025056606600a11d0b696d79386f974e459a3fbc568ec"}, + {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:db756e48f9c5c607b5e33dd36b1d5872d0422e960145b08ab0ec7fd420e9d649"}, + {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:232ac332403e37e4a03d209a3f92ed9071f7d3dbda70e2a5e9cff1c4ba9f0678"}, + {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e5c1502d4ace69a179305abb3f0bb6141cbe4714bc9b31d427329a95acfc8bdd"}, + {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:2502dd2a736c879c0f0d3e2161e74d9907231e25d35794584b1ca5284e43f596"}, + {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23e8565ab7ff33218530bc817922fae827420f143479b753104ab801145b1d5b"}, + {file = "charset_normalizer-3.3.0-cp310-cp310-win32.whl", hash = "sha256:1872d01ac8c618a8da634e232f24793883d6e456a66593135aeafe3784b0848d"}, + {file = "charset_normalizer-3.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:557b21a44ceac6c6b9773bc65aa1b4cc3e248a5ad2f5b914b91579a32e22204d"}, + {file = "charset_normalizer-3.3.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d7eff0f27edc5afa9e405f7165f85a6d782d308f3b6b9d96016c010597958e63"}, + {file = "charset_normalizer-3.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6a685067d05e46641d5d1623d7c7fdf15a357546cbb2f71b0ebde91b175ffc3e"}, + {file = "charset_normalizer-3.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0d3d5b7db9ed8a2b11a774db2bbea7ba1884430a205dbd54a32d61d7c2a190fa"}, + {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2935ffc78db9645cb2086c2f8f4cfd23d9b73cc0dc80334bc30aac6f03f68f8c"}, + {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fe359b2e3a7729010060fbca442ca225280c16e923b37db0e955ac2a2b72a05"}, + {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:380c4bde80bce25c6e4f77b19386f5ec9db230df9f2f2ac1e5ad7af2caa70459"}, + {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0d1e3732768fecb052d90d62b220af62ead5748ac51ef61e7b32c266cac9293"}, + {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1b2919306936ac6efb3aed1fbf81039f7087ddadb3160882a57ee2ff74fd2382"}, + {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f8888e31e3a85943743f8fc15e71536bda1c81d5aa36d014a3c0c44481d7db6e"}, + {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:82eb849f085624f6a607538ee7b83a6d8126df6d2f7d3b319cb837b289123078"}, + {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7b8b8bf1189b3ba9b8de5c8db4d541b406611a71a955bbbd7385bbc45fcb786c"}, + {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5adf257bd58c1b8632046bbe43ee38c04e1038e9d37de9c57a94d6bd6ce5da34"}, + {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c350354efb159b8767a6244c166f66e67506e06c8924ed74669b2c70bc8735b1"}, + {file = "charset_normalizer-3.3.0-cp311-cp311-win32.whl", hash = "sha256:02af06682e3590ab952599fbadac535ede5d60d78848e555aa58d0c0abbde786"}, + {file = "charset_normalizer-3.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:86d1f65ac145e2c9ed71d8ffb1905e9bba3a91ae29ba55b4c46ae6fc31d7c0d4"}, + {file = "charset_normalizer-3.3.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:3b447982ad46348c02cb90d230b75ac34e9886273df3a93eec0539308a6296d7"}, + {file = "charset_normalizer-3.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:abf0d9f45ea5fb95051c8bfe43cb40cda383772f7e5023a83cc481ca2604d74e"}, + {file = "charset_normalizer-3.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b09719a17a2301178fac4470d54b1680b18a5048b481cb8890e1ef820cb80455"}, + {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b3d9b48ee6e3967b7901c052b670c7dda6deb812c309439adaffdec55c6d7b78"}, + {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:edfe077ab09442d4ef3c52cb1f9dab89bff02f4524afc0acf2d46be17dc479f5"}, + {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3debd1150027933210c2fc321527c2299118aa929c2f5a0a80ab6953e3bd1908"}, + {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86f63face3a527284f7bb8a9d4f78988e3c06823f7bea2bd6f0e0e9298ca0403"}, + {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:24817cb02cbef7cd499f7c9a2735286b4782bd47a5b3516a0e84c50eab44b98e"}, + {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c71f16da1ed8949774ef79f4a0260d28b83b3a50c6576f8f4f0288d109777989"}, + {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:9cf3126b85822c4e53aa28c7ec9869b924d6fcfb76e77a45c44b83d91afd74f9"}, + {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:b3b2316b25644b23b54a6f6401074cebcecd1244c0b8e80111c9a3f1c8e83d65"}, + {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:03680bb39035fbcffe828eae9c3f8afc0428c91d38e7d61aa992ef7a59fb120e"}, + {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4cc152c5dd831641e995764f9f0b6589519f6f5123258ccaca8c6d34572fefa8"}, + {file = "charset_normalizer-3.3.0-cp312-cp312-win32.whl", hash = "sha256:b8f3307af845803fb0b060ab76cf6dd3a13adc15b6b451f54281d25911eb92df"}, + {file = "charset_normalizer-3.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:8eaf82f0eccd1505cf39a45a6bd0a8cf1c70dcfc30dba338207a969d91b965c0"}, + {file = "charset_normalizer-3.3.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:67b8cc9574bb518ec76dc8e705d4c39ae78bb96237cb533edac149352c1f39fe"}, + {file = "charset_normalizer-3.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ac71b2977fb90c35d41c9453116e283fac47bb9096ad917b8819ca8b943abecd"}, + {file = "charset_normalizer-3.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3ae38d325b512f63f8da31f826e6cb6c367336f95e418137286ba362925c877e"}, + {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:542da1178c1c6af8873e143910e2269add130a299c9106eef2594e15dae5e482"}, + {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:30a85aed0b864ac88309b7d94be09f6046c834ef60762a8833b660139cfbad13"}, + {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aae32c93e0f64469f74ccc730a7cb21c7610af3a775157e50bbd38f816536b38"}, + {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15b26ddf78d57f1d143bdf32e820fd8935d36abe8a25eb9ec0b5a71c82eb3895"}, + {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7f5d10bae5d78e4551b7be7a9b29643a95aded9d0f602aa2ba584f0388e7a557"}, + {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:249c6470a2b60935bafd1d1d13cd613f8cd8388d53461c67397ee6a0f5dce741"}, + {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c5a74c359b2d47d26cdbbc7845e9662d6b08a1e915eb015d044729e92e7050b7"}, + {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:b5bcf60a228acae568e9911f410f9d9e0d43197d030ae5799e20dca8df588287"}, + {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:187d18082694a29005ba2944c882344b6748d5be69e3a89bf3cc9d878e548d5a"}, + {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:81bf654678e575403736b85ba3a7867e31c2c30a69bc57fe88e3ace52fb17b89"}, + {file = "charset_normalizer-3.3.0-cp38-cp38-win32.whl", hash = "sha256:85a32721ddde63c9df9ebb0d2045b9691d9750cb139c161c80e500d210f5e26e"}, + {file = "charset_normalizer-3.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:468d2a840567b13a590e67dd276c570f8de00ed767ecc611994c301d0f8c014f"}, + {file = "charset_normalizer-3.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e0fc42822278451bc13a2e8626cf2218ba570f27856b536e00cfa53099724828"}, + {file = "charset_normalizer-3.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:09c77f964f351a7369cc343911e0df63e762e42bac24cd7d18525961c81754f4"}, + {file = "charset_normalizer-3.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:12ebea541c44fdc88ccb794a13fe861cc5e35d64ed689513a5c03d05b53b7c82"}, + {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:805dfea4ca10411a5296bcc75638017215a93ffb584c9e344731eef0dcfb026a"}, + {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:96c2b49eb6a72c0e4991d62406e365d87067ca14c1a729a870d22354e6f68115"}, + {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aaf7b34c5bc56b38c931a54f7952f1ff0ae77a2e82496583b247f7c969eb1479"}, + {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:619d1c96099be5823db34fe89e2582b336b5b074a7f47f819d6b3a57ff7bdb86"}, + {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a0ac5e7015a5920cfce654c06618ec40c33e12801711da6b4258af59a8eff00a"}, + {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:93aa7eef6ee71c629b51ef873991d6911b906d7312c6e8e99790c0f33c576f89"}, + {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7966951325782121e67c81299a031f4c115615e68046f79b85856b86ebffc4cd"}, + {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:02673e456dc5ab13659f85196c534dc596d4ef260e4d86e856c3b2773ce09843"}, + {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:c2af80fb58f0f24b3f3adcb9148e6203fa67dd3f61c4af146ecad033024dde43"}, + {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:153e7b6e724761741e0974fc4dcd406d35ba70b92bfe3fedcb497226c93b9da7"}, + {file = "charset_normalizer-3.3.0-cp39-cp39-win32.whl", hash = "sha256:d47ecf253780c90ee181d4d871cd655a789da937454045b17b5798da9393901a"}, + {file = "charset_normalizer-3.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:d97d85fa63f315a8bdaba2af9a6a686e0eceab77b3089af45133252618e70884"}, + {file = "charset_normalizer-3.3.0-py3-none-any.whl", hash = "sha256:e46cd37076971c1040fc8c41273a8b3e2c624ce4f2be3f5dfcb7a430c1d3acc2"}, +] + +[[package]] +name = "click" +version = "8.1.7" +requires_python = ">=3.7" +summary = "Composable command line interface toolkit" +dependencies = [ + "colorama; platform_system == \"Windows\"", +] +files = [ + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, +] + [[package]] name = "colorama" version = "0.4.6" @@ -28,6 +296,30 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +[[package]] +name = "cssutils" +version = "2.7.1" +requires_python = ">=3.7" +summary = "A CSS Cascading Style Sheets library for Python" +files = [ + {file = "cssutils-2.7.1-py3-none-any.whl", hash = "sha256:1e92e0d9dab2ec8af9f38d715393964ba533dc3beacab9b072511dfc241db775"}, + {file = "cssutils-2.7.1.tar.gz", hash = "sha256:340ecfd9835d21df8f98500f0dfcea0aee41cb4e19ecbc2cf94f0a6d36d7cb6c"}, +] + +[[package]] +name = "dict2css" +version = "0.3.0" +requires_python = ">=3.6" +summary = "A μ-library for constructing cascading style sheets from Python dictionaries." +dependencies = [ + "cssutils>=2.2.0", + "domdf-python-tools>=2.2.0", +] +files = [ + {file = "dict2css-0.3.0-py3-none-any.whl", hash = "sha256:ef934ce73a225fdd5f811b484fe9e2dd768f7ef14a89fc8f4eb5672597131d00"}, + {file = "dict2css-0.3.0.tar.gz", hash = "sha256:1e8b1bf580dca2083198f88a60ec88c878a8829d760dfe45483ef80fe2905117"}, +] + [[package]] name = "distlib" version = "0.3.7" @@ -37,6 +329,31 @@ files = [ {file = "distlib-0.3.7.tar.gz", hash = "sha256:9dafe54b34a028eafd95039d5e5d4851a13734540f1331060d31c9916e7147a8"}, ] +[[package]] +name = "docutils" +version = "0.18.1" +requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +summary = "Docutils -- Python Documentation Utilities" +files = [ + {file = "docutils-0.18.1-py2.py3-none-any.whl", hash = "sha256:23010f129180089fbcd3bc08cfefccb3b890b0050e1ca00c867036e9d161b98c"}, + {file = "docutils-0.18.1.tar.gz", hash = "sha256:679987caf361a7539d76e584cbeddc311e3aee937877c87346f31debc63e9d06"}, +] + +[[package]] +name = "domdf-python-tools" +version = "3.6.1" +requires_python = ">=3.6" +summary = "Helpful functions for Python 🐍 🛠️" +dependencies = [ + "importlib-metadata>=3.6.0; python_version < \"3.9\"", + "natsort>=7.0.1", + "typing-extensions>=3.7.4.1", +] +files = [ + {file = "domdf_python_tools-3.6.1-py3-none-any.whl", hash = "sha256:e18158460850957f18e740eb94ede56f580ddb0cb162ab9d9834ed8bbb1b6431"}, + {file = "domdf_python_tools-3.6.1.tar.gz", hash = "sha256:acc04563d23bce4d437dd08af6b9bea788328c412772a044d8ca428a7ad861be"}, +] + [[package]] name = "exceptiongroup" version = "1.1.3" @@ -57,6 +374,20 @@ files = [ {file = "filelock-3.12.4.tar.gz", hash = "sha256:2e6f249f1f3654291606e046b09f1fd5eac39b360664c27f5aad072012f8bcbd"}, ] +[[package]] +name = "html5lib" +version = "1.1" +requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +summary = "HTML parser based on the WHATWG HTML specification" +dependencies = [ + "six>=1.9", + "webencodings", +] +files = [ + {file = "html5lib-1.1-py2.py3-none-any.whl", hash = "sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d"}, + {file = "html5lib-1.1.tar.gz", hash = "sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f"}, +] + [[package]] name = "identify" version = "2.5.30" @@ -67,6 +398,39 @@ files = [ {file = "identify-2.5.30.tar.gz", hash = "sha256:f302a4256a15c849b91cfcdcec052a8ce914634b2f77ae87dad29cd749f2d88d"}, ] +[[package]] +name = "idna" +version = "3.4" +requires_python = ">=3.5" +summary = "Internationalized Domain Names in Applications (IDNA)" +files = [ + {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, + {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, +] + +[[package]] +name = "imagesize" +version = "1.4.1" +requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +summary = "Getting image size from png/jpeg/jpeg2000/gif file" +files = [ + {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"}, + {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, +] + +[[package]] +name = "importlib-metadata" +version = "6.8.0" +requires_python = ">=3.8" +summary = "Read metadata from Python packages" +dependencies = [ + "zipp>=0.5", +] +files = [ + {file = "importlib_metadata-6.8.0-py3-none-any.whl", hash = "sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb"}, + {file = "importlib_metadata-6.8.0.tar.gz", hash = "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743"}, +] + [[package]] name = "iniconfig" version = "2.0.0" @@ -77,6 +441,104 @@ files = [ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] +[[package]] +name = "jinja2" +version = "3.1.2" +requires_python = ">=3.7" +summary = "A very fast and expressive template engine." +dependencies = [ + "MarkupSafe>=2.0", +] +files = [ + {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, + {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, +] + +[[package]] +name = "livereload" +version = "2.6.3" +summary = "Python LiveReload is an awesome tool for web developers" +dependencies = [ + "six", + "tornado; python_version > \"2.7\"", +] +files = [ + {file = "livereload-2.6.3-py2.py3-none-any.whl", hash = "sha256:ad4ac6f53b2d62bb6ce1a5e6e96f1f00976a32348afedcb4b6d68df2a1d346e4"}, + {file = "livereload-2.6.3.tar.gz", hash = "sha256:776f2f865e59fde56490a56bcc6773b6917366bce0c267c60ee8aaf1a0959869"}, +] + +[[package]] +name = "markdown-it-py" +version = "3.0.0" +requires_python = ">=3.8" +summary = "Python port of markdown-it. Markdown parsing, done right!" +dependencies = [ + "mdurl~=0.1", +] +files = [ + {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, + {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, +] + +[[package]] +name = "markupsafe" +version = "2.1.3" +requires_python = ">=3.7" +summary = "Safely add untrusted strings to HTML/XML markup." +files = [ + {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"}, + {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"}, +] + [[package]] name = "maturin" version = "1.3.0" @@ -101,6 +563,131 @@ files = [ {file = "maturin-1.3.0.tar.gz", hash = "sha256:f6c69bc7ae147a5effd55587447b35cab1ceb726ba244d08698bc7518b8688ac"}, ] +[[package]] +name = "mdit-py-plugins" +version = "0.4.0" +requires_python = ">=3.8" +summary = "Collection of plugins for markdown-it-py" +dependencies = [ + "markdown-it-py<4.0.0,>=1.0.0", +] +files = [ + {file = "mdit_py_plugins-0.4.0-py3-none-any.whl", hash = "sha256:b51b3bb70691f57f974e257e367107857a93b36f322a9e6d44ca5bf28ec2def9"}, + {file = "mdit_py_plugins-0.4.0.tar.gz", hash = "sha256:d8ab27e9aed6c38aa716819fedfde15ca275715955f8a185a8e1cf90fb1d2c1b"}, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +requires_python = ">=3.7" +summary = "Markdown URL utilities" +files = [ + {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, + {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, +] + +[[package]] +name = "msgpack" +version = "1.0.7" +requires_python = ">=3.8" +summary = "MessagePack serializer" +files = [ + {file = "msgpack-1.0.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:04ad6069c86e531682f9e1e71b71c1c3937d6014a7c3e9edd2aa81ad58842862"}, + {file = "msgpack-1.0.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cca1b62fe70d761a282496b96a5e51c44c213e410a964bdffe0928e611368329"}, + {file = "msgpack-1.0.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e50ebce52f41370707f1e21a59514e3375e3edd6e1832f5e5235237db933c98b"}, + {file = "msgpack-1.0.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a7b4f35de6a304b5533c238bee86b670b75b03d31b7797929caa7a624b5dda6"}, + {file = "msgpack-1.0.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28efb066cde83c479dfe5a48141a53bc7e5f13f785b92ddde336c716663039ee"}, + {file = "msgpack-1.0.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4cb14ce54d9b857be9591ac364cb08dc2d6a5c4318c1182cb1d02274029d590d"}, + {file = "msgpack-1.0.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b573a43ef7c368ba4ea06050a957c2a7550f729c31f11dd616d2ac4aba99888d"}, + {file = "msgpack-1.0.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ccf9a39706b604d884d2cb1e27fe973bc55f2890c52f38df742bc1d79ab9f5e1"}, + {file = "msgpack-1.0.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cb70766519500281815dfd7a87d3a178acf7ce95390544b8c90587d76b227681"}, + {file = "msgpack-1.0.7-cp310-cp310-win32.whl", hash = "sha256:b610ff0f24e9f11c9ae653c67ff8cc03c075131401b3e5ef4b82570d1728f8a9"}, + {file = "msgpack-1.0.7-cp310-cp310-win_amd64.whl", hash = "sha256:a40821a89dc373d6427e2b44b572efc36a2778d3f543299e2f24eb1a5de65415"}, + {file = "msgpack-1.0.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:576eb384292b139821c41995523654ad82d1916da6a60cff129c715a6223ea84"}, + {file = "msgpack-1.0.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:730076207cb816138cf1af7f7237b208340a2c5e749707457d70705715c93b93"}, + {file = "msgpack-1.0.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:85765fdf4b27eb5086f05ac0491090fc76f4f2b28e09d9350c31aac25a5aaff8"}, + {file = "msgpack-1.0.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3476fae43db72bd11f29a5147ae2f3cb22e2f1a91d575ef130d2bf49afd21c46"}, + {file = "msgpack-1.0.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d4c80667de2e36970ebf74f42d1088cc9ee7ef5f4e8c35eee1b40eafd33ca5b"}, + {file = "msgpack-1.0.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b0bf0effb196ed76b7ad883848143427a73c355ae8e569fa538365064188b8e"}, + {file = "msgpack-1.0.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f9a7c509542db4eceed3dcf21ee5267ab565a83555c9b88a8109dcecc4709002"}, + {file = "msgpack-1.0.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:84b0daf226913133f899ea9b30618722d45feffa67e4fe867b0b5ae83a34060c"}, + {file = "msgpack-1.0.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ec79ff6159dffcc30853b2ad612ed572af86c92b5168aa3fc01a67b0fa40665e"}, + {file = "msgpack-1.0.7-cp311-cp311-win32.whl", hash = "sha256:3e7bf4442b310ff154b7bb9d81eb2c016b7d597e364f97d72b1acc3817a0fdc1"}, + {file = "msgpack-1.0.7-cp311-cp311-win_amd64.whl", hash = "sha256:3f0c8c6dfa6605ab8ff0611995ee30d4f9fcff89966cf562733b4008a3d60d82"}, + {file = "msgpack-1.0.7-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f0936e08e0003f66bfd97e74ee530427707297b0d0361247e9b4f59ab78ddc8b"}, + {file = "msgpack-1.0.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:98bbd754a422a0b123c66a4c341de0474cad4a5c10c164ceed6ea090f3563db4"}, + {file = "msgpack-1.0.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b291f0ee7961a597cbbcc77709374087fa2a9afe7bdb6a40dbbd9b127e79afee"}, + {file = "msgpack-1.0.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebbbba226f0a108a7366bf4b59bf0f30a12fd5e75100c630267d94d7f0ad20e5"}, + {file = "msgpack-1.0.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e2d69948e4132813b8d1131f29f9101bc2c915f26089a6d632001a5c1349672"}, + {file = "msgpack-1.0.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bdf38ba2d393c7911ae989c3bbba510ebbcdf4ecbdbfec36272abe350c454075"}, + {file = "msgpack-1.0.7-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:993584fc821c58d5993521bfdcd31a4adf025c7d745bbd4d12ccfecf695af5ba"}, + {file = "msgpack-1.0.7-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:52700dc63a4676669b341ba33520f4d6e43d3ca58d422e22ba66d1736b0a6e4c"}, + {file = "msgpack-1.0.7-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e45ae4927759289c30ccba8d9fdce62bb414977ba158286b5ddaf8df2cddb5c5"}, + {file = "msgpack-1.0.7-cp312-cp312-win32.whl", hash = "sha256:27dcd6f46a21c18fa5e5deed92a43d4554e3df8d8ca5a47bf0615d6a5f39dbc9"}, + {file = "msgpack-1.0.7-cp312-cp312-win_amd64.whl", hash = "sha256:7687e22a31e976a0e7fc99c2f4d11ca45eff652a81eb8c8085e9609298916dcf"}, + {file = "msgpack-1.0.7-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5b6ccc0c85916998d788b295765ea0e9cb9aac7e4a8ed71d12e7d8ac31c23c95"}, + {file = "msgpack-1.0.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:235a31ec7db685f5c82233bddf9858748b89b8119bf4538d514536c485c15fe0"}, + {file = "msgpack-1.0.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cab3db8bab4b7e635c1c97270d7a4b2a90c070b33cbc00c99ef3f9be03d3e1f7"}, + {file = "msgpack-1.0.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bfdd914e55e0d2c9e1526de210f6fe8ffe9705f2b1dfcc4aecc92a4cb4b533d"}, + {file = "msgpack-1.0.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36e17c4592231a7dbd2ed09027823ab295d2791b3b1efb2aee874b10548b7524"}, + {file = "msgpack-1.0.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38949d30b11ae5f95c3c91917ee7a6b239f5ec276f271f28638dec9156f82cfc"}, + {file = "msgpack-1.0.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ff1d0899f104f3921d94579a5638847f783c9b04f2d5f229392ca77fba5b82fc"}, + {file = "msgpack-1.0.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:dc43f1ec66eb8440567186ae2f8c447d91e0372d793dfe8c222aec857b81a8cf"}, + {file = "msgpack-1.0.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:dd632777ff3beaaf629f1ab4396caf7ba0bdd075d948a69460d13d44357aca4c"}, + {file = "msgpack-1.0.7-cp38-cp38-win32.whl", hash = "sha256:4e71bc4416de195d6e9b4ee93ad3f2f6b2ce11d042b4d7a7ee00bbe0358bd0c2"}, + {file = "msgpack-1.0.7-cp38-cp38-win_amd64.whl", hash = "sha256:8f5b234f567cf76ee489502ceb7165c2a5cecec081db2b37e35332b537f8157c"}, + {file = "msgpack-1.0.7-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bfef2bb6ef068827bbd021017a107194956918ab43ce4d6dc945ffa13efbc25f"}, + {file = "msgpack-1.0.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:484ae3240666ad34cfa31eea7b8c6cd2f1fdaae21d73ce2974211df099a95d81"}, + {file = "msgpack-1.0.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3967e4ad1aa9da62fd53e346ed17d7b2e922cba5ab93bdd46febcac39be636fc"}, + {file = "msgpack-1.0.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8dd178c4c80706546702c59529ffc005681bd6dc2ea234c450661b205445a34d"}, + {file = "msgpack-1.0.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6ffbc252eb0d229aeb2f9ad051200668fc3a9aaa8994e49f0cb2ffe2b7867e7"}, + {file = "msgpack-1.0.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:822ea70dc4018c7e6223f13affd1c5c30c0f5c12ac1f96cd8e9949acddb48a61"}, + {file = "msgpack-1.0.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:384d779f0d6f1b110eae74cb0659d9aa6ff35aaf547b3955abf2ab4c901c4819"}, + {file = "msgpack-1.0.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f64e376cd20d3f030190e8c32e1c64582eba56ac6dc7d5b0b49a9d44021b52fd"}, + {file = "msgpack-1.0.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5ed82f5a7af3697b1c4786053736f24a0efd0a1b8a130d4c7bfee4b9ded0f08f"}, + {file = "msgpack-1.0.7-cp39-cp39-win32.whl", hash = "sha256:f26a07a6e877c76a88e3cecac8531908d980d3d5067ff69213653649ec0f60ad"}, + {file = "msgpack-1.0.7-cp39-cp39-win_amd64.whl", hash = "sha256:1dc93e8e4653bdb5910aed79f11e165c85732067614f180f70534f056da97db3"}, + {file = "msgpack-1.0.7.tar.gz", hash = "sha256:572efc93db7a4d27e404501975ca6d2d9775705c2d922390d878fcf768d92c87"}, +] + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +requires_python = ">=3.5" +summary = "Type system extensions for programs checked with the mypy type checker." +files = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] + +[[package]] +name = "myst-parser" +version = "2.0.0" +requires_python = ">=3.8" +summary = "An extended [CommonMark](https://spec.commonmark.org/) compliant parser," +dependencies = [ + "docutils<0.21,>=0.16", + "jinja2", + "markdown-it-py~=3.0", + "mdit-py-plugins~=0.4", + "pyyaml", + "sphinx<8,>=6", +] +files = [ + {file = "myst_parser-2.0.0-py3-none-any.whl", hash = "sha256:7c36344ae39c8e740dad7fdabf5aa6fc4897a813083c6cc9990044eb93656b14"}, + {file = "myst_parser-2.0.0.tar.gz", hash = "sha256:ea929a67a6a0b1683cdbe19b8d2e724cd7643f8aa3e7bb18dd65beac3483bead"}, +] + +[[package]] +name = "natsort" +version = "8.4.0" +requires_python = ">=3.7" +summary = "Simple yet flexible natural sorting in Python." +files = [ + {file = "natsort-8.4.0-py3-none-any.whl", hash = "sha256:4732914fb471f56b5cce04d7bae6f164a592c7712e1c85f9ef585e197299521c"}, + {file = "natsort-8.4.0.tar.gz", hash = "sha256:45312c4a0e5507593da193dedd04abb1469253b601ecaf63445ad80f0a1ea581"}, +] + [[package]] name = "nodeenv" version = "1.8.0" @@ -124,6 +711,16 @@ files = [ {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, ] +[[package]] +name = "pathspec" +version = "0.11.2" +requires_python = ">=3.7" +summary = "Utility library for gitignore style pattern matching of file paths." +files = [ + {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"}, + {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, +] + [[package]] name = "pip" version = "23.2.1" @@ -186,6 +783,16 @@ files = [ {file = "psutil-5.9.5.tar.gz", hash = "sha256:5410638e4df39c54d957fc51ce03048acd8e6d60abc0f5107af51e5fb566eb3c"}, ] +[[package]] +name = "pygments" +version = "2.16.1" +requires_python = ">=3.7" +summary = "Pygments is a syntax highlighting package written in Python." +files = [ + {file = "Pygments-2.16.1-py3-none-any.whl", hash = "sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692"}, + {file = "Pygments-2.16.1.tar.gz", hash = "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29"}, +] + [[package]] name = "pyperf" version = "2.6.1" @@ -217,6 +824,15 @@ files = [ {file = "pytest-7.4.2.tar.gz", hash = "sha256:a766259cfab564a2ad52cb1aae1b881a75c3eb7e34ca3779697c23ed47c47069"}, ] +[[package]] +name = "pytz" +version = "2023.3.post1" +summary = "World timezone definitions, modern and historical" +files = [ + {file = "pytz-2023.3.post1-py2.py3-none-any.whl", hash = "sha256:ce42d816b81b68506614c11e8937d3aa9e41007ceb50bfdcb0749b921bf646c7"}, + {file = "pytz-2023.3.post1.tar.gz", hash = "sha256:7b4fddbeb94a1eba4b557da24f19fdf9db575192544270a9101d8509f9f43d7b"}, +] + [[package]] name = "pyyaml" version = "6.0.1" @@ -263,6 +879,67 @@ files = [ {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, ] +[[package]] +name = "requests" +version = "2.31.0" +requires_python = ">=3.7" +summary = "Python HTTP for Humans." +dependencies = [ + "certifi>=2017.4.17", + "charset-normalizer<4,>=2", + "idna<4,>=2.5", + "urllib3<3,>=1.21.1", +] +files = [ + {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, + {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, +] + +[[package]] +name = "ruamel-yaml" +version = "0.17.35" +requires_python = ">=3" +summary = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" +dependencies = [ + "ruamel-yaml-clib>=0.2.7; platform_python_implementation == \"CPython\" and python_version < \"3.13\"", +] +files = [ + {file = "ruamel.yaml-0.17.35-py3-none-any.whl", hash = "sha256:b105e3e6fc15b41fdb201ba1b95162ae566a4ef792b9f884c46b4ccc5513a87a"}, + {file = "ruamel.yaml-0.17.35.tar.gz", hash = "sha256:801046a9caacb1b43acc118969b49b96b65e8847f29029563b29ac61d02db61b"}, +] + +[[package]] +name = "ruamel-yaml-clib" +version = "0.2.8" +requires_python = ">=3.6" +summary = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" +files = [ + {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b42169467c42b692c19cf539c38d4602069d8c1505e97b86387fcf7afb766e1d"}, + {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:07238db9cbdf8fc1e9de2489a4f68474e70dffcb32232db7c08fa61ca0c7c462"}, + {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:fff3573c2db359f091e1589c3d7c5fc2f86f5bdb6f24252c2d8e539d4e45f412"}, + {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-win32.whl", hash = "sha256:c69212f63169ec1cfc9bb44723bf2917cbbd8f6191a00ef3410f5a7fe300722d"}, + {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-win_amd64.whl", hash = "sha256:cabddb8d8ead485e255fe80429f833172b4cadf99274db39abc080e068cbcc31"}, + {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:bef08cd86169d9eafb3ccb0a39edb11d8e25f3dae2b28f5c52fd997521133069"}, + {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:b16420e621d26fdfa949a8b4b47ade8810c56002f5389970db4ddda51dbff248"}, + {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:25c515e350e5b739842fc3228d662413ef28f295791af5e5110b543cf0b57d9b"}, + {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-win32.whl", hash = "sha256:53a300ed9cea38cf5a2a9b069058137c2ca1ce658a874b79baceb8f892f915a7"}, + {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-win_amd64.whl", hash = "sha256:c2a72e9109ea74e511e29032f3b670835f8a59bbdc9ce692c5b4ed91ccf1eedb"}, + {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:ebc06178e8821efc9692ea7544aa5644217358490145629914d8020042c24aa1"}, + {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_13_0_arm64.whl", hash = "sha256:edaef1c1200c4b4cb914583150dcaa3bc30e592e907c01117c08b13a07255ec2"}, + {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d176b57452ab5b7028ac47e7b3cf644bcfdc8cacfecf7e71759f7f51a59e5c92"}, + {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1b617618914cb00bf5c34d4357c37aa15183fa229b24767259657746c9077615"}, + {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:a6a9ffd280b71ad062eae53ac1659ad86a17f59a0fdc7699fd9be40525153337"}, + {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:700e4ebb569e59e16a976857c8798aee258dceac7c7d6b50cab63e080058df91"}, + {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-win32.whl", hash = "sha256:955eae71ac26c1ab35924203fda6220f84dce57d6d7884f189743e2abe3a9fbe"}, + {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-win_amd64.whl", hash = "sha256:56f4252222c067b4ce51ae12cbac231bce32aee1d33fbfc9d17e5b8d6966c312"}, + {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:03d1162b6d1df1caa3a4bd27aa51ce17c9afc2046c31b0ad60a0a96ec22f8001"}, + {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:bba64af9fa9cebe325a62fa398760f5c7206b215201b0ec825005f1b18b9bccf"}, + {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:da09ad1c359a728e112d60116f626cc9f29730ff3e0e7db72b9a2dbc2e4beed5"}, + {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-win32.whl", hash = "sha256:84b554931e932c46f94ab306913ad7e11bba988104c5cff26d90d03f68258cd5"}, + {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-win_amd64.whl", hash = "sha256:25ac8c08322002b06fa1d49d1646181f0b2c72f5cbc15a85e80b4c30a544bb15"}, + {file = "ruamel.yaml.clib-0.2.8.tar.gz", hash = "sha256:beb2e0404003de9a4cab9753a8805a8fe9320ee6673136ed7f04255fe60bb512"}, +] + [[package]] name = "ruff" version = "0.0.292" @@ -298,6 +975,48 @@ files = [ {file = "setuptools-68.2.2.tar.gz", hash = "sha256:4ac1475276d2f1c48684874089fefcd83bd7162ddaafb81fac866ba0db282a87"}, ] +[[package]] +name = "shibuya" +version = "2023.10.5" +requires_python = ">=3.7" +summary = "A clean, responsive, and customizable Sphinx documentation theme with light/dark mode." +dependencies = [ + "Sphinx", +] +files = [ + {file = "shibuya-2023.10.5-py3-none-any.whl", hash = "sha256:609617862c99953db84e6aad89b319dfa43cc9e95dd2e8d678d0eb5aba7d5cfb"}, + {file = "shibuya-2023.10.5.tar.gz", hash = "sha256:9cff5496585763ee95478f380a54e0bc8af96d121954bcfde2282bdc0654213f"}, +] + +[[package]] +name = "six" +version = "1.16.0" +requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +summary = "Python 2 and 3 compatibility utilities" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + +[[package]] +name = "snowballstemmer" +version = "2.2.0" +summary = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." +files = [ + {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, + {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, +] + +[[package]] +name = "soupsieve" +version = "2.5" +requires_python = ">=3.8" +summary = "A modern CSS selector implementation for Beautiful Soup." +files = [ + {file = "soupsieve-2.5-py3-none-any.whl", hash = "sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7"}, + {file = "soupsieve-2.5.tar.gz", hash = "sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690"}, +] + [[package]] name = "sourcery" version = "1.10.1" @@ -308,6 +1027,226 @@ files = [ {file = "sourcery-1.10.1-py2.py3-none-win_amd64.whl", hash = "sha256:c5adfd268dcff47c155e8765d78a71de8eef9331281ab127eae28d9581b1e775"}, ] +[[package]] +name = "sphinx" +version = "7.1.2" +requires_python = ">=3.8" +summary = "Python documentation generator" +dependencies = [ + "Jinja2>=3.0", + "Pygments>=2.13", + "alabaster<0.8,>=0.7", + "babel>=2.9", + "colorama>=0.4.5; sys_platform == \"win32\"", + "docutils<0.21,>=0.18.1", + "imagesize>=1.3", + "importlib-metadata>=4.8; python_version < \"3.10\"", + "packaging>=21.0", + "requests>=2.25.0", + "snowballstemmer>=2.0", + "sphinxcontrib-applehelp", + "sphinxcontrib-devhelp", + "sphinxcontrib-htmlhelp>=2.0.0", + "sphinxcontrib-jsmath", + "sphinxcontrib-qthelp", + "sphinxcontrib-serializinghtml>=1.1.5", +] +files = [ + {file = "sphinx-7.1.2-py3-none-any.whl", hash = "sha256:d170a81825b2fcacb6dfd5a0d7f578a053e45d3f2b153fecc948c37344eb4cbe"}, + {file = "sphinx-7.1.2.tar.gz", hash = "sha256:780f4d32f1d7d1126576e0e5ecc19dc32ab76cd24e950228dcf7b1f6d3d9e22f"}, +] + +[[package]] +name = "sphinx-autobuild" +version = "2021.3.14" +requires_python = ">=3.6" +summary = "Rebuild Sphinx documentation on changes, with live-reload in the browser." +dependencies = [ + "colorama", + "livereload", + "sphinx", +] +files = [ + {file = "sphinx-autobuild-2021.3.14.tar.gz", hash = "sha256:de1ca3b66e271d2b5b5140c35034c89e47f263f2cd5db302c9217065f7443f05"}, + {file = "sphinx_autobuild-2021.3.14-py3-none-any.whl", hash = "sha256:8fe8cbfdb75db04475232f05187c776f46f6e9e04cacf1e49ce81bdac649ccac"}, +] + +[[package]] +name = "sphinx-autodoc-typehints" +version = "1.24.0" +requires_python = ">=3.8" +summary = "Type hints (PEP 484) support for the Sphinx autodoc extension" +dependencies = [ + "sphinx>=7.0.1", +] +files = [ + {file = "sphinx_autodoc_typehints-1.24.0-py3-none-any.whl", hash = "sha256:6a73c0c61a9144ce2ed5ef2bed99d615254e5005c1cc32002017d72d69fb70e6"}, + {file = "sphinx_autodoc_typehints-1.24.0.tar.gz", hash = "sha256:94e440066941bb237704bb880785e2d05e8ae5406c88674feefbb938ad0dc6af"}, +] + +[[package]] +name = "sphinx-design" +version = "0.5.0" +requires_python = ">=3.8" +summary = "A sphinx extension for designing beautiful, view size responsive web components." +dependencies = [ + "sphinx<8,>=5", +] +files = [ + {file = "sphinx_design-0.5.0-py3-none-any.whl", hash = "sha256:1af1267b4cea2eedd6724614f19dcc88fe2e15aff65d06b2f6252cee9c4f4c1e"}, + {file = "sphinx_design-0.5.0.tar.gz", hash = "sha256:e8e513acea6f92d15c6de3b34e954458f245b8e761b45b63950f65373352ab00"}, +] + +[[package]] +name = "sphinx-jinja2-compat" +version = "0.2.0" +requires_python = ">=3.6" +summary = "Patches Jinja2 v3 to restore compatibility with earlier Sphinx versions." +dependencies = [ + "jinja2>=2.10", + "markupsafe>=1", +] +files = [ + {file = "sphinx_jinja2_compat-0.2.0-py3-none-any.whl", hash = "sha256:a5f3112d6873991c2cf28e37287163a0485d9c0812863b8aa4df7182722501fb"}, + {file = "sphinx_jinja2_compat-0.2.0.tar.gz", hash = "sha256:c41346d859653e202b623f4236da8936243ed734abf5984adc3bef59d6f9a946"}, +] + +[[package]] +name = "sphinx-prompt" +version = "1.5.0" +summary = "Sphinx directive to add unselectable prompt" +dependencies = [ + "Sphinx", + "pygments", +] +files = [ + {file = "sphinx_prompt-1.5.0-py3-none-any.whl", hash = "sha256:fa4e90d8088b5a996c76087d701fc7e31175f8b9dc4aab03a507e45051067162"}, +] + +[[package]] +name = "sphinx-tabs" +version = "3.4.1" +requires_python = "~=3.7" +summary = "Tabbed views for Sphinx" +dependencies = [ + "docutils~=0.18.0", + "pygments", + "sphinx", +] +files = [ + {file = "sphinx-tabs-3.4.1.tar.gz", hash = "sha256:d2a09f9e8316e400d57503f6df1c78005fdde220e5af589cc79d493159e1b832"}, + {file = "sphinx_tabs-3.4.1-py3-none-any.whl", hash = "sha256:7cea8942aeccc5d01a995789c01804b787334b55927f29b36ba16ed1e7cb27c6"}, +] + +[[package]] +name = "sphinx-toolbox" +version = "3.5.0" +requires_python = ">=3.7" +summary = "Box of handy tools for Sphinx 🧰 📔" +dependencies = [ + "apeye>=0.4.0", + "autodocsumm>=0.2.0", + "beautifulsoup4>=4.9.1", + "cachecontrol[filecache]>=0.13.0", + "dict2css>=0.2.3", + "docutils>=0.16", + "domdf-python-tools>=2.9.0", + "filelock>=3.8.0", + "html5lib>=1.1", + "ruamel-yaml>=0.16.12", + "sphinx-autodoc-typehints>=1.11.1", + "sphinx-jinja2-compat>=0.1.0", + "sphinx-prompt>=1.1.0", + "sphinx-tabs<3.5.0,>=1.2.1", + "sphinx>=3.2.0", + "tabulate>=0.8.7", + "typing-extensions!=3.10.0.1,>=3.7.4.3", +] +files = [ + {file = "sphinx_toolbox-3.5.0-py3-none-any.whl", hash = "sha256:20dfd3566717db6f2da7a400a54dc4b946f064fb31250fa44802d54cfb9b8a03"}, + {file = "sphinx_toolbox-3.5.0.tar.gz", hash = "sha256:e5b5a7153f1997572d71a06aaf6cec225483492ec2c60097a84f15aad6df18b7"}, +] + +[[package]] +name = "sphinxcontrib-applehelp" +version = "1.0.4" +requires_python = ">=3.8" +summary = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" +files = [ + {file = "sphinxcontrib-applehelp-1.0.4.tar.gz", hash = "sha256:828f867945bbe39817c210a1abfd1bc4895c8b73fcaade56d45357a348a07d7e"}, + {file = "sphinxcontrib_applehelp-1.0.4-py3-none-any.whl", hash = "sha256:29d341f67fb0f6f586b23ad80e072c8e6ad0b48417db2bde114a4c9746feb228"}, +] + +[[package]] +name = "sphinxcontrib-devhelp" +version = "1.0.2" +requires_python = ">=3.5" +summary = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." +files = [ + {file = "sphinxcontrib-devhelp-1.0.2.tar.gz", hash = "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"}, + {file = "sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e"}, +] + +[[package]] +name = "sphinxcontrib-htmlhelp" +version = "2.0.1" +requires_python = ">=3.8" +summary = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" +files = [ + {file = "sphinxcontrib-htmlhelp-2.0.1.tar.gz", hash = "sha256:0cbdd302815330058422b98a113195c9249825d681e18f11e8b1f78a2f11efff"}, + {file = "sphinxcontrib_htmlhelp-2.0.1-py3-none-any.whl", hash = "sha256:c38cb46dccf316c79de6e5515e1770414b797162b23cd3d06e67020e1d2a6903"}, +] + +[[package]] +name = "sphinxcontrib-jsmath" +version = "1.0.1" +requires_python = ">=3.5" +summary = "A sphinx extension which renders display math in HTML via JavaScript" +files = [ + {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, + {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, +] + +[[package]] +name = "sphinxcontrib-mermaid" +version = "0.9.2" +requires_python = ">=3.7" +summary = "Mermaid diagrams in yours Sphinx powered docs" +files = [ + {file = "sphinxcontrib-mermaid-0.9.2.tar.gz", hash = "sha256:252ef13dd23164b28f16d8b0205cf184b9d8e2b714a302274d9f59eb708e77af"}, + {file = "sphinxcontrib_mermaid-0.9.2-py3-none-any.whl", hash = "sha256:6795a72037ca55e65663d2a2c1a043d636dc3d30d418e56dd6087d1459d98a5d"}, +] + +[[package]] +name = "sphinxcontrib-qthelp" +version = "1.0.3" +requires_python = ">=3.5" +summary = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." +files = [ + {file = "sphinxcontrib-qthelp-1.0.3.tar.gz", hash = "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72"}, + {file = "sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"}, +] + +[[package]] +name = "sphinxcontrib-serializinghtml" +version = "1.1.5" +requires_python = ">=3.5" +summary = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." +files = [ + {file = "sphinxcontrib-serializinghtml-1.1.5.tar.gz", hash = "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"}, + {file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"}, +] + +[[package]] +name = "tabulate" +version = "0.9.0" +requires_python = ">=3.7" +summary = "Pretty-print tabular data" +files = [ + {file = "tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f"}, + {file = "tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c"}, +] + [[package]] name = "tomli" version = "2.0.1" @@ -318,6 +1257,45 @@ files = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] +[[package]] +name = "tornado" +version = "6.3.3" +requires_python = ">= 3.8" +summary = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." +files = [ + {file = "tornado-6.3.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:502fba735c84450974fec147340016ad928d29f1e91f49be168c0a4c18181e1d"}, + {file = "tornado-6.3.3-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:805d507b1f588320c26f7f097108eb4023bbaa984d63176d1652e184ba24270a"}, + {file = "tornado-6.3.3-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bd19ca6c16882e4d37368e0152f99c099bad93e0950ce55e71daed74045908f"}, + {file = "tornado-6.3.3-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ac51f42808cca9b3613f51ffe2a965c8525cb1b00b7b2d56828b8045354f76a"}, + {file = "tornado-6.3.3-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:71a8db65160a3c55d61839b7302a9a400074c9c753040455494e2af74e2501f2"}, + {file = "tornado-6.3.3-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:ceb917a50cd35882b57600709dd5421a418c29ddc852da8bcdab1f0db33406b0"}, + {file = "tornado-6.3.3-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:7d01abc57ea0dbb51ddfed477dfe22719d376119844e33c661d873bf9c0e4a16"}, + {file = "tornado-6.3.3-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:9dc4444c0defcd3929d5c1eb5706cbe1b116e762ff3e0deca8b715d14bf6ec17"}, + {file = "tornado-6.3.3-cp38-abi3-win32.whl", hash = "sha256:65ceca9500383fbdf33a98c0087cb975b2ef3bfb874cb35b8de8740cf7f41bd3"}, + {file = "tornado-6.3.3-cp38-abi3-win_amd64.whl", hash = "sha256:22d3c2fa10b5793da13c807e6fc38ff49a4f6e1e3868b0a6f4164768bb8e20f5"}, + {file = "tornado-6.3.3.tar.gz", hash = "sha256:e7d8db41c0181c80d76c982aacc442c0783a2c54d6400fe028954201a2e032fe"}, +] + +[[package]] +name = "typing-extensions" +version = "4.8.0" +requires_python = ">=3.8" +summary = "Backported and Experimental Type Hints for Python 3.8+" +files = [ + {file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"}, + {file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"}, +] + +[[package]] +name = "urllib3" +version = "2.0.6" +requires_python = ">=3.7" +summary = "HTTP library with thread-safe connection pooling, file post, and more." +files = [ + {file = "urllib3-2.0.6-py3-none-any.whl", hash = "sha256:7a7c7003b000adf9e7ca2a377c9688bbc54ed41b985789ed576570342a375cd2"}, + {file = "urllib3-2.0.6.tar.gz", hash = "sha256:b19e1a85d206b56d7df1d5e683df4a7725252a964e3993648dd0fb5a1c157564"}, +] + [[package]] name = "virtualenv" version = "20.24.5" @@ -332,3 +1310,22 @@ files = [ {file = "virtualenv-20.24.5-py3-none-any.whl", hash = "sha256:b80039f280f4919c77b30f1c23294ae357c4c8701042086e3fc005963e4e537b"}, {file = "virtualenv-20.24.5.tar.gz", hash = "sha256:e8361967f6da6fbdf1426483bfe9fca8287c242ac0bc30429905721cefbff752"}, ] + +[[package]] +name = "webencodings" +version = "0.5.1" +summary = "Character encoding aliases for legacy web content" +files = [ + {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, + {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, +] + +[[package]] +name = "zipp" +version = "3.17.0" +requires_python = ">=3.8" +summary = "Backport of pathlib-compatible object wrapper for zip files" +files = [ + {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"}, + {file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"}, +] diff --git a/pyproject.toml b/pyproject.toml index 296683d..41bf9da 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -52,6 +52,16 @@ dev = [ "sourcery>=1.10.1", "pip>=23.2.1", ] +docs = [ + "sphinx>=7.1.2", + "sphinx-autobuild>=2021.3.14", + "sphinx-toolbox>=3.5.0", + "blacken-docs>=1.16.0", + "sphinx-design>=0.5.0", + "sphinxcontrib-mermaid>=0.9.2", + "shibuya>=2023.10.5", + "myst-parser>=2.0.0", +] [tool.pdm.scripts] lint = "pre-commit run --all-files" @@ -92,3 +102,34 @@ ignore = [ ] line-length = 120 target-version = "py38" + + +[tool.ruff.pydocstyle] +convention = "google" + +[tool.ruff.pep8-naming] +classmethod-decorators = [ + "classmethod", +] + +[tool.ruff.isort] +known-first-party = ["src", "tests"] + +[tool.ruff.per-file-ignores] +"**/*.*" = ["ANN101", "ANN401", "ANN102", "TD",] +"docs/**/*.*" = [ + "S", + "B", + "DTZ", + "A", + "TCH", + "ERA", + "D", + "RET", + "E731", + "RUF012", + "FA100", + "ARG001", +] +"docs/conf.py" = ["FIX002", "ARG001",] +"tools/**/*.*" = ["D", "ARG", "EM", "TRY", "G", "FBT", "INP"] diff --git a/tools/build_docs.py b/tools/build_docs.py new file mode 100644 index 0000000..eba5a77 --- /dev/null +++ b/tools/build_docs.py @@ -0,0 +1,53 @@ +from __future__ import annotations + +import argparse +import shutil +import subprocess +from contextlib import contextmanager +from pathlib import Path + +REDIRECT_TEMPLATE = """ + + + + Page Redirection + + + + + + You are being redirected. If this does not work, click this link + + +""" + +parser = argparse.ArgumentParser() +parser.add_argument("output") + + +@contextmanager +def checkout(branch: str) -> None: + subprocess.run(["git", "checkout", branch], check=True) # noqa: S603 S607 + yield + subprocess.run(["git", "checkout", "-"], check=True) # noqa: S603 S607 + + +def build(output_dir: str) -> None: + subprocess.run(["make", "docs"], check=True) # noqa: S603 S607 + + output_dir = Path(output_dir) + output_dir.mkdir() + output_dir.joinpath(".nojekyll").touch(exist_ok=True) + output_dir.joinpath("index.html").write_text(REDIRECT_TEMPLATE.format(target="latest")) + + docs_src_path = Path("docs/_build/html") + shutil.copytree(docs_src_path, output_dir / "latest", dirs_exist_ok=True) + + +def main() -> None: + args = parser.parse_args() + build(output_dir=args.output) + + +if __name__ == "__main__": + main() From 0ab1c30be6b4992dd23677a9f4d88a444668f06d Mon Sep 17 00:00:00 2001 From: Jacob Coffee Date: Sat, 7 Oct 2023 18:46:03 -0500 Subject: [PATCH 4/9] infra: add CODEOWNERS --- .github/CODEOWNERS | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..6c97be0 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,10 @@ +# Code owner settings for `litestar` +# @maintainers should be assigned to all reviews. +# Most specific assignment takes precedence though, so if you add a more specific thing than the `*` glob, you must also add @maintainers +# For more info about code owners see https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners#codeowners-file-example + +# Global Assignment +* @litestar-org/maintainers @litestar-org/members + +# Documentation +docs/* @litestar-org/maintainers @JacobCoffee @provinzkraut From cc5638c32d87d173f915f97a40f16f8770fa660e Mon Sep 17 00:00:00 2001 From: Jacob Coffee Date: Sat, 7 Oct 2023 18:46:44 -0500 Subject: [PATCH 5/9] fix(ci): change cargo readme --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 1b348bf..f4f9ef5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "fast_query_parsers" authors = ["Na'aman Hirschfeld "] description = "Ultra-fast query string and url-encoded form-data parsers" -readme = "README.md" +readme = "README.rst" license-file = "LICENSE" repository = "https://github.com/litestar-org/fast-query-parsers" version = "1.0.3" From cc1251faf46d0658c03fb3556bc057d276a0c84e Mon Sep 17 00:00:00 2001 From: Jacob Coffee Date: Sat, 7 Oct 2023 18:48:41 -0500 Subject: [PATCH 6/9] fix(ci): change pyproject readme --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 41bf9da..c29a3e4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ requires-python = ">=3.8" license = {text = "MIT"} version = "1.0.4" description = "Ultra-fast query string and url-encoded form-data parsers" -readme = "README.md" +readme = "README.rst" dependencies = [] classifiers = [ "Development Status :: 5 - Production/Stable", From 2b694ae3d5a55db3e1dcfbc2a3b6116d61d17fdf Mon Sep 17 00:00:00 2001 From: Jacob Coffee Date: Sat, 7 Oct 2023 18:53:34 -0500 Subject: [PATCH 7/9] fix(docs): update maintainers skip-checks:true --- pyproject.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index c29a3e4..0664f2c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,6 +40,9 @@ authors = [ ] maintainers = [ {name = "Jacob Coffee", email = "jacob@z7x.org"}, + {name = "Cody Fincher", email = "cody.fincher@gmail.com"}, + {name = "Janek Nouvertné", email = "provinzkraut@posteo.de"}, + {name = "Peter Schutt", email = "peter.github@proton.me"}, ] [tool.pdm.dev-dependencies] From fee333fc4385fd1a252130edb5be85940e21a16b Mon Sep 17 00:00:00 2001 From: Jacob Coffee Date: Sat, 7 Oct 2023 18:55:15 -0500 Subject: [PATCH 8/9] chore: move table --- README.rst | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/README.rst b/README.rst index 246953d..796fdbc 100644 --- a/README.rst +++ b/README.rst @@ -5,6 +5,18 @@ .. :align: center .. :class: dark_logo ++-----------+-----+------------------------------------------------------------------------------------------------------------------+ +| Project | | Status | ++===========+=====+==================================================================================================================+ +| CI/CD | | |Publish| |CI| | ++-----------+-----+------------------------------------------------------------------------------------------------------------------+ +| Package | | |PyPI - Version| |PyPI - Support Python Versions| |PyPI - Downloads| | ++-----------+-----+------------------------------------------------------------------------------------------------------------------+ +| Community | | |Reddit| |Discord| |Matrix| |Medium| |Twitter| |Blog| | ++-----------+-----+------------------------------------------------------------------------------------------------------------------+ +| Meta | | |Litestar Project| |License - MIT| |Litestar Sponsors| |linting - Ruff| |code style - Black| | ++-----------+-----+------------------------------------------------------------------------------------------------------------------+ + ================== Fast Query Parsers ================== @@ -34,20 +46,6 @@ Contributing Contributions are welcome! Please see the :doc:`contributing` for more details. -Status ------- - -+-----------+-----+------------------------------------------------------------------------------------------------------------------+ -| Project | | Status | -+===========+=====+==================================================================================================================+ -| CI/CD | | |Publish| |CI| | -+-----------+-----+------------------------------------------------------------------------------------------------------------------+ -| Package | | |PyPI - Version| |PyPI - Support Python Versions| |PyPI - Downloads| | -+-----------+-----+------------------------------------------------------------------------------------------------------------------+ -| Community | | |Reddit| |Discord| |Matrix| |Medium| |Twitter| |Blog| | -+-----------+-----+------------------------------------------------------------------------------------------------------------------+ -| Meta | | |Litestar Project| |License - MIT| |Litestar Sponsors| |linting - Ruff| |code style - Black| | -+-----------+-----+------------------------------------------------------------------------------------------------------------------+ .. |Publish| image:: https://github.com/litestar-org/fast-query-parsers/actions/workflows/publish.yaml/badge.svg :target: https://github.com/litestar-org/fast-query-parsers/actions/workflows/publish.yaml From b233c6b5f95105b570d229205375e305a868bb76 Mon Sep 17 00:00:00 2001 From: Jacob Coffee Date: Sat, 7 Oct 2023 19:02:22 -0500 Subject: [PATCH 9/9] chore: fix --- README.rst | 11 ++++++++--- docs/usage/index.rst | 12 ++++++++---- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/README.rst b/README.rst index 796fdbc..af351db 100644 --- a/README.rst +++ b/README.rst @@ -36,15 +36,20 @@ Benchmarks .. code-block:: console - stdlib parse_qs parsing url-encoded values into dict: Mean +- std dev: 8.99 us +- 0.09 us + stdlib parse_qs parsing url-encoded values into dict: + Mean +- std dev: 8.99 us +- 0.09 us ..................... - parse_url_encoded_dict parse url-encoded values into dict: Mean +- std dev: 3.77 us +- 0.08 us + parse_url_encoded_dict parse url-encoded values into dict: + Mean +- std dev: 3.77 us +- 0.08 us Contributing ------------ Contributions are welcome! -Please see the :doc:`contributing` for more details. + +Please see the +`contribution guide `_ +for more details. .. |Publish| image:: https://github.com/litestar-org/fast-query-parsers/actions/workflows/publish.yaml/badge.svg diff --git a/docs/usage/index.rst b/docs/usage/index.rst index 94a2fa9..156e0b9 100644 --- a/docs/usage/index.rst +++ b/docs/usage/index.rst @@ -33,13 +33,17 @@ Query string parsing is more than x5 times faster than the standard library: .. code-block:: console - stdlib parse_qsl parsing query string: Mean +- std dev: 2.86 us +- 0.03 us + stdlib parse_qsl parsing query string: + Mean +- std dev: 2.86 us +- 0.03 us ..................... - parse_query_string parsing query string: Mean +- std dev: 916 ns +- 13 ns + parse_query_string parsing query string: + Mean +- std dev: 916 ns +- 13 ns ..................... - stdlib parse_qsl parsing urlencoded query string: Mean +- std dev: 8.30 us +- 0.10 us + stdlib parse_qsl parsing urlencoded query string: + Mean +- std dev: 8.30 us +- 0.10 us ..................... - parse_query_string urlencoded query string: Mean +- std dev: 1.50 us +- 0.03 us + parse_query_string urlencoded query string: + Mean +- std dev: 1.50 us +- 0.03 us ``parse_url_encoded_dict`` ~~~~~~~~~~~~~~~~~~~~~~~~~~