Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,25 @@ jobs:

- name: Run tests
run: uv run --no-sync pytest -v

ruff:
name: Ruff ${{ matrix.command }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# check and format are separate so a failure names which one
command: ["check", "format --check"]
steps:
- uses: actions/checkout@v7

- name: Install uv
uses: astral-sh/setup-uv@v9.0.0
with:
enable-cache: true

- name: Install the project
run: uv sync --locked

- name: Run ruff ${{ matrix.command }}
run: uv run --no-sync ruff ${{ matrix.command }} .
76 changes: 75 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,10 @@ audible-quickstart = "audible_cli:quickstart"
[dependency-groups]
dev = [
"pyinstaller",
"pytest>=8.4.2"
"pytest>=8.4.2",
# Pinned: the enabled rule families pull in new stable rules on an
# upgrade, which would turn the gate red without a code change
"ruff==0.16.2"
]

[tool.hatch.build.targets.sdist]
Expand Down Expand Up @@ -105,6 +108,41 @@ src = ["src", "plugin_cmds", "utils"]
target-version = "py311"
output-format = "grouped"

[tool.ruff.format]
# Files the formatter has never run over. Take one off the list by
# running `ruff format` on it in a commit of its own.
exclude = [
"docs/source/conf.py",
"plugin_cmds/cmd_decrypt.py",
"plugin_cmds/cmd_get-annotations.py",
"plugin_cmds/cmd_goodreads-transform.py",
"plugin_cmds/cmd_image-urls.py",
"plugin_cmds/cmd_listening-stats.py",
"plugin_cmds/convert_oa_cred.py",
"plugin_cmds/README.md",
"pyi_entrypoint.py",
"README.md",
"src/audible_cli/cli.py",
"src/audible_cli/cmds/cmd_activation_bytes.py",
"src/audible_cli/cmds/cmd_api.py",
"src/audible_cli/cmds/cmd_download.py",
"src/audible_cli/cmds/cmd_library.py",
"src/audible_cli/cmds/cmd_manage.py",
"src/audible_cli/cmds/cmd_quickstart.py",
"src/audible_cli/cmds/cmd_wishlist.py",
"src/audible_cli/cmds/__init__.py",
"src/audible_cli/config.py",
"src/audible_cli/constants.py",
"src/audible_cli/decorators.py",
"src/audible_cli/downloader.py",
"src/audible_cli/_logging.py",
"src/audible_cli/__main__.py",
"src/audible_cli/models.py",
"src/audible_cli/plugins.py",
"src/audible_cli/utils.py",
"utils/update_chapter_titles.py",
]

[tool.ruff.lint]
ignore = [
"D10", # temporarily ignore missing docstrings
Expand Down Expand Up @@ -150,5 +188,41 @@ lines-after-imports = 2
[tool.ruff.lint.per-file-ignores]
"tests/*" = ["S101"]

# Baseline: findings that predate the Ruff gate. Each entry lists the rules a
# file already breaks. A new file, and a rule not listed for a file, both
# still fail; another violation of a rule already listed for that same file
# does not, because per-file-ignores keys on file and rule rather than on
# individual findings. Shrink the list by fixing a rule in a file and
# dropping its code here.
"docs/source/conf.py" = ["A001", "I001"]
"plugin_cmds/cmd_decrypt.py" = ["C401", "C417", "PLR0917", "PLW0108", "Q000", "RUF005", "RUF100", "UP006", "UP007", "UP045", "W291", "W293"]
"plugin_cmds/cmd_get-annotations.py" = ["F541", "I001"]
"plugin_cmds/cmd_goodreads-transform.py" = ["D202", "D415", "G004", "I001", "W293"]
"plugin_cmds/cmd_image-urls.py" = ["D415", "I001"]
"plugin_cmds/cmd_listening-stats.py" = ["C416", "D403", "D415", "I001", "Q000", "UP034"]
"plugin_cmds/convert_oa_cred.py" = ["A002", "C408", "D205", "D209", "D415", "I001", "Q000", "W291", "W293"]
"pyi_entrypoint.py" = ["Q000"]
"src/audible_cli/__init__.py" = ["RUF022", "UP009"]
"src/audible_cli/__main__.py" = ["I001"]
"src/audible_cli/_logging.py" = ["B028", "C408", "D205", "D209", "G004", "UP007", "UP045"]
"src/audible_cli/cli.py" = ["C408", "D415", "I001"]
"src/audible_cli/cmds/__init__.py" = ["D205", "D212", "D416", "I001"]
"src/audible_cli/cmds/cmd_activation_bytes.py" = ["I001"]
"src/audible_cli/cmds/cmd_api.py" = ["D415", "G004", "W291"]
"src/audible_cli/cmds/cmd_download.py" = ["ASYNC240", "C901", "D403", "D415", "G004", "I001", "PLR0917", "PLR5501", "PLW0603", "PLW2901", "RUF010", "S101", "UP015"]
"src/audible_cli/cmds/cmd_library.py" = ["D403", "D415", "I001"]
"src/audible_cli/cmds/cmd_manage.py" = ["D403", "D415", "PLR0917"]
"src/audible_cli/cmds/cmd_quickstart.py" = ["D415", "I001", "W291"]
"src/audible_cli/cmds/cmd_wishlist.py" = ["D403", "D415", "G004", "I001", "Q000"]
"src/audible_cli/config.py" = ["B904", "D202", "D415", "D416", "D417", "G004", "I001", "UP006", "UP007", "UP035", "UP045", "W291", "W293"]
"src/audible_cli/constants.py" = ["UP006", "UP035"]
"src/audible_cli/decorators.py" = ["B904", "D205", "D415", "F541", "G004", "I001", "RUF001", "UP035", "W293"]
"src/audible_cli/downloader.py" = ["G004", "PGH004", "PLR0917", "RUF100", "UP006", "UP007", "UP015", "UP035", "UP045", "W293"]
"src/audible_cli/exceptions.py" = ["D415", "UP032"]
"src/audible_cli/models.py" = ["B904", "D202", "D205", "D415", "F541", "G004", "I001", "S101", "UP006", "UP007", "UP035", "UP045", "W291", "W293"]
"src/audible_cli/plugins.py" = ["D200", "D201", "D202", "D205", "D212", "D415", "D416", "PGH004", "Q000", "RUF010", "RUF021", "RUF100", "UP007", "UP025", "UP031"]
"src/audible_cli/utils.py" = ["D202", "G004", "I001", "PGH004", "PLR0917", "UP006", "UP007", "UP035", "UP045"]
"utils/update_chapter_titles.py" = ["C408", "D205", "D212", "D415", "Q000", "S101", "W293"]

[tool.pytest.ini_options]
testpaths = ["tests"]
12 changes: 8 additions & 4 deletions tests/test_download_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,15 @@ def download(session, tmp_path, *extra):
return CliRunner().invoke(
cmd_download.cli,
[
"--asin", "ASIN0001",
"--asin",
"ASIN0001",
"--cover",
"--output-dir", str(tmp_path),
"--filename-mode", "ascii",
"--chapter-type", "flat",
"--output-dir",
str(tmp_path),
"--filename-mode",
"ascii",
"--chapter-type",
"flat",
*extra,
],
obj=session,
Expand Down
4 changes: 1 addition & 3 deletions tests/test_download_queue.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,7 @@ async def main():
for i, job in enumerate(jobs):
cmd_download.QUEUE.put_nowait((job, {"n": i}))

consumers = [
asyncio.create_task(consume(run)) for _ in range(sim_jobs)
]
consumers = [asyncio.create_task(consume(run)) for _ in range(sim_jobs)]
try:
await asyncio.wait_for(cmd_download.QUEUE.join(), timeout=timeout)
finally:
Expand Down
8 changes: 6 additions & 2 deletions tests/test_models_dates.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,14 @@ def test_items_without_any_date_are_kept_not_crashed_on(fields):
def test_date_added_branch_still_filters():
items = [
library_item(
"KEEP", purchase_date=None, library_status={"date_added": "2020-05-05T10:00:00Z"}
"KEEP",
purchase_date=None,
library_status={"date_added": "2020-05-05T10:00:00Z"},
),
library_item(
"DROP", purchase_date=None, library_status={"date_added": "2001-01-01T10:00:00Z"}
"DROP",
purchase_date=None,
library_status={"date_added": "2001-01-01T10:00:00Z"},
),
]

Expand Down
27 changes: 27 additions & 0 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading