Name | terracomp-typer JSON |
Version |
0.0.7
JSON |
| download |
home_page | |
Summary | |
upload_time | 2023-04-01 00:06:09 |
maintainer | |
docs_url | None |
author | Niklas Rosenstein |
requires_python | >=3.7,<4.0 |
license | MIT |
keywords |
|
VCS |
|
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# terracomp-typer
[Typer]: https://typer.tiangolo.com/
This package allows you to easily build a [Typer][] CLI application from a Python module hierarchy.
### Quickstart
```
$ tree src/mypackage/commands/
src/mypackage/
├── __init__.py
├── __main__.py
└── commands
├── __init__.py
├── hello.py
└── bye.py
```
```py
# src/mypackage/commands/hello.py
def main(name: str) -> None:
print("Hello,", name)
```
```py
# src/mypackage/__main__.py
from terracomp_typer import build_app_from_module
if __name__ == "__main__":
app = build_app_from_module("mypackage.commands")
app()
```
### Features
* Packages are treated as command groups and _may_ define a `def callback(): ...` (see `Typer.add_callback()`).
* Modules are treated as commands and _must_ define a `def main(): ...` (see `Typer.command()`).
* Underscores in package or module names are normalized to hyphens (e.g `my_command` -> `my-command`).
* Command(-group) help text is extracted from the package or module docstring, or from the `main()` docstring.
* [WIP] Improved and dynamic dependency injection.
* Support for new-style type hints in older versions of Python and Typer (e.g. `str | None`).
### Dependency Injection
The `terracomp_typer.DependencyInjector` is essentially a mapping of types to a corresponding implementation. It allows
you to bind any function to the given dependencies based on the function signature.
The `build_app_from_module()` takes a `dependencies` argument which populates a `DependencyInjector`. All `callback()`
and `main()` functions encountered and added to a `typer.Typer` object are first bound to the dependencies that can be
served by the injector.
The types for which injection can take place must be known in advance. If the implementation is not known in advance,
a `callback()` can accept the `DependencyInjector` as an argument and inform about the dependencies that will be
provided by the callback, allowing any of its subcommands to resolve it.
```py
# src/mypackages/commands/__init__.py
"""
This is a cool CLI that uses terracomp-typer.
"""
from mypackage.config import CliConfig
from pathlib import Path
from terracomp_typer import DependencyInjector, DelayedBinding
from typer import Option
def callback(
config_file: Path = Option(Path("~/.config/mypackage.ini"), help="Path to the configuration file."),
dependencies: DependencyInjector = DelayedBinding(CliConfig),
) -> None:
dependencies.register_supplier(CliConfig, lambda: CliConfig.load(config_file))
```
```py
# src/mypackage/commands/hello.py
from mypackage.config import CliConfig
def main(name: str, config: CliConfig) -> None:
# ...
```
In the above example, the `config` parameter is not passed by [Typer][], but instead by the `DependencyInjector` per the implementation in the previous `callback()` snippet.
__Known caveats__
* Only concrete types are supported (no `Optional[CliConfig]` or vice versa).
## New-style type hint support
Through `typeapi`, we can convert new-tyle type hints such as `str | None` or `list[int]` to their corresponding
representation using `typing` before the function signature is parsed by [Typer][]. Usually, ty
```py
# src/mypackage/commands/hello.py
from mypackage.config import CliConfig
def main(name: str | None = None) -> None:
# ...
```
Raw data
{
"_id": null,
"home_page": "",
"name": "terracomp-typer",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.7,<4.0",
"maintainer_email": "",
"keywords": "",
"author": "Niklas Rosenstein",
"author_email": "rosensteinniklas@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/77/c3/6283f685bc5ed8a237779c442ac3f9b3b63eaf51ba49ff6ad5eaede3d1e2/terracomp_typer-0.0.7.tar.gz",
"platform": null,
"description": "# terracomp-typer\n\n [Typer]: https://typer.tiangolo.com/\n\nThis package allows you to easily build a [Typer][] CLI application from a Python module hierarchy.\n\n### Quickstart\n\n```\n$ tree src/mypackage/commands/\nsrc/mypackage/\n\u251c\u2500\u2500 __init__.py\n\u251c\u2500\u2500 __main__.py\n\u2514\u2500\u2500 commands\n \u251c\u2500\u2500 __init__.py\n \u251c\u2500\u2500 hello.py\n \u2514\u2500\u2500 bye.py\n```\n\n```py\n# src/mypackage/commands/hello.py\ndef main(name: str) -> None:\n print(\"Hello,\", name)\n```\n\n```py\n# src/mypackage/__main__.py\nfrom terracomp_typer import build_app_from_module\n\nif __name__ == \"__main__\":\n app = build_app_from_module(\"mypackage.commands\")\n app()\n```\n\n### Features\n\n* Packages are treated as command groups and _may_ define a `def callback(): ...` (see `Typer.add_callback()`).\n* Modules are treated as commands and _must_ define a `def main(): ...` (see `Typer.command()`).\n* Underscores in package or module names are normalized to hyphens (e.g `my_command` -> `my-command`).\n* Command(-group) help text is extracted from the package or module docstring, or from the `main()` docstring.\n* [WIP] Improved and dynamic dependency injection.\n* Support for new-style type hints in older versions of Python and Typer (e.g. `str | None`).\n\n### Dependency Injection\n\nThe `terracomp_typer.DependencyInjector` is essentially a mapping of types to a corresponding implementation. It allows\nyou to bind any function to the given dependencies based on the function signature.\n\nThe `build_app_from_module()` takes a `dependencies` argument which populates a `DependencyInjector`. All `callback()`\nand `main()` functions encountered and added to a `typer.Typer` object are first bound to the dependencies that can be\nserved by the injector.\n\nThe types for which injection can take place must be known in advance. If the implementation is not known in advance,\na `callback()` can accept the `DependencyInjector` as an argument and inform about the dependencies that will be\nprovided by the callback, allowing any of its subcommands to resolve it.\n\n```py\n# src/mypackages/commands/__init__.py\n\"\"\"\nThis is a cool CLI that uses terracomp-typer.\n\"\"\"\n\nfrom mypackage.config import CliConfig\nfrom pathlib import Path\nfrom terracomp_typer import DependencyInjector, DelayedBinding\nfrom typer import Option\n\ndef callback(\n config_file: Path = Option(Path(\"~/.config/mypackage.ini\"), help=\"Path to the configuration file.\"),\n dependencies: DependencyInjector = DelayedBinding(CliConfig),\n) -> None:\n dependencies.register_supplier(CliConfig, lambda: CliConfig.load(config_file))\n```\n\n```py\n# src/mypackage/commands/hello.py\nfrom mypackage.config import CliConfig\n\ndef main(name: str, config: CliConfig) -> None:\n # ...\n```\n\nIn the above example, the `config` parameter is not passed by [Typer][], but instead by the `DependencyInjector` per the implementation in the previous `callback()` snippet.\n\n__Known caveats__\n\n* Only concrete types are supported (no `Optional[CliConfig]` or vice versa).\n\n## New-style type hint support\n\nThrough `typeapi`, we can convert new-tyle type hints such as `str | None` or `list[int]` to their corresponding\nrepresentation using `typing` before the function signature is parsed by [Typer][]. Usually, ty\n\n```py\n# src/mypackage/commands/hello.py\nfrom mypackage.config import CliConfig\n\ndef main(name: str | None = None) -> None:\n # ...\n```\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "",
"version": "0.0.7",
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "9b9b3592fd586972aacc981621bded49a50642f0f98ee7d3ae989ba7db4ed059",
"md5": "8896f7216764c67d9080287daf3e2b5c",
"sha256": "38c5a0fc42fca9a763c711e70d91912f6dfd15aa5af9df46b384032eac3d9f29"
},
"downloads": -1,
"filename": "terracomp_typer-0.0.7-py3-none-any.whl",
"has_sig": false,
"md5_digest": "8896f7216764c67d9080287daf3e2b5c",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7,<4.0",
"size": 8049,
"upload_time": "2023-04-01T00:06:02",
"upload_time_iso_8601": "2023-04-01T00:06:02.642086Z",
"url": "https://files.pythonhosted.org/packages/9b/9b/3592fd586972aacc981621bded49a50642f0f98ee7d3ae989ba7db4ed059/terracomp_typer-0.0.7-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "77c36283f685bc5ed8a237779c442ac3f9b3b63eaf51ba49ff6ad5eaede3d1e2",
"md5": "e6dc4eb1030124065b5e091a9ead3fe0",
"sha256": "a8b79b8fb96a956fe39dd03441adc723db6cb72d3cb5060fb1acc3acdb2b6382"
},
"downloads": -1,
"filename": "terracomp_typer-0.0.7.tar.gz",
"has_sig": false,
"md5_digest": "e6dc4eb1030124065b5e091a9ead3fe0",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7,<4.0",
"size": 6781,
"upload_time": "2023-04-01T00:06:09",
"upload_time_iso_8601": "2023-04-01T00:06:09.597892Z",
"url": "https://files.pythonhosted.org/packages/77/c3/6283f685bc5ed8a237779c442ac3f9b3b63eaf51ba49ff6ad5eaede3d1e2/terracomp_typer-0.0.7.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-04-01 00:06:09",
"github": false,
"gitlab": false,
"bitbucket": false,
"lcname": "terracomp-typer"
}