diff --git a/.flake8 b/.flake8 deleted file mode 100644 index f4546adb..00000000 --- a/.flake8 +++ /dev/null @@ -1,2 +0,0 @@ -[flake8] -max_line_length = 88 diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 18758124..32007dea 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -13,7 +13,8 @@ pre-commit run --all-files # to run on all files now ## Docstrings -Follow [Google style](https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings) +Follow +[Google style](https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings) for docstrings. ## Localization diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 696a67a2..23960303 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -12,7 +12,10 @@ Please include **code** that reproduces the issue. -The [best reproductions](https://stackoverflow.com/help/minimal-reproducible-example) are [self-contained scripts](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) with minimal dependencies. +The [best reproductions](https://stackoverflow.com/help/minimal-reproducible-example) +are +[self-contained scripts](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) +with minimal dependencies. ```python code goes here diff --git a/.github/SECURITY.md b/.github/SECURITY.md index 198aa76f..74487a66 100644 --- a/.github/SECURITY.md +++ b/.github/SECURITY.md @@ -1,4 +1,4 @@ # Security policy -Security reports can be made via [Tidelift](https://tidelift.com/security). -Tidelift will coordinate the fix and disclosure. +Security reports can be made via [Tidelift](https://tidelift.com/security). Tidelift +will coordinate the fix and disclosure. diff --git a/.github/workflows/labels.yml b/.github/workflows/labels.yml index 90696d0a..859c9483 100644 --- a/.github/workflows/labels.yml +++ b/.github/workflows/labels.yml @@ -1,4 +1,8 @@ name: Sync labels + +permissions: + pull-requests: write + on: push: branches: diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 5e79664a..85097631 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -2,6 +2,12 @@ name: Lint on: [push, pull_request, workflow_dispatch] +env: + FORCE_COLOR: 1 + +permissions: + contents: read + jobs: lint: runs-on: ubuntu-latest diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2e18713a..decdc3c6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -24,7 +24,6 @@ jobs: allow-prereleases: true cache: pip - - name: Install Linux dependencies if: startsWith(matrix.os, 'ubuntu') run: | diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bf3a88c5..b190cffe 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,56 +1,24 @@ repos: - - repo: https://github.com/asottile/pyupgrade - rev: v3.14.0 + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.1.6 hooks: - - id: pyupgrade - args: [--py38-plus] + - id: ruff + args: [--fix, --exit-non-zero-on-fix] - repo: https://github.com/psf/black-pre-commit-mirror - rev: 23.9.1 + rev: 23.11.0 hooks: - id: black - - repo: https://github.com/PyCQA/isort - rev: 5.12.0 - hooks: - - id: isort - args: [--add-import=from __future__ import annotations] - - - repo: https://github.com/PyCQA/autoflake - rev: v2.2.1 - hooks: - - id: autoflake - name: autoflake - args: - [ - "--in-place", - "--remove-unused-variables", - "--remove-all-unused-imports", - ] - language: python - files: \.py$ - - - repo: https://github.com/PyCQA/flake8 - rev: 6.1.0 - hooks: - - id: flake8 - additional_dependencies: - [flake8-2020, flake8-errmsg, flake8-implicit-str-concat] - - - repo: https://github.com/pre-commit/pygrep-hooks - rev: v1.10.0 - hooks: - - id: python-check-blanket-noqa - - id: python-no-log-warn - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.5.0 hooks: - id: check-case-conflict - id: check-merge-conflict - id: check-json - id: check-toml - id: check-yaml + - id: debug-statements - id: end-of-file-fixer - id: trailing-whitespace exclude: \.github/ISSUE_TEMPLATE\.md|\.github/PULL_REQUEST_TEMPLATE\.md @@ -63,20 +31,20 @@ repos: files: "src/" - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.5.1 + rev: v1.7.0 hooks: - id: mypy additional_dependencies: [pytest, types-freezegun, types-setuptools] args: [--strict, --pretty, --show-error-codes] - repo: https://github.com/tox-dev/pyproject-fmt - rev: 1.2.0 + rev: 1.5.1 hooks: - id: pyproject-fmt additional_dependencies: [tox] - repo: https://github.com/abravalheri/validate-pyproject - rev: v0.14 + rev: v0.15 hooks: - id: validate-pyproject @@ -85,5 +53,17 @@ repos: hooks: - id: tox-ini-fmt + - repo: https://github.com/pre-commit/mirrors-prettier + rev: v3.1.0 + hooks: + - id: prettier + args: [--prose-wrap=always, --print-width=88] + exclude: \.github/ISSUE_TEMPLATE\.md|\.github/PULL_REQUEST_TEMPLATE\.md + + - repo: meta + hooks: + - id: check-hooks-apply + - id: check-useless-excludes + ci: autoupdate_schedule: quarterly diff --git a/README.md b/README.md index 51d52306..f4293062 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,9 @@ [![MIT License](https://img.shields.io/github/license/python-humanize/humanize.svg)](LICENCE) [![Tidelift](https://tidelift.com/badges/package/pypi/humanize)](https://tidelift.com/subscription/pkg/pypi-humanize?utm_source=pypi-humanize&utm_medium=badge) -This modest package contains various common humanization utilities, like turning -a number into a fuzzy human-readable duration ("3 minutes ago") or into a -human-readable size or throughput. It is localized to: +This modest package contains various common humanization utilities, like turning a +number into a fuzzy human-readable duration ("3 minutes ago") or into a human-readable +size or throughput. It is localized to: - Arabic - Basque diff --git a/RELEASING.md b/RELEASING.md index 5217c004..bc830b5d 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -1,8 +1,8 @@ # Release Checklist - [ ] Get `main` to the appropriate code release state. - [GitHub Actions](https://github.com/python-humanize/humanize/actions) should be running - cleanly for all merges to `main`. + [GitHub Actions](https://github.com/python-humanize/humanize/actions) should be + running cleanly for all merges to `main`. [![GitHub Actions status](https://github.com/python-humanize/humanize/workflows/Test/badge.svg)](https://github.com/python-humanize/humanize/actions) * [ ] Start from a freshly cloned repo: @@ -16,7 +16,7 @@ cd humanize scripts/generate-translation-binaries.sh ``` -* [ ] (Optional) Create a distribution and release on **TestPyPI**: +- [ ] (Optional) Create a distribution and release on **TestPyPI**: ```bash pip install -U pip build keyring twine @@ -33,13 +33,13 @@ pip3 install -U -i https://test.pypi.org/simple/ humanize --pre python3 -c "import humanize; print(humanize.__version__)" ``` -* [ ] Tag with the version number: +- [ ] Tag with the version number: ```bash git tag -a 2.1.0 -m "Release 2.1.0" ``` -* [ ] Create a distribution and release on **live PyPI**: +- [ ] Create a distribution and release on **live PyPI**: ```bash pip install -U pip build keyring twine @@ -48,7 +48,7 @@ python -m build twine check --strict dist/* && twine upload --repository pypi dist/* ``` -* [ ] Check installation: +- [ ] Check installation: ```bash pip uninstall -y humanize @@ -56,13 +56,15 @@ pip install -U humanize python3 -c "import humanize; print(humanize.__version__)" ``` -* [ ] Push tag: - ```bash +- [ ] Push tag: + +```bash git push --tags ``` -* [ ] Edit release draft, adjust text if needed: https://github.com/python-humanize/humanize/releases +- [ ] Edit release draft, adjust text if needed: + https://github.com/python-humanize/humanize/releases -* [ ] Check next tag is correct, amend if needed +- [ ] Check next tag is correct, amend if needed -* [ ] Publish release +- [ ] Publish release diff --git a/docs/index.md b/docs/index.md index 6cf2eb15..80d4bb24 100644 --- a/docs/index.md +++ b/docs/index.md @@ -2,10 +2,10 @@ Welcome to the humanize API reference. -* [Number](number.md) -* [Time](time.md) -* [Filesize](filesize.md) -* [I18n](i18n.md) +- [Number](number.md) +- [Time](time.md) +- [Filesize](filesize.md) +- [I18n](i18n.md) {% include-markdown "../README.md" diff --git a/pyproject.toml b/pyproject.toml index 431ef31a..5ba7c132 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -62,8 +62,31 @@ artifacts = [ [tool.hatch.version.raw-options] local_scheme = "no-local-version" -[tool.isort] -profile = "black" +[tool.ruff] +line-length = 88 +select = [ + "E", # pycodestyle errors + "EM", # flake8-errmsg + "F", # pyflakes errors + "I", # isort + "ISC", # flake8-implicit-str-concat + "PGH", # pygrep-hooks + "RUF100", # unused noqa (yesqa) + "UP", # pyupgrade + "W", # pycodestyle warnings + "YTT", # flake8-2020 + # "LOG", # TODO: enable flake8-logging when it's not in preview anymore +] +extend-ignore = [ + "E203", # Whitespace before ':' + "E221", # Multiple spaces before operator + "E226", # Missing whitespace around arithmetic operator + "E241", # Multiple spaces after ',' +] + +[tool.ruff.isort] +required-imports = ["from __future__ import annotations"] +known-first-party = ["humanize"] [tool.pytest.ini_options] addopts = "--color=yes" diff --git a/src/humanize/number.py b/src/humanize/number.py index ff0c7e25..9329c286 100644 --- a/src/humanize/number.py +++ b/src/humanize/number.py @@ -8,10 +8,9 @@ from typing import TYPE_CHECKING from .i18n import _gettext as _ -from .i18n import _ngettext +from .i18n import _ngettext, decimal_separator, thousands_separator from .i18n import _ngettext_noop as NS_ from .i18n import _pgettext as P_ -from .i18n import decimal_separator, thousands_separator if TYPE_CHECKING: if sys.version_info >= (3, 10): diff --git a/tests/test_number.py b/tests/test_number.py index bc677859..9bb94756 100644 --- a/tests/test_number.py +++ b/tests/test_number.py @@ -190,15 +190,15 @@ def test_fractional(test_input: float | str, expected: str) -> None: ([5781651000], "5.78 x 10⁹"), (["1000"], "1.00 x 10³"), (["99"], "9.90 x 10¹"), - ([float(0.3)], "3.00 x 10⁻¹"), + ([0.3], "3.00 x 10⁻¹"), (["foo"], "foo"), ([None], "None"), ([1000, 1], "1.0 x 10³"), - ([float(0.3), 1], "3.0 x 10⁻¹"), + ([0.3, 1], "3.0 x 10⁻¹"), ([1000, 0], "1 x 10³"), - ([float(0.3), 0], "3 x 10⁻¹"), - ([float(1e20)], "1.00 x 10²⁰"), - ([float(2e-20)], "2.00 x 10⁻²⁰"), + ([0.3, 0], "3 x 10⁻¹"), + ([1e20], "1.00 x 10²⁰"), + ([2e-20], "2.00 x 10⁻²⁰"), ([float(-3e20)], "-3.00 x 10²⁰"), ([float(-4e-20)], "-4.00 x 10⁻²⁰"), ([math.nan], "NaN"),