confarg 0.0.1.dev3__tar.gz → 0.0.1.dev5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {confarg-0.0.1.dev3 → confarg-0.0.1.dev5}/PKG-INFO +45 -57
- {confarg-0.0.1.dev3 → confarg-0.0.1.dev5}/README.md +41 -54
- {confarg-0.0.1.dev3 → confarg-0.0.1.dev5}/pyproject.toml +4 -3
- confarg-0.0.1.dev5/src/confarg/__init__.py +33 -0
- confarg-0.0.1.dev3/src/confarg/__init__.py → confarg-0.0.1.dev5/src/confarg/_api.py +120 -142
- {confarg-0.0.1.dev3 → confarg-0.0.1.dev5}/src/confarg/_callable.py +43 -76
- {confarg-0.0.1.dev3 → confarg-0.0.1.dev5}/src/confarg/_defaults.py +11 -1
- {confarg-0.0.1.dev3 → confarg-0.0.1.dev5}/src/confarg/_files.py +24 -10
- confarg-0.0.1.dev5/src/confarg/_import.py +40 -0
- {confarg-0.0.1.dev3 → confarg-0.0.1.dev5}/src/confarg/_merge.py +33 -3
- {confarg-0.0.1.dev3 → confarg-0.0.1.dev5}/src/confarg/_parse_cli.py +34 -21
- {confarg-0.0.1.dev3 → confarg-0.0.1.dev5}/src/confarg/_parse_env.py +4 -4
- {confarg-0.0.1.dev3 → confarg-0.0.1.dev5}/src/confarg/_serialize.py +2 -3
- {confarg-0.0.1.dev3 → confarg-0.0.1.dev5}/src/confarg/_types.py +41 -35
- confarg-0.0.1.dev5/src/confarg/cli/__init__.py +15 -0
- confarg-0.0.1.dev5/src/confarg/cli/argparse/__init__.py +34 -0
- confarg-0.0.1.dev5/src/confarg/cli/argparse/_build.py +653 -0
- {confarg-0.0.1.dev3/src/confarg → confarg-0.0.1.dev5/src/confarg/cli/argparse}/_completion.py +134 -96
- confarg-0.0.1.dev5/src/confarg/cli/argparse/_namespace.py +271 -0
- confarg-0.0.1.dev5/src/confarg/cli/argparse/_register.py +196 -0
- confarg-0.0.1.dev5/src/confarg/cli/argparse/_spec.py +147 -0
- confarg-0.0.1.dev5/src/confarg/cli/click/__init__.py +22 -0
- confarg-0.0.1.dev5/src/confarg/cli/click/_completion.py +82 -0
- confarg-0.0.1.dev5/src/confarg/cli/click/_context.py +128 -0
- confarg-0.0.1.dev5/src/confarg/cli/click/_register.py +147 -0
- confarg-0.0.1.dev5/src/confarg/cli/cyclopts/__init__.py +20 -0
- confarg-0.0.1.dev5/src/confarg/cli/cyclopts/_context.py +137 -0
- confarg-0.0.1.dev5/src/confarg/cli/cyclopts/_register.py +173 -0
- {confarg-0.0.1.dev3 → confarg-0.0.1.dev5}/src/confarg/dictexpr/__init__.py +3 -3
- {confarg-0.0.1.dev3 → confarg-0.0.1.dev5}/src/confarg/dictexpr/_expressions.py +16 -15
- confarg-0.0.1.dev3/src/confarg/_errors.py → confarg-0.0.1.dev5/src/confarg/exceptions.py +8 -2
- {confarg-0.0.1.dev3 → confarg-0.0.1.dev5}/src/confarg/typedload/__init__.py +2 -2
- {confarg-0.0.1.dev3 → confarg-0.0.1.dev5}/src/confarg/typedload/_coerce.py +34 -5
- {confarg-0.0.1.dev3 → confarg-0.0.1.dev5}/src/confarg/typedload/_construct.py +43 -57
- confarg-0.0.1.dev3/src/confarg/_argparse.py +0 -970
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: confarg
|
|
3
|
-
Version: 0.0.1.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 0.0.1.dev5
|
|
4
|
+
Summary: Load and resolve complex configurations from files, environment variables and command line arguments. Keep your favorite CLI library.
|
|
5
5
|
Author: confarg
|
|
6
6
|
Author-email: confarg <280620574+confarg@users.noreply.github.com>
|
|
7
|
+
License-Expression: MPL-2.0
|
|
7
8
|
Requires-Dist: argcomplete>=3.0 ; extra == 'completion'
|
|
8
9
|
Requires-Python: >=3.12
|
|
9
10
|
Project-URL: Documentation, https://confarg.github.io/confarg
|
|
@@ -11,37 +12,64 @@ Project-URL: Repository, https://github.com/confarg/confarg
|
|
|
11
12
|
Provides-Extra: completion
|
|
12
13
|
Description-Content-Type: text/markdown
|
|
13
14
|
|
|
14
|
-
# A tool to manage complex
|
|
15
|
+
# A tool to manage complex configurations
|
|
15
16
|
|
|
17
|
+
> Load and resolve complex configurations from files, environment variables and command line arguments. Keep your data structures and favorite CLI library.
|
|
16
18
|
|
|
17
|
-
|
|
19
|
+
`confarg` is a Python library that helps you load configurations in a modular fashion from multiple sources: files, environment variables, and command line arguments.
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
It can handle deeply nested configurations, type unions, derived classes, expressions and variable interpolation, configuration compositions and more, and can integrate with your favorite argument parser library such as `argparse`, `click` or `typer`.
|
|
20
22
|
|
|
21
|
-
It
|
|
23
|
+
`confarg` is not a framework. No decorator, base class or special annotation type required: none are provided. It is just a tool for the deserialization and serialization of complex configurations. Its footprint in your code is typically a few lines of code, making it easy to switch to it, or away from it.
|
|
22
24
|
|
|
23
|
-
|
|
25
|
+
## Install
|
|
24
26
|
|
|
25
|
-
|
|
27
|
+
```bash
|
|
28
|
+
pip install confarg
|
|
29
|
+
```
|
|
26
30
|
|
|
31
|
+
`confarg` comes with no dependency, but installing additional libraries such as `pyyaml` unlocks the support of extra configuration file formats.
|
|
27
32
|
|
|
28
|
-
##
|
|
33
|
+
## TL;DR
|
|
29
34
|
|
|
30
|
-
|
|
35
|
+
This library lets you read configurations stored in classes like this
|
|
31
36
|
|
|
32
|
-
|
|
37
|
+
```python
|
|
38
|
+
@dataclass
|
|
39
|
+
class Config:
|
|
40
|
+
value: float
|
|
41
|
+
flag: bool
|
|
42
|
+
subconfig: SubConfig1 | SubConfig2
|
|
43
|
+
```
|
|
33
44
|
|
|
34
|
-
|
|
45
|
+
with this kind of code
|
|
35
46
|
|
|
36
|
-
|
|
47
|
+
```python
|
|
48
|
+
config = confarg.load(Config)
|
|
49
|
+
```
|
|
37
50
|
|
|
38
|
-
|
|
51
|
+
which lets you build a configuration object from files,
|
|
52
|
+
|
|
53
|
+
```yaml
|
|
54
|
+
value: 1.0
|
|
55
|
+
flag: false
|
|
56
|
+
subconfig:
|
|
57
|
+
foo: 42
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
but also and simultaneously from environment variables,
|
|
61
|
+
|
|
62
|
+
```properties
|
|
63
|
+
MYAPP_VALUE=0.0
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
and command line arguments,
|
|
39
67
|
|
|
40
68
|
```bash
|
|
41
|
-
|
|
69
|
+
myapp --subconfig.foo=33
|
|
42
70
|
```
|
|
43
71
|
|
|
44
|
-
|
|
72
|
+
Still here? Read along, we are just getting started.
|
|
45
73
|
|
|
46
74
|
## Getting started
|
|
47
75
|
|
|
@@ -411,46 +439,6 @@ db:
|
|
|
411
439
|
__include__: ./db_config.yaml
|
|
412
440
|
```
|
|
413
441
|
|
|
414
|
-
## `confarg` and command-line interfaces
|
|
415
|
-
|
|
416
|
-
Command line arguments are an essential part of `confarg`. We have seen how they are parsed and consumed implicitly by `confarg.load`.
|
|
417
|
-
|
|
418
|
-
Although it is not needed for `confarg` to work, application generally provide a command line interface to offer some help and parse parameters.
|
|
419
|
-
|
|
420
|
-
### What to expect from a CLI regarding complex configurations
|
|
421
|
-
|
|
422
|
-
We are used to the great user experience provided by CLI libraries such as `click`, `typer` or `cyclopts`. However, porting this great UX to complex configurations is no small feat because of their size and dynamic nature. Inline help is bound to be both very long, reflecting the configuration's complexity, and incomplete, as options coming from derived classes are not available. This could be frustrating.
|
|
423
|
-
|
|
424
|
-
At the same time, the command line is not the main configuration interface: configuration files are. Building a great CLI UX for complex configuration has a somewhat poor benefit/effort ratio.
|
|
425
|
-
|
|
426
|
-
### Using a CLI library
|
|
427
|
-
|
|
428
|
-
The python ecosystem offers many libraries to build powerful and beautiful CLI apps, such as `click`, `typer` or `cyclopts`. Those libraries parse and consume command line arguments, but they also offer a rich user experience by providing help on available commands, sometimes even auto-completion. Some like `cyclopts` also parse concrete nested dataclasses using the dot-separated field command line argument convention used by `confarg` and similar libraries.
|
|
429
|
-
|
|
430
|
-
Should you use such a library, `confarg` can coexist with them by parsing unused arguments. Currently however, `confarg` will essentially work in "suppress" (`argparse` terminology) or "hidden" (`click` terminology) mode: the arguments won't show in the help generated by those libraries.
|
|
431
|
-
|
|
432
|
-
### Building your interface with `argparse`
|
|
433
|
-
|
|
434
|
-
If you manage your interface yourself with `argparse`, `confarg` can step in and provide (limited) help for command line arguments. This is currently an experimental feature.
|
|
435
|
-
|
|
436
|
-
Not registering `confarg` with your `ArgumentParser` and running in hidden mode is of course an option.
|
|
437
|
-
|
|
438
|
-
### Optional command line argument prefix
|
|
439
|
-
|
|
440
|
-
When mixing `confarg` arguments with other application arguments, you may worry about name conflicts, or you may want to clearly identify which arguments belong to the configuration handled by `confarg`, especially if `confarg` is running in hidden arguments mode.
|
|
441
|
-
|
|
442
|
-
For this purpose, you can specify a prefix for `confarg` command line arguments, using the `cli_prefix` parameter:
|
|
443
|
-
|
|
444
|
-
```python
|
|
445
|
-
config = confarg.load(Config, args=rgs, cli_prefix="settings")
|
|
446
|
-
```
|
|
447
|
-
|
|
448
|
-
The command line now cleanly conveys which arguments are routed to the configuration.
|
|
449
|
-
|
|
450
|
-
```python
|
|
451
|
-
myapp.py --app_arg=hello --settings.config=config.yaml --settings.resources.cpu_count=2
|
|
452
|
-
```
|
|
453
|
-
|
|
454
442
|
## Next steps
|
|
455
443
|
|
|
456
444
|
We have more than scratched the surface, and you should have enough knowledge to cover most of your needs.
|
|
@@ -1,34 +1,61 @@
|
|
|
1
|
-
# A tool to manage complex
|
|
1
|
+
# A tool to manage complex configurations
|
|
2
2
|
|
|
3
|
+
> Load and resolve complex configurations from files, environment variables and command line arguments. Keep your data structures and favorite CLI library.
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
`confarg` is a Python library that helps you load configurations in a modular fashion from multiple sources: files, environment variables, and command line arguments.
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
It can handle deeply nested configurations, type unions, derived classes, expressions and variable interpolation, configuration compositions and more, and can integrate with your favorite argument parser library such as `argparse`, `click` or `typer`.
|
|
7
8
|
|
|
8
|
-
It
|
|
9
|
+
`confarg` is not a framework. No decorator, base class or special annotation type required: none are provided. It is just a tool for the deserialization and serialization of complex configurations. Its footprint in your code is typically a few lines of code, making it easy to switch to it, or away from it.
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
## Install
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
```bash
|
|
14
|
+
pip install confarg
|
|
15
|
+
```
|
|
13
16
|
|
|
17
|
+
`confarg` comes with no dependency, but installing additional libraries such as `pyyaml` unlocks the support of extra configuration file formats.
|
|
14
18
|
|
|
15
|
-
##
|
|
19
|
+
## TL;DR
|
|
16
20
|
|
|
17
|
-
|
|
21
|
+
This library lets you read configurations stored in classes like this
|
|
18
22
|
|
|
19
|
-
|
|
23
|
+
```python
|
|
24
|
+
@dataclass
|
|
25
|
+
class Config:
|
|
26
|
+
value: float
|
|
27
|
+
flag: bool
|
|
28
|
+
subconfig: SubConfig1 | SubConfig2
|
|
29
|
+
```
|
|
20
30
|
|
|
21
|
-
|
|
31
|
+
with this kind of code
|
|
22
32
|
|
|
23
|
-
|
|
33
|
+
```python
|
|
34
|
+
config = confarg.load(Config)
|
|
35
|
+
```
|
|
24
36
|
|
|
25
|
-
|
|
37
|
+
which lets you build a configuration object from files,
|
|
38
|
+
|
|
39
|
+
```yaml
|
|
40
|
+
value: 1.0
|
|
41
|
+
flag: false
|
|
42
|
+
subconfig:
|
|
43
|
+
foo: 42
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
but also and simultaneously from environment variables,
|
|
47
|
+
|
|
48
|
+
```properties
|
|
49
|
+
MYAPP_VALUE=0.0
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
and command line arguments,
|
|
26
53
|
|
|
27
54
|
```bash
|
|
28
|
-
|
|
55
|
+
myapp --subconfig.foo=33
|
|
29
56
|
```
|
|
30
57
|
|
|
31
|
-
|
|
58
|
+
Still here? Read along, we are just getting started.
|
|
32
59
|
|
|
33
60
|
## Getting started
|
|
34
61
|
|
|
@@ -398,46 +425,6 @@ db:
|
|
|
398
425
|
__include__: ./db_config.yaml
|
|
399
426
|
```
|
|
400
427
|
|
|
401
|
-
## `confarg` and command-line interfaces
|
|
402
|
-
|
|
403
|
-
Command line arguments are an essential part of `confarg`. We have seen how they are parsed and consumed implicitly by `confarg.load`.
|
|
404
|
-
|
|
405
|
-
Although it is not needed for `confarg` to work, application generally provide a command line interface to offer some help and parse parameters.
|
|
406
|
-
|
|
407
|
-
### What to expect from a CLI regarding complex configurations
|
|
408
|
-
|
|
409
|
-
We are used to the great user experience provided by CLI libraries such as `click`, `typer` or `cyclopts`. However, porting this great UX to complex configurations is no small feat because of their size and dynamic nature. Inline help is bound to be both very long, reflecting the configuration's complexity, and incomplete, as options coming from derived classes are not available. This could be frustrating.
|
|
410
|
-
|
|
411
|
-
At the same time, the command line is not the main configuration interface: configuration files are. Building a great CLI UX for complex configuration has a somewhat poor benefit/effort ratio.
|
|
412
|
-
|
|
413
|
-
### Using a CLI library
|
|
414
|
-
|
|
415
|
-
The python ecosystem offers many libraries to build powerful and beautiful CLI apps, such as `click`, `typer` or `cyclopts`. Those libraries parse and consume command line arguments, but they also offer a rich user experience by providing help on available commands, sometimes even auto-completion. Some like `cyclopts` also parse concrete nested dataclasses using the dot-separated field command line argument convention used by `confarg` and similar libraries.
|
|
416
|
-
|
|
417
|
-
Should you use such a library, `confarg` can coexist with them by parsing unused arguments. Currently however, `confarg` will essentially work in "suppress" (`argparse` terminology) or "hidden" (`click` terminology) mode: the arguments won't show in the help generated by those libraries.
|
|
418
|
-
|
|
419
|
-
### Building your interface with `argparse`
|
|
420
|
-
|
|
421
|
-
If you manage your interface yourself with `argparse`, `confarg` can step in and provide (limited) help for command line arguments. This is currently an experimental feature.
|
|
422
|
-
|
|
423
|
-
Not registering `confarg` with your `ArgumentParser` and running in hidden mode is of course an option.
|
|
424
|
-
|
|
425
|
-
### Optional command line argument prefix
|
|
426
|
-
|
|
427
|
-
When mixing `confarg` arguments with other application arguments, you may worry about name conflicts, or you may want to clearly identify which arguments belong to the configuration handled by `confarg`, especially if `confarg` is running in hidden arguments mode.
|
|
428
|
-
|
|
429
|
-
For this purpose, you can specify a prefix for `confarg` command line arguments, using the `cli_prefix` parameter:
|
|
430
|
-
|
|
431
|
-
```python
|
|
432
|
-
config = confarg.load(Config, args=rgs, cli_prefix="settings")
|
|
433
|
-
```
|
|
434
|
-
|
|
435
|
-
The command line now cleanly conveys which arguments are routed to the configuration.
|
|
436
|
-
|
|
437
|
-
```python
|
|
438
|
-
myapp.py --app_arg=hello --settings.config=config.yaml --settings.resources.cpu_count=2
|
|
439
|
-
```
|
|
440
|
-
|
|
441
428
|
## Next steps
|
|
442
429
|
|
|
443
430
|
We have more than scratched the surface, and you should have enough knowledge to cover most of your needs.
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
authors = [
|
|
3
3
|
{ name = "confarg", email = "280620574+confarg@users.noreply.github.com" },
|
|
4
4
|
]
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
description = "Load and resolve complex configurations from files, environment variables and command line arguments. Keep your favorite CLI library."
|
|
6
|
+
license = "MPL-2.0"
|
|
7
7
|
name = "confarg"
|
|
8
8
|
readme = "README.md"
|
|
9
9
|
requires-python = ">=3.12"
|
|
10
|
-
version = "0.0.1.
|
|
10
|
+
version = "0.0.1.dev5"
|
|
11
11
|
|
|
12
12
|
[project.urls]
|
|
13
13
|
Documentation = "https://confarg.github.io/confarg"
|
|
@@ -31,6 +31,7 @@ dev = [
|
|
|
31
31
|
"pytest>=8.0",
|
|
32
32
|
"pyyaml>=6.0",
|
|
33
33
|
"tomli-w>=1.0",
|
|
34
|
+
"ty>=0.0.39",
|
|
34
35
|
"typer>=0.25.1",
|
|
35
36
|
"zensical>=0.0.41",
|
|
36
37
|
]
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
|
|
5
|
+
"""A tool to manage complex configurations.
|
|
6
|
+
|
|
7
|
+
> Load and resolve complex configurations from files, environment variables and command line arguments. Keep your data
|
|
8
|
+
> structures and favorite CLI library.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from confarg import exceptions
|
|
14
|
+
from confarg._api import build, dump, dump_file, from_dict, load, merge, resolve
|
|
15
|
+
from confarg._types import TagPolicy
|
|
16
|
+
|
|
17
|
+
__all__ = [ # noqa: RUF022
|
|
18
|
+
# Two-step API
|
|
19
|
+
"merge",
|
|
20
|
+
"build",
|
|
21
|
+
# Three-step API (dict-centric)
|
|
22
|
+
"resolve",
|
|
23
|
+
"from_dict",
|
|
24
|
+
# One-step convenience
|
|
25
|
+
"load",
|
|
26
|
+
# Dump
|
|
27
|
+
"dump",
|
|
28
|
+
"dump_file",
|
|
29
|
+
# Types
|
|
30
|
+
"TagPolicy",
|
|
31
|
+
# Exceptions / warnings
|
|
32
|
+
"exceptions",
|
|
33
|
+
]
|