maxb2 / typer-config Goto Github PK
View Code? Open in Web Editor NEWUtilities for working with configuration files in typer CLIs.
Home Page: https://maxb2.github.io/typer-config/
License: MIT License
Utilities for working with configuration files in typer CLIs.
Home Page: https://maxb2.github.io/typer-config/
License: MIT License
The project is internally typed, but mypy complains about client uses since the package does not broadcast being PEP 561 compliant.
$ mypy .
cli.py:12: error: Skipping analyzing "typer_config": module is installed, but missing library stubs or py.typed marker [import]
cli.py:12: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
Found 1 error in 1 file (checked 26 source files)
Adding an empty stub or marker file should resolve this problem.
This is a great library and I'm very glad that you've created it. Would it at all to add the future of automatically saving params into some format that could be read again later? This way we'll have serialization that very well complements the existing deserialization.
Current (taken from https://maxb2.github.io/typer-config/0.5.0/examples/simple_yaml/):
import typer
from typer_config import yaml_conf_callback
app = typer.Typer()
@app.command()
def main(
arg1: str,
config: str = typer.Option(
"",
callback=yaml_conf_callback,
is_eager=True, # THIS IS REALLY IMPORTANT
),
opt1: str = typer.Option(...),
opt2: str = typer.Option("hello"),
):
typer.echo(f"{opt1} {opt2} {arg1}")
if __name__ == "__main__":
app()
Possible new API
import typer
from typer_config import yaml_conf_callback
app = typer.Typer()
@app.command()
def main(
arg1: str,
config: str = typer.Option(
"",
callback=yaml_conf_callback(save="./config_save_folder"),
is_eager=True, # THIS IS REALLY IMPORTANT
),
opt1: str = typer.Option(...),
opt2: str = typer.Option("hello"),
):
typer.echo(f"{opt1} {opt2} {arg1}")
if __name__ == "__main__":
app()
So the callback would be a higher order function. Could this potentially make sense?
There seems to be an ini_loader
, but no use_ini()
. Also, the help for the ini_loader
refers to subpath_loader
which isn't actually in the repo.
Could we refactor subpath_loader
to be a function of (ConfigDict) -> ConfigDict
? Then have a loader just apply the transformer. It would open up many more possibilities.
Blocks starting with ```{.python title="simple_app.py" test="true"}
are not recognized by blacken-docs
for formatting.
Blocks with ```python title="simple_app.py"
are fine though.
First discovered in #117
The example in #117 doesn't work (you get missing argument LABEL_NAMES
) with typer-config
.
However, if you make a similar click
app, it works fine:
# app.py
import click
@click.command(context_settings = {"default_map": {"my_list": [1,2,3]}})
@click.option('--my-list', type=list)
@click.pass_context
def hello(ctx, my_list):
print(my_list)
print(ctx.get_parameter_source("my_list"))
print(ctx.default_map)
if __name__ == '__main__':
hello()
Then invoked, you get:
$ python app.py
[1, 2, 3]
ParameterSource.DEFAULT_MAP
{'my_list': [1, 2, 3]}
as expected.
Hello!
I am very happy I found as solution to this "config" support for typer, so first and foremost, thanks for the lib!
Now I think the API of the lib could be improved a bit.
Maybe I missed something, and if that's the case I apologies, but I feel like it would be super nice to have the ability to easily load the config from a custom location.
Right now the only way I found is to override the config
parameter on each command with something like:
config: Annotated[
pathlib.Path,
typer.Option(
callback=yaml_conf_callback,
is_eager=True, # THIS IS REALLY IMPORTANT
),
] = "/my-custom-path/config.yaml",
I feel like it would be a better dev experience if one could do something like:
@use_yaml_config(config_location="/my-custom-path/config.yaml")
Thanks ๐
It would be nice to add the pyproject.toml
example as a test.
In the midst of looking at the elegant code for #27 , I noticed a possible simplification for improving the developer experience of this library.
Instead of the current invocation of
@app.command()
def main(
arg1: str,
config: str = typer.Option(
"",
callback=yaml_conf_callback,
is_eager=True, # THIS IS REALLY IMPORTANT
),
opt1: str = typer.Option(...),
opt2: str = typer.Option("hello"),
):
typer.echo(f"{opt1} {opt2} {arg1}")
Could we instead use
@app.command()
@use_config(callback=yaml_conf_callback)
def main(
arg1: str,
opt1: str = typer.Option(...),
opt2: str = typer.Option("hello"),
):
typer.echo(f"{opt1} {opt2} {arg1}")
In this case, we could also quite nicely integrate this with #27 through the following:
@app.command()
@use_config(callback=yaml_conf_callback, save_location="./saved.yaml")
def main(
arg1: str,
opt1: str = typer.Option(...),
opt2: str = typer.Option("hello"),
):
typer.echo(f"{opt1} {opt2} {arg1}")
Really amazing tool, thanks for building it! I'm leveraging the yaml_config
, and i'm wondering if there's support for having nested values in a config for overriding purposes.
Imagine, for example, you have multiple typer apps (say, generate_data
, and label_data
), with some shared variables, (say input_file_name
, label_names
), for example.
@app.command()
def generate_data(label_names: ..., input_data: ...):
...
@app.command()
def label_data(label_names: ..., input_data: ...):
...
I could imagine a yaml file like so
label_names
- label1
- label2
generate_data:
input_data: generator.csv
label_data:
input_data: generator_output.csv
Such that a single config can be shared, and you can have overrides for specific typer apps. Curious your thoughts!
.py
file as markdown/html?I would prefer make for portability, but the release duty extracts a version number into python making that difficult.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.