diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml new file mode 100644 index 0000000..7ffddfe --- /dev/null +++ b/.github/dependabot.yaml @@ -0,0 +1,13 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" # zizmor: ignore[dependabot-cooldown] + directory: "/" + schedule: + interval: "weekly" + target-branch: main + + - package-ecosystem: "cargo" # zizmor: ignore[dependabot-cooldown] + directory: "/" + schedule: + interval: "weekly" + target-branch: main \ No newline at end of file diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index eab081e..cb9605c 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -7,11 +7,52 @@ on: workflow_dispatch: +permissions: {} + concurrency: group: ci-${{ github.ref }} - cancel-in-progress: ${{ !startsWith(github.ref, 'refs/tags/') }} + cancel-in-progress: ${{ github.ref_type != 'tag' }} + +env: + (^_^): &interpreters "3.10 3.11 3.12 3.13 3.14 3.14t 3.15 3.15t pypy3.11" + โ—‹_โ—‹: &interpreters_without_pypy "3.10 3.11 3.12 3.13 3.14 3.14t 3.15 3.15t" + jobs: + tools: + name: ${{ matrix.name }} + runs-on: ubuntu-latest + + strategy: + matrix: + include: + - name: "zizmor" + command: zizmor .github/ + + - name: "typos" + command: typos --config typos.toml + + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + with: + python-version: "3.14" + + - name: "Install uv" + uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 + with: + # zizmor: ignore[cache-poisoning] + enable-cache: ${{ github.event_name == 'pull_request' }} + + - name: "Install ${{ matrix.name }}" + run: uv pip install --group ${{ matrix.name }} --system + + - name: "Run ${{ matrix.name }}" + run: ${{ matrix.command }} + build-linux: runs-on: ubuntu-latest strategy: @@ -19,46 +60,51 @@ jobs: platform: - { target: x86_64, - interpreter: "3.10 3.11 3.12 3.13 3.14 3.14t 3.15 3.15t pypy3.11", + interpreter: *interpreters } - { target: x86, - interpreter: "3.10 3.11 3.12 3.13 3.14 3.14t 3.15 3.15t pypy3.11", + interpreter: *interpreters } - { target: aarch64, - interpreter: "3.10 3.11 3.12 3.13 3.14 3.14t 3.15 3.15t pypy3.11", + interpreter: *interpreters } - { target: armv7, - interpreter: "3.10 3.11 3.12 3.13 3.14 3.14t 3.15 3.15t pypy3.11", + interpreter: *interpreters } - { target: s390x, - interpreter: "3.10 3.11 3.12 3.13 3.14 3.14t 3.15 3.15t pypy3.11", + interpreter: *interpreters } - { target: ppc64le, - interpreter: "3.10 3.11 3.12 3.13 3.14 3.14t 3.15 3.15t pypy3.11", + interpreter: *interpreters } steps: - - uses: actions/checkout@v6.0.2 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - - uses: actions/setup-python@v6.2.0 + - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: "3.x" - - uses: PyO3/maturin-action@v1.51.0 + - uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1.51.0 + # zizmor: ignore[cache-poisoning] with: target: ${{ matrix.platform.target }} - args: --release --out dist --interpreter ${{ matrix.platform.interpreter }} - sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} + sccache: ${{ github.ref_type != 'tag' }} manylinux: auto + args: >- + --release + --out dist + --interpreter ${{ matrix.platform.interpreter }} + --compatibility pypi - - uses: actions/upload-artifact@v7.0.1 + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: wheels-linux-${{ matrix.platform.target }} path: dist @@ -70,38 +116,43 @@ jobs: platform: - { target: x86_64, - interpreter: "3.10 3.11 3.12 3.13 3.14 3.14t 3.15 3.15t pypy3.11", + interpreter: *interpreters } - { target: x86, - interpreter: "3.10 3.11 3.12 3.13 3.14 3.14t 3.15 3.15t pypy3.11", + interpreter: *interpreters } - { target: aarch64, - interpreter: "3.10 3.11 3.12 3.13 3.14 3.14t 3.15 3.15t pypy3.11", + interpreter: *interpreters } - { target: armv7, - interpreter: "3.10 3.11 3.12 3.13 3.14 3.14t 3.15 3.15t pypy3.11", + interpreter: *interpreters } steps: - - uses: actions/checkout@v6.0.2 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - - uses: actions/setup-python@v6.2.0 + - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: "3.x" - - uses: PyO3/maturin-action@v1.51.0 + - uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1.51.0 + # zizmor: ignore[cache-poisoning] with: target: ${{ matrix.platform.target }} - args: --release --out dist --interpreter ${{ matrix.platform.interpreter }} - sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} + sccache: ${{ github.ref_type != 'tag' }} manylinux: musllinux_1_2 + args: >- + --release + --out dist + --interpreter ${{ matrix.platform.interpreter }} + --compatibility pypi - - uses: actions/upload-artifact@v7.0.1 + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: wheels-musllinux-${{ matrix.platform.target }} path: dist @@ -113,30 +164,35 @@ jobs: platform: - { target: x64, - interpreter: "3.10 3.11 3.12 3.13 3.14 3.14t 3.15 3.15t pypy3.11", + interpreter: *interpreters } - { target: x86, - interpreter: "3.10 3.11 3.12 3.13 3.14 3.14t 3.15 3.15t", + interpreter: *interpreters_without_pypy, } steps: - - uses: actions/checkout@v6.0.2 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - - uses: actions/setup-python@v6.2.0 + - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: "3.x" architecture: ${{ matrix.platform.target }} - - uses: PyO3/maturin-action@v1.51.0 + - uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1.51.0 + # zizmor: ignore[cache-poisoning] with: target: ${{ matrix.platform.target }} - args: --release --out dist --interpreter ${{ matrix.platform.interpreter }} - sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} + sccache: ${{ github.ref_type != 'tag' }} + args: >- + --release + --out dist + --interpreter ${{ matrix.platform.interpreter }} + --compatibility pypi - - uses: actions/upload-artifact@v7.0.1 + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: wheels-windows-${{ matrix.platform.target }} path: dist @@ -148,29 +204,34 @@ jobs: platform: - { target: x86_64, - interpreter: "3.10 3.11 3.12 3.13 3.14 3.14t 3.15 3.15t pypy3.11", + interpreter: *interpreters } - { target: aarch64, - interpreter: "3.10 3.11 3.12 3.13 3.14 3.14t 3.15 3.15t pypy3.11", + interpreter: *interpreters } steps: - - uses: actions/checkout@v6.0.2 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - - uses: actions/setup-python@v6.2.0 + - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: "3.x" - - uses: PyO3/maturin-action@v1.51.0 + - uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1.51.0 + # zizmor: ignore[cache-poisoning] with: target: ${{ matrix.platform.target }} - args: --release --out dist --interpreter ${{ matrix.platform.interpreter }} - sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} + sccache: ${{ github.ref_type != 'tag' }} + args: >- + --release + --out dist + --interpreter ${{ matrix.platform.interpreter }} + --compatibility pypi - - uses: actions/upload-artifact@v7.0.1 + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: wheels-macos-${{ matrix.platform.target }} path: dist @@ -178,25 +239,25 @@ jobs: build-sdist: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6.0.2 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Build sdist - uses: PyO3/maturin-action@v1.51.0 + uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1.51.0 with: command: sdist args: --out dist - name: Upload sdist - uses: actions/upload-artifact@v7.0.1 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: wheels-sdist path: dist release: runs-on: ubuntu-latest - if: startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' + if: github.ref_type != 'tag' || github.event_name == 'workflow_dispatch' needs: - build-linux - build-musllinux @@ -209,14 +270,14 @@ jobs: contents: write steps: - - uses: actions/download-artifact@v8.0.1 + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: pattern: wheels-* merge-multiple: true path: dist - name: Publish to PyPI - if: startsWith(github.ref, 'refs/tags/') - uses: pypa/gh-action-pypi-publish@release/v1 + if: github.ref_type != 'tag' + uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2 with: packages-dir: dist diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 8c10711..b703340 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -3,29 +3,35 @@ name: Deploy Docs on: workflow_dispatch: -permissions: - contents: write - pages: write - id-token: write - jobs: build: runs-on: ubuntu-latest + permissions: + contents: write steps: - - uses: actions/checkout@v6.0.2 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + # zizmor: ignore[artipacked] with: fetch-depth: 0 - - uses: actions/setup-python@v6.2.0 + - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: 3.14 - - run: pip install "mkdocs-material" "mkdocstrings[python]" + - name: "Install uv" + uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 + with: + enable-cache: false + + - run: uv pip install --group docs --system - run: mkdocs gh-deploy --config-file docs/mkdocs.yml --force deploy_mkdocs: needs: build + permissions: + pages: write + id-token: write environment: name: github-pages @@ -34,15 +40,16 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6.0.2 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: gh-pages + persist-credentials: false - - uses: actions/configure-pages@v6.0.0 + - uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0 - - uses: actions/upload-pages-artifact@v5.0.0 + - uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0 with: path: "." - id: deployment - uses: actions/deploy-pages@v5.0.0 + uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0 diff --git a/.github/workflows/python-test.yml b/.github/workflows/python-test.yml index 90156d8..caed670 100644 --- a/.github/workflows/python-test.yml +++ b/.github/workflows/python-test.yml @@ -13,6 +13,7 @@ concurrency: env: RUST_BACKTRACE: 1 + UV_PYTHON_DOWNLOADS: 0 jobs: test-python: @@ -22,33 +23,53 @@ jobs: strategy: fail-fast: false matrix: - python-version: - - "3.10" - - "3.11" - - "3.12" - - "3.13" - - "3.14" - - "3.14t" - - "3.15" - - "3.15t" - - "pypy3.11" + python-version: [ + "3.10", + "3.11", + "3.12", + "3.13", + "3.14", "3.14t", + "3.15", "3.15t", + "pypy3.11", + ] steps: - - uses: actions/checkout@v6.0.2 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + - uses: dtolnay/rust-toolchain@stable # zizmor: ignore[unpinned-uses] - - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 + if: github.event_name == 'pull_request' && github.run_attempt == 1 + with: + lookup-only: false # zizmor: ignore[cache-poisoning] + shared-key: ${{ matrix.python-version }} - - uses: actions/setup-python@v6.2.0 + - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: ${{ matrix.python-version }} allow-prereleases: true - - run: pip install virtualenv - - run: pip install -r requirements-dev.txt - - run: virtualenv --no-vcs-ignore .venv + - name: "Install uv" + uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 + with: + enable-cache: false + + - name: "Create and activate .venv" + run: | + uv venv .venv --python ${{ matrix.python-version }} + echo ".venv/bin" >> "$GITHUB_PATH" + echo "PYO3_PYTHON=.venv/bin/python3" >> "$GITHUB_ENV" - - run: maturin develop --features use-small-offset - - run: pytest -v -n auto + - name: "Install dependencies" + run: uv pip install --group ci + + - name: "Run maturin" + run: maturin develop --features use-small-offset + + - name: "Run pytest" + run: pytest -v -n auto env: HYPOTHESIS_PROFILE: slow @@ -61,19 +82,41 @@ jobs: os: [ubuntu, macos, windows] steps: - - uses: actions/checkout@v6.0.2 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - - uses: dtolnay/rust-toolchain@stable + - uses: dtolnay/rust-toolchain@stable # zizmor: ignore[unpinned-uses] - - uses: actions/setup-python@v6.2.0 + - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: "3.13" - - run: pip install virtualenv - - run: pip install -r requirements-dev.txt - - run: virtualenv --no-vcs-ignore .venv - - - run: maturin develop --features use-small-offset - - run: pytest -v -n auto + - name: "Install uv" + uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 + with: + enable-cache: false + + - name: "Create and activate .venv" + shell: bash + run: | + uv venv .venv --python 3.13 + if [[ "${{ matrix.os }}" == "windows" ]]; then + echo ".venv/Scripts" >> "$GITHUB_PATH" + echo "PYO3_PYTHON=.venv/Scripts/python" >> "$GITHUB_ENV" + echo "UV_LINK_MODE=copy" >> "$GITHUB_ENV" + else + echo ".venv/bin" >> "$GITHUB_PATH" + echo "PYO3_PYTHON=.venv/bin/python3" >> "$GITHUB_ENV" + fi + + - name: "Install dependencies" + run: uv pip install --group ci + + - name: "Run maturin" + run: maturin develop --features use-small-offset + + - name: "Run pytest" + run: pytest -v -n auto env: HYPOTHESIS_PROFILE: slow diff --git a/Cargo.toml b/Cargo.toml index 847fd49..1f017b3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,13 +24,24 @@ strip = true [dependencies] allocator-api2 = "0.4.0" cfg-if = "1.0.4" -chrono = "0.4.44" -fastrand = "2.4.1" -parking_lot = {version="0.12.5", default-features=false} -pyo3 = {version="0.29", default-features=false, features=["macros", "chrono"]} +chrono = "0.4.45" +fastrand = "2.5.0" +parking_lot = { + version = "0.12.5", + default-features = false, +} +pyo3 = { + version = "0.29.1", + default-features = false, + features = ["macros", "chrono"], +} [build-dependencies] -pyo3-build-config = {version="0.29", default-features=false, features=["resolve-config"]} +pyo3-build-config = { + version = "0.29.1", + default-features = false, + features = ["resolve-config"], +} [features] default = ["inline-more", "extension-module"] diff --git a/README.md b/README.md index 393f167..a07784a 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ It uses Google's high-performance SwissTable hash map. Thanks to [hashbrown](htt It has very low memory usage. - **โญ Zero Dependency** \ -As we said, `cachebox` is written in *Rust* so you don't have to install any other dependecies. +As we said, `cachebox` is written in *Rust* so you don't have to install any other dependencies. - **๐Ÿงถ Thread safe** \ It's completely thread-safe and uses *Rust* mutex to prevent problems. @@ -118,7 +118,7 @@ d2 = make_dict("cachebox", 10) assert d2 == {"name": "cachebox", "age": 10} ``` -You can use cache alghoritms without the `cached` decorator -- just import the cache alghoritm you want and use it like a dictionary. +You can use cache algorithms without the `cached` decorator -- just import the cache algorithm you want and use it like a dictionary. ```python from cachebox import FIFOCache diff --git a/cachebox/_core.pyi b/cachebox/_core.pyi index 2269d8a..322b377 100644 --- a/cachebox/_core.pyi +++ b/cachebox/_core.pyi @@ -361,7 +361,7 @@ class Cache(BaseCacheImpl[KT, VT]): default: typing.Optional[DT] = None, ) -> typing.Optional[VT | DT]: """ - Get `key`s value, or atomatically insert `default` and return it. + Get `key`s value, or automatically insert `default` and return it. If `key` exists, its current value is returned and `default` is ignored. Otherwise `default` is inserted for `key` and returned. @@ -382,7 +382,7 @@ class Cache(BaseCacheImpl[KT, VT]): factory: typing.Callable[[], DT], ) -> VT | DT: """ - Get `key`s value, or atomatically create and insert one via `factory`. + Get `key`s value, or automatically create and insert one via `factory`. If `key` exists, its current value is returned and `factory` is not called. Otherwise `factory` is called exactly once under an internal lock, its result is inserted and returned. @@ -542,7 +542,7 @@ class FIFOCache(BaseCacheImpl[KT, VT]): default: typing.Optional[DT] = None, ) -> typing.Optional[VT | DT]: """ - Get `key`s value, or atomatically insert `default` and return it. + Get `key`s value, or automatically insert `default` and return it. If `key` exists, its current value is returned and `default` is ignored. Otherwise `default` is inserted for `key` and returned. @@ -563,7 +563,7 @@ class FIFOCache(BaseCacheImpl[KT, VT]): factory: typing.Callable[[], DT], ) -> VT | DT: """ - Get `key`s value, or atomatically create and insert one via `factory`. + Get `key`s value, or automatically create and insert one via `factory`. If `key` exists, its current value is returned and `factory` is not called. Otherwise `factory` is called exactly once under an internal lock, its result is inserted and returned. @@ -756,7 +756,7 @@ class RRCache(BaseCacheImpl[KT, VT]): default: typing.Optional[DT] = None, ) -> typing.Optional[VT | DT]: """ - Get `key`s value, or atomatically insert `default` and return it. + Get `key`s value, or automatically insert `default` and return it. If `key` exists, its current value is returned and `default` is ignored. Otherwise `default` is inserted for `key` and returned. @@ -777,7 +777,7 @@ class RRCache(BaseCacheImpl[KT, VT]): factory: typing.Callable[[], DT], ) -> VT | DT: """ - Get `key`s value, or atomatically create and insert one via `factory`. + Get `key`s value, or automatically create and insert one via `factory`. If `key` exists, its current value is returned and `factory` is not called. Otherwise `factory` is called exactly once under an internal lock, its result is inserted and returned. @@ -963,7 +963,7 @@ class LRUCache(BaseCacheImpl[KT, VT]): default: typing.Optional[DT] = None, ) -> typing.Optional[VT | DT]: """ - Get `key`s value, or atomatically insert `default` and return it. + Get `key`s value, or automatically insert `default` and return it. If `key` exists, its current value is returned and `default` is ignored. Otherwise `default` is inserted for `key` and returned. @@ -984,7 +984,7 @@ class LRUCache(BaseCacheImpl[KT, VT]): factory: typing.Callable[[], DT], ) -> VT | DT: """ - Get `key`s value, or atomatically create and insert one via `factory`. + Get `key`s value, or automatically create and insert one via `factory`. If `key` exists, its current value is returned and `factory` is not called. Otherwise `factory` is called exactly once under an internal lock, its result is inserted and returned. @@ -1211,7 +1211,7 @@ class LFUCache(BaseCacheImpl[KT, VT]): default: typing.Optional[DT] = None, ) -> typing.Optional[VT | DT]: """ - Get `key`s value, or atomatically insert `default` and return it. + Get `key`s value, or automatically insert `default` and return it. If `key` exists, its current value is returned and `default` is ignored. Otherwise `default` is inserted for `key` and returned. @@ -1232,7 +1232,7 @@ class LFUCache(BaseCacheImpl[KT, VT]): factory: typing.Callable[[], DT], ) -> VT | DT: """ - Get `key`s value, or atomatically create and insert one via `factory`. + Get `key`s value, or automatically create and insert one via `factory`. If `key` exists, its current value is returned and `factory` is not called. Otherwise `factory` is called exactly once under an internal lock, its result is inserted and returned. @@ -1418,7 +1418,7 @@ class TTLCache(BaseCacheImpl[KT, VT]): default: typing.Optional[DT] = None, ) -> typing.Optional[VT | DT]: """ - Get `key`s value, or atomatically insert `default` and return it. + Get `key`s value, or automatically insert `default` and return it. If `key` exists, its current value is returned and `default` is ignored. Otherwise `default` is inserted for `key` and returned. @@ -1439,7 +1439,7 @@ class TTLCache(BaseCacheImpl[KT, VT]): factory: typing.Callable[[], DT], ) -> VT | DT: """ - Get `key`s value, or atomatically create and insert one via `factory`. + Get `key`s value, or automatically create and insert one via `factory`. If `key` exists, its current value is returned and `factory` is not called. Otherwise `factory` is called exactly once under an internal lock, its result is inserted and returned. @@ -1683,7 +1683,7 @@ class VTTLCache(BaseCacheImpl[KT, VT]): ttl: float | timedelta | datetime | None = None, ) -> typing.Optional[VT | DT]: """ - Get `key`s value, or atomatically insert `default` and return it. + Get `key`s value, or automatically insert `default` and return it. If `key` exists, its current value is returned and `default` is ignored. Otherwise `default` is inserted for `key` and returned. @@ -1706,7 +1706,7 @@ class VTTLCache(BaseCacheImpl[KT, VT]): ttl: float | timedelta | datetime | None = None, ) -> VT | DT: """ - Get `key`s value, or atomatically create and insert one via `factory`. + Get `key`s value, or automatically create and insert one via `factory`. If `key` exists, its current value is returned and `factory` is not called. Otherwise `factory` is called exactly once under an internal lock, its result is inserted and returned. diff --git a/docs/docs/getting-started.md b/docs/docs/getting-started.md index c236054..2867d71 100644 --- a/docs/docs/getting-started.md +++ b/docs/docs/getting-started.md @@ -268,7 +268,7 @@ class OrderRepository(BaseRepository): In this example, each repository class maintains an independent cache while reusing the same cached method implementation. -## Using a Cache Implemetations +## Using a Cache Implementations You can use all cache implementations without `@cached` method. You only need to import the classes you want and can work with them like a regular dictionaries (except for [`VTTLCache`](api/impls.md#cachebox._cachebox.VTTLCache), this have some differences). diff --git a/pyproject.toml b/pyproject.toml index adff184..e660ee6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["maturin>=1.14.1,<2.0"] +requires = ["maturin == 1.14.1"] build-backend = "maturin" [tool.maturin] @@ -7,7 +7,7 @@ module-name = "cachebox._core" [project] name = "cachebox" -requires-python = ">=3.9" +requires-python = ">=3.10" keywords = ["caching", "cached", "cachebox", "cache", "in-memory-caching", "memoizing"] authors = [ { name = "awolverp", email = "awolverp@gmail.com" } @@ -50,3 +50,31 @@ Issues = "https://github.com/awolverp/cachebox/issues" [tool.mypy] disable_error_code = "attr-defined, type-arg, no-untyped-def, no-any-return" + +[dependency-groups] +maturin = [ + "maturin == 1.14.1 ; sys_platform != 'linux'", + "maturin[patchelf] == 1.14.1 ; sys_platform == 'linux'", +] +typos = ["typos == 1.48.0"] +zizmor = ["zizmor == 1.29.0"] +docs = [ + "mkdocs-material == 9.7.7", + "mkdocstrings[python] == 1.0.6", +] +test = [ + "pytest == 9.1.1", + "hypothesis == 6.165.0", + "pytest-asyncio == 1.4.0", + "pytest-xdist == 3.8.0", +] +ci = [ + { include-group = "maturin" }, + { include-group = "test" }, +] +dev = [ + { include-group = "ci" }, + { include-group = "docs" }, + { include-group = "zizmor" }, + { include-group = "typos" }, +] diff --git a/requirements-dev.txt b/requirements-dev.txt deleted file mode 100644 index d6d984d..0000000 --- a/requirements-dev.txt +++ /dev/null @@ -1,7 +0,0 @@ -maturin -pytest -hypothesis -pytest-asyncio -pytest-xdist -mkdocs-material -mkdocstrings[python] diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..31578d3 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "stable" \ No newline at end of file diff --git a/src/hashbrown/control/bitmask.rs b/src/hashbrown/control/bitmask.rs index 8370515..d811fab 100644 --- a/src/hashbrown/control/bitmask.rs +++ b/src/hashbrown/control/bitmask.rs @@ -1,4 +1,7 @@ -use super::group::{BITMASK_ITER_MASK, BITMASK_STRIDE, BitMaskWord, NonZeroBitMaskWord}; +use super::group::BitMaskWord; +use super::group::NonZeroBitMaskWord; +use super::group::BITMASK_ITER_MASK; +use super::group::BITMASK_STRIDE; /// A bit mask which contains the result of a `Match` operation on a `Group` and /// allows iterating through them. diff --git a/src/hashbrown/control/group/lsx.rs b/src/hashbrown/control/group/lsx.rs index 7da098a..0cb847b 100644 --- a/src/hashbrown/control/group/lsx.rs +++ b/src/hashbrown/control/group/lsx.rs @@ -1,4 +1,5 @@ -use super::super::{BitMask, Tag}; +use super::super::BitMask; +use super::super::Tag; use core::mem; use core::num::NonZeroU16; diff --git a/src/hashbrown/control/group/mod.rs b/src/hashbrown/control/group/mod.rs index 8975f94..ac0ac4f 100644 --- a/src/hashbrown/control/group/mod.rs +++ b/src/hashbrown/control/group/mod.rs @@ -43,5 +43,8 @@ cfg_if::cfg_if! { use generic as imp; } } +pub(super) use self::imp::BitMaskWord; pub(crate) use self::imp::Group; -pub(super) use self::imp::{BitMaskWord, NonZeroBitMaskWord, BITMASK_ITER_MASK, BITMASK_STRIDE}; +pub(super) use self::imp::NonZeroBitMaskWord; +pub(super) use self::imp::BITMASK_ITER_MASK; +pub(super) use self::imp::BITMASK_STRIDE; diff --git a/src/hashbrown/control/group/neon.rs b/src/hashbrown/control/group/neon.rs index c64b891..ce8d7d9 100644 --- a/src/hashbrown/control/group/neon.rs +++ b/src/hashbrown/control/group/neon.rs @@ -1,4 +1,5 @@ -use super::super::{BitMask, Tag}; +use super::super::BitMask; +use super::super::Tag; use core::arch::aarch64 as neon; use core::mem; use core::num::NonZeroU64; diff --git a/src/hashbrown/control/group/sse2.rs b/src/hashbrown/control/group/sse2.rs index 2b12c01..f5150a9 100644 --- a/src/hashbrown/control/group/sse2.rs +++ b/src/hashbrown/control/group/sse2.rs @@ -1,4 +1,5 @@ -use super::super::{BitMask, Tag}; +use super::super::BitMask; +use super::super::Tag; use core::mem; use core::num::NonZeroU16; diff --git a/src/hashbrown/control/mod.rs b/src/hashbrown/control/mod.rs index 62ef8bf..0842411 100644 --- a/src/hashbrown/control/mod.rs +++ b/src/hashbrown/control/mod.rs @@ -3,8 +3,7 @@ mod group; mod tag; use self::bitmask::BitMask; -pub(crate) use self::{ - bitmask::BitMaskIter, - group::Group, - tag::{Tag, TagSliceExt}, -}; +pub(crate) use self::bitmask::BitMaskIter; +pub(crate) use self::group::Group; +pub(crate) use self::tag::Tag; +pub(crate) use self::tag::TagSliceExt; diff --git a/src/hashbrown/control/tag.rs b/src/hashbrown/control/tag.rs index 486bbba..4e56089 100644 --- a/src/hashbrown/control/tag.rs +++ b/src/hashbrown/control/tag.rs @@ -1,4 +1,5 @@ -use core::{fmt, mem}; +use core::fmt; +use core::mem; /// Single tag in a control group. #[derive(Copy, Clone, PartialEq, Eq)] diff --git a/src/hashbrown/raw.rs b/src/hashbrown/raw.rs index a375d6d..1cc39c8 100644 --- a/src/hashbrown/raw.rs +++ b/src/hashbrown/raw.rs @@ -2643,7 +2643,7 @@ impl RawTableInner { unsafe { self.ctrl.as_ptr().add(index).cast() } } - /// Gets the slice of all control bytes, as possibily uninitialized tags. + /// Gets the slice of all control bytes, as possibly uninitialized tags. fn ctrl_slice(&mut self) -> &mut [mem::MaybeUninit] { // SAFETY: We have the correct number of control bytes. unsafe { slice::from_raw_parts_mut(self.ctrl.as_ptr().cast(), self.num_ctrl_bytes()) } diff --git a/src/hashbrown/scopeguard.rs b/src/hashbrown/scopeguard.rs index 26532b8..1b4a2d6 100644 --- a/src/hashbrown/scopeguard.rs +++ b/src/hashbrown/scopeguard.rs @@ -1,9 +1,8 @@ // Extracted from the scopeguard crate -use core::{ - mem::ManuallyDrop, - ops::{Deref, DerefMut}, - ptr, -}; +use core::mem::ManuallyDrop; +use core::ops::Deref; +use core::ops::DerefMut; +use core::ptr; pub(crate) struct ScopeGuard where diff --git a/src/internal/onceinit.rs b/src/internal/onceinit.rs index 325d94a..6df2817 100644 --- a/src/internal/onceinit.rs +++ b/src/internal/onceinit.rs @@ -1,9 +1,9 @@ //! According to PyO3 updates, we can write `__init__` methods inside the Rust, which allows developers //! to use classes as subclass in Python. //! -//! All of classes must implement `__new__` and `__init__` methods. +//! All classes must implement `__new__` and `__init__` methods. //! - In `__new__` methods, we should allocate memory for the type; -//! - And in `__init__` methods, we should initialize and constrcut the type, according to parameters. +//! - And in `__init__` methods, we should initialize and construct the type, according to parameters. //! //! There are types that help us to create these methods completely thread-safe. diff --git a/src/internal/pickle.rs b/src/internal/pickle.rs index 07d8a85..8b97171 100644 --- a/src/internal/pickle.rs +++ b/src/internal/pickle.rs @@ -138,7 +138,7 @@ pub struct Pickle(alias::PyObject); impl Pickle { /// Begin building a top-level pickle tuple with exactly `size` slots. #[inline] - pub fn builder<'py>(py: pyo3::Python<'py>, size: usize) -> pyo3::PyResult> { + pub fn builder(py: pyo3::Python, size: usize) -> pyo3::PyResult { PickleBuilder::new(py, size) } @@ -193,15 +193,15 @@ pub trait Builder: Sized + sealed::Receive { Ok(self) } - fn begin_tuple<'a>(&'a mut self, size: usize) -> pyo3::PyResult> { + fn begin_tuple(&mut self, size: usize) -> pyo3::PyResult> { TupleBuilder::new(self, size) } - fn begin_list<'a>(&'a mut self) -> pyo3::PyResult> { + fn begin_list(&mut self) -> pyo3::PyResult> { ListBuilder::new(self) } - fn begin_dict<'a>(&'a mut self) -> pyo3::PyResult> { + fn begin_dict(&mut self) -> pyo3::PyResult> { DictBuilder::new(self) } } diff --git a/src/internal/utils.rs b/src/internal/utils.rs index ce3f24b..e078c26 100644 --- a/src/internal/utils.rs +++ b/src/internal/utils.rs @@ -185,7 +185,7 @@ where /// # Safety /// The pointer must be valid, non-null, live Python object. #[inline(never)] -pub unsafe fn get_type_name<'a>(py: pyo3::Python<'a>, obj: *mut pyo3::ffi::PyObject) -> String { +pub unsafe fn get_type_name(py: pyo3::Python, obj: *mut pyo3::ffi::PyObject) -> String { use pyo3::types::PyStringMethods; use pyo3::types::PyTypeMethods; diff --git a/src/lib.rs b/src/lib.rs index 60ffb25..d5cad38 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,11 +1,10 @@ #[macro_use] mod macro_rules; mod hashbrown; -mod typeref; - pub mod internal; pub mod policies; pub mod pyclasses; +mod typeref; #[pyo3::pymodule] mod _core { @@ -83,18 +82,21 @@ mod _core { use crate::pyclasses::vttlcache::PyVTTLCacheKeys; #[pymodule_export] use crate::pyclasses::vttlcache::PyVTTLCacheValues; + #[pymodule_export] + #[allow(non_upper_case_globals)] + const __version__: &str = env!("CARGO_PKG_VERSION"); #[pymodule_init] pub fn init(m: &pyo3::Bound<'_, pyo3::types::PyModule>) -> pyo3::PyResult<()> { typeref::initialize_typeref(m.py()); - m.add("__version__", env!("CARGO_PKG_VERSION"))?; - - #[cfg(feature = "use-small-offset")] - m.add("_use_small_offset_feature", true)?; - - #[cfg(not(feature = "use-small-offset"))] - m.add("_use_small_offset_feature", false)?; + m.add( + "_use_small_offset_feature", + cfg_select! { + feature = "use-small-offset" => true, + not(feature = "use-small-offset") => false, + }, + )?; Ok(()) } diff --git a/src/policies/common.rs b/src/policies/common.rs index 9f657dc..926e44a 100644 --- a/src/policies/common.rs +++ b/src/policies/common.rs @@ -1,4 +1,4 @@ -//! Common implementations accross multiple policies +//! Common implementations across multiple policies use crate::internal::alias; use crate::internal::utils; diff --git a/src/policies/fifopolicy.rs b/src/policies/fifopolicy.rs index b4cdbf6..e071bc8 100644 --- a/src/policies/fifopolicy.rs +++ b/src/policies/fifopolicy.rs @@ -162,11 +162,10 @@ impl FIFOPolicy { #[inline] fn decrement_indexes(&mut self, start: usize, end: usize) { - #[cfg(not(feature = "use-small-offset"))] - const MAX_FRONT_OFFSET: usize = usize::MAX - isize::MAX as usize; - - #[cfg(feature = "use-small-offset")] - const MAX_FRONT_OFFSET: usize = u8::MAX as usize; + const MAX_FRONT_OFFSET: usize = cfg_select! { + feature = "use-small-offset" => u8::MAX as usize, + not(feature = "use-small-offset") => usize::MAX - isize::MAX as usize, + }; // Fast path: shifting the entire front is a single counter increment. // Guard against overflow; the full-normalization path below handles that case. @@ -255,7 +254,7 @@ impl PolicyExt for FIFOPolicy { fn get( &mut self, py: pyo3::Python, - key: &::Key, + key: &::Key, ) -> pyo3::PyResult> { let eq = |index: &usize| get_handle!(&self, *index).key().py_eq(py, key); match self.table.get(key.hash(), eq)? { @@ -300,7 +299,7 @@ impl PolicyExt for FIFOPolicy { let eq = |index: &usize| Ok::<_, pyo3::PyErr>(*index - self.front_offset == 0); let removed_key_table = self.table.remove_entry(front.key().hash(), eq).unwrap(); - if crate::hashbrown::util::unlikely(removed_key_table.is_none()) { + if hashbrown::util::unlikely(removed_key_table.is_none()) { unreachable!("popitem key not found in table"); } @@ -417,7 +416,7 @@ impl PolicyExt for FIFOPolicy { fn from_pickle( maxsize: usize, - getsizeof: Option, + getsizeof: Option, _global_ttl: Option, builded: pyo3::Bound<'_, pyo3::types::PyTuple>, ) -> pyo3::PyResult<(Self::Shared, Self)> { diff --git a/src/policies/lfupolicy.rs b/src/policies/lfupolicy.rs index 82010e8..f22c30b 100644 --- a/src/policies/lfupolicy.rs +++ b/src/policies/lfupolicy.rs @@ -319,7 +319,7 @@ impl PolicyExt for LFUPolicy { fn get( &mut self, py: pyo3::Python, - key: &::Key, + key: &::Key, ) -> pyo3::PyResult> { let cursor = self .table diff --git a/src/policies/lrupolicy.rs b/src/policies/lrupolicy.rs index 244cab9..9142a5f 100644 --- a/src/policies/lrupolicy.rs +++ b/src/policies/lrupolicy.rs @@ -168,7 +168,7 @@ impl PolicyExt for LRUPolicy { fn get( &mut self, py: pyo3::Python, - key: &::Key, + key: &::Key, ) -> pyo3::PyResult> { unsafe { let bucket = self @@ -338,7 +338,7 @@ impl PolicyExt for LRUPolicy { fn from_pickle( maxsize: usize, - getsizeof: Option, + getsizeof: Option, _global_ttl: Option, builded: pyo3::Bound<'_, pyo3::types::PyTuple>, ) -> pyo3::PyResult<(Self::Shared, Self)> { diff --git a/src/policies/mod.rs b/src/policies/mod.rs index 2c62800..1850443 100644 --- a/src/policies/mod.rs +++ b/src/policies/mod.rs @@ -1,12 +1,10 @@ pub mod common; -pub mod traits; - pub mod fifopolicy; pub mod lfupolicy; pub mod lrupolicy; pub mod nopolicy; pub mod rrpolicy; +pub mod traits; pub mod ttlpolicy; pub mod vttlpolicy; - pub mod wrapped; diff --git a/src/policies/nopolicy.rs b/src/policies/nopolicy.rs index 585878f..6511dd9 100644 --- a/src/policies/nopolicy.rs +++ b/src/policies/nopolicy.rs @@ -108,7 +108,7 @@ impl NoPolicy { } } -impl traits::PolicyExt for NoPolicy { +impl PolicyExt for NoPolicy { type Shared = Shared; type Handle = Handle; @@ -133,7 +133,7 @@ impl traits::PolicyExt for NoPolicy { fn get( &mut self, py: pyo3::Python, - key: &::Key, + key: &::Key, ) -> pyo3::PyResult> { let bucket = self.table.find(key.hash(), |x| key.py_eq(py, x.key()))?; Ok(bucket.map(|x| unsafe { x.as_ref() })) @@ -142,7 +142,7 @@ impl traits::PolicyExt for NoPolicy { fn entry<'a>( &'a mut self, py: pyo3::Python, - key: &::Key, + key: &::Key, shared: &'a Self::Shared, ) -> pyo3::PyResult, Self::Vacant<'a>>> { match self.table.find(key.hash(), |x| key.py_eq(py, x.key()))? { diff --git a/src/policies/rrpolicy.rs b/src/policies/rrpolicy.rs index 7797641..7db9ba5 100644 --- a/src/policies/rrpolicy.rs +++ b/src/policies/rrpolicy.rs @@ -135,7 +135,7 @@ impl PolicyExt for RRPolicy { fn get( &mut self, py: pyo3::Python, - key: &::Key, + key: &::Key, ) -> pyo3::PyResult> { let bucket = self.table.find(key.hash(), |x| key.py_eq(py, x.key()))?; Ok(bucket.map(|x| unsafe { x.as_ref() })) @@ -144,7 +144,7 @@ impl PolicyExt for RRPolicy { fn entry<'a>( &'a mut self, py: pyo3::Python, - key: &::Key, + key: &::Key, shared: &'a Self::Shared, ) -> pyo3::PyResult, Self::Vacant<'a>>> { match self.table.find(key.hash(), |x| key.py_eq(py, x.key()))? { diff --git a/src/policies/traits.rs b/src/policies/traits.rs index 99da9b2..7509949 100644 --- a/src/policies/traits.rs +++ b/src/policies/traits.rs @@ -41,7 +41,7 @@ pub trait VacantExt { /// Evicts one entry, freeing budget for a subsequent insert or replace. /// - /// This method is exists here because after calling [`PolicyExt::entry`], we can't use + /// This method is existing here because after calling [`PolicyExt::entry`], we can't use /// policy. /// /// # Errors @@ -68,10 +68,10 @@ pub trait SharedExt: Send + Sync { /// Returns the generation version. fn generation_version(&self) -> &utils::GenerationVersion; - /// Returns a reference to configued getsizeof function. + /// Returns a reference to configured getsizeof function. fn getsizeof(&self) -> &utils::GetsizeofFunction; - /// Returns a reference to configued getsizeof function. + /// Returns a reference to configured getsizeof function. fn global_ttl(&self) -> Option; /// Make a clone of `self`. @@ -97,7 +97,7 @@ pub trait PolicyExt: Sized { /// Returns the current total cumulative size consumed by all stored entries. fn current_size(&self) -> usize; - /// Looks up a handle by `hash` and `eq`, applying policy side-effects on hit. + /// Looks up a handle by `hash` and `eq`, applying policy side effects on hit. /// /// # Errors /// Returns `Err` if `eq` raises a Python exception. @@ -139,14 +139,14 @@ pub trait PolicyExt: Sized { /// Make a clone of `self`. fn clone_ref(&mut self, py: pyo3::Python) -> Self; - /// Buildes the pickle. + /// Builds the pickle. /// Should not add items to pickle more than the configured [`Self::PICKLE_SIZE`]. fn build_pickle( &self, tuple: &mut pickle::TupleBuilder<'_, pickle::PickleBuilder>, ) -> pyo3::PyResult<()>; - /// Loads the builded pickle. + /// Loads the built pickle. fn from_pickle( maxsize: usize, getsizeof: Option, diff --git a/src/policies/ttlpolicy.rs b/src/policies/ttlpolicy.rs index e430636..e53a358 100644 --- a/src/policies/ttlpolicy.rs +++ b/src/policies/ttlpolicy.rs @@ -252,11 +252,10 @@ impl TTLPolicy { #[inline] fn decrement_indexes(&mut self, start: usize, end: usize) { - #[cfg(not(feature = "use-small-offset"))] - const MAX_FRONT_OFFSET: usize = usize::MAX - isize::MAX as usize; - - #[cfg(feature = "use-small-offset")] - const MAX_FRONT_OFFSET: usize = u8::MAX as usize; + const MAX_FRONT_OFFSET: usize = cfg_select! { + feature = "use-small-offset" => u8::MAX as usize, + not(feature = "use-small-offset") => usize::MAX - isize::MAX as usize, + }; // Fast path: shifting the entire front is a single counter increment. // Guard against overflow; the full-normalization path below handles that case. @@ -323,7 +322,7 @@ impl TTLPolicy { let eq = |index: &usize| Ok::<_, pyo3::PyErr>((*index - self.front_offset) == 0); let removed_key_table = self.table.remove_entry(handle.key().hash(), eq).unwrap(); - if crate::hashbrown::util::unlikely(removed_key_table.is_none()) { + if hashbrown::util::unlikely(removed_key_table.is_none()) { unreachable!("popitem key not found in table"); } @@ -427,7 +426,7 @@ impl PolicyExt for TTLPolicy { let eq = |index: &usize| Ok::<_, pyo3::PyErr>(*index - self.front_offset == 0); let removed_key_table = self.table.remove_entry(front.key().hash(), eq).unwrap(); - if crate::hashbrown::util::unlikely(removed_key_table.is_none()) { + if hashbrown::util::unlikely(removed_key_table.is_none()) { unreachable!("popitem key not found in table"); } @@ -554,7 +553,7 @@ impl PolicyExt for TTLPolicy { fn from_pickle( maxsize: usize, - getsizeof: Option, + getsizeof: Option, global_ttl: Option, builded: pyo3::Bound<'_, pyo3::types::PyTuple>, ) -> pyo3::PyResult<(Self::Shared, Self)> { diff --git a/src/policies/vttlpolicy.rs b/src/policies/vttlpolicy.rs index e8e88c1..8d261e6 100644 --- a/src/policies/vttlpolicy.rs +++ b/src/policies/vttlpolicy.rs @@ -504,7 +504,7 @@ impl PolicyExt for VTTLPolicy { fn from_pickle( maxsize: usize, - getsizeof: Option, + getsizeof: Option, _global_ttl: Option, builded: pyo3::Bound<'_, pyo3::types::PyTuple>, ) -> pyo3::PyResult<(Self::Shared, Self)> { diff --git a/src/pyclasses/cache.rs b/src/pyclasses/cache.rs index 64829d3..886cfeb 100644 --- a/src/pyclasses/cache.rs +++ b/src/pyclasses/cache.rs @@ -156,12 +156,12 @@ impl PyCache { #[inline] fn __sizeof__(&self) -> usize { - const FIXED_SIZE: usize = std::mem::size_of::>(); + const FIXED_SIZE: usize = size_of::>(); let inner = self.0.get(); let policy = inner.policy(); - FIXED_SIZE + (policy.table().capacity() * std::mem::size_of::()) + FIXED_SIZE + (policy.table().capacity() * size_of::()) } #[inline] @@ -312,13 +312,13 @@ impl PyCache { } } - /// Get `key`s value, or atomatically insert `default` and return it. + /// Get `key`s value, or automatically insert `default` and return it. /// /// If `key` exists, its current value is returned and `default` is ignored. - /// Otherwise `default` is inserted for `key` and returned. + /// Otherwise, `default` is inserted for `key` and returned. /// /// Use `setdefault_with`, if computing the value is expensive or has side - /// effectes. + /// effects. #[pyo3(signature = (key, default=utils::OptionalArgument::Undefined))] fn setdefault( &self, @@ -357,7 +357,7 @@ impl PyCache { Ok(default_object) } - /// Get `key`s value, or atomatically create and insert one via `factory`. + /// Get `key`s value, or automatically create and insert one via `factory`. /// /// If `key` exists, its current value is returned and `factory` is not called. /// Otherwise `factory` is called exactly once under an internal lock, its @@ -537,8 +537,8 @@ impl PyCache { let gv = inner.shared().generation_version().clone(); let initial_gv = gv.get(); - // SAFETY: We cannot use lifetimes here, but we're tracking changes using [`GenerationVersion`] let result = PyCacheItems { + // SAFETY: We cannot use lifetimes here, but we're tracking changes using [`GenerationVersion`] iter: parking_lot::Mutex::new(unsafe { inner.policy().table().iter() }), gv, initial_gv, @@ -552,8 +552,8 @@ impl PyCache { let gv = inner.shared().generation_version().clone(); let initial_gv = gv.get(); - // SAFETY: We cannot use lifetimes here, but we're tracking changes using [`GenerationVersion`] let result = PyCacheValues { + // SAFETY: We cannot use lifetimes here, but we're tracking changes using [`GenerationVersion`] iter: parking_lot::Mutex::new(unsafe { inner.policy().table().iter() }), gv, initial_gv, @@ -566,8 +566,8 @@ impl PyCache { let gv = inner.shared().generation_version().clone(); let initial_gv = gv.get(); - // SAFETY: We cannot use lifetimes here, but we're tracking changes using [`GenerationVersion`] let result = PyCacheKeys { + // SAFETY: We cannot use lifetimes here, but we're tracking changes using [`GenerationVersion`] iter: parking_lot::Mutex::new(unsafe { inner.policy().table().iter() }), gv, initial_gv, diff --git a/src/pyclasses/fifocache.rs b/src/pyclasses/fifocache.rs index 78556b3..a0b8133 100644 --- a/src/pyclasses/fifocache.rs +++ b/src/pyclasses/fifocache.rs @@ -163,13 +163,13 @@ impl PyFIFOCache { #[inline] fn __sizeof__(&self) -> usize { - const FIXED_SIZE: usize = std::mem::size_of::>(); + const FIXED_SIZE: usize = size_of::>(); let inner = self.0.get(); let policy = inner.policy(); - let table_cap = policy.table().capacity() * std::mem::size_of::(); - let vecdeque_cap = policy.entries().capacity() * std::mem::size_of::(); + let table_cap = policy.table().capacity() * size_of::(); + let vecdeque_cap = policy.entries().capacity() * size_of::(); FIXED_SIZE + table_cap + vecdeque_cap } @@ -318,7 +318,7 @@ impl PyFIFOCache { } } - /// Get `key`s value, or atomatically insert `default` and return it. + /// Get `key`s value, or automatically insert `default` and return it. /// /// If `key` exists, its current value is returned and `default` is ignored. /// Otherwise `default` is inserted for `key` and returned. @@ -363,7 +363,7 @@ impl PyFIFOCache { Ok(default_object) } - /// Get `key`s value, or atomatically create and insert one via `factory`. + /// Get `key`s value, or automatically create and insert one via `factory`. /// /// If `key` exists, its current value is returned and `factory` is not called. /// Otherwise `factory` is called exactly once under an internal lock, its diff --git a/src/pyclasses/lfucache.rs b/src/pyclasses/lfucache.rs index 1615a05..7d58393 100644 --- a/src/pyclasses/lfucache.rs +++ b/src/pyclasses/lfucache.rs @@ -179,13 +179,13 @@ impl PyLFUCache { #[inline] fn __sizeof__(&self) -> usize { - const FIXED_SIZE: usize = std::mem::size_of::>(); + const FIXED_SIZE: usize = size_of::>(); let inner = self.0.get(); let policy = inner.policy(); let table_cap = policy.table().capacity() * 8; - let list_cap = policy.heap().len() * std::mem::size_of::(); + let list_cap = policy.heap().len() * size_of::(); FIXED_SIZE + table_cap + list_cap } @@ -336,7 +336,7 @@ impl PyLFUCache { } } - /// Get `key`s value, or atomatically insert `default` and return it. + /// Get `key`s value, or automatically insert `default` and return it. /// /// If `key` exists, its current value is returned and `default` is ignored. /// Otherwise `default` is inserted for `key` and returned. @@ -382,10 +382,10 @@ impl PyLFUCache { Ok(default_object) } - /// Get `key`s value, or atomatically create and insert one via `factory`. + /// Get `key`s value, or automatically create and insert one via `factory`. /// /// If `key` exists, its current value is returned and `factory` is not called. - /// Otherwise `factory` is called exactly once under an internal lock, its + /// Otherwise, `factory` is called exactly once under an internal lock, its /// result is inserted and returned. /// /// Warning: `factory` must not call back into this cache (deadlock risk) or block diff --git a/src/pyclasses/lrucache.rs b/src/pyclasses/lrucache.rs index 14d4ec2..8b42299 100644 --- a/src/pyclasses/lrucache.rs +++ b/src/pyclasses/lrucache.rs @@ -189,13 +189,13 @@ impl PyLRUCache { #[inline] fn __sizeof__(&self) -> usize { - const FIXED_SIZE: usize = std::mem::size_of::>(); + const FIXED_SIZE: usize = size_of::>(); let inner = self.0.get(); let policy = inner.policy(); let table_cap = policy.table().capacity() * 8; - let list_cap = policy.list().len() * std::mem::size_of::(); + let list_cap = policy.list().len() * size_of::(); FIXED_SIZE + table_cap + list_cap } @@ -345,7 +345,7 @@ impl PyLRUCache { } } - /// Get `key`s value, or atomatically insert `default` and return it. + /// Get `key`s value, or automatically insert `default` and return it. /// /// If `key` exists, its current value is returned and `default` is ignored. /// Otherwise `default` is inserted for `key` and returned. @@ -390,7 +390,7 @@ impl PyLRUCache { Ok(default_object) } - /// Get `key`s value, or atomatically create and insert one via `factory`. + /// Get `key`s value, or automatically create and insert one via `factory`. /// /// If `key` exists, its current value is returned and `factory` is not called. /// Otherwise `factory` is called exactly once under an internal lock, its diff --git a/src/pyclasses/rrcache.rs b/src/pyclasses/rrcache.rs index f1ee98e..91a653e 100644 --- a/src/pyclasses/rrcache.rs +++ b/src/pyclasses/rrcache.rs @@ -160,12 +160,12 @@ impl PyRRCache { #[inline] fn __sizeof__(&self) -> usize { - const FIXED_SIZE: usize = std::mem::size_of::>(); + const FIXED_SIZE: usize = size_of::>(); let inner = self.0.get(); let policy = inner.policy(); - FIXED_SIZE + policy.table().capacity() * std::mem::size_of::() + FIXED_SIZE + policy.table().capacity() * size_of::() } #[inline] @@ -316,7 +316,7 @@ impl PyRRCache { } } - /// Get `key`s value, or atomatically insert `default` and return it. + /// Get `key`s value, or automatically insert `default` and return it. /// /// If `key` exists, its current value is returned and `default` is ignored. /// Otherwise `default` is inserted for `key` and returned. @@ -361,7 +361,7 @@ impl PyRRCache { Ok(default_object) } - /// Get `key`s value, or atomatically create and insert one via `factory`. + /// Get `key`s value, or automatically create and insert one via `factory`. /// /// If `key` exists, its current value is returned and `factory` is not called. /// Otherwise `factory` is called exactly once under an internal lock, its diff --git a/src/pyclasses/ttlcache.rs b/src/pyclasses/ttlcache.rs index 607deb4..9445811 100644 --- a/src/pyclasses/ttlcache.rs +++ b/src/pyclasses/ttlcache.rs @@ -10,7 +10,7 @@ use crate::policies::wrapped::Wrapped; implement_pyclass! { /// A Time-To-Live (TTL) cache eviction policy: each entry carries an expiration timestamp /// and is considered stale โ€” and eligible for eviction - once that deadline has passed, - /// regardless of how recently or frequently it was accessed. + /// regardless of how recently, or frequently it was accessed. [subclass, extends=crate::pyclasses::base::PyBaseCacheImpl, generic, frozen] PyTTLCache as "TTLCache" (onceinit::OnceInit>); } @@ -155,14 +155,13 @@ impl PyTTLCache { #[inline] fn __sizeof__(&self) -> usize { - const FIXED_SIZE: usize = std::mem::size_of::>(); + const FIXED_SIZE: usize = size_of::>(); let inner = self.0.get(); let policy = inner.policy(); - let table_cap = policy.table().capacity() * std::mem::size_of::(); - let vecdeque_cap = - policy.entries().capacity() * std::mem::size_of::(); + let table_cap = policy.table().capacity() * size_of::(); + let vecdeque_cap = policy.entries().capacity() * size_of::(); FIXED_SIZE + table_cap + vecdeque_cap } @@ -322,13 +321,13 @@ impl PyTTLCache { } } - /// Get `key`s value, or atomatically insert `default` and return it. + /// Get `key`s value, or automatically insert `default` and return it. /// /// If `key` exists, its current value is returned and `default` is ignored. - /// Otherwise `default` is inserted for `key` and returned. + /// Otherwise, `default` is inserted for `key` and returned. /// /// Use `setdefault_with`, if computing the value is expensive or has side - /// effectes. + /// effects. #[pyo3(signature = (key, default=utils::OptionalArgument::Undefined))] fn setdefault( &self, @@ -368,10 +367,10 @@ impl PyTTLCache { Ok(default_object) } - /// Get `key`s value, or atomatically create and insert one via `factory`. + /// Get `key`s value, or automatically create and insert one via `factory`. /// /// If `key` exists, its current value is returned and `factory` is not called. - /// Otherwise `factory` is called exactly once under an internal lock, its + /// Otherwise, `factory` is called exactly once under an internal lock, its /// result is inserted and returned. /// /// Warning: `factory` must not call back into this cache (deadlock risk) or block diff --git a/src/pyclasses/vttlcache.rs b/src/pyclasses/vttlcache.rs index ce597d0..32b19cf 100644 --- a/src/pyclasses/vttlcache.rs +++ b/src/pyclasses/vttlcache.rs @@ -143,13 +143,13 @@ impl PyVTTLCache { #[inline] fn __sizeof__(&self) -> usize { - const FIXED_SIZE: usize = std::mem::size_of::>(); + const FIXED_SIZE: usize = size_of::>(); let inner = self.0.get(); let policy = inner.policy(); let table_cap = policy.table().capacity() * 8; - let list_cap = policy.heap().len() * std::mem::size_of::(); + let list_cap = policy.heap().len() * size_of::(); FIXED_SIZE + table_cap + list_cap } diff --git a/tests/test_utils.py b/tests/test_utils.py index ee453d1..f262cb6 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -570,7 +570,7 @@ def run(): t.join(timeout=2.0) if t.is_alive(): - pytest.fail("deadlock happend - thread hung waiting on its own lock") + pytest.fail("deadlock happen - thread hung waiting on its own lock") assert "err" in result @@ -609,7 +609,7 @@ async def run(): try: await asyncio.wait_for(t, timeout=2.0) except TimeoutError: - pytest.fail("deadlock happend - task hung waiting on its own lock") + pytest.fail("deadlock happen - task hung waiting on its own lock") assert "err" in result diff --git a/typos.toml b/typos.toml new file mode 100644 index 0000000..3518788 --- /dev/null +++ b/typos.toml @@ -0,0 +1,13 @@ +[default.extend-words] +# error: `builded` should be `built` +# --> .\src\policies\ttlpolicy.rs:569:20 +# | +# 569 | let list = builded.get_item(0)?.cast_into::()?; +# | ^^^^^^^ +builded = "builded" +# error: `fo` should be `of`, `for`, `do`, `go`, `to` +# --> .\src\policies\fifopolicy.rs:212:66 +# | +# 212 | // - All others: (vd_idx + fo) - fo = vd_idx +# | ^^ +fo = "fo" \ No newline at end of file