Skip to content

Commit 1fd15b5

Browse files
authored
Merge pull request #270 from DanCardin/dc/kwonly
fix: kw_only dataclass inheritance mis-ordering.
2 parents 2160ccb + 07eb30e commit 1fd15b5

6 files changed

Lines changed: 37 additions & 4 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## 0.32
44

5+
### 0.32.1
6+
7+
- fix: kw_only dataclass inheritance mis-ordering.
8+
59
### 0.32.0
610
- feat: Add `epilog=` field on commands for text which should go after the argument help.
711
- refactor: All root objects (Command/Arg/Subcommand) to have "Final" variants which represent their post-normalization shape.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "cappa"
3-
version = "0.32.0"
3+
version = "0.32.1"
44
description = "Declarative CLI argument parser."
55

66
urls = { repository = "https://github.com/dancardin/cappa" }

src/cappa/command.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,9 @@ def collect(
217217
raw_subcommands.append((arg, None, None))
218218

219219
else:
220-
for field, param_view in zip(fields, function_view.parameters):
220+
param_by_name = {p.name: p for p in function_view.parameters}
221+
for field in fields:
222+
param_view = param_by_name[field.name]
221223
arg_help = help_text.args.get(param_view.name)
222224

223225
maybe_subcommand = Subcommand.detect(

tests/test_base.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import cappa
77
from cappa.command import Command
8-
from tests.utils import Backend, backends
8+
from tests.utils import Backend, backends, require_dataclass_kw_only
99

1010

1111
@backends
@@ -165,6 +165,27 @@ class Example: ...
165165
assert result == Example()
166166

167167

168+
@require_dataclass_kw_only
169+
@backends
170+
def test_kw_only_base_class_field_ordering(backend: Backend):
171+
kwargs = {"kw_only": True}
172+
173+
@dataclass(**kwargs)
174+
class Base:
175+
name: str = "hello"
176+
177+
@dataclass
178+
class Child(Base):
179+
number: int = 0
180+
181+
result = cappa.parse(
182+
cappa.Command(Child, default_long=True),
183+
argv=["--name", "world"],
184+
backend=backend,
185+
)
186+
assert result == Child(number=0, name="world")
187+
188+
168189
@backends
169190
def test_collect_skips_non_init_fields(backend: Backend):
170191
@dataclass

tests/utils.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import contextlib
44
import os
5+
import sys
56
from dataclasses import dataclass
67
from typing import Any, Union
78
from unittest.mock import patch
@@ -23,9 +24,14 @@
2324
"invoke",
2425
"invoke_async",
2526
"parse",
27+
"require_dataclass_kw_only",
2628
"runner",
2729
]
2830

31+
require_dataclass_kw_only = pytest.mark.skipif(
32+
sys.version_info < (3, 10), reason="kw_only requires Python 3.10+"
33+
)
34+
2935
backends = pytest.mark.parametrize(
3036
"backend",
3137
[

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)