@@ -177,16 +177,20 @@ See [annotations](./annotation.md) for more details.
177
177
178
178
Controls the default argument value at the CLI level. Generally, you can avoid
179
179
direct use of cappa' s default by simply using the source class' native default
180
- mechanism. (i.e. `foo: int = 0 ` or `foo: int = field(default = 0 )` for
181
- dataclasses).
180
+ mechanism. (i.e. `foo: int = 0 ` , `foo: int = field(default = 0 )` , or
181
+ `foo: list[ str ] = field( default_factory = list )` for dataclasses).
182
182
183
- However it can be convenient to use cappa' s default because it does not affect
184
- the optionality of the field in question in the resultant class constructor.
183
+ However it ** can** be convenient to use cappa' s default because it does not affect
184
+ whether the underlying class definition makes that field required in the class '
185
+ constructor.
185
186
186
187
```{note}
187
- The `default` value is not parsed by `parse` . That is to say, if no value is
188
- selected at the CLI and the default value is used instead, it will not be
189
- coerced into the annotated type automatically.
188
+ The `default` value is not ** typically** parsed by the given `parse` function.
189
+ That is to say, if no value is selected at the CLI and the default value is used
190
+ instead; it will not be coerced into the annotated type automatically.
191
+
192
+ (`Env` , `Prompt` , and `Confirm` are exceptions to this rule, explained in their
193
+ sections below).
190
194
191
195
The reason for this is twofold:
192
196
@@ -196,21 +200,103 @@ The reason for this is twofold:
196
200
would infer `parse=Foo` and attempt to pass `Foo(Foo(' ' ))` during parsing.
197
201
```
198
202
199
- # ## Environment Variable Fallback
203
+ Additionally there are a number of natively integrated objects that can be used
204
+ as default to create more complex behaviors given a ** missing** CLI argument.
205
+ The below objects will not be evaluated unless the user did not supply a value
206
+ for the argument it' s attached to.
207
+
208
+ - [cappa.Default](cappa.Default)
209
+ - [cappa.Env](cappa.Env)
210
+ - [cappa.Prompt](cappa.Prompt)/ [cappa.Confirm](cappa.Confirm)
211
+ - [cappa.ValueFrom](cappa.ValueFrom)
212
+
213
+ # ## `Default`
214
+
215
+ All other types of default are ultimately shorthand forms of `Default` . The
216
+ `Default` construct allows for specifying an ordered chain of default fallback
217
+ options, with an optional static fallback item at the end.
218
+
219
+ For example:
220
+
221
+ - `foo: int = 4 ` is the same as `default=Default(default = 4 )` . This unconditionally defaults to 4 .
222
+
223
+ - `foo: Annotated[int , Arg(default = Env(" FOO" ))] = 4 ` is the same as
224
+ `Arg(default = Default(Env(" FOO" ), default = 4 )`. This attempts to read the environment variable ` FOO `,
225
+ and falls back to 4 if the env var is unset.
226
+
227
+ - `foo: Annotated[int , Arg(default = Env(" FOO" ) | Prompt(" Gimme" ))]` is the same as
228
+ `Arg(default = Default(Env(" FOO" ), Prompt(" Gimme" ))`. This attempts to read the environment variable ` FOO `,
229
+ followed by a user prompt if the env var is unset.
230
+
231
+ As shown above, any combination of defaultable values can be used as fallbacks of one another by using
232
+ the `| ` operator to chain them together.
200
233
201
- You can also use the default field to supply supported kinds of
202
- default- value- getting behaviors.
234
+ As noted above, a value produced by `Default.default` ** does not ** invoke the `Arg.parse` parser. This is
235
+ for similar reasons as to native dataclass defaults. The programmer is supplying the default value
236
+ which should not ** need** to be parsed.
237
+
238
+ # ## `Env`
239
+
240
+ [cappa.Env](cappa.Env) performs environment variable lookups in an attempt to provide a value to the
241
+ class field.
203
242
204
- `Env` is one such example, where with
205
243
`Arg(... , default = Env(" FOO" , default = ' default value' ))` , cappa will attempt to
206
244
look up the environment variable `FOO ` for the default value, if there was no
207
245
supplied value at the CLI level.
208
246
209
- ```{eval - rst}
210
- .. autoapiclass:: cappa.Env
211
- :noindex:
247
+ As noted above, a value produced by `Env` ** does** invoke the `Arg.parse` parser. This is
248
+ because `Env` values will always be returned as a string, very similarly to a normal pre- parse
249
+ CLI value.
250
+
251
+ # ## `Prompt`/`Confirm`
252
+
253
+ [cappa.Prompt](cappa.Prompt) and [cappa.Confirm](cappa.Confirm) can be used to ask for user input
254
+ to fulfill the value.
255
+
256
+ ```{note}
257
+ `rich.prompt.Prompt` and `rich.prompt.Confirm` can also be used transparently for the same purpose.
258
+ ```
259
+
260
+ ```python
261
+ import cappa
262
+
263
+ class Example:
264
+ value: Annotated[int , cappa.Arg(default = cappa.Prompt(" A number value" ))]
265
+ is_ok: Annotated[bool , cappa.Arg(default = cappa.Confirm(" You sure?" ))]
266
+ ```
267
+
268
+ As noted above, a value produced by `Prompt` / `Confirm` ** does** invoke the `Arg.parse` parser. This is
269
+ because these values will always be returned as a string, very similarly to a normal pre- parse
270
+ CLI value.
271
+
272
+ # ## `ValueFrom`
273
+
274
+ [cappa.ValueFrom](cappa.ValueFrom) is a means for calling an arbitrary function at mapping time,
275
+ to allow for dynamic default values.
276
+
277
+ ```{info}
278
+ A dataclass `field(default_factory = list )` is internally the same thing as `default=ValueFrom(list )` !
212
279
```
213
280
281
+ ```python
282
+ from pathlib import Path
283
+ import cappa
284
+
285
+ def load_default(key):
286
+ config = json.loads(Path(" config.json" ).read_text())
287
+ return config[key]
288
+
289
+ class Example:
290
+ value: Annotated[int , cappa.Arg(default = cappa.ValueFrom(load_default, key = ' value' ))]
291
+ ```
292
+
293
+ This construct is able to be automatically supplied with [cappa.State](State), in the even shared
294
+ parse state is required to evaluate a field' s default.
295
+
296
+ As noted above, a value produced by `ValueFrom` ** does not ** invoke the `Arg.parse` parser. This is
297
+ because the called function is programmer- supplied and can/ should just return the correct end
298
+ value.
299
+
214
300
(arg- group)=
215
301
# # `Arg.group`: Groups (and Mutual Exclusion)
216
302
0 commit comments