diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 59aaa6b..f9ec440 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,27 +7,25 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [2.7, 3.6, 3.7, 3.8, 3.9] + python-version: + ["3.8.*", "3.9.*", "3.10.*", "3.11.*", "3.12.*", "3.13.*"] steps: - - uses: actions/checkout@master - - name: set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install -U setuptools - pip install -r requirements.txt - pip install . - - name: Run mypy - if: "matrix.python-version != '2.7' && matrix.python-version != 'pypy2'" - run: | + - uses: actions/checkout@master + - name: set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -U setuptools + pip install -r requirements.txt + pip install . + pip install tox + - name: Run mypy + run: | pip install -U mypy mypy -p zxcvbn --ignore-missing-imports - - name: Run tests - run: | - pytest -v - - name: Test Compatibility - run: | - python tests/test_compatibility.py tests/password_expected_value.json + - name: Run tests + run: | + tox diff --git a/README.rst b/README.rst index fb3d411..b41a3af 100644 --- a/README.rst +++ b/README.rst @@ -16,7 +16,7 @@ time. Features -------- -- **Tested in Python versions 2.7, 3.6-3.9** +- **Tested in Python versions 3.8-3.13** - Accepts user data to be added to the dictionaries that are tested against (name, birthdate, etc) - Gives a score to the password, from 0 (terrible) to 4 (great) - Provides feedback on the password and ways to improve it diff --git a/requirements.txt b/requirements.txt index e0fa86f..5ac1407 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,5 @@ -pytest==3.5.0 +# For older Python versions < 3.6 install Pytest 3.5.0 +pytest==3.5.0; python_version < "3.6" + +# For Python 3.6+, install a more modern Pytest: +pytest==7.4.2; python_version >= "3.6" diff --git a/tests/zxcvbn_test.py b/tests/zxcvbn_test.py index 6f1bda3..6dce19d 100644 --- a/tests/zxcvbn_test.py +++ b/tests/zxcvbn_test.py @@ -36,3 +36,12 @@ def test_dictionary_password(): assert result["feedback"]["warning"] == \ "A word by itself is easy to guess.", \ "Gives specific error for single-word passwords" + +def test_empty_password(): + input_ = None + password = "" + + try: + zxcvbn(password, user_inputs=[input_]) + except IndexError as ie: + assert False, "Empty password raised IndexError" diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..f73fe62 --- /dev/null +++ b/tox.ini @@ -0,0 +1,10 @@ +[tox] +envlist = py38, py39, py310, py311, py312, py313 +isolated_build = True + +[testenv] +deps = + pytest +commands = + pytest + python tests/test_compatibility.py tests/password_expected_value.json diff --git a/zxcvbn/scoring.py b/zxcvbn/scoring.py index 49fa13d..4e3cbc0 100644 --- a/zxcvbn/scoring.py +++ b/zxcvbn/scoring.py @@ -173,6 +173,10 @@ def make_bruteforce_match(i, j): # helper: step backwards through optimal.m starting at the end, # constructing the final optimal match sequence. def unwind(n): + if n == 0: + # return empty list for zero-length password + return [] + optimal_match_sequence = [] k = n - 1 # find the final best sequence length and score