Name | django-typer JSON |
Version |
3.0.0
JSON |
| download |
home_page | None |
Summary | Use Typer to define the CLI for your Django management commands. |
upload_time | 2025-02-17 03:31:14 |
maintainer | None |
docs_url | None |
author | Brian Kohan |
requires_python | <4.0,>=3.9 |
license | MIT |
keywords |
django
cli
management
typer
commands
|
VCS |
 |
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# django-typer
[](https://opensource.org/licenses/MIT)
[](https://github.com/astral-sh/ruff)
[](https://pypi.python.org/pypi/django-typer/)
[](https://pypi.python.org/pypi/django-typer/)
[](https://pypi.org/project/django-typer/)
[](https://pypi.python.org/pypi/django-typer)
[](http://django-typer.readthedocs.io/?badge=latest/)
[](https://codecov.io/gh/django-commons/django-typer)
[](https://github.com/django-commons/django-typer/actions/workflows/test.yml?query=branch:main)
[](https://github.com/django-commons/django-typer/actions/workflows/lint.yml?query=branch:main)
[](https://djangopackages.org/packages/p/django-typer/)
Use static typing to define the CLI for your [Django](https://www.djangoproject.com/) management commands with [Typer](https://typer.tiangolo.com/). Optionally use the provided [TyperCommand](https://django-typer.readthedocs.io/en/latest/reference.html#django_typer.TyperCommand) class that inherits from [BaseCommand](https://docs.djangoproject.com/en/stable/howto/custom-management-commands/#django.core.management.BaseCommand). This class maps the [Typer](https://typer.tiangolo.com/) interface onto a class based interface that Django developers will be familiar with. All of the [BaseCommand](https://docs.djangoproject.com/en/stable/howto/custom-management-commands/#django.core.management.BaseCommand) functionality is inherited, so that [TyperCommand](https://django-typer.readthedocs.io/en/latest/reference.html#django_typer.TyperCommand) can be a drop in replacement.
**django-typer makes it easy to:**
* Define your command CLI interface in a clear, DRY and safe way using type hints
* Create subcommands and hierarchical groups of commands.
* Use the full power of [Typer](https://typer.tiangolo.com/)'s parameter types to validate and parse command line inputs.
* Create beautiful and information dense help outputs.
* Configure the rendering of exception stack traces using [rich](https://rich.readthedocs.io/en/latest/).
* [Install shell tab-completion support](https://django-typer.readthedocs.io/en/latest/shell_completion.html) for [bash](https://www.gnu.org/software/bash/), [zsh](https://www.zsh.org/), [fish](https://fishshell.com/), and [powershell](https://learn.microsoft.com/en-us/powershell/scripting/overview).
* [Create custom and portable shell tab-completions for your CLI parameters.](https://django-typer.readthedocs.io/en/latest/shell_completion.html#defining-custom-completions)
* Port existing commands ([TyperCommand](https://django-typer.readthedocs.io/en/latest/reference.html#django_typer.TyperCommand) is interface compatible with [BaseCommand](https://docs.djangoproject.com/en/stable/howto/custom-management-commands/#django.core.management.BaseCommand)).
* Use either a Django-style class-based interface or the Typer-style interface to define commands.
* Add plugins to upstream commands.
Please refer to the [full documentation](https://django-typer.readthedocs.io/) for more information.

## 🚨 Upgrade Notice
**There are breaking changes between 2.x and 3.x, mostly involving shell tab completion. [See the changelog for migration steps](https://django-typer.readthedocs.io/en/latest/changelog.html#migrating-from-2-x-to-3-x)**.
## Installation
1. Clone django-typer from GitHub or install a release off [PyPI](https://pypi.org/project/django-typer/):
```bash
pip install django-typer
```
[rich](https://rich.readthedocs.io/en/latest/) is a powerful library for rich text and beautiful formatting in the terminal. It is not required but highly recommended for the best experience:
```bash
pip install "django-typer[rich]"
```
2. Optionally add `django_typer` to your `INSTALLED_APPS` setting:
```python
INSTALLED_APPS = [
...
'django_typer',
]
```
*You only need to install django_typer as an app if you want to use the shell completion command to enable tab-completion or if you would like django-typer to install [rich traceback rendering](https://django-typer.readthedocs.io/en/latest/howto.html#configure-rich-stack-traces) for you - which it does by default if rich is also installed.*
## Basic Example
[TyperCommand](https://django-typer.readthedocs.io/en/latest/reference.html#django_typer.TyperCommand) is a drop in extension to [BaseCommand](https://docs.djangoproject.com/en/stable/howto/custom-management-commands/#django.core.management.BaseCommand). All of the documented features of [BaseCommand](https://docs.djangoproject.com/en/stable/howto/custom-management-commands/#django.core.management.BaseCommand) work the same way!
```python
from django_typer.management import TyperCommand
class Command(TyperCommand):
def handle(self, arg1: str, arg2: str, arg3: float = 0.5, arg4: int = 1):
"""
A basic command that uses Typer
"""
```
Or, you may also use an interface identical to [Typer](https://typer.tiangolo.com/)'s. Simply import [Typer](https://typer.tiangolo.com/) from django_typer instead of typer.
```python
from django_typer.management import Typer
app = Typer()
@app.command()
def main(arg1: str, arg2: str, arg3: float = 0.5, arg4: int = 1):
"""
A basic command that uses Typer
"""
```

## Multiple Subcommands Example
Commands with multiple subcommands can be defined:
```python
import typing as t
from django.utils.translation import gettext_lazy as _
from typer import Argument
from django_typer.management import TyperCommand, command
class Command(TyperCommand):
"""
A command that defines subcommands.
"""
@command()
def create(
self,
name: t.Annotated[str, Argument(help=_("The name of the object to create."))],
):
"""
Create an object.
"""
@command()
def delete(
self, id: t.Annotated[int, Argument(help=_("The id of the object to delete."))]
):
"""
Delete an object.
"""
```
Or using the typer-style interface this could be written:
```python
from django_typer.management import Typer
import typing as t
from django.utils.translation import gettext_lazy as _
from typer import Argument
app = Typer(help="A command that defines subcommands.")
@app.command()
def create(
name: t.Annotated[str, Argument(help=_("The name of the object to create."))],
):
"""
Create an object.
"""
@app.command()
def delete(
id: t.Annotated[int, Argument(help=_("The id of the object to delete."))]
):
"""
Delete an object.
"""
```



## Grouping and Hierarchies Example
More complex groups and subcommand hierarchies can be defined. For example, this command defines a group of commands called math, with subcommands divide and multiply. The group has a common initializer that optionally sets a float precision value. We would invoke this command like so:
```bash
./manage.py hierarchy math --precision 5 divide 10 2.1
./manage.py hierarchy math multiply 10 2
```
Using the class-based interface we could define the command like this:
```python
import typing as t
from functools import reduce
from django.utils.translation import gettext_lazy as _
from typer import Argument, Option
from django_typer.management import TyperCommand, group
class Command(TyperCommand):
help = _("A more complex command that defines a hierarchy of subcommands.")
precision = 2
@group(help=_("Do some math at the given precision."))
def math(
self,
precision: t.Annotated[
int, Option(help=_("The number of decimal places to output."))
] = precision,
):
self.precision = precision
# helps can be passed to the decorators
@math.command(help=_("Multiply the given numbers."))
def multiply(
self,
numbers: t.Annotated[
t.List[float], Argument(help=_("The numbers to multiply"))
],
):
return f"{reduce(lambda x, y: x * y, [1, *numbers]):.{self.precision}f}"
# or if no help is supplied to the decorators, the docstring if present
# will be used!
@math.command()
def divide(
self,
numerator: t.Annotated[float, Argument(help=_("The numerator"))],
denominator: t.Annotated[float, Argument(help=_("The denominator"))],
floor: t.Annotated[bool, Option(help=_("Use floor division"))] = False,
):
"""
Divide the given numbers.
"""
if floor:
return str(numerator // denominator)
return f"{numerator / denominator:.{self.precision}f}"
```
The typer-style interface builds a [TyperCommand](https://django-typer.readthedocs.io/en/latest/reference.html#django_typer.TyperCommand) class for us **that allows you to optionally accept the self argument in your commands.** We could define the above command using the typer interface like this:
```python
import typing as t
from functools import reduce
from django.utils.translation import gettext_lazy as _
from typer import Argument, Option
from django_typer.management import Typer
app = Typer(help=_("A more complex command that defines a hierarchy of subcommands."))
math_grp = Typer(help=_("Do some math at the given precision."))
app.add_typer(math_grp, name="math")
@math_grp.callback()
def math(
self,
precision: t.Annotated[
int, Option(help=_("The number of decimal places to output."))
] = 2,
):
self.precision = precision
@math_grp.command(help=_("Multiply the given numbers."))
def multiply(
self,
numbers: t.Annotated[
t.List[float], Argument(help=_("The numbers to multiply"))
],
):
return f"{reduce(lambda x, y: x * y, [1, *numbers]):.{self.precision}f}"
@math_grp.command()
def divide(
self,
numerator: t.Annotated[float, Argument(help=_("The numerator"))],
denominator: t.Annotated[float, Argument(help=_("The denominator"))],
floor: t.Annotated[bool, Option(help=_("Use floor division"))] = False,
):
"""
Divide the given numbers.
"""
if floor:
return str(numerator // denominator)
return f"{numerator / denominator:.{self.precision}f}"
```




Raw data
{
"_id": null,
"home_page": null,
"name": "django-typer",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.9",
"maintainer_email": null,
"keywords": "django, CLI, management, Typer, commands",
"author": "Brian Kohan",
"author_email": "bckohan@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/c4/6e/75a3d464ceb87121fda707746191bf27d0c442f7e88e7d80b9d01844cfdd/django_typer-3.0.0.tar.gz",
"platform": null,
"description": "# django-typer\n\n\n[](https://opensource.org/licenses/MIT)\n[](https://github.com/astral-sh/ruff)\n[](https://pypi.python.org/pypi/django-typer/)\n[](https://pypi.python.org/pypi/django-typer/)\n[](https://pypi.org/project/django-typer/)\n[](https://pypi.python.org/pypi/django-typer)\n[](http://django-typer.readthedocs.io/?badge=latest/)\n[](https://codecov.io/gh/django-commons/django-typer)\n[](https://github.com/django-commons/django-typer/actions/workflows/test.yml?query=branch:main)\n[](https://github.com/django-commons/django-typer/actions/workflows/lint.yml?query=branch:main)\n[](https://djangopackages.org/packages/p/django-typer/)\n\nUse static typing to define the CLI for your [Django](https://www.djangoproject.com/) management commands with [Typer](https://typer.tiangolo.com/). Optionally use the provided [TyperCommand](https://django-typer.readthedocs.io/en/latest/reference.html#django_typer.TyperCommand) class that inherits from [BaseCommand](https://docs.djangoproject.com/en/stable/howto/custom-management-commands/#django.core.management.BaseCommand). This class maps the [Typer](https://typer.tiangolo.com/) interface onto a class based interface that Django developers will be familiar with. All of the [BaseCommand](https://docs.djangoproject.com/en/stable/howto/custom-management-commands/#django.core.management.BaseCommand) functionality is inherited, so that [TyperCommand](https://django-typer.readthedocs.io/en/latest/reference.html#django_typer.TyperCommand) can be a drop in replacement.\n\n**django-typer makes it easy to:**\n\n * Define your command CLI interface in a clear, DRY and safe way using type hints\n * Create subcommands and hierarchical groups of commands.\n * Use the full power of [Typer](https://typer.tiangolo.com/)'s parameter types to validate and parse command line inputs.\n * Create beautiful and information dense help outputs.\n * Configure the rendering of exception stack traces using [rich](https://rich.readthedocs.io/en/latest/).\n * [Install shell tab-completion support](https://django-typer.readthedocs.io/en/latest/shell_completion.html) for [bash](https://www.gnu.org/software/bash/), [zsh](https://www.zsh.org/), [fish](https://fishshell.com/), and [powershell](https://learn.microsoft.com/en-us/powershell/scripting/overview).\n * [Create custom and portable shell tab-completions for your CLI parameters.](https://django-typer.readthedocs.io/en/latest/shell_completion.html#defining-custom-completions)\n * Port existing commands ([TyperCommand](https://django-typer.readthedocs.io/en/latest/reference.html#django_typer.TyperCommand) is interface compatible with [BaseCommand](https://docs.djangoproject.com/en/stable/howto/custom-management-commands/#django.core.management.BaseCommand)).\n * Use either a Django-style class-based interface or the Typer-style interface to define commands.\n * Add plugins to upstream commands.\n\nPlease refer to the [full documentation](https://django-typer.readthedocs.io/) for more information.\n\n\n\n## \ud83d\udea8 Upgrade Notice\n\n**There are breaking changes between 2.x and 3.x, mostly involving shell tab completion. [See the changelog for migration steps](https://django-typer.readthedocs.io/en/latest/changelog.html#migrating-from-2-x-to-3-x)**.\n\n## Installation\n\n1. Clone django-typer from GitHub or install a release off [PyPI](https://pypi.org/project/django-typer/):\n\n ```bash\n pip install django-typer\n ```\n\n [rich](https://rich.readthedocs.io/en/latest/) is a powerful library for rich text and beautiful formatting in the terminal. It is not required but highly recommended for the best experience:\n\n ```bash\n pip install \"django-typer[rich]\"\n ```\n\n2. Optionally add `django_typer` to your `INSTALLED_APPS` setting:\n\n ```python\n INSTALLED_APPS = [\n ...\n 'django_typer',\n ]\n ```\n\n*You only need to install django_typer as an app if you want to use the shell completion command to enable tab-completion or if you would like django-typer to install [rich traceback rendering](https://django-typer.readthedocs.io/en/latest/howto.html#configure-rich-stack-traces) for you - which it does by default if rich is also installed.*\n\n## Basic Example\n\n[TyperCommand](https://django-typer.readthedocs.io/en/latest/reference.html#django_typer.TyperCommand) is a drop in extension to [BaseCommand](https://docs.djangoproject.com/en/stable/howto/custom-management-commands/#django.core.management.BaseCommand). All of the documented features of [BaseCommand](https://docs.djangoproject.com/en/stable/howto/custom-management-commands/#django.core.management.BaseCommand) work the same way!\n\n```python\nfrom django_typer.management import TyperCommand\n\nclass Command(TyperCommand):\n def handle(self, arg1: str, arg2: str, arg3: float = 0.5, arg4: int = 1):\n \"\"\"\n A basic command that uses Typer\n \"\"\"\n```\n\nOr, you may also use an interface identical to [Typer](https://typer.tiangolo.com/)'s. Simply import [Typer](https://typer.tiangolo.com/) from django_typer instead of typer.\n\n```python\nfrom django_typer.management import Typer\n\napp = Typer()\n\n@app.command()\ndef main(arg1: str, arg2: str, arg3: float = 0.5, arg4: int = 1):\n \"\"\"\n A basic command that uses Typer\n \"\"\"\n```\n\n\n\n## Multiple Subcommands Example\n\n\n\nCommands with multiple subcommands can be defined:\n\n```python\n import typing as t\n\n from django.utils.translation import gettext_lazy as _\n from typer import Argument\n\n from django_typer.management import TyperCommand, command\n\n\n class Command(TyperCommand):\n \"\"\"\n A command that defines subcommands.\n \"\"\"\n\n @command()\n def create(\n self,\n name: t.Annotated[str, Argument(help=_(\"The name of the object to create.\"))],\n ):\n \"\"\"\n Create an object.\n \"\"\"\n\n @command()\n def delete(\n self, id: t.Annotated[int, Argument(help=_(\"The id of the object to delete.\"))]\n ):\n \"\"\"\n Delete an object.\n \"\"\"\n\n```\n\nOr using the typer-style interface this could be written:\n\n```python\nfrom django_typer.management import Typer\nimport typing as t\n\nfrom django.utils.translation import gettext_lazy as _\nfrom typer import Argument\n\napp = Typer(help=\"A command that defines subcommands.\")\n\n@app.command()\ndef create(\n name: t.Annotated[str, Argument(help=_(\"The name of the object to create.\"))],\n):\n \"\"\"\n Create an object.\n \"\"\"\n\n@app.command()\ndef delete(\n id: t.Annotated[int, Argument(help=_(\"The id of the object to delete.\"))]\n):\n \"\"\"\n Delete an object.\n \"\"\"\n```\n\n\n\n\n\n\n## Grouping and Hierarchies Example\n\nMore complex groups and subcommand hierarchies can be defined. For example, this command defines a group of commands called math, with subcommands divide and multiply. The group has a common initializer that optionally sets a float precision value. We would invoke this command like so:\n\n```bash\n./manage.py hierarchy math --precision 5 divide 10 2.1\n./manage.py hierarchy math multiply 10 2\n```\n\nUsing the class-based interface we could define the command like this:\n\n```python\n import typing as t\n from functools import reduce\n\n from django.utils.translation import gettext_lazy as _\n from typer import Argument, Option\n\n from django_typer.management import TyperCommand, group\n\n\n class Command(TyperCommand):\n\n help = _(\"A more complex command that defines a hierarchy of subcommands.\")\n\n precision = 2\n\n @group(help=_(\"Do some math at the given precision.\"))\n def math(\n self,\n precision: t.Annotated[\n int, Option(help=_(\"The number of decimal places to output.\"))\n ] = precision,\n ):\n self.precision = precision\n\n # helps can be passed to the decorators\n @math.command(help=_(\"Multiply the given numbers.\"))\n def multiply(\n self,\n numbers: t.Annotated[\n t.List[float], Argument(help=_(\"The numbers to multiply\"))\n ],\n ):\n return f\"{reduce(lambda x, y: x * y, [1, *numbers]):.{self.precision}f}\"\n\n # or if no help is supplied to the decorators, the docstring if present\n # will be used!\n @math.command()\n def divide(\n self,\n numerator: t.Annotated[float, Argument(help=_(\"The numerator\"))],\n denominator: t.Annotated[float, Argument(help=_(\"The denominator\"))],\n floor: t.Annotated[bool, Option(help=_(\"Use floor division\"))] = False,\n ):\n \"\"\"\n Divide the given numbers.\n \"\"\"\n if floor:\n return str(numerator // denominator)\n return f\"{numerator / denominator:.{self.precision}f}\"\n\n```\n\nThe typer-style interface builds a [TyperCommand](https://django-typer.readthedocs.io/en/latest/reference.html#django_typer.TyperCommand) class for us **that allows you to optionally accept the self argument in your commands.** We could define the above command using the typer interface like this:\n\n```python\n\nimport typing as t\nfrom functools import reduce\n\nfrom django.utils.translation import gettext_lazy as _\nfrom typer import Argument, Option\n\nfrom django_typer.management import Typer\n\n\napp = Typer(help=_(\"A more complex command that defines a hierarchy of subcommands.\"))\n\n\nmath_grp = Typer(help=_(\"Do some math at the given precision.\"))\n\napp.add_typer(math_grp, name=\"math\")\n\n@math_grp.callback()\ndef math(\n self,\n precision: t.Annotated[\n int, Option(help=_(\"The number of decimal places to output.\"))\n ] = 2,\n):\n self.precision = precision\n\n\n@math_grp.command(help=_(\"Multiply the given numbers.\"))\ndef multiply(\n self,\n numbers: t.Annotated[\n t.List[float], Argument(help=_(\"The numbers to multiply\"))\n ],\n):\n return f\"{reduce(lambda x, y: x * y, [1, *numbers]):.{self.precision}f}\"\n\n@math_grp.command()\ndef divide(\n self,\n numerator: t.Annotated[float, Argument(help=_(\"The numerator\"))],\n denominator: t.Annotated[float, Argument(help=_(\"The denominator\"))],\n floor: t.Annotated[bool, Option(help=_(\"Use floor division\"))] = False,\n):\n \"\"\"\n Divide the given numbers.\n \"\"\"\n if floor:\n return str(numerator // denominator)\n return f\"{numerator / denominator:.{self.precision}f}\"\n```\n\n\n\n\n\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Use Typer to define the CLI for your Django management commands.",
"version": "3.0.0",
"project_urls": {
"Changelog": "https://django-typer.readthedocs.io/en/latest/changelog.html",
"Code_of_Conduct": "https://github.com/django-commons/membership/blob/main/CODE_OF_CONDUCT.md",
"Documentation": "https://django-typer.readthedocs.io",
"Homepage": "https://django-typer.readthedocs.io",
"Issues": "https://github.com/django-commons/django-typer/issues",
"Repository": "https://github.com/django-commons/django-typer"
},
"split_keywords": [
"django",
" cli",
" management",
" typer",
" commands"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "9e62258a4f716611523aac059d2f40130eb906bdacf563f6e12ad4e6f65e6aa3",
"md5": "ec81746d0738fcaf8e98ce61351d8db6",
"sha256": "b03b9cda603ece6555cf621e889669848074728963a2c894da7db3ce3e7f4e6e"
},
"downloads": -1,
"filename": "django_typer-3.0.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "ec81746d0738fcaf8e98ce61351d8db6",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.9",
"size": 292824,
"upload_time": "2025-02-17T03:31:12",
"upload_time_iso_8601": "2025-02-17T03:31:12.182292Z",
"url": "https://files.pythonhosted.org/packages/9e/62/258a4f716611523aac059d2f40130eb906bdacf563f6e12ad4e6f65e6aa3/django_typer-3.0.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "c46e75a3d464ceb87121fda707746191bf27d0c442f7e88e7d80b9d01844cfdd",
"md5": "cbb12f6231c7991c2c16018ccdd3b2f3",
"sha256": "38b9f8e2c2de9593511a0f969034bf64b6bd387549eecdf252832b3e606d5df7"
},
"downloads": -1,
"filename": "django_typer-3.0.0.tar.gz",
"has_sig": false,
"md5_digest": "cbb12f6231c7991c2c16018ccdd3b2f3",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.9",
"size": 149897,
"upload_time": "2025-02-17T03:31:14",
"upload_time_iso_8601": "2025-02-17T03:31:14.661927Z",
"url": "https://files.pythonhosted.org/packages/c4/6e/75a3d464ceb87121fda707746191bf27d0c442f7e88e7d80b9d01844cfdd/django_typer-3.0.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-02-17 03:31:14",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "django-commons",
"github_project": "membership",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "django-typer"
}