Declarative CLIs with argparse and dataclasses
npx @tessl/cli install tessl/pypi-argparse-dataclass@2.0.00
# Argparse Dataclass
1
2
A Python library that provides a declarative approach to building command-line interfaces by combining Python's argparse module with dataclasses. It enables developers to define CLI argument structures using dataclass syntax, automatically generating argument parsers that handle type conversion, default values, boolean flags, and argument validation.
3
4
## Package Information
5
6
- **Package Name**: argparse-dataclass
7
- **Language**: Python
8
- **Installation**: `pip install argparse-dataclass`
9
- **Minimum Python Version**: 3.8
10
11
## Core Imports
12
13
```python
14
from argparse_dataclass import dataclass, ArgumentParser, parse_args, parse_known_args
15
```
16
17
Standard dataclass import for use with ArgumentParser:
18
19
```python
20
from dataclasses import dataclass, field
21
from argparse_dataclass import ArgumentParser
22
```
23
24
## Basic Usage
25
26
### Using the Enhanced Dataclass Decorator
27
28
```python
29
from argparse_dataclass import dataclass
30
31
@dataclass
32
class Options:
33
x: int = 42
34
verbose: bool = False
35
36
# Parse arguments directly from the class
37
options = Options.parse_args(['--x', '10', '--verbose'])
38
print(options) # Options(x=10, verbose=True)
39
```
40
41
### Using ArgumentParser Class
42
43
```python
44
from dataclasses import dataclass, field
45
from argparse_dataclass import ArgumentParser
46
47
@dataclass
48
class Options:
49
name: str
50
count: int = 1
51
verbose: bool = False
52
53
parser = ArgumentParser(Options)
54
options = parser.parse_args(['--name', 'test', '--count', '5'])
55
print(options) # Options(name='test', count=5, verbose=False)
56
```
57
58
### Using Standalone Functions
59
60
```python
61
from dataclasses import dataclass
62
from argparse_dataclass import parse_args
63
64
@dataclass
65
class Options:
66
input_file: str
67
output_file: str = "output.txt"
68
69
options = parse_args(Options, ['--input-file', 'data.txt'])
70
print(options) # Options(input_file='data.txt', output_file='output.txt')
71
```
72
73
## Capabilities
74
75
### Enhanced Dataclass Decorator
76
77
An enhanced version of the standard dataclass decorator that adds a `parse_args` static method to the decorated class.
78
79
```python { .api }
80
def dataclass(
81
cls=None,
82
*,
83
init=True,
84
repr=True,
85
eq=True,
86
order=False,
87
unsafe_hash=False,
88
frozen=False
89
):
90
"""
91
Enhanced dataclass decorator that adds parse_args static method.
92
93
Parameters are identical to the standard dataclasses.dataclass decorator.
94
95
The decorated class gains a static method:
96
- parse_args(args=None): Parse command line arguments and return instance
97
98
Returns:
99
Decorated class with added parse_args static method
100
"""
101
```
102
103
Usage example:
104
105
```python
106
from argparse_dataclass import dataclass
107
108
@dataclass
109
class Config:
110
host: str = "localhost"
111
port: int = 8080
112
debug: bool = False
113
114
# Use the added parse_args method
115
config = Config.parse_args(['--host', 'example.com', '--port', '9000', '--debug'])
116
```
117
118
### ArgumentParser Class
119
120
A command-line argument parser that derives its options from a dataclass, extending the standard argparse.ArgumentParser.
121
122
```python { .api }
123
class ArgumentParser(argparse.ArgumentParser, Generic[OptionsType]):
124
"""
125
Command line argument parser that derives its options from a dataclass.
126
127
Parameters:
128
- options_class: Type[OptionsType] - The dataclass that defines the options
129
- *args, **kwargs - Passed along to argparse.ArgumentParser
130
"""
131
132
def __init__(self, options_class: Type[OptionsType], *args, **kwargs): ...
133
134
def parse_args(self, args: ArgsType = None, namespace=None) -> OptionsType:
135
"""
136
Parse arguments and return as the dataclass type.
137
138
Parameters:
139
- args: Optional[Sequence[str]] - Arguments to parse (defaults to sys.argv)
140
- namespace: Not supported (raises ValueError if provided)
141
142
Returns:
143
Instance of the dataclass with parsed values
144
"""
145
146
def parse_known_args(
147
self, args: ArgsType = None, namespace=None
148
) -> Tuple[OptionsType, List[str]]:
149
"""
150
Parse known arguments and return tuple containing dataclass type
151
and list of remaining arguments.
152
153
Parameters:
154
- args: Optional[Sequence[str]] - Arguments to parse
155
- namespace: Not supported (raises ValueError if provided)
156
157
Returns:
158
Tuple of (dataclass instance, list of remaining arguments)
159
"""
160
```
161
162
Usage example:
163
164
```python
165
from dataclasses import dataclass
166
from argparse_dataclass import ArgumentParser
167
168
@dataclass
169
class Settings:
170
config_path: str
171
workers: int = 4
172
enable_logging: bool = True
173
174
parser = ArgumentParser(Settings)
175
settings = parser.parse_args(['--config-path', '/etc/app.conf', '--workers', '8'])
176
```
177
178
### Standalone Parsing Functions
179
180
Functions that provide parsing capabilities without needing to instantiate an ArgumentParser.
181
182
```python { .api }
183
def parse_args(options_class: Type[OptionsType], args: ArgsType = None) -> OptionsType:
184
"""
185
Parse arguments and return as the dataclass type.
186
187
Parameters:
188
- options_class: Type[OptionsType] - The dataclass type to use for parsing
189
- args: Optional[Sequence[str]] - Arguments to parse (defaults to sys.argv)
190
191
Returns:
192
Instance of the dataclass with parsed values
193
"""
194
195
def parse_known_args(
196
options_class: Type[OptionsType], args: ArgsType = None
197
) -> Tuple[OptionsType, List[str]]:
198
"""
199
Parse known arguments and return tuple containing dataclass type
200
and list of remaining arguments.
201
202
Parameters:
203
- options_class: Type[OptionsType] - The dataclass type to use for parsing
204
- args: Optional[Sequence[str]] - Arguments to parse (defaults to sys.argv)
205
206
Returns:
207
Tuple of (dataclass instance, list of remaining arguments)
208
"""
209
```
210
211
Usage example:
212
213
```python
214
from dataclasses import dataclass
215
from argparse_dataclass import parse_args, parse_known_args
216
217
@dataclass
218
class Options:
219
input_dir: str
220
output_format: str = "json"
221
222
# Parse all arguments
223
options = parse_args(Options, ['--input-dir', '/data', '--output-format', 'xml'])
224
225
# Parse known arguments, ignore unknown ones
226
options, remaining = parse_known_args(Options, [
227
'--input-dir', '/data',
228
'--unknown-flag', 'value'
229
])
230
```
231
232
## Advanced Usage Patterns
233
234
### Field Metadata Configuration
235
236
Control argument parsing behavior using field metadata:
237
238
```python
239
from dataclasses import dataclass, field
240
from argparse_dataclass import ArgumentParser
241
242
@dataclass
243
class AdvancedOptions:
244
# Custom argument names
245
input_file: str = field(metadata=dict(args=["-i", "--input"]))
246
247
# Positional arguments
248
output_file: str = field(metadata=dict(args=["output"]))
249
250
# Choices constraint
251
format: str = field(metadata=dict(choices=["json", "xml", "yaml"]))
252
253
# Custom type converter
254
date: str = field(metadata=dict(type=lambda x: x.upper()))
255
256
# Help text
257
verbose: bool = field(default=False, metadata=dict(help="Enable verbose output"))
258
259
# Multiple arguments
260
files: List[str] = field(default_factory=list, metadata=dict(nargs="+"))
261
262
# Required flag (for boolean)
263
force: bool = field(metadata=dict(required=True))
264
265
parser = ArgumentParser(AdvancedOptions)
266
```
267
268
### Type Annotations Support
269
270
Support for various Python type annotations:
271
272
```python
273
from dataclasses import dataclass
274
from typing import Optional, List, Literal
275
from argparse_dataclass import ArgumentParser
276
277
@dataclass
278
class TypedOptions:
279
# Basic types
280
count: int = 1
281
ratio: float = 0.5
282
name: str = "default"
283
enabled: bool = False
284
285
# Optional types
286
description: Optional[str] = None
287
max_items: Optional[int] = None
288
289
# List types (requires nargs metadata)
290
tags: List[str] = field(default_factory=list, metadata=dict(nargs="*"))
291
292
# Literal types (automatic choices)
293
log_level: Literal["debug", "info", "warning", "error"] = "info"
294
295
parser = ArgumentParser(TypedOptions)
296
```
297
298
### Boolean Flag Handling
299
300
Different patterns for boolean flags:
301
302
```python
303
from dataclasses import dataclass, field
304
from argparse_dataclass import ArgumentParser
305
306
@dataclass
307
class BooleanOptions:
308
# Standard boolean flag (--flag to set True)
309
verbose: bool = False
310
311
# Inverted boolean flag (--no-quiet to set False)
312
quiet: bool = True
313
314
# Custom flag name with inversion
315
logging: bool = field(default=True, metadata=dict(args=["--logging-off"]))
316
317
# Required boolean (supports --flag/--no-flag)
318
confirm: bool = field(metadata=dict(required=True))
319
320
parser = ArgumentParser(BooleanOptions)
321
322
# Usage examples:
323
# --verbose (sets verbose=True)
324
# --no-quiet (sets quiet=False)
325
# --logging-off (sets logging=False)
326
# --confirm or --no-confirm (required, sets confirm=True/False)
327
```
328
329
## Types and Constants
330
331
```python { .api }
332
from typing import TypeVar, Optional, Sequence, Type, Tuple, List
333
334
# Type variables
335
OptionsType = TypeVar("OptionsType")
336
ArgsType = Optional[Sequence[str]]
337
338
# Package version
339
__version__ = "2.0.0"
340
```
341
342
## Error Handling
343
344
The library raises specific exceptions for various error conditions:
345
346
- `TypeError`: Raised when the options_class is not a dataclass
347
- `ValueError`: Raised for various validation errors:
348
- Mixed types in Literal annotations
349
- Invalid nargs configuration without proper type hints
350
- Conflicting choices and Literal type definitions
351
- Supplying namespace parameter to parse methods (not supported)
352
353
Example error handling:
354
355
```python
356
from dataclasses import dataclass
357
from argparse_dataclass import ArgumentParser
358
359
@dataclass
360
class Options:
361
count: int
362
363
try:
364
parser = ArgumentParser(Options)
365
options = parser.parse_args(['--count', 'invalid'])
366
except SystemExit:
367
# argparse calls sys.exit() on parse errors
368
print("Invalid arguments provided")
369
except TypeError as e:
370
print(f"Configuration error: {e}")
371
except ValueError as e:
372
print(f"Validation error: {e}")
373
```
374
375
## Supported Metadata Fields
376
377
The following metadata fields can be used in dataclass field definitions to customize argument parsing:
378
379
- `args`: List[str] - Custom argument names/flags (e.g., `["-v", "--verbose"]`)
380
- `choices`: List - Allowed values for the field
381
- `help`: str - Help text displayed in usage information
382
- `type`: Callable - Custom type converter function
383
- `metavar`: str - Placeholder name for argument value in help text
384
- `nargs`: Union[int, str] - Number of arguments to consume (`"*"`, `"+"`, `"?"`, or specific number)
385
- `required`: bool - Whether the argument is required (for optional arguments and boolean flags)
386
387
## Compatibility Notes
388
389
- **Python 3.8+**: Required minimum version
390
- **Python 3.9+**: Uses built-in `argparse.BooleanOptionalAction`
391
- **Python 3.8**: Uses backported `BooleanOptionalAction` implementation
392
- **Type hints**: Full support for modern Python typing features including `Literal`, `Union`, `Optional`