0
# Signature Arguments
1
2
Tools for adding arguments to parsers based on function, method, and class signatures. These utilities automatically introspect Python callables and generate appropriate argument configurations using type hints and docstrings, enabling seamless integration between existing code and command-line interfaces.
3
4
## Capabilities
5
6
### SignatureArguments Class
7
8
Mixin class that provides methods for adding arguments based on callable signatures with automatic type detection and parameter introspection.
9
10
```python { .api }
11
class SignatureArguments:
12
def add_class_arguments(self,
13
theclass: Type,
14
nested_key: Optional[str] = None,
15
as_group: bool = True,
16
as_positional: bool = False,
17
default: Optional[Union[dict, Namespace, Any, Type]] = None,
18
skip: Optional[Set[Union[str, int]]] = None,
19
instantiate: bool = True,
20
fail_untyped: bool = True,
21
sub_configs: bool = False,
22
**kwargs
23
) -> List[str]:
24
"""
25
Add arguments for a class constructor.
26
27
Args:
28
theclass: Class to introspect for arguments
29
nested_key: Key for nested configuration
30
as_group: Whether to group arguments
31
as_positional: Whether to add as positional argument
32
default: Default value or configuration
33
skip: Parameter names/positions to skip
34
instantiate: Whether to instantiate the class
35
fail_untyped: Whether to fail on untyped parameters
36
sub_configs: Whether to enable sub-configurations
37
38
Returns:
39
List[str]: List of added argument names
40
"""
41
42
def add_method_arguments(self,
43
theclass: Type,
44
themethod: str,
45
nested_key: Optional[str] = None,
46
as_group: bool = True,
47
as_positional: bool = False,
48
skip: Optional[Set[Union[str, int]]] = None,
49
fail_untyped: bool = True,
50
sub_configs: bool = False,
51
**kwargs
52
) -> List[str]:
53
"""
54
Add arguments for a class method.
55
56
Args:
57
theclass: Class containing the method
58
themethod: Method name to introspect
59
nested_key: Key for nested configuration
60
as_group: Whether to group arguments
61
as_positional: Whether to add as positional argument
62
skip: Parameter names/positions to skip
63
fail_untyped: Whether to fail on untyped parameters
64
sub_configs: Whether to enable sub-configurations
65
66
Returns:
67
List[str]: List of added argument names
68
"""
69
70
def add_function_arguments(self,
71
function: Callable,
72
nested_key: Optional[str] = None,
73
as_group: bool = True,
74
as_positional: bool = False,
75
skip: Optional[Set[Union[str, int]]] = None,
76
fail_untyped: bool = True,
77
sub_configs: bool = False,
78
**kwargs
79
) -> List[str]:
80
"""
81
Add arguments for a function.
82
83
Args:
84
function: Function to introspect for arguments
85
nested_key: Key for nested configuration
86
as_group: Whether to group arguments
87
as_positional: Whether to add as positional argument
88
skip: Parameter names/positions to skip
89
fail_untyped: Whether to fail on untyped parameters
90
sub_configs: Whether to enable sub-configurations
91
92
Returns:
93
List[str]: List of added argument names
94
"""
95
96
def add_subclass_arguments(self,
97
baseclass: Union[Type, Tuple[Type, ...]],
98
nested_key: str,
99
as_group: bool = True,
100
skip: Optional[Set[str]] = None,
101
instantiate: bool = True,
102
required: bool = False,
103
metavar: str = "CONFIG | CLASS_PATH_OR_NAME | .INIT_ARG_NAME VALUE",
104
help: str = "One or more arguments specifying \"class_path\" and \"init_args\"...",
105
**kwargs
106
) -> List[str]:
107
"""
108
Add arguments for subclass selection and instantiation.
109
110
Args:
111
baseclass: Base class or tuple of base classes
112
nested_key: Key for nested configuration
113
as_group: Whether to group arguments
114
skip: Parameter names to skip
115
instantiate: Whether to instantiate the selected class
116
required: Whether subclass selection is required
117
metavar: Metavar for help display
118
help: Help text for the subclass argument
119
120
Returns:
121
List[str]: List of added argument names
122
"""
123
```
124
125
### Dataclass Composition
126
127
Utility for composing multiple dataclasses into a single dataclass for complex configuration scenarios.
128
129
```python { .api }
130
def compose_dataclasses(*dataclasses: Type) -> Type:
131
"""
132
Create a dataclass that inherits from multiple dataclasses.
133
134
Args:
135
*dataclasses: Dataclass types to compose
136
137
Returns:
138
Type: New dataclass inheriting from all input dataclasses
139
"""
140
```
141
142
## Usage Examples
143
144
### Basic Class Arguments
145
146
```python
147
from jsonargparse import ArgumentParser
148
from dataclasses import dataclass
149
150
@dataclass
151
class ModelConfig:
152
hidden_size: int = 128
153
dropout_rate: float = 0.1
154
num_layers: int = 3
155
activation: str = "relu"
156
157
# Create parser and add class arguments
158
parser = ArgumentParser()
159
parser.add_class_arguments(ModelConfig, "model")
160
161
# Parse arguments
162
config = parser.parse_args()
163
164
# Access nested configuration
165
print(f"Hidden size: {config.model.hidden_size}")
166
print(f"Dropout: {config.model.dropout_rate}")
167
168
# Instantiate the class if needed
169
model_instance = ModelConfig(**config.model.as_dict())
170
```
171
172
Usage:
173
```bash
174
python script.py --model.hidden_size 256 --model.dropout_rate 0.2 --model.num_layers 5
175
```
176
177
### Function Arguments
178
179
```python
180
from jsonargparse import ArgumentParser
181
182
def train_model(
183
data_path: str,
184
model_name: str,
185
epochs: int = 100,
186
learning_rate: float = 0.001,
187
batch_size: int = 32,
188
save_checkpoints: bool = True
189
) -> None:
190
"""Train a machine learning model.
191
192
Args:
193
data_path: Path to training data
194
model_name: Name of the model architecture
195
epochs: Number of training epochs
196
learning_rate: Learning rate for training
197
batch_size: Batch size for training
198
save_checkpoints: Whether to save model checkpoints
199
"""
200
print(f"Training {model_name} for {epochs} epochs")
201
print(f"Data: {data_path}, LR: {learning_rate}, Batch: {batch_size}")
202
203
# Add function arguments to parser
204
parser = ArgumentParser()
205
parser.add_function_arguments(train_model)
206
207
config = parser.parse_args()
208
209
# Call function with parsed arguments
210
train_model(
211
data_path=config.data_path,
212
model_name=config.model_name,
213
epochs=config.epochs,
214
learning_rate=config.learning_rate,
215
batch_size=config.batch_size,
216
save_checkpoints=config.save_checkpoints
217
)
218
```
219
220
### Method Arguments
221
222
```python
223
from jsonargparse import ArgumentParser
224
225
class DataProcessor:
226
def __init__(self, base_path: str):
227
self.base_path = base_path
228
229
def process(self,
230
input_format: str,
231
output_format: str = "json",
232
validate: bool = True,
233
chunk_size: int = 1000
234
) -> None:
235
"""Process data with specified parameters.
236
237
Args:
238
input_format: Format of input data
239
output_format: Format for output data
240
validate: Whether to validate processed data
241
chunk_size: Size of processing chunks
242
"""
243
print(f"Processing {input_format} -> {output_format}")
244
print(f"Validation: {validate}, Chunk size: {chunk_size}")
245
246
# Add method arguments
247
parser = ArgumentParser()
248
parser.add_method_arguments(DataProcessor, "process")
249
250
config = parser.parse_args()
251
252
# Create instance and call method
253
processor = DataProcessor("/data")
254
processor.process(
255
input_format=config.input_format,
256
output_format=config.output_format,
257
validate=config.validate,
258
chunk_size=config.chunk_size
259
)
260
```
261
262
### Subclass Arguments
263
264
```python
265
from jsonargparse import ArgumentParser
266
from abc import ABC, abstractmethod
267
268
class Optimizer(ABC):
269
@abstractmethod
270
def step(self) -> None:
271
pass
272
273
class SGD(Optimizer):
274
def __init__(self, learning_rate: float = 0.01, momentum: float = 0.0):
275
self.learning_rate = learning_rate
276
self.momentum = momentum
277
278
def step(self) -> None:
279
print(f"SGD step: lr={self.learning_rate}, momentum={self.momentum}")
280
281
class Adam(Optimizer):
282
def __init__(self, learning_rate: float = 0.001, beta1: float = 0.9, beta2: float = 0.999):
283
self.learning_rate = learning_rate
284
self.beta1 = beta1
285
self.beta2 = beta2
286
287
def step(self) -> None:
288
print(f"Adam step: lr={self.learning_rate}, β1={self.beta1}, β2={self.beta2}")
289
290
# Add subclass arguments for optimizer selection
291
parser = ArgumentParser()
292
parser.add_subclass_arguments(Optimizer, "optimizer", required=True)
293
294
config = parser.parse_args()
295
296
# The optimizer is automatically instantiated
297
optimizer = config.optimizer
298
optimizer.step()
299
```
300
301
Usage:
302
```bash
303
# Use SGD optimizer
304
python script.py --optimizer SGD --optimizer.learning_rate 0.02 --optimizer.momentum 0.9
305
306
# Use Adam optimizer
307
python script.py --optimizer Adam --optimizer.learning_rate 0.0005 --optimizer.beta1 0.95
308
```
309
310
### Composed Dataclasses
311
312
```python
313
from dataclasses import dataclass
314
from jsonargparse import ArgumentParser, compose_dataclasses
315
316
@dataclass
317
class ModelConfig:
318
hidden_size: int = 128
319
num_layers: int = 3
320
321
@dataclass
322
class TrainingConfig:
323
epochs: int = 100
324
learning_rate: float = 0.001
325
batch_size: int = 32
326
327
@dataclass
328
class LoggingConfig:
329
log_level: str = "INFO"
330
log_file: str = "training.log"
331
332
# Compose all configs into one
333
AllConfig = compose_dataclasses(ModelConfig, TrainingConfig, LoggingConfig)
334
335
parser = ArgumentParser()
336
parser.add_class_arguments(AllConfig)
337
338
config = parser.parse_args()
339
340
# Access all composed fields
341
print(f"Model: {config.hidden_size} hidden, {config.num_layers} layers")
342
print(f"Training: {config.epochs} epochs, lr={config.learning_rate}")
343
print(f"Logging: level={config.log_level}, file={config.log_file}")
344
```
345
346
### Nested Configuration
347
348
```python
349
from dataclasses import dataclass
350
from jsonargparse import ArgumentParser
351
352
@dataclass
353
class DatabaseConfig:
354
host: str = "localhost"
355
port: int = 5432
356
username: str = "user"
357
password: str = "pass"
358
359
@dataclass
360
class CacheConfig:
361
enabled: bool = True
362
ttl: int = 3600
363
max_size: int = 1000
364
365
@dataclass
366
class AppConfig:
367
debug: bool = False
368
workers: int = 4
369
370
parser = ArgumentParser()
371
372
# Add nested configurations
373
parser.add_class_arguments(DatabaseConfig, "database", as_group=True)
374
parser.add_class_arguments(CacheConfig, "cache", as_group=True)
375
parser.add_class_arguments(AppConfig, "app", as_group=True)
376
377
config = parser.parse_args()
378
379
# Access nested configs
380
print(f"DB: {config.database.host}:{config.database.port}")
381
print(f"Cache: enabled={config.cache.enabled}, ttl={config.cache.ttl}")
382
print(f"App: debug={config.app.debug}, workers={config.app.workers}")
383
```
384
385
Usage:
386
```bash
387
python script.py --database.host db.example.com --database.port 3306 \
388
--cache.enabled --cache.ttl 7200 \
389
--app.debug --app.workers 8
390
```
391
392
### Skip Parameters
393
394
```python
395
from jsonargparse import ArgumentParser
396
397
def process_data(
398
input_file: str,
399
output_file: str,
400
temp_dir: str = "/tmp", # Skip this parameter
401
debug_mode: bool = False,
402
log_level: str = "INFO" # Skip this parameter too
403
) -> None:
404
"""Process data files."""
405
print(f"Processing {input_file} -> {output_file}")
406
407
parser = ArgumentParser()
408
409
# Skip temp_dir (index 2) and log_level (by name)
410
parser.add_function_arguments(
411
process_data,
412
skip={"temp_dir", 4} # Skip by name and position
413
)
414
415
config = parser.parse_args()
416
417
# Only input_file, output_file, and debug_mode will be available
418
process_data(
419
input_file=config.input_file,
420
output_file=config.output_file,
421
debug_mode=config.debug_mode,
422
# temp_dir and log_level use their defaults
423
)
424
```
425
426
## Advanced Features
427
428
### Configuration Groups
429
430
Arguments can be organized into logical groups for better help display:
431
432
```python
433
parser.add_class_arguments(ModelConfig, "model", as_group=True)
434
parser.add_class_arguments(TrainingConfig, "training", as_group=True)
435
```
436
437
### Default Value Handling
438
439
Provide custom default values or configurations:
440
441
```python
442
# Use custom defaults
443
default_config = {"hidden_size": 256, "dropout_rate": 0.2}
444
parser.add_class_arguments(ModelConfig, default=default_config)
445
446
# Use existing instance as default
447
existing_config = ModelConfig(hidden_size=512, num_layers=6)
448
parser.add_class_arguments(ModelConfig, default=existing_config)
449
```
450
451
### Type Validation
452
453
Control behavior for untyped parameters:
454
455
```python
456
# Fail on untyped parameters (default)
457
parser.add_function_arguments(my_function, fail_untyped=True)
458
459
# Allow untyped parameters (treated as strings)
460
parser.add_function_arguments(my_function, fail_untyped=False)
461
```