Skip to content

Commit 6cb92ec

Browse files
authored
Declare 3.13 support and drop 3.9 (#184)
1 parent ae78f56 commit 6cb92ec

File tree

9 files changed

+89
-79
lines changed

9 files changed

+89
-79
lines changed

.github/workflows/check.yml

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,44 +14,35 @@ concurrency:
1414

1515
jobs:
1616
test:
17-
name: test on CPython ${{ matrix.py }}
17+
name: test ${{ matrix.py }}
1818
runs-on: ubuntu-latest
1919
strategy:
2020
fail-fast: false
2121
matrix:
2222
py:
23+
- "3.13"
2324
- "3.12"
2425
- "3.11"
2526
- "3.10"
26-
- "3.9"
2727
steps:
28+
- name: setup uv for tox
29+
uses: yezz123/setup-uv@v4
2830
- name: setup python for tox
2931
uses: actions/setup-python@v5
3032
with:
3133
python-version: "3.12"
3234
- name: install tox
33-
run: python -m pip install tox-uv
35+
run: uv pip install tox tox-uv --system
3436
- uses: actions/checkout@v4
3537
- name: setup python for test ${{ matrix.py }}
3638
uses: actions/setup-python@v5
3739
with:
3840
python-version: ${{ matrix.py }}
39-
- name: Pick environment to run
40-
run: |
41-
import codecs; import os; import sys
42-
env = f"TOXENV=py3{sys.version_info[1]}\n"
43-
print(f"Picked:\n{env}for{sys.version}")
44-
with codecs.open(os.environ["GITHUB_ENV"], "a", "utf-8") as file_handler:
45-
file_handler.write(env)
46-
shell: python
41+
allow-prereleases: true
4742
- name: setup test suite
48-
run: tox -vv --notest
43+
run: tox run -vv --notest --skip-missing-interpreters false -e ${{ matrix.py }}
4944
- name: run test suite
50-
run: tox --skip-pkg-install
51-
env:
52-
PYTEST_ADDOPTS: "-vv --durations=20"
53-
CI_RUN: "yes"
54-
DIFF_AGAINST: HEAD
45+
run: tox run --skip-pkg-install -e ${{ matrix.py }}
5546

5647
check:
5748
name: tox env ${{ matrix.tox_env }}
@@ -62,16 +53,18 @@ jobs:
6253
tox_env:
6354
- type
6455
- dev
65-
- pkg_check
56+
- readme
6657
steps:
58+
- name: setup uv for tox
59+
uses: yezz123/setup-uv@v4
6760
- uses: actions/checkout@v4
6861
- name: setup Python 3.12
6962
uses: actions/setup-python@v5
7063
with:
7164
python-version: "3.12"
7265
- name: install tox
73-
run: python -m pip install tox
74-
- name: run check for ${{ matrix.tox_env }}
75-
run: python -m tox -e ${{ matrix.tox_env }}
76-
env:
77-
UPGRADE_ADVISORY: "yes"
66+
run: uv pip install tox tox-uv --system
67+
- name: Setup test suite
68+
run: tox -vv --notest --skip-missing-interpreters false -e ${{ matrix.tox_env }}
69+
- name: Run test suite
70+
run: tox --skip-pkg-install -e ${{ matrix.tox_env }}

.github/workflows/release.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@ jobs:
1616
uses: actions/setup-python@v5
1717
with:
1818
python-version: "3.12"
19+
- name: setup uv for tox
20+
uses: yezz123/setup-uv@v4
1921
- name: Install build
20-
run: python -m pip install build
22+
run: uv pip install build[uv] --system
2123
- uses: actions/checkout@v4
2224
with:
2325
fetch-depth: 0
2426
- name: Build package
25-
run: pyproject-build -s -w . -o dist
27+
run: pyproject-build --installer uv --sdist --wheel . --outdir dist
2628
- name: Publish to PyPI
2729
uses: pypa/[email protected]

.pre-commit-config.yaml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ repos:
88
rev: 0.29.2
99
hooks:
1010
- id: check-github-workflows
11-
args: [ "--verbose" ]
11+
args: ["--verbose"]
1212
- repo: https://github.com/codespell-project/codespell
1313
rev: v2.3.0
1414
hooks:
1515
- id: codespell
16-
args: ["--write-changes"]
16+
additional_dependencies: ["tomli>=2.0.1"]
1717
- repo: https://github.com/tox-dev/tox-ini-fmt
18-
rev: "1.3.1"
18+
rev: "1.3.2"
1919
hooks:
2020
- id: tox-ini-fmt
2121
args: ["-p", "fix"]
@@ -24,11 +24,16 @@ repos:
2424
hooks:
2525
- id: pyproject-fmt
2626
- repo: https://github.com/astral-sh/ruff-pre-commit
27-
rev: "v0.6.3"
27+
rev: "v0.6.4"
2828
hooks:
2929
- id: ruff-format
3030
- id: ruff
3131
args: ["--fix", "--unsafe-fixes", "--exit-non-zero-on-fix"]
32+
- repo: https://github.com/rbubley/mirrors-prettier
33+
rev: "v3.3.3"
34+
hooks:
35+
- id: prettier
36+
args: ["--print-width=120", "--prose-wrap=always"]
3237
- repo: meta
3338
hooks:
3439
- id: check-hooks-apply

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ All notable changes to this project will be documented in this file.
66

77
- Allow to add content to directive.
88
- Fix Sphinx warnings about parallel reads.
9-
- Add `force_args_lower` to enable `:ref:` links with mixed-case program names and arguments.
9+
- Add `force_args_lower` to enable `:ref:` links with mixed-case program names and arguments.
1010

1111
## 1.13.1
1212

README.md

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ Render CLI arguments (sub-commands friendly) defined by the argparse module. For
1818
python -m pip install sphinx-argparse-cli
1919
```
2020

21+
[README.md](README.md)
22+
2123
## enable in your `conf.py`
2224

2325
```python
@@ -29,22 +31,23 @@ extensions = ["sphinx_argparse_cli"]
2931

3032
Within the reStructuredText files use the `sphinx_argparse_cli` directive that takes, at least, two arguments:
3133

32-
| Name | Description |
33-
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
34-
| module | the module path to where the parser is defined |
35-
| func | the name of the function that once called with no arguments constructs the parser |
36-
| prog | (optional) when provided, overwrites the `<prog>` name. |
37-
| hook | (optional) hook `argparse` to retrieve the parser if `func` uses a parser instead of returning it. |
38-
| title | (optional) when provided, overwrites the `<prog> - CLI interface` title added by default and when empty, will not be included |
39-
| description | (optional) when provided, overwrites the description and when empty, will not be included |
40-
| epilog | (optional) when provided, overwrites the epilog and when empty, will not be included |
41-
| usage_width | (optional) how large should usage examples be - defaults to 100 character |
42-
| usage_first | (optional) show usage before description |
43-
| group_title_prefix | (optional) groups subsections title prefixes, accepts the string `{prog}` as a replacement for the program name - defaults to `{prog}` |
44-
| group_sub_title_prefix | (optional) subcommands groups subsections title prefixes, accepts replacement of `{prog}` and `{subcommand}` for program and subcommand name - defaults to `{prog} {subcommand}` |
45-
| no_default_values | (optional) suppresses generation of `default` entries |
46-
| force_refs_lower | (optional) Sphinx `:ref:` only supports lower-case references. With this, any capital letter in generated reference anchors are lowered and given an `_` prefix (i.e. `A` becomes `_a`) |
47-
For example:
34+
| Name | Description |
35+
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
36+
| module | the module path to where the parser is defined |
37+
| func | the name of the function that once called with no arguments constructs the parser |
38+
| prog | (optional) when provided, overwrites the `<prog>` name. |
39+
| hook | (optional) hook `argparse` to retrieve the parser if `func` uses a parser instead of returning it. |
40+
| title | (optional) when provided, overwrites the `<prog> - CLI interface` title added by default and when empty, will not be included |
41+
| description | (optional) when provided, overwrites the description and when empty, will not be included |
42+
| epilog | (optional) when provided, overwrites the epilog and when empty, will not be included |
43+
| usage_width | (optional) how large should usage examples be - defaults to 100 character |
44+
| usage_first | (optional) show usage before description |
45+
| group_title_prefix | (optional) groups subsections title prefixes, accepts the string `{prog}` as a replacement for the program name - defaults to `{prog}` |
46+
| group_sub_title_prefix | (optional) subcommands groups subsections title prefixes, accepts replacement of `{prog}` and `{subcommand}` for program and subcommand name - defaults to `{prog} {subcommand}` |
47+
| no_default_values | (optional) suppresses generation of `default` entries |
48+
| force_refs_lower | (optional) Sphinx `:ref:` only supports lower-case references. With this, any capital letter in generated reference anchors are lowered and given an `_` prefix (i.e. `A` becomes `_a`) |
49+
50+
> > > > > > > bda12fb (Declare 3.13 support and drop 3.9) For example:
4851
4952
```rst
5053
.. sphinx_argparse_cli::
@@ -86,11 +89,12 @@ being `cli`:
8689
- to refer to flag `--magic` of the `run` sub-command use ``:ref:`cli:tox-run---magic` ``.
8790

8891
Due to Sphinx's `:ref:` only supporting lower-case values, if you need to distinguish mixed case program names or
89-
arguments, set the `:force_refs_lower:` argument. With this flag, captial-letters in references will be converted to
90-
their lower-case counterpart and prefixed with an `_`. For example:
92+
arguments, set the `:force_refs_lower:` argument. With this flag, captial-letters in references will be converted to
93+
their lower-case counterpart and prefixed with an `_`. For example:
9194

9295
- A `prog` name `SampleProgram` will be referenced as ``:ref:`_sample_program...` ``.
93-
- To distinguish between mixed case flags `-a` and `-A` use ``:ref:`_sample_program--a` `` and ``:ref:`_sample_program--_a` `` respectively
96+
- To distinguish between mixed case flags `-a` and `-A` use ``:ref:`_sample_program--a` `` and
97+
``:ref:`_sample_program--_a` `` respectively
9498

9599
Note that if you are _not_ concernced about using internal Sphinx `:ref:` cross-references, you may choose to leave this
96100
off to maintain mixed-case anchors in your output HTML; but be aware that later enabling it will change your anchors in

pyproject.toml

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ license = "MIT"
1717
maintainers = [
1818
{ name = "Bernat Gabor", email = "[email protected]" },
1919
] # noqa: E999
20-
requires-python = ">=3.9"
20+
requires-python = ">=3.10"
2121
classifiers = [
2222
"Development Status :: 5 - Production/Stable",
2323
"Environment :: Console",
@@ -27,10 +27,10 @@ classifiers = [
2727
"License :: OSI Approved :: MIT License",
2828
"Operating System :: OS Independent",
2929
"Programming Language :: Python :: 3 :: Only",
30-
"Programming Language :: Python :: 3.9",
3130
"Programming Language :: Python :: 3.10",
3231
"Programming Language :: Python :: 3.11",
3332
"Programming Language :: Python :: 3.12",
33+
"Programming Language :: Python :: 3.13",
3434
"Programming Language :: Python :: Implementation :: CPython",
3535
"Topic :: Documentation",
3636
"Topic :: Documentation :: Sphinx",
@@ -39,12 +39,12 @@ dynamic = [
3939
"version",
4040
]
4141
dependencies = [
42-
"sphinx>=7.3.7",
42+
"sphinx>=8.0.2",
4343
]
4444
optional-dependencies.test = [
4545
"covdefaults>=2.3",
4646
"defusedxml>=0.7.1", # needed for sphinx.testing
47-
"pytest>=8.2.2",
47+
"pytest>=8.3.2",
4848
"pytest-cov>=5",
4949
]
5050
urls.Documentation = "https://github.com/tox-dev/sphinx-argparse-cli#sphinx-argparse-cli"
@@ -64,8 +64,11 @@ version.source = "vcs"
6464
line-length = 120
6565

6666
[tool.ruff]
67-
target-version = "py38"
67+
target-version = "py310"
6868
line-length = 120
69+
format.preview = true
70+
format.docstring-code-line-length = 100
71+
format.docstring-code-format = true
6972
lint.select = [
7073
"ALL",
7174
]
@@ -76,6 +79,7 @@ lint.ignore = [
7679
"CPY", # No copyright statements
7780
"D203", # `one-blank-line-before-class` (D203) and `no-blank-line-before-class` (D211) are incompatible
7881
"D212", # `multi-line-summary-first-line` (D212) and `multi-line-summary-second-line` (D213) are incompatible
82+
"DOC", # not yet supported
7983
"ISC001", # Conflict with formatter
8084
"S104", # Possible binding to all interface
8185
]
@@ -85,14 +89,14 @@ lint.per-file-ignores."roots/**/*.py" = [
8589
"INP001", # no namespace
8690
]
8791
lint.per-file-ignores."tests/**/*.py" = [
88-
"D", # don"t care about documentation in tests
89-
"FBT", # don"t care about booleans as positional arguments in tests
92+
"D", # don't care about documentation in tests
93+
"FBT", # don't care about booleans as positional arguments in tests
9094
"INP001", # no implicit namespace
9195
"PLC2701", # private import
9296
"PLR0913", # any number of arguments in tests
9397
"PLR0917", # any number of arguments in tests
9498
"PLR2004", # Magic value used in comparison, consider replacing with a constant variable
95-
"S101", # asserts allowed in tests...
99+
"S101", # asserts allowed in tests
96100
"S603", # `subprocess` call: check for execution of untrusted input
97101
]
98102
lint.isort = { known-first-party = [
@@ -105,6 +109,9 @@ lint.isort = { known-first-party = [
105109
builtin = "clear,usage,en-GB_to_en-US"
106110
count = true
107111

112+
[tool.pyproject-fmt]
113+
max_supported_python = "3.13"
114+
108115
[tool.coverage]
109116
html.show_contexts = true
110117
html.skip_covered = false
@@ -121,6 +128,6 @@ run.plugins = [
121128
run.relative_files = true
122129

123130
[tool.mypy]
124-
python_version = "3.11"
131+
python_version = "3.12"
125132
show_error_codes = true
126133
strict = true

src/sphinx_argparse_cli/_logic.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
)
1616
from collections import defaultdict
1717
from pathlib import Path
18-
from typing import TYPE_CHECKING, Any, ClassVar, Iterator, NamedTuple, cast
18+
from typing import TYPE_CHECKING, Any, ClassVar, NamedTuple, cast
1919

2020
from docutils.nodes import (
2121
Element,
@@ -41,6 +41,8 @@
4141
from sphinx.util.logging import getLogger
4242

4343
if TYPE_CHECKING:
44+
from collections.abc import Iterator
45+
4446
from docutils.parsers.rst.states import RSTState, RSTStateMachine
4547

4648

@@ -273,7 +275,7 @@ def _mk_option_line(self, action: Action, prefix: str) -> list_item:
273275
"no_default_values" not in self.options
274276
and action.default != SUPPRESS
275277
and not re.match(r".*[ (]default[s]? .*", (action.help or ""))
276-
and not isinstance(action, (_StoreTrueAction, _StoreFalseAction))
278+
and not isinstance(action, _StoreTrueAction | _StoreFalseAction)
277279
):
278280
line += Text(" (default: ")
279281
line += literal(text=str(action.default).replace(str(Path.cwd()), "{cwd}"))

tests/test_logic.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@
1818

1919
@pytest.fixture(scope="session")
2020
def opt_grp_name() -> tuple[str, str]:
21-
if sys.version_info >= (3, 10): # pragma: no branch # https://bugs.python.org/issue9694
22-
return "options", "options" # pragma: no cover
21+
return "options", "options" # pragma: no cover
2322
return "optional arguments", "optional-arguments" # pragma: no cover
2423

2524

0 commit comments

Comments
 (0)