Name | typer-builder JSON |
Version |
0.0.11
JSON |
| download |
home_page | |
Summary | |
upload_time | 2023-12-15 13:51:09 |
maintainer | |
docs_url | None |
author | Niklas Rosenstein |
requires_python | >=3.7 |
license | MIT |
keywords |
|
VCS |
|
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# typer-builder
[Typer]: https://typer.tiangolo.com/
[pep585]: https://www.python.org/dev/peps/pep-0585/
[pep604]: https://www.python.org/dev/peps/pep-0604/
[typeapi]: https://github.com/NiklasRosenstein/python-typeapi
A framework for simplifying the development of [Typer][] based CLIs supporting modern type hints and hierarchical
dependency injection.
__Table of Contents__
* [Introduction](#introduction)
* [Example](#example)
* [Documentation](#documentation)
* [New-style type hint support](#new-style-type-hint-support)
* [Dependency injection](#dependency-injection)
## Introduction
The `build_app_from_module()` inspect a hierarchy of Python modules to build a Typer command and group structure.
Packages are treated as command groups and may define a `callback()` member. Modules are treated commands and must
define a `main()` member. Modules and packages prefixed with an underscore ( `_` ) are ignored. Help text is extracted
from the `main()` docstring or the module docstring.
In addition, we provide support for new-style type hints ([PEP 585 - Type Hinting Generics in Standard Collections][pep585]
and [PEP 604 - Union Operators][pep604]) in older versions of Python as well as adapt it for Typer (e.g. `list[str]`
and `str | None`), as well as a method of injecting dependencies to functions that are not sourced from the command-line.
### Example
```
$ tree src/mypackage/
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 typer_builder import build_app_from_module
if __name__ == "__main__":
app = build_app_from_module("mypackage.commands")
app()
```
## Documentation
### New-style type hint support
Through [`typeapi`][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][].
```py
# src/mypackage/commands/create_user.py
from ___future__ import annotations
def main(name: str | None = None, groups: list[str] | None = None) -> None:
# ...
```
[`typeapi`][typeapi] also allows us to convert `list[str]` to `List[str]` and `dict[str, int]` to `Dict[str, int]` for
Python versions prior to 3.9. This is necessary because [Typer][] does not support the new-style type hints.
### Dependency injection
The `typer_builder.Dependencies` object is used to map types to concrete values or functions that provide them.
Functions wrapped with `Dependencies.bind()` will have their arguments resolved by the injector based on type
annotations. Every `build_app_from_module()` call creates a new `Dependencies` instance. Dependencies can be
injected from the outside by passing a `Dependencies` instance to `build_app_from_module()` or by providing
additional dependencies via a `callback()` function on the command group.
Note that the `Dependencies` does not understand generics with different type parameters. For example, it makes
no distinction between `MyGeneric[int]` and `MyGeneric[str]`. This is a limitation of the current implementation as well
as the Python type system.
The most common use case for dependency injection is to inject configuration managers or clients into subcommands. For
an example, you should check out the [examples/dependency-injection](./examples/dependency-injection) directory.
## License
This project is licensed under the terms of the MIT license.
Raw data
{
"_id": null,
"home_page": "",
"name": "typer-builder",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": "",
"keywords": "",
"author": "Niklas Rosenstein",
"author_email": "rosensteinniklas@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/ab/0f/ee027c4f8f0c6377a0620c9e03a762a2a0e7fe58431376c3b5843c48863e/typer_builder-0.0.11.tar.gz",
"platform": null,
"description": "# typer-builder\n\n [Typer]: https://typer.tiangolo.com/\n [pep585]: https://www.python.org/dev/peps/pep-0585/\n [pep604]: https://www.python.org/dev/peps/pep-0604/\n [typeapi]: https://github.com/NiklasRosenstein/python-typeapi\n\nA framework for simplifying the development of [Typer][] based CLIs supporting modern type hints and hierarchical\ndependency injection. \n\n__Table of Contents__\n\n* [Introduction](#introduction)\n * [Example](#example)\n* [Documentation](#documentation)\n * [New-style type hint support](#new-style-type-hint-support)\n * [Dependency injection](#dependency-injection)\n\n\n## Introduction\n\nThe `build_app_from_module()` inspect a hierarchy of Python modules to build a Typer command and group structure.\nPackages are treated as command groups and may define a `callback()` member. Modules are treated commands and must\ndefine a `main()` member. Modules and packages prefixed with an underscore ( `_` ) are ignored. Help text is extracted\nfrom the `main()` docstring or the module docstring.\n\nIn addition, we provide support for new-style type hints ([PEP 585 - Type Hinting Generics in Standard Collections][pep585]\nand [PEP 604 - Union Operators][pep604]) in older versions of Python as well as adapt it for Typer (e.g. `list[str]`\nand `str | None`), as well as a method of injecting dependencies to functions that are not sourced from the command-line.\n\n\n### Example\n\n```\n$ tree src/mypackage/\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 typer_builder import build_app_from_module\n\nif __name__ == \"__main__\":\n app = build_app_from_module(\"mypackage.commands\")\n app()\n```\n\n\n## Documentation\n\n### New-style type hint support\n\nThrough [`typeapi`][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][].\n\n```py\n# src/mypackage/commands/create_user.py\nfrom ___future__ import annotations\n\ndef main(name: str | None = None, groups: list[str] | None = None) -> None:\n # ...\n```\n\n[`typeapi`][typeapi] also allows us to convert `list[str]` to `List[str]` and `dict[str, int]` to `Dict[str, int]` for\nPython versions prior to 3.9. This is necessary because [Typer][] does not support the new-style type hints.\n\n### Dependency injection\n\nThe `typer_builder.Dependencies` object is used to map types to concrete values or functions that provide them.\nFunctions wrapped with `Dependencies.bind()` will have their arguments resolved by the injector based on type\nannotations. Every `build_app_from_module()` call creates a new `Dependencies` instance. Dependencies can be\ninjected from the outside by passing a `Dependencies` instance to `build_app_from_module()` or by providing\nadditional dependencies via a `callback()` function on the command group.\n\nNote that the `Dependencies` does not understand generics with different type parameters. For example, it makes\nno distinction between `MyGeneric[int]` and `MyGeneric[str]`. This is a limitation of the current implementation as well\nas the Python type system.\n\nThe most common use case for dependency injection is to inject configuration managers or clients into subcommands. For\nan example, you should check out the [examples/dependency-injection](./examples/dependency-injection) directory.\n\n\n## License\n\nThis project is licensed under the terms of the MIT license.\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "",
"version": "0.0.11",
"project_urls": {
"Bug Tracker": "https://github.com/NiklasRosenstein/python-typer-builder/issues",
"Repository": "https://github.com/NiklasRosenstein/typer-builder"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "0c0fbdb530946d65b736ec13f191e8e49cfbce748a41bf6259308858de863805",
"md5": "ded0b37df385886e26da58e861e04b80",
"sha256": "1b185818cf7dd5873692cbb79e06a9ef878c0bd487c103251a3792e8899b639d"
},
"downloads": -1,
"filename": "typer_builder-0.0.11-py3-none-any.whl",
"has_sig": false,
"md5_digest": "ded0b37df385886e26da58e861e04b80",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 9759,
"upload_time": "2023-12-15T13:51:07",
"upload_time_iso_8601": "2023-12-15T13:51:07.973512Z",
"url": "https://files.pythonhosted.org/packages/0c/0f/bdb530946d65b736ec13f191e8e49cfbce748a41bf6259308858de863805/typer_builder-0.0.11-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "ab0fee027c4f8f0c6377a0620c9e03a762a2a0e7fe58431376c3b5843c48863e",
"md5": "9d60abbbd8f3253c2b93caf75c3f5cf3",
"sha256": "b3bb4ccf79d56f5656f69243785a527d26812db70d7b799d6eded14baad99062"
},
"downloads": -1,
"filename": "typer_builder-0.0.11.tar.gz",
"has_sig": false,
"md5_digest": "9d60abbbd8f3253c2b93caf75c3f5cf3",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 9478,
"upload_time": "2023-12-15T13:51:09",
"upload_time_iso_8601": "2023-12-15T13:51:09.152232Z",
"url": "https://files.pythonhosted.org/packages/ab/0f/ee027c4f8f0c6377a0620c9e03a762a2a0e7fe58431376c3b5843c48863e/typer_builder-0.0.11.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-12-15 13:51:09",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "NiklasRosenstein",
"github_project": "python-typer-builder",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "typer-builder"
}