File python-zxcvbn-rs-py-0.1.1+5.obscpio of Package python-zxcvbn-rs-py

07070100000000000081A40000000000000000000000016746D5B8000000CF000000000000000000000000000000000000002A00000000python-zxcvbn-rs-py-0.1.1+5/.editorconfig# http://editorconfig.org

root = true

[*]
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
insert_final_newline = true
charset = utf-8
end_of_line = lf

[*.{py,pyi,rs}]
indent_size = 4
07070100000001000041ED0000000000000000000000026746D5B800000000000000000000000000000000000000000000002400000000python-zxcvbn-rs-py-0.1.1+5/.github07070100000002000041ED0000000000000000000000026746D5B800000000000000000000000000000000000000000000002E00000000python-zxcvbn-rs-py-0.1.1+5/.github/workflows07070100000003000081A40000000000000000000000016746D5B800001301000000000000000000000000000000000000003500000000python-zxcvbn-rs-py-0.1.1+5/.github/workflows/CI.yml# This file is autogenerated by maturin v1.7.4
# To update, run
#
#    maturin generate-ci github
#
name: CI

on:
  push:
    branches:
      - main
      - master
    tags:
      - '*'
  pull_request:
  workflow_dispatch:

permissions:
  contents: read

jobs:
  linux:
    runs-on: ${{ matrix.platform.runner }}
    strategy:
      matrix:
        platform:
          - runner: ubuntu-latest
            target: x86_64
          - runner: ubuntu-latest
            target: x86
          - runner: ubuntu-latest
            target: aarch64
          - runner: ubuntu-latest
            target: armv7
          - runner: ubuntu-latest
            target: s390x
          - runner: ubuntu-latest
            target: ppc64le
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: 3.x
      - name: Build wheels
        uses: PyO3/maturin-action@v1
        with:
          target: ${{ matrix.platform.target }}
          args: --release --out dist --find-interpreter
          sccache: 'true'
          manylinux: auto
      - name: Upload wheels
        uses: actions/upload-artifact@v4
        with:
          name: wheels-linux-${{ matrix.platform.target }}
          path: dist

  musllinux:
    runs-on: ${{ matrix.platform.runner }}
    strategy:
      matrix:
        platform:
          - runner: ubuntu-latest
            target: x86_64
          - runner: ubuntu-latest
            target: x86
          - runner: ubuntu-latest
            target: aarch64
          - runner: ubuntu-latest
            target: armv7
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: 3.x
      - name: Build wheels
        uses: PyO3/maturin-action@v1
        with:
          target: ${{ matrix.platform.target }}
          args: --release --out dist --find-interpreter
          sccache: 'true'
          manylinux: musllinux_1_2
      - name: Upload wheels
        uses: actions/upload-artifact@v4
        with:
          name: wheels-musllinux-${{ matrix.platform.target }}
          path: dist

  windows:
    runs-on: ${{ matrix.platform.runner }}
    strategy:
      matrix:
        platform:
          - runner: windows-latest
            target: x64
          - runner: windows-latest
            target: x86
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: 3.x
          architecture: ${{ matrix.platform.target }}
      - name: Build wheels
        uses: PyO3/maturin-action@v1
        with:
          target: ${{ matrix.platform.target }}
          args: --release --out dist --find-interpreter
          sccache: 'true'
      - name: Upload wheels
        uses: actions/upload-artifact@v4
        with:
          name: wheels-windows-${{ matrix.platform.target }}
          path: dist

  macos:
    runs-on: ${{ matrix.platform.runner }}
    strategy:
      matrix:
        platform:
          - runner: macos-12
            target: x86_64
          - runner: macos-14
            target: aarch64
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: 3.x
      - name: Build wheels
        uses: PyO3/maturin-action@v1
        with:
          target: ${{ matrix.platform.target }}
          args: --release --out dist --find-interpreter
          sccache: 'true'
      - name: Upload wheels
        uses: actions/upload-artifact@v4
        with:
          name: wheels-macos-${{ matrix.platform.target }}
          path: dist

  sdist:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build sdist
        uses: PyO3/maturin-action@v1
        with:
          command: sdist
          args: --out dist
      - name: Upload sdist
        uses: actions/upload-artifact@v4
        with:
          name: wheels-sdist
          path: dist

  release:
    name: Release
    runs-on: ubuntu-latest
    if: ${{ startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' }}
    needs: [linux, musllinux, windows, macos, sdist]
    permissions:
      # Use to sign the release artifacts
      id-token: write
      # Used to upload release artifacts
      contents: write
      # Used to generate artifact attestation
      attestations: write
    steps:
      - uses: actions/download-artifact@v4
      - name: Generate artifact attestation
        uses: actions/attest-build-provenance@v1
        with:
          subject-path: 'wheels-*/*'
      - name: Publish to PyPI
        if: "startsWith(github.ref, 'refs/tags/')"
        uses: PyO3/maturin-action@v1
        env:
          MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
        with:
          command: upload
          args: --non-interactive --skip-existing wheels-*/*
07070100000004000081A40000000000000000000000016746D5B800000449000000000000000000000000000000000000004000000000python-zxcvbn-rs-py-0.1.1+5/.github/workflows/documentation.ymlname: Build documentation

on:
  push:
    branches:
      - main

# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
  contents: read
  pages: write
  id-token: write

# Allow one concurrent deployment
concurrency:
  group: "pages"
  cancel-in-progress: true

# Default to bash
defaults:
  run:
    shell: bash

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3
    - name: Set up Python
      uses: actions/setup-python@v4
      with:
        python-version: '3.10'
    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install hatch
        hatch env create
    - name: Build
      run: hatch run docs-build
    - name: Upload artifact
      uses: actions/upload-pages-artifact@v1
      with:
        path: ./site

  deploy:
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v1
07070100000005000081A40000000000000000000000016746D5B8000002A3000000000000000000000000000000000000002700000000python-zxcvbn-rs-py-0.1.1+5/.gitignore/target

# Byte-compiled / optimized / DLL files
__pycache__/
.pytest_cache/
*.py[cod]

# C extensions
*.so

# Distribution / packaging
.Python
.venv/
env/
bin/
build/
develop-eggs/
dist/
eggs/
lib/
lib64/
parts/
sdist/
var/
include/
man/
venv/
*.egg-info/
.installed.cfg
*.egg

# Installer logs
pip-log.txt
pip-delete-this-directory.txt
pip-selfcheck.json

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.cache
nosetests.xml
coverage.xml

# Translations
*.mo

# Mr Developer
.mr.developer.cfg
.project
.pydevproject

# Rope
.ropeproject

# Django stuff:
*.log
*.pot

.DS_Store

# Sphinx documentation
docs/_build/

# PyCharm
.idea/

# Pyenv
.python-version

venv*/
07070100000006000041ED0000000000000000000000026746D5B800000000000000000000000000000000000000000000002400000000python-zxcvbn-rs-py-0.1.1+5/.vscode07070100000007000081A40000000000000000000000016746D5B800000247000000000000000000000000000000000000003200000000python-zxcvbn-rs-py-0.1.1+5/.vscode/settings.json{
  "python.analysis.typeCheckingMode": "basic",
  "python.analysis.autoImportCompletions": true,
  "python.terminal.activateEnvironment": true,
  "python.terminal.activateEnvInCurrentTerminal": true,
  "python.testing.unittestEnabled": false,
  "editor.rulers": [88],
  "python.defaultInterpreterPath": "${workspaceFolder}/.hatch/zxcvbn-rs-py/bin/python",
  "[python]": {
    "editor.formatOnSave": true,
    "editor.codeActionsOnSave": {
      "source.fixAll": "explicit",
      "source.organizeImports": "explicit"
    },
    "editor.defaultFormatter": "charliermarsh.ruff"
  }
}
07070100000008000081A40000000000000000000000016746D5B800004490000000000000000000000000000000000000002700000000python-zxcvbn-rs-py-0.1.1+5/Cargo.lock# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3

[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
 "memchr",
]

[[package]]
name = "android-tzdata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"

[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
 "libc",
]

[[package]]
name = "autocfg"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"

[[package]]
name = "bit-set"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1"
dependencies = [
 "bit-vec",
]

[[package]]
name = "bit-vec"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"

[[package]]
name = "bumpalo"
version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"

[[package]]
name = "cc"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47"
dependencies = [
 "shlex",
]

[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"

[[package]]
name = "chrono"
version = "0.4.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
dependencies = [
 "android-tzdata",
 "iana-time-zone",
 "js-sys",
 "num-traits",
 "wasm-bindgen",
 "windows-targets",
]

[[package]]
name = "core-foundation-sys"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"

[[package]]
name = "darling"
version = "0.20.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
dependencies = [
 "darling_core",
 "darling_macro",
]

[[package]]
name = "darling_core"
version = "0.20.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5"
dependencies = [
 "fnv",
 "ident_case",
 "proc-macro2",
 "quote",
 "strsim",
 "syn",
]

[[package]]
name = "darling_macro"
version = "0.20.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
dependencies = [
 "darling_core",
 "quote",
 "syn",
]

[[package]]
name = "deranged"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
dependencies = [
 "powerfmt",
]

[[package]]
name = "derive_builder"
version = "0.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947"
dependencies = [
 "derive_builder_macro",
]

[[package]]
name = "derive_builder_core"
version = "0.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8"
dependencies = [
 "darling",
 "proc-macro2",
 "quote",
 "syn",
]

[[package]]
name = "derive_builder_macro"
version = "0.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c"
dependencies = [
 "derive_builder_core",
 "syn",
]

[[package]]
name = "either"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"

[[package]]
name = "fancy-regex"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "531e46835a22af56d1e3b66f04844bed63158bc094a628bec1d321d9b4c44bf2"
dependencies = [
 "bit-set",
 "regex-automata",
 "regex-syntax",
]

[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"

[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"

[[package]]
name = "iana-time-zone"
version = "0.1.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220"
dependencies = [
 "android_system_properties",
 "core-foundation-sys",
 "iana-time-zone-haiku",
 "js-sys",
 "wasm-bindgen",
 "windows-core",
]

[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
 "cc",
]

[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"

[[package]]
name = "indoc"
version = "2.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5"

[[package]]
name = "itertools"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
dependencies = [
 "either",
]

[[package]]
name = "js-sys"
version = "0.3.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9"
dependencies = [
 "wasm-bindgen",
]

[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"

[[package]]
name = "libc"
version = "0.2.164"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f"

[[package]]
name = "log"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"

[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"

[[package]]
name = "memoffset"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
dependencies = [
 "autocfg",
]

[[package]]
name = "num-conv"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"

[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
 "autocfg",
]

[[package]]
name = "once_cell"
version = "1.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"

[[package]]
name = "portable-atomic"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6"

[[package]]
name = "powerfmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"

[[package]]
name = "proc-macro2"
version = "1.0.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
dependencies = [
 "unicode-ident",
]

[[package]]
name = "pyo3"
version = "0.23.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f54b3d09cbdd1f8c20650b28e7b09e338881482f4aa908a5f61a00c98fba2690"
dependencies = [
 "cfg-if",
 "indoc",
 "libc",
 "memoffset",
 "once_cell",
 "portable-atomic",
 "pyo3-build-config",
 "pyo3-ffi",
 "pyo3-macros",
 "unindent",
]

[[package]]
name = "pyo3-build-config"
version = "0.23.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3015cf985888fe66cfb63ce0e321c603706cd541b7aec7ddd35c281390af45d8"
dependencies = [
 "once_cell",
 "target-lexicon",
]

[[package]]
name = "pyo3-ffi"
version = "0.23.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fca7cd8fd809b5ac4eefb89c1f98f7a7651d3739dfb341ca6980090f554c270"
dependencies = [
 "libc",
 "pyo3-build-config",
]

[[package]]
name = "pyo3-macros"
version = "0.23.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34e657fa5379a79151b6ff5328d9216a84f55dc93b17b08e7c3609a969b73aa0"
dependencies = [
 "proc-macro2",
 "pyo3-macros-backend",
 "quote",
 "syn",
]

[[package]]
name = "pyo3-macros-backend"
version = "0.23.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "295548d5ffd95fd1981d2d3cf4458831b21d60af046b729b6fd143b0ba7aee2f"
dependencies = [
 "heck",
 "proc-macro2",
 "pyo3-build-config",
 "quote",
 "syn",
]

[[package]]
name = "quote"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
dependencies = [
 "proc-macro2",
]

[[package]]
name = "regex"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
dependencies = [
 "aho-corasick",
 "memchr",
 "regex-automata",
 "regex-syntax",
]

[[package]]
name = "regex-automata"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
dependencies = [
 "aho-corasick",
 "memchr",
 "regex-syntax",
]

[[package]]
name = "regex-syntax"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"

[[package]]
name = "serde"
version = "1.0.215"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
dependencies = [
 "serde_derive",
]

[[package]]
name = "serde_derive"
version = "1.0.215"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
dependencies = [
 "proc-macro2",
 "quote",
 "syn",
]

[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"

[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"

[[package]]
name = "syn"
version = "2.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e"
dependencies = [
 "proc-macro2",
 "quote",
 "unicode-ident",
]

[[package]]
name = "target-lexicon"
version = "0.12.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"

[[package]]
name = "time"
version = "0.3.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
dependencies = [
 "deranged",
 "num-conv",
 "powerfmt",
 "serde",
 "time-core",
]

[[package]]
name = "time-core"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"

[[package]]
name = "unicode-ident"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"

[[package]]
name = "unindent"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce"

[[package]]
name = "wasm-bindgen"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e"
dependencies = [
 "cfg-if",
 "once_cell",
 "wasm-bindgen-macro",
]

[[package]]
name = "wasm-bindgen-backend"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358"
dependencies = [
 "bumpalo",
 "log",
 "once_cell",
 "proc-macro2",
 "quote",
 "syn",
 "wasm-bindgen-shared",
]

[[package]]
name = "wasm-bindgen-macro"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56"
dependencies = [
 "quote",
 "wasm-bindgen-macro-support",
]

[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68"
dependencies = [
 "proc-macro2",
 "quote",
 "syn",
 "wasm-bindgen-backend",
 "wasm-bindgen-shared",
]

[[package]]
name = "wasm-bindgen-shared"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d"

[[package]]
name = "web-sys"
version = "0.3.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112"
dependencies = [
 "js-sys",
 "wasm-bindgen",
]

[[package]]
name = "windows-core"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
 "windows-targets",
]

[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
 "windows_aarch64_gnullvm",
 "windows_aarch64_msvc",
 "windows_i686_gnu",
 "windows_i686_gnullvm",
 "windows_i686_msvc",
 "windows_x86_64_gnu",
 "windows_x86_64_gnullvm",
 "windows_x86_64_msvc",
]

[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"

[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"

[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"

[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"

[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"

[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"

[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"

[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"

[[package]]
name = "zxcvbn"
version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad76e35b00ad53688d6b90c431cabe3cbf51f7a4a154739e04b63004ab1c736c"
dependencies = [
 "chrono",
 "derive_builder",
 "fancy-regex",
 "itertools",
 "lazy_static",
 "regex",
 "time",
 "wasm-bindgen",
 "web-sys",
]

[[package]]
name = "zxcvbn-rs-py"
version = "0.1.1"
dependencies = [
 "pyo3",
 "zxcvbn",
]
07070100000009000081A40000000000000000000000016746D5B800000109000000000000000000000000000000000000002700000000python-zxcvbn-rs-py-0.1.1+5/Cargo.toml[package]
name = "zxcvbn-rs-py"
version = "0.1.1"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
name = "zxcvbn_rs_py"
crate-type = ["cdylib"]

[dependencies]
pyo3 = "^0.23"
zxcvbn = "3.1.0"
0707010000000A000081A40000000000000000000000016746D5B800000427000000000000000000000000000000000000002400000000python-zxcvbn-rs-py-0.1.1+5/LICENSEMIT License

Copyright (c) 2023, Fief

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

0707010000000B000081A40000000000000000000000016746D5B80000055E000000000000000000000000000000000000002600000000python-zxcvbn-rs-py-0.1.1+5/README.md# zxcvbn-rs-py

<p align="center">
    <em>Python bindings for <a href="https://github.com/shssoichiro/zxcvbn-rs">zxcvbn-rs</a>, the Rust implementation of zxcvbn</em>
</p>

[![build](https://github.com/fief-dev/zxcvbn-rs-py/workflows/CI/badge.svg)](https://github.com/fief-dev/zxcvbn-rs-py/actions)
[![PyPI version](https://badge.fury.io/py/zxcvbn-rs-py.svg)](https://badge.fury.io/py/zxcvbn-rs-py)

---

**Documentation**: <a href="https://fief-dev.github.io/zxcvbn-rs-py/" target="_blank">https://fief-dev.github.io/zxcvbn-rs-py/</a>

**Source Code**: <a href="https://github.com/fief-dev/zxcvbn-rs-py" target="_blank">https://github.com/fief-dev/zxcvbn-rs-py</a>

---

## Installation

```sh
pip install zxcvbn-rs-py
```

## Quickstart

```py
from zxcvbn_rs_py import zxcvbn

r = zxcvbn("correcthorsebatterystaple")
print(r.score)
```

## Benchmark

Thanks to its Rust core, zxcvbn-rs-py is **~5 times faster** than the pure Python implementation, [zxcvbn-python](https://github.com/dwolfhub/zxcvbn-python).

![zxcvbn-rs-py benchmark](https://raw.githubusercontent.com/fief-dev/zxcvbn-rs-py/main/benchmark/benchmark.svg?sanitize=true)

## Serve the documentation

You can serve the Mkdocs documentation with:

```bash
hatch run docs-serve
```

It'll automatically watch for changes in your code.

## License

This project is licensed under the terms of the MIT license.
0707010000000C000041ED0000000000000000000000026746D5B800000000000000000000000000000000000000000000002600000000python-zxcvbn-rs-py-0.1.1+5/benchmark0707010000000D000081A40000000000000000000000016746D5B800000122000000000000000000000000000000000000003400000000python-zxcvbn-rs-py-0.1.1+5/benchmark/benchmark.dat"Case"	"zxcvbn"	"zxcvbn_rs_py"
"Length 4"	0.1059061661362648	0.00814666599035263
"Length 8"	0.33018958382308483	0.044096667785197496
"Length 16"	0.645416583865881	0.0927467499859631
"Length 32"	2.0843886681832373	0.3682430819608271
"Repetition"	0.8810213343240321	0.09670516801998019
0707010000000E000081A40000000000000000000000016746D5B8000036E5000000000000000000000000000000000000003400000000python-zxcvbn-rs-py-0.1.1+5/benchmark/benchmark.svg<?xml version="1.0" encoding="utf-8"  standalone="no"?>
<svg 
 width="1280" height="800"
 viewBox="0 0 1280 800"
 xmlns="http://www.w3.org/2000/svg"
 xmlns:xlink="http://www.w3.org/1999/xlink"
>

<title>Gnuplot</title>
<desc>Produced by GNUPLOT 5.4 patchlevel 6 </desc>

<g id="gnuplot_canvas">

<rect x="0" y="0" width="1280" height="800" fill="#ffffff"/>
<defs>

	<circle id='gpDot' r='0.5' stroke-width='0.5' stroke='currentColor'/>
	<path id='gpPt0' stroke-width='0.222' stroke='currentColor' d='M-1,0 h2 M0,-1 v2'/>
	<path id='gpPt1' stroke-width='0.222' stroke='currentColor' d='M-1,-1 L1,1 M1,-1 L-1,1'/>
	<path id='gpPt2' stroke-width='0.222' stroke='currentColor' d='M-1,0 L1,0 M0,-1 L0,1 M-1,-1 L1,1 M-1,1 L1,-1'/>
	<rect id='gpPt3' stroke-width='0.222' stroke='currentColor' x='-1' y='-1' width='2' height='2'/>
	<rect id='gpPt4' stroke-width='0.222' stroke='currentColor' fill='currentColor' x='-1' y='-1' width='2' height='2'/>
	<circle id='gpPt5' stroke-width='0.222' stroke='currentColor' cx='0' cy='0' r='1'/>
	<use xlink:href='#gpPt5' id='gpPt6' fill='currentColor' stroke='none'/>
	<path id='gpPt7' stroke-width='0.222' stroke='currentColor' d='M0,-1.33 L-1.33,0.67 L1.33,0.67 z'/>
	<use xlink:href='#gpPt7' id='gpPt8' fill='currentColor' stroke='none'/>
	<use xlink:href='#gpPt7' id='gpPt9' stroke='currentColor' transform='rotate(180)'/>
	<use xlink:href='#gpPt9' id='gpPt10' fill='currentColor' stroke='none'/>
	<use xlink:href='#gpPt3' id='gpPt11' stroke='currentColor' transform='rotate(45)'/>
	<use xlink:href='#gpPt11' id='gpPt12' fill='currentColor' stroke='none'/>
	<path id='gpPt13' stroke-width='0.222' stroke='currentColor' d='M0,1.330 L1.265,0.411 L0.782,-1.067 L-0.782,-1.076 L-1.265,0.411 z'/>
	<use xlink:href='#gpPt13' id='gpPt14' fill='currentColor' stroke='none'/>
	<filter id='textbox' filterUnits='objectBoundingBox' x='0' y='0' height='1' width='1'>
	  <feFlood flood-color='#FFFFFF' flood-opacity='1' result='bgnd'/>
	  <feComposite in='SourceGraphic' in2='bgnd' operator='atop'/>
	</filter>
	<filter id='greybox' filterUnits='objectBoundingBox' x='0' y='0' height='1' width='1'>
	  <feFlood flood-color='lightgrey' flood-opacity='1' result='grey'/>
	  <feComposite in='SourceGraphic' in2='grey' operator='atop'/>
	</filter>
</defs>
<g fill="none" color="#FFFFFF" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
	<path stroke='black'  d='M72.53,742.40 L81.53,742.40 M1254.82,742.40 L1245.82,742.40  '/>	<g transform="translate(64.14,746.30)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="end">
		<text> 0</text>
	</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
	<path stroke='black'  d='M72.53,597.52 L81.53,597.52 M1254.82,597.52 L1245.82,597.52  '/>	<g transform="translate(64.14,601.42)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="end">
		<text> 0.5</text>
	</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
	<path stroke='black'  d='M72.53,452.64 L81.53,452.64 M1254.82,452.64 L1245.82,452.64  '/>	<g transform="translate(64.14,456.54)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="end">
		<text> 1</text>
	</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
	<path stroke='black'  d='M72.53,307.77 L81.53,307.77 M1254.82,307.77 L1245.82,307.77  '/>	<g transform="translate(64.14,311.67)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="end">
		<text> 1.5</text>
	</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
	<path stroke='black'  d='M72.53,162.89 L81.53,162.89 M1254.82,162.89 L1245.82,162.89  '/>	<g transform="translate(64.14,166.79)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="end">
		<text> 2</text>
	</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
	<path stroke='black'  d='M72.53,18.01 L81.53,18.01 M1254.82,18.01 L1245.82,18.01  '/>	<g transform="translate(64.14,21.91)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="end">
		<text> 2.5</text>
	</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
	<path stroke='black'  d='M269.58,742.40 L269.58,733.40 M269.58,18.01 L269.58,27.01  '/>	<g transform="translate(269.58,764.30)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="middle">
		<text>Length 4</text>
	</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
	<path stroke='black'  d='M466.63,742.40 L466.63,733.40 M466.63,18.01 L466.63,27.01  '/>	<g transform="translate(466.63,764.30)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="middle">
		<text>Length 8</text>
	</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
	<path stroke='black'  d='M663.68,742.40 L663.68,733.40 M663.68,18.01 L663.68,27.01  '/>	<g transform="translate(663.68,764.30)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="middle">
		<text>Length 16</text>
	</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
	<path stroke='black'  d='M860.72,742.40 L860.72,733.40 M860.72,18.01 L860.72,27.01  '/>	<g transform="translate(860.72,764.30)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="middle">
		<text>Length 32</text>
	</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
	<path stroke='black'  d='M1057.77,742.40 L1057.77,733.40 M1057.77,18.01 L1057.77,27.01  '/>	<g transform="translate(1057.77,764.30)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="middle">
		<text>Repetition</text>
	</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
	<path stroke='black'  d='M72.53,18.01 L72.53,742.40 L1254.82,742.40 L1254.82,18.01 L72.53,18.01 Z  '/></g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
	<g transform="translate(19.18,380.21) rotate(270)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="middle">
		<text>Milliseconds</text>
	</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
	<g transform="translate(663.67,791.30)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="middle">
		<text>Test cases</text>
	</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
	<g id="gnuplot_plot_1"  fill="none"><title>gnuplot_plot_1</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
	<g transform="translate(1187.09,39.91)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="end">
		<text>zxcvbn</text>
	</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
	<g stroke='none' shape-rendering='crispEdges'>
		<polygon fill = 'rgb(148,   0, 211)' points = '1195.48,40.51 1238.04,40.51 1238.04,31.51 1195.48,31.51 '/>
	</g>
	<path stroke='rgb(  0,   0,   0)'  d='M1195.48,40.51 L1238.04,40.51 L1238.04,31.51 L1195.48,31.51 L1195.48,40.51 Z  '/></g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
	<g stroke='none' shape-rendering='crispEdges'>
		<polygon fill = 'rgb(148,   0, 211)' points = '203.90,742.40 269.59,742.40 269.59,711.70 203.90,711.70 '/>
	</g>
	<path stroke='rgb(  0,   0,   0)'  d='M203.90,742.40 L203.90,711.71 L269.58,711.71 L269.58,742.40 L203.90,742.40 Z  '/></g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
	<g stroke='none' shape-rendering='crispEdges'>
		<polygon fill = 'rgb(148,   0, 211)' points = '400.94,742.40 466.64,742.40 466.64,646.72 400.94,646.72 '/>
	</g>
	<path stroke='rgb(  0,   0,   0)'  d='M400.94,742.40 L400.94,646.73 L466.63,646.73 L466.63,742.40 L400.94,742.40 Z  '/></g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
	<g stroke='none' shape-rendering='crispEdges'>
		<polygon fill = 'rgb(148,   0, 211)' points = '597.99,742.40 663.69,742.40 663.69,555.38 597.99,555.38 '/>
	</g>
	<path stroke='rgb(  0,   0,   0)'  d='M597.99,742.40 L597.99,555.39 L663.68,555.39 L663.68,742.40 L597.99,742.40 Z  '/></g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
	<g stroke='none' shape-rendering='crispEdges'>
		<polygon fill = 'rgb(148,   0, 211)' points = '795.04,742.40 860.73,742.40 860.73,138.43 795.04,138.43 '/>
	</g>
	<path stroke='rgb(  0,   0,   0)'  d='M795.04,742.40 L795.04,138.44 L860.72,138.44 L860.72,742.40 L795.04,742.40 Z  '/></g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
	<g stroke='none' shape-rendering='crispEdges'>
		<polygon fill = 'rgb(148,   0, 211)' points = '992.09,742.40 1057.78,742.40 1057.78,487.11 992.09,487.11 '/>
	</g>
	<path stroke='rgb(  0,   0,   0)'  d='M992.09,742.40 L992.09,487.12 L1057.77,487.12 L1057.77,742.40 L992.09,742.40 Z  '/></g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
	</g>
	<g id="gnuplot_plot_2"  fill="none"><title>gnuplot_plot_2</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
	<g transform="translate(1187.09,57.91)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="end">
		<text>zxcvbn_rs_py</text>
	</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
	<g stroke='none' shape-rendering='crispEdges'>
		<polygon fill = 'rgb(  0, 158, 115)' points = '1195.48,58.51 1238.04,58.51 1238.04,49.51 1195.48,49.51 '/>
	</g>
	<path stroke='rgb(  0,   0,   0)'  d='M1195.48,58.51 L1238.04,58.51 L1238.04,49.51 L1195.48,49.51 L1195.48,58.51 Z  '/></g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
	<g stroke='none' shape-rendering='crispEdges'>
		<polygon fill = 'rgb(  0, 158, 115)' points = '269.58,742.40 335.27,742.40 335.27,740.03 269.58,740.03 '/>
	</g>
	<path stroke='rgb(  0,   0,   0)'  d='M269.58,742.40 L269.58,740.04 L335.26,740.04 L335.26,742.40 L269.58,742.40 Z  '/></g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
	<g stroke='none' shape-rendering='crispEdges'>
		<polygon fill = 'rgb(  0, 158, 115)' points = '466.63,742.40 532.32,742.40 532.32,729.61 466.63,729.61 '/>
	</g>
	<path stroke='rgb(  0,   0,   0)'  d='M466.63,742.40 L466.63,729.62 L532.31,729.62 L532.31,742.40 L466.63,742.40 Z  '/></g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
	<g stroke='none' shape-rendering='crispEdges'>
		<polygon fill = 'rgb(  0, 158, 115)' points = '663.68,742.40 729.37,742.40 729.37,715.52 663.68,715.52 '/>
	</g>
	<path stroke='rgb(  0,   0,   0)'  d='M663.68,742.40 L663.68,715.53 L729.36,715.53 L729.36,742.40 L663.68,742.40 Z  '/></g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
	<g stroke='none' shape-rendering='crispEdges'>
		<polygon fill = 'rgb(  0, 158, 115)' points = '860.72,742.40 926.42,742.40 926.42,635.69 860.72,635.69 '/>
	</g>
	<path stroke='rgb(  0,   0,   0)'  d='M860.72,742.40 L860.72,635.70 L926.41,635.70 L926.41,742.40 L860.72,742.40 Z  '/></g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
	<g stroke='none' shape-rendering='crispEdges'>
		<polygon fill = 'rgb(  0, 158, 115)' points = '1057.77,742.40 1123.46,742.40 1123.46,714.37 1057.77,714.37 '/>
	</g>
	<path stroke='rgb(  0,   0,   0)'  d='M1057.77,742.40 L1057.77,714.38 L1123.45,714.38 L1123.45,742.40 L1057.77,742.40 Z  '/></g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
	</g>
<g fill="none" color="#FFFFFF" stroke="rgb(  0, 158, 115)" stroke-width="2.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="2.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
<g fill="none" color="black" stroke="black" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
	<path stroke='black'  d='M72.53,18.01 L72.53,742.40 L1254.82,742.40 L1254.82,18.01 L72.53,18.01 Z  '/></g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
</g>
</g>
</svg>

0707010000000F000081A40000000000000000000000016746D5B80000017A000000000000000000000000000000000000002F00000000python-zxcvbn-rs-py-0.1.1+5/benchmark/plot.pltset terminal svg size 1280,800 noenhanced background rgb 'white'
set output 'benchmark/benchmark.svg'

set style data histogram
set style histogram cluster gap 1

set style fill solid border rgb "black"
set auto x
set yrange [0:*]
set ylabel "Milliseconds"
set xlabel "Test cases"
plot 'benchmark/benchmark.dat' using 2:xtic(1) title col, \
        '' using 3:xtic(1) title col
07070100000010000081A40000000000000000000000016746D5B8000003A9000000000000000000000000000000000000002D00000000python-zxcvbn-rs-py-0.1.1+5/benchmark/run.pyimport csv
import timeit

LIBRARIES = [
    "zxcvbn",
    "zxcvbn_rs_py",
]

PASSWORDS = {
    "Length 4": "igrI",
    "Length 8": "UzA170rl",
    "Length 16": "pvmXR8ECp10UIRCs",
    "Length 32": "MtvEJJUM2K0mKAyWKy0emf6Bt9xyxrru",
    "Repetition": "a" * 16,
}

NB_LOOP = 500
REPEAT = 5

with open("benchmark/benchmark.dat", "w") as file:
    writer = csv.writer(file, delimiter="\t", quoting=csv.QUOTE_NONNUMERIC)
    writer.writerow(("Case", *LIBRARIES))
    for key, value in PASSWORDS.items():
        row = [key]
        print(f"Run benchmark for {key}...")
        for library in LIBRARIES:
            result = min(
                timeit.repeat(
                    f"zxcvbn('{value}')",
                    setup=f"from {library} import zxcvbn",
                    number=NB_LOOP,
                    repeat=REPEAT,
                )
            )
            row.append(result / NB_LOOP * 1000)
        writer.writerow(row)
07070100000011000081ED0000000000000000000000016746D5B8000000F8000000000000000000000000000000000000003000000000python-zxcvbn-rs-py-0.1.1+5/benchmark/script.sh# !/bin/bash

set -e

VENV=venv-bench
LIBRARIES=("zxcvbn" "zxcvbn-rs-py")

rm -rf $VENV
python -m venv $VENV

for LIBRARY in ${LIBRARIES[@]}
do
  ./$VENV/bin/pip install $LIBRARY
done

./$VENV/bin/python benchmark/run.py
gnuplot benchmark/plot.plt
07070100000012000041ED0000000000000000000000026746D5B800000000000000000000000000000000000000000000002100000000python-zxcvbn-rs-py-0.1.1+5/docs07070100000013000081A40000000000000000000000016746D5B800000013000000000000000000000000000000000000002A00000000python-zxcvbn-rs-py-0.1.1+5/docs/index.md--8<-- "README.md"
07070100000014000041ED0000000000000000000000026746D5B800000000000000000000000000000000000000000000002B00000000python-zxcvbn-rs-py-0.1.1+5/docs/reference07070100000015000081A40000000000000000000000016746D5B800000157000000000000000000000000000000000000003B00000000python-zxcvbn-rs-py-0.1.1+5/docs/reference/zxcvbn_rs_py.md# Reference

::: zxcvbn_rs_py
    options:
      members:
      - CrackTimesDisplay
      - CrackTimesSeconds
      - Entropy
      - Feedback
      - Suggestion
      - Warning
      - zxcvbn
      show_root_heading: false
      show_source: false
      allow_inspection: false
      separate_signature: true
      show_if_no_docstring: true
07070100000016000081A40000000000000000000000016746D5B800000670000000000000000000000000000000000000002700000000python-zxcvbn-rs-py-0.1.1+5/mkdocs.ymlsite_name: zxcvbn-rs-py
site_description: zxcvbn password strength library for Python using Rust bindings

repo_url: https://github.com/fief-dev/zxcvbn-rs-py
repo_name: fief-dev/zxcvbn-rs-py

theme:
    name: material
    icon:
        logo: material/key-chain-variant
    palette:
        # Palette toggle for light mode
        - media: "(prefers-color-scheme: light)"
          scheme: default
          primary: black
          accent: amber
          toggle:
            icon: material/brightness-7
            name: Switch to dark mode

        # Palette toggle for dark mode
        - media: "(prefers-color-scheme: dark)"
          scheme: slate
          primary: black
          accent: amber
          toggle:
            icon: material/brightness-4
            name: Switch to light mode
    features:
      - navigation.instant
      - navigation.expand
      - navigation.indexes
      - navigation.top
      - search.suggest
      - search.highlight
      - content.code.copy

markdown_extensions:
    - toc:
        permalink: true
    - pymdownx.highlight:
        anchor_linenums: true
    - pymdownx.tasklist:
        custom_checkbox: true
    - pymdownx.inlinehilite
    - pymdownx.snippets
    - pymdownx.superfences

plugins:
    - search
    - mkdocstrings:
        handlers:
            python:
                paths: [./zxcvbn_rs_py]
                import:
                    - https://docs.python.org/3.10/objects.inv
                options:
                    docstring_style: google

watch:
    - docs
    - zxcvbn_rs_py

nav:
    - About: index.md
    - Reference:
        - zxcvbn_rs_py: reference/zxcvbn_rs_py.md
07070100000017000081A40000000000000000000000016746D5B800000504000000000000000000000000000000000000002B00000000python-zxcvbn-rs-py-0.1.1+5/pyproject.toml[build-system]
requires = ["maturin>=1.4.0,<2.0.0"]
build-backend = "maturin"

[project]
name = "zxcvbn-rs-py"
authors = [
  { name = "François Voron", email = "contact@fief.dev" }
]
description = "Python bindings for zxcvbn-rs, the Rust implementation of zxcvbn"
readme = "README.md"
requires-python = ">=3.9,<3.14"
dynamic = ["version"]
classifiers = [
    "Programming Language :: Rust",
    "Programming Language :: Python :: Implementation :: CPython",
    "Programming Language :: Python :: Implementation :: PyPy",
    "Topic :: Security",
]

[project.urls]
Documentation = "https://fief-dev.github.io/zxcvbn-rs-py/"
Source = "https://github.com/fief-dev/zxcvbn-rs-py"

[tool.maturin]
features = ["pyo3/extension-module"]

[tool.ruff]
target-version = "py39"

[tool.ruff.lint]
extend-select = ["I", "TRY", "UP"]

[tool.hatch]

[tool.hatch.envs.default]
installer = "uv"
python = "3.9"
dependencies = [
    "maturin",
    "mkdocs-material",
    "mkdocstrings[python]>=0.18",
    "black",
    "mypy",
    "ruff",
    "pip",
    "pytest",
]

[tool.hatch.envs.default.scripts]
lint = [
  "cargo fmt",
  "ruff format .",
  "ruff check --fix .",
]
lint-check = [
  "ruff format --check .",
  "ruff check .",
]
docs-serve = "mkdocs serve"
docs-build = "mkdocs build"
test = "pytest"
07070100000018000041ED0000000000000000000000026746D5B800000000000000000000000000000000000000000000002000000000python-zxcvbn-rs-py-0.1.1+5/src07070100000019000081A40000000000000000000000016746D5B800003BA8000000000000000000000000000000000000002700000000python-zxcvbn-rs-py-0.1.1+5/src/lib.rsextern crate zxcvbn;

use pyo3::exceptions::PyRuntimeError;
use pyo3::prelude::*;
use std::fmt;

#[pyclass(eq, eq_int)]
#[pyo3(module = "zxcvbn_rs_py")]
#[derive(Clone, PartialEq, Eq)]
pub enum Score {
    /// Can be cracked with 10^3 guesses or less.
    ZERO = 0,
    /// Can be cracked with 10^6 guesses or less.
    ONE,
    /// Can be cracked with 10^8 guesses or less.
    TWO,
    /// Can be cracked with 10^10 guesses or less.
    THREE,
    /// Requires more than 10^10 guesses to crack.
    FOUR,
}

fn match_score(score: zxcvbn::Score) -> Result<Score, PyErr> {
    match score {
        zxcvbn::Score::Zero => Ok(Score::ZERO),
        zxcvbn::Score::One => Ok(Score::ONE),
        zxcvbn::Score::Two => Ok(Score::TWO),
        zxcvbn::Score::Three => Ok(Score::THREE),
        zxcvbn::Score::Four => Ok(Score::FOUR),
        _ => {
            Err(PyRuntimeError::new_err(
                "zxcvbn entropy score must be in the range 0-4",
            ))
        }
    }
}

#[pyclass(eq, eq_int)]
#[pyo3(module = "zxcvbn_rs_py")]
#[derive(Clone, PartialEq, Eq)]
enum Warning {
    StraightRowsOfKeysAreEasyToGuess,
    ShortKeyboardPatternsAreEasyToGuess,
    RepeatsLikeAaaAreEasyToGuess,
    RepeatsLikeAbcAbcAreOnlySlightlyHarderToGuess,
    ThisIsATop10Password,
    ThisIsATop100Password,
    ThisIsACommonPassword,
    ThisIsSimilarToACommonlyUsedPassword,
    SequencesLikeAbcAreEasyToGuess,
    RecentYearsAreEasyToGuess,
    AWordByItselfIsEasyToGuess,
    DatesAreOftenEasyToGuess,
    NamesAndSurnamesByThemselvesAreEasyToGuess,
    CommonNamesAndSurnamesAreEasyToGuess,
}

impl fmt::Display for Warning {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Warning::StraightRowsOfKeysAreEasyToGuess => {
                write!(f, "Straight rows of keys are easy to guess.")
            }
            Warning::ShortKeyboardPatternsAreEasyToGuess => {
                write!(f, "Short keyboard patterns are easy to guess.")
            }
            Warning::RepeatsLikeAaaAreEasyToGuess => {
                write!(f, "Repeats like \"aaa\" are easy to guess.")
            }
            Warning::RepeatsLikeAbcAbcAreOnlySlightlyHarderToGuess => write!(
                f,
                "Repeats like \"abcabcabc\" are only slightly harder to guess than \"abc\"."
            ),
            Warning::ThisIsATop10Password => write!(f, "This is a top-10 common password."),
            Warning::ThisIsATop100Password => write!(f, "This is a top-100 common password."),
            Warning::ThisIsACommonPassword => write!(f, "This is a very common password."),
            Warning::ThisIsSimilarToACommonlyUsedPassword => {
                write!(f, "This is similar to a commonly used password.")
            }
            Warning::SequencesLikeAbcAreEasyToGuess => {
                write!(f, "Sequences like abc or 6543 are easy to guess.")
            }
            Warning::RecentYearsAreEasyToGuess => write!(f, "Recent years are easy to guess."),
            Warning::AWordByItselfIsEasyToGuess => write!(f, "A word by itself is easy to guess."),
            Warning::DatesAreOftenEasyToGuess => write!(f, "Dates are often easy to guess."),
            Warning::NamesAndSurnamesByThemselvesAreEasyToGuess => {
                write!(f, "Names and surnames by themselves are easy to guess.")
            }
            Warning::CommonNamesAndSurnamesAreEasyToGuess => {
                write!(f, "Common names and surnames are easy to guess.")
            }
        }
    }
}

#[pymethods]
impl Warning {
    fn __str__(&self) -> PyResult<String> {
        Ok(format!("{self}"))
    }
}

fn match_warning(warning: zxcvbn::feedback::Warning) -> Warning {
    match warning {
        zxcvbn::feedback::Warning::StraightRowsOfKeysAreEasyToGuess => {
            Warning::StraightRowsOfKeysAreEasyToGuess
        }
        zxcvbn::feedback::Warning::ShortKeyboardPatternsAreEasyToGuess => {
            Warning::ShortKeyboardPatternsAreEasyToGuess
        }
        zxcvbn::feedback::Warning::RepeatsLikeAaaAreEasyToGuess => {
            Warning::RepeatsLikeAaaAreEasyToGuess
        }
        zxcvbn::feedback::Warning::RepeatsLikeAbcAbcAreOnlySlightlyHarderToGuess => {
            Warning::RepeatsLikeAbcAbcAreOnlySlightlyHarderToGuess
        }
        zxcvbn::feedback::Warning::ThisIsATop10Password => Warning::ThisIsATop10Password,
        zxcvbn::feedback::Warning::ThisIsATop100Password => Warning::ThisIsATop100Password,
        zxcvbn::feedback::Warning::ThisIsACommonPassword => Warning::ThisIsACommonPassword,
        zxcvbn::feedback::Warning::ThisIsSimilarToACommonlyUsedPassword => {
            Warning::ThisIsSimilarToACommonlyUsedPassword
        }
        zxcvbn::feedback::Warning::SequencesLikeAbcAreEasyToGuess => {
            Warning::SequencesLikeAbcAreEasyToGuess
        }
        zxcvbn::feedback::Warning::RecentYearsAreEasyToGuess => Warning::RecentYearsAreEasyToGuess,
        zxcvbn::feedback::Warning::AWordByItselfIsEasyToGuess => {
            Warning::AWordByItselfIsEasyToGuess
        }
        zxcvbn::feedback::Warning::DatesAreOftenEasyToGuess => Warning::DatesAreOftenEasyToGuess,
        zxcvbn::feedback::Warning::NamesAndSurnamesByThemselvesAreEasyToGuess => {
            Warning::NamesAndSurnamesByThemselvesAreEasyToGuess
        }
        zxcvbn::feedback::Warning::CommonNamesAndSurnamesAreEasyToGuess => {
            Warning::CommonNamesAndSurnamesAreEasyToGuess
        }
    }
}

#[pyclass(eq, eq_int)]
#[pyo3(module = "zxcvbn_rs_py")]
#[derive(Clone, PartialEq, Eq)]
enum Suggestion {
    UseAFewWordsAvoidCommonPhrases,
    NoNeedForSymbolsDigitsOrUppercaseLetters,
    AddAnotherWordOrTwo,
    CapitalizationDoesntHelpVeryMuch,
    AllUppercaseIsAlmostAsEasyToGuessAsAllLowercase,
    ReversedWordsArentMuchHarderToGuess,
    PredictableSubstitutionsDontHelpVeryMuch,
    UseALongerKeyboardPatternWithMoreTurns,
    AvoidRepeatedWordsAndCharacters,
    AvoidSequences,
    AvoidRecentYears,
    AvoidYearsThatAreAssociatedWithYou,
    AvoidDatesAndYearsThatAreAssociatedWithYou,
}

impl fmt::Display for Suggestion {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Suggestion::UseAFewWordsAvoidCommonPhrases => {
                write!(f, "Use a few words, avoid common phrases.")
            }
            Suggestion::NoNeedForSymbolsDigitsOrUppercaseLetters => {
                write!(f, "No need for symbols, digits, or uppercase letters.")
            }
            Suggestion::AddAnotherWordOrTwo => {
                write!(f, "Add another word or two. Uncommon words are better.")
            }
            Suggestion::CapitalizationDoesntHelpVeryMuch => {
                write!(f, "Capitalization doesn't help very much.")
            }
            Suggestion::AllUppercaseIsAlmostAsEasyToGuessAsAllLowercase => write!(
                f,
                "All-uppercase is almost as easy to guess as all-lowercase."
            ),
            Suggestion::ReversedWordsArentMuchHarderToGuess => {
                write!(f, "Reversed words aren't much harder to guess.")
            }
            Suggestion::PredictableSubstitutionsDontHelpVeryMuch => write!(
                f,
                "Predictable substitutions like '@' instead of 'a' don't help very much."
            ),
            Suggestion::UseALongerKeyboardPatternWithMoreTurns => {
                write!(f, "Use a longer keyboard pattern with more turns.")
            }
            Suggestion::AvoidRepeatedWordsAndCharacters => {
                write!(f, "Avoid repeated words and characters.")
            }
            Suggestion::AvoidSequences => write!(f, "Avoid sequences."),
            Suggestion::AvoidRecentYears => write!(f, "Avoid recent years."),
            Suggestion::AvoidYearsThatAreAssociatedWithYou => {
                write!(f, "Avoid years that are associated with you.")
            }
            Suggestion::AvoidDatesAndYearsThatAreAssociatedWithYou => {
                write!(f, "Avoid dates and years that are associated with you.")
            }
        }
    }
}

#[pymethods]
impl Suggestion {
    fn __str__(&self) -> PyResult<String> {
        Ok(format!("{self}"))
    }
}

fn match_suggestion(suggestion: zxcvbn::feedback::Suggestion) -> Suggestion {
    match suggestion {
        zxcvbn::feedback::Suggestion::UseAFewWordsAvoidCommonPhrases => {
            Suggestion::UseAFewWordsAvoidCommonPhrases
        }
        zxcvbn::feedback::Suggestion::NoNeedForSymbolsDigitsOrUppercaseLetters => {
            Suggestion::NoNeedForSymbolsDigitsOrUppercaseLetters
        }
        zxcvbn::feedback::Suggestion::AddAnotherWordOrTwo => Suggestion::AddAnotherWordOrTwo,
        zxcvbn::feedback::Suggestion::CapitalizationDoesntHelpVeryMuch => {
            Suggestion::CapitalizationDoesntHelpVeryMuch
        }
        zxcvbn::feedback::Suggestion::AllUppercaseIsAlmostAsEasyToGuessAsAllLowercase => {
            Suggestion::AllUppercaseIsAlmostAsEasyToGuessAsAllLowercase
        }
        zxcvbn::feedback::Suggestion::ReversedWordsArentMuchHarderToGuess => {
            Suggestion::ReversedWordsArentMuchHarderToGuess
        }
        zxcvbn::feedback::Suggestion::PredictableSubstitutionsDontHelpVeryMuch => {
            Suggestion::PredictableSubstitutionsDontHelpVeryMuch
        }
        zxcvbn::feedback::Suggestion::UseALongerKeyboardPatternWithMoreTurns => {
            Suggestion::UseALongerKeyboardPatternWithMoreTurns
        }
        zxcvbn::feedback::Suggestion::AvoidRepeatedWordsAndCharacters => {
            Suggestion::AvoidRepeatedWordsAndCharacters
        }
        zxcvbn::feedback::Suggestion::AvoidSequences => Suggestion::AvoidSequences,
        zxcvbn::feedback::Suggestion::AvoidRecentYears => Suggestion::AvoidRecentYears,
        zxcvbn::feedback::Suggestion::AvoidYearsThatAreAssociatedWithYou => {
            Suggestion::AvoidYearsThatAreAssociatedWithYou
        }
        zxcvbn::feedback::Suggestion::AvoidDatesAndYearsThatAreAssociatedWithYou => {
            Suggestion::AvoidDatesAndYearsThatAreAssociatedWithYou
        }
    }
}

#[pyclass]
#[pyo3(module = "zxcvbn_rs_py")]
#[derive(Clone)]
struct Feedback {
    #[pyo3(get)]
    warning: Option<Warning>,
    #[pyo3(get)]
    suggestions: Vec<Suggestion>,
}

#[pyclass]
#[pyo3(module = "zxcvbn_rs_py")]
#[derive(Clone)]
struct CrackTimesSeconds {
    #[pyo3(get)]
    offline_fast_hashing_1e10_per_second: f64,
    #[pyo3(get)]
    offline_slow_hashing_1e4_per_second: f64,
    #[pyo3(get)]
    online_no_throttling_10_per_second: f64,
    #[pyo3(get)]
    online_throttling_100_per_hour: f64,
}

#[pyclass]
#[pyo3(module = "zxcvbn_rs_py")]
#[derive(Clone)]
struct CrackTimesDisplay {
    #[pyo3(get)]
    offline_fast_hashing_1e10_per_second: String,
    #[pyo3(get)]
    offline_slow_hashing_1e4_per_second: String,
    #[pyo3(get)]
    online_no_throttling_10_per_second: String,
    #[pyo3(get)]
    online_throttling_100_per_hour: String,
}

fn crack_time_seconds_to_float(crack_time: zxcvbn::time_estimates::CrackTimeSeconds) -> f64 {
    match crack_time {
        zxcvbn::time_estimates::CrackTimeSeconds::Integer(i) => i as f64,
        zxcvbn::time_estimates::CrackTimeSeconds::Float(f) => f,
    }
}

#[pyclass]
#[pyo3(module = "zxcvbn_rs_py")]
struct Entropy {
    /// Estimated guesses needed to crack the password
    #[pyo3(get)]
    guesses: u64,

    /// Order of magnitude of `guesses`
    #[pyo3(get)]
    guesses_log10: f64,

    /// List of back-of-the-envelope crack time estimations based on a few scenarios.
    #[pyo3(get)]
    crack_times_seconds: CrackTimesSeconds,

    /// Same as crack_times_seconds, with friendlier display string values.
    #[pyo3(get)]
    crack_times_display: CrackTimesDisplay,

    /// Overall strength score from 0-4.
    /// Any score less than 3 should be considered too weak.
    #[pyo3(get)]
    score: Score,

    /// Verbal feedback to help choose better passwords. Set when `score` <= 2.
    #[pyo3(get)]
    feedback: Option<Feedback>,

    /// The list of patterns the guess calculation was based on
    // sequence: Vec<Match>,

    /// How long it took to calculate the answer.
    #[pyo3(get)]
    calc_time: u128,
}

#[pyfunction]
#[pyo3(name = "zxcvbn", signature = (password, user_inputs=None))]
fn zxcvbn_rs_py_fn(password: &str, user_inputs: Option<Vec<String>>) -> PyResult<Entropy> {
    let user_inputs_unwrapped = user_inputs.unwrap_or_default();
    let user_inputs_vec: Vec<&str> = user_inputs_unwrapped.iter().map(|s| s.as_str()).collect();
    let string_slice: &[&str] = &user_inputs_vec;
    let estimate = zxcvbn::zxcvbn(password, string_slice);
    let feedback: Option<Feedback> = estimate.feedback().map(|f| Feedback {
            warning: f.warning().map(match_warning),
            suggestions: f
                .suggestions()
                .iter()
                .map(|s| match_suggestion(*s))
                .collect::<Vec<Suggestion>>()
                .to_vec(),
        });

    let crack_times = estimate.crack_times();
    let online_throttling_100_per_hour = crack_times.online_throttling_100_per_hour();
    let online_no_throttling_10_per_second = crack_times.online_no_throttling_10_per_second();
    let offline_slow_hashing_1e4_per_second = crack_times.offline_slow_hashing_1e4_per_second();
    let offline_fast_hashing_1e10_per_second = crack_times.offline_fast_hashing_1e10_per_second();

    Ok(Entropy {
        guesses: estimate.guesses(),
        guesses_log10: estimate.guesses_log10(),
        crack_times_seconds: CrackTimesSeconds {
            online_throttling_100_per_hour: crack_time_seconds_to_float(
                online_throttling_100_per_hour,
            ),
            online_no_throttling_10_per_second: crack_time_seconds_to_float(
                online_no_throttling_10_per_second,
            ),
            offline_slow_hashing_1e4_per_second: crack_time_seconds_to_float(
                offline_slow_hashing_1e4_per_second,
            ),
            offline_fast_hashing_1e10_per_second: crack_time_seconds_to_float(
                offline_fast_hashing_1e10_per_second,
            ),
        },
        crack_times_display: CrackTimesDisplay {
            online_throttling_100_per_hour: format!("{online_throttling_100_per_hour}"),
            online_no_throttling_10_per_second: format!("{online_no_throttling_10_per_second}"),
            offline_slow_hashing_1e4_per_second: format!("{offline_slow_hashing_1e4_per_second}"),
            offline_fast_hashing_1e10_per_second: format!("{offline_fast_hashing_1e10_per_second}"),
        },
        score: match_score(estimate.score())?,
        feedback,
        calc_time: estimate.calculation_time().as_millis(),
    })
}

#[pymodule]
#[pyo3(name = "zxcvbn_rs_py")]
fn zxcvbn_rs_py_module(m: &Bound<'_, PyModule>) -> PyResult<()> {
    m.add("__version__", env!("CARGO_PKG_VERSION"))?;
    m.add_class::<Score>()?;
    m.add_class::<Entropy>()?;
    m.add_class::<Warning>()?;
    m.add_class::<Suggestion>()?;
    m.add_class::<Feedback>()?;
    m.add_class::<CrackTimesDisplay>()?;
    m.add_class::<CrackTimesSeconds>()?;
    m.add_function(wrap_pyfunction!(zxcvbn_rs_py_fn, m)?)?;
    Ok(())
}
0707010000001A000041ED0000000000000000000000026746D5B800000000000000000000000000000000000000000000002200000000python-zxcvbn-rs-py-0.1.1+5/tests0707010000001B000081A40000000000000000000000016746D5B800000000000000000000000000000000000000000000002E00000000python-zxcvbn-rs-py-0.1.1+5/tests/__init__.py0707010000001C000081A40000000000000000000000016746D5B80000012E000000000000000000000000000000000000003700000000python-zxcvbn-rs-py-0.1.1+5/tests/test_zxcvbn_rs_py.pyimport pytest

from zxcvbn_rs_py import Score, zxcvbn


@pytest.mark.parametrize(
    "password,score",
    [
        ("correcthorsebatterystaple", Score.FOUR),
    ],
)
def test_zxcvbn_rs_py(password: str, score: Score) -> None:
    r = zxcvbn("correcthorsebatterystaple")
    assert r.score == score
0707010000001D000041ED0000000000000000000000026746D5B800000000000000000000000000000000000000000000002900000000python-zxcvbn-rs-py-0.1.1+5/zxcvbn_rs_py0707010000001E000081A40000000000000000000000016746D5B80000015B000000000000000000000000000000000000003500000000python-zxcvbn-rs-py-0.1.1+5/zxcvbn_rs_py/__init__.pyfrom .zxcvbn_rs_py import (
    CrackTimesDisplay,
    CrackTimesSeconds,
    Entropy,
    Feedback,
    Score,
    Suggestion,
    Warning,
    __version__,
    zxcvbn,
)

__all__ = [
    "CrackTimesDisplay",
    "CrackTimesSeconds",
    "Entropy",
    "Feedback",
    "Score",
    "Suggestion",
    "Warning",
    "__version__",
    "zxcvbn",
]
0707010000001F000081A40000000000000000000000016746D5B800000000000000000000000000000000000000000000003200000000python-zxcvbn-rs-py-0.1.1+5/zxcvbn_rs_py/py.typed07070100000020000081A40000000000000000000000016746D5B800000B6E000000000000000000000000000000000000003A00000000python-zxcvbn-rs-py-0.1.1+5/zxcvbn_rs_py/zxcvbn_rs_py.pyifrom enum import Enum, auto

__version__: str

class Warning(Enum):
    StraightRowsOfKeysAreEasyToGuess = auto()
    ShortKeyboardPatternsAreEasyToGuess = auto()
    RepeatsLikeAaaAreEasyToGuess = auto()
    RepeatsLikeAbcAbcAreOnlySlightlyHarderToGuess = auto()
    ThisIsATop10Password = auto()
    ThisIsATop100Password = auto()
    ThisIsACommonPassword = auto()
    ThisIsSimilarToACommonlyUsedPassword = auto()
    SequencesLikeAbcAreEasyToGuess = auto()
    RecentYearsAreEasyToGuess = auto()
    AWordByItselfIsEasyToGuess = auto()
    DatesAreOftenEasyToGuess = auto()
    NamesAndSurnamesByThemselvesAreEasyToGuess = auto()
    CommonNamesAndSurnamesAreEasyToGuess = auto()

class Suggestion(Enum):
    UseAFewWordsAvoidCommonPhrases = auto()
    NoNeedForSymbolsDigitsOrUppercaseLetters = auto()
    AddAnotherWordOrTwo = auto()
    CapitalizationDoesntHelpVeryMuch = auto()
    AllUppercaseIsAlmostAsEasyToGuessAsAllLowercase = auto()
    ReversedWordsArentMuchHarderToGuess = auto()
    PredictableSubstitutionsDontHelpVeryMuch = auto()
    UseALongerKeyboardPatternWithMoreTurns = auto()
    AvoidRepeatedWordsAndCharacters = auto()
    AvoidSequences = auto()
    AvoidRecentYears = auto()
    AvoidYearsThatAreAssociatedWithYou = auto()
    AvoidDatesAndYearsThatAreAssociatedWithYou = auto()

class Feedback:
    warning: Warning | None
    suggestions: list[Suggestion]

class CrackTimesSeconds:
    offline_fast_hashing_1e10_per_second: float
    offline_slow_hashing_1e4_per_second: float
    online_no_throttling_10_per_second: float
    online_throttling_100_per_hour: float

class CrackTimesDisplay:
    offline_fast_hashing_1e10_per_second: str
    offline_slow_hashing_1e4_per_second: str
    online_no_throttling_10_per_second: str
    online_throttling_100_per_hour: str

class Entropy:
    """Result of a password strength check."""

    guesses: int
    """Estimated guesses needed to crack the password"""

    guesses_log10: float
    """Order of magnitude of `guesses`."""

    crack_times_seconds: CrackTimesSeconds
    """List of back-of-the-envelope crack time estimations based on a few scenarios."""

    crack_times_display: CrackTimesDisplay
    """Same as crack_times_seconds, with friendlier display string values."""

    score: int
    """
    Overall strength score from 0-4.
    Any score less than 3 should be considered too weak.
    """

    feedback: Feedback | None
    """Verbal feedback to help choose better passwords. Set when `score` <= 2."""

    calc_time: int
    """How long it took to calculate the answer."""

def zxcvbn(password: str, user_inputs: list[str] | None = None) -> Entropy:
    """
    Measure the strength of a password.

    Args:
        password: The password to check.
        user_inputs: Optional list of strings input by the user
        in other fields to match against the password.

    Returns:
        An `Entropy` object.
    """
    ...
07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!139 blocks
openSUSE Build Service is sponsored by