mainpy


Namemainpy JSON
Version 1.4.0 PyPI version JSON
download
home_pagehttps://github.com/jorenham/mainpy
SummarySimplify your project entrypoint with @main
upload_time2024-09-02 13:27:07
maintainerNone
docs_urlNone
authorJoren Hammudoglu
requires_python<4.0,>=3.8
licenseMIT
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            <h1 align="center"><code>@main</code>.py</h1>

<p align="center">
    <a href="https://pypi.org/project/mainpy/">
        <img
            alt="mainpy - PyPI"
            src="https://img.shields.io/pypi/v/mainpy?style=flat"
        />
    </a>
    <a href="https://github.com/jorenham/mainpy">
        <img
            alt="mainpy - Python Versions"
            src="https://img.shields.io/pypi/pyversions/mainpy?style=flat"
        />
    </a>
    <a href="https://github.com/jorenham/mainpy">
        <img
            alt="mainpy - license"
            src="https://img.shields.io/github/license/jorenham/mainpy?style=flat"
        />
    </a>
</p>
<p align="center">
    <a href="https://github.com/jorenham/mainpy/actions?query=workflow%3ACI">
        <img
            alt="mainpy - CI"
            src="https://github.com/jorenham/mainpy/workflows/CI/badge.svg"
        />
    </a>
    <a href="https://github.com/pre-commit/pre-commit">
        <img
            alt="mainpy - pre-commit"
            src="https://img.shields.io/badge/pre--commit-enabled-orange?logo=pre-commit"
        />
    </a>
    <!-- <a href="https://github.com/KotlinIsland/basedmypy">
        <img
            alt="mainpy - basedmypy"
            src="https://img.shields.io/badge/basedmypy-checked-fd9002"
        />
    </a> -->
    <a href="https://detachhead.github.io/basedpyright">
        <img
            alt="mainpy - basedpyright"
            src="https://img.shields.io/badge/basedpyright-checked-42b983"
        />
    </a>
    <a href="https://github.com/astral-sh/ruff">
        <img
            alt="mainpy - ruff"
            src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json"
        />
    </a>
</p>

---

## Basic Examples

With `mainpy`, there's no need to write `if __name__ == '__main__'` the
boilerplate anymore:

<table>
<tr>
<th width="415px">without <code>mainpy</code></th>
<th width="415px">with <code>mainpy</code></th>
</tr>
<tr>
<td width="415px">

```python
if __name__ == '__main__':
    app()

def app(): ...
```

</td>
<td width="415px">

```python
from mainpy import main

@main
def app(): ...
```

</td>
</tr>
</table>

For async apps, the improvement becomes even more obvious:

<table>
<tr>
<th width="415px">without <code>mainpy</code></th>
<th width="415px">with <code>mainpy</code></th>
</tr>
<tr>
<td width="415px">

```python
import asyncio

async def async_app(): ...

if __name__ == '__main__':
    with asyncio.Runner() as runner:
        runner.run(async_app())
```

</td>
<td width="415px">

```python
from mainpy import main

@main
async def async_app(): ...
```

</td>
</tr>
</table>

## External Libraries

Even though `mainpy` requires no other dependencies than `typing_extensions`
(on Python < 3.10), it has optional support for [`uvloop`][UVLOOP], and plays
nicely with popular CLI libraries, e.g. [`click`][CLICK] and [`typer`][TYPER].

### `uvloop`

If you have [uvloop][UVLOOP] installed, mainpy will automatically call
`uvloop.install()` before running your async main function.
This can be disabled by setting `use_uvloop=False`, e.g.:

```python
@main(use_uvloop=False)
async def app(): ...
```

### Click

With [`click`][CLICK] you can simply add the decorator as usual.

> [!IMPORTANT]
> The `@mainpy.main` decorator must come *before* `@click.command()`.

```python
import mainpy
import click

@mainpy.main
@click.command()
def click_command():
    click.echo('Hello from click_command')
```

The function that is decorated with `@mainpy.main` is executed immediately.
But a `@click.group` must be defined *before* the command function.
In this case, `mainpy.main` should be called *after* all has been setup:

```python
import mainpy
import click

@click.group()
def group(): ...

@group.command()
def command(): ...

mainpy.main(group)
```

### Typer

A [`typer`][TYPER] internally does some initialization after a command
has been defined.
Instead of using `@mainpy.main` on the command itself, you should use
`mainpy.main()` manually:

```python
import mainpy
import typer

app = typer.Typer()

@app.command()
def command():
    typer.echo('typer.Typer()')

mainpy.main(command)
```

## Debug mode

Optionally, Python's [development mode][DEVMODE] can be emulated by passing
`debug=True` to `mainpy.main`. This does three things:

- Enable the [faulthandler][FAULTHANDLER]
- Configure [`warnings`][WARNINGS] to display all warnings
- Runs `async` functions in [debug mode][ADEBUG]

```python
@main(debug=True)
def app(): ...
```

## Installation

The `mainpy` package is available on [pypi][PYPI] for Python $\ge 3.8$:

```shell
pip install mainpy
```

Additionally, you can install the [`uvloop`][UVLOOP] extra which will install
`uvloop>=0.14` (unless you're on windows):

```shell
pip install mainpy[uvloop]
```

[PYPI]: https://pypi.org/project/mainpy/
[UVLOOP]: https://github.com/MagicStack/uvloop
[CLICK]: https://github.com/pallets/click
[TYPER]: https://github.com/tiangolo/typer
[DEVMODE]: https://docs.python.org/3/library/devmode.html
[FAULTHANDLER]: https://docs.python.org/3/library/faulthandler.html
[WARNINGS]: https://docs.python.org/3/library/warnings.html
[ADEBUG]: https://docs.python.org/3/library/asyncio-dev.html#asyncio-debug-mode

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/jorenham/mainpy",
    "name": "mainpy",
    "maintainer": null,
    "docs_url": null,
    "requires_python": "<4.0,>=3.8",
    "maintainer_email": null,
    "keywords": null,
    "author": "Joren Hammudoglu",
    "author_email": "jhammudoglu@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/42/02/60b572ff3587599bff94f9cf87aa75f9ae8c0399a3c02fca17a445e21855/mainpy-1.4.0.tar.gz",
    "platform": null,
    "description": "<h1 align=\"center\"><code>@main</code>.py</h1>\n\n<p align=\"center\">\n    <a href=\"https://pypi.org/project/mainpy/\">\n        <img\n            alt=\"mainpy - PyPI\"\n            src=\"https://img.shields.io/pypi/v/mainpy?style=flat\"\n        />\n    </a>\n    <a href=\"https://github.com/jorenham/mainpy\">\n        <img\n            alt=\"mainpy - Python Versions\"\n            src=\"https://img.shields.io/pypi/pyversions/mainpy?style=flat\"\n        />\n    </a>\n    <a href=\"https://github.com/jorenham/mainpy\">\n        <img\n            alt=\"mainpy - license\"\n            src=\"https://img.shields.io/github/license/jorenham/mainpy?style=flat\"\n        />\n    </a>\n</p>\n<p align=\"center\">\n    <a href=\"https://github.com/jorenham/mainpy/actions?query=workflow%3ACI\">\n        <img\n            alt=\"mainpy - CI\"\n            src=\"https://github.com/jorenham/mainpy/workflows/CI/badge.svg\"\n        />\n    </a>\n    <a href=\"https://github.com/pre-commit/pre-commit\">\n        <img\n            alt=\"mainpy - pre-commit\"\n            src=\"https://img.shields.io/badge/pre--commit-enabled-orange?logo=pre-commit\"\n        />\n    </a>\n    <!-- <a href=\"https://github.com/KotlinIsland/basedmypy\">\n        <img\n            alt=\"mainpy - basedmypy\"\n            src=\"https://img.shields.io/badge/basedmypy-checked-fd9002\"\n        />\n    </a> -->\n    <a href=\"https://detachhead.github.io/basedpyright\">\n        <img\n            alt=\"mainpy - basedpyright\"\n            src=\"https://img.shields.io/badge/basedpyright-checked-42b983\"\n        />\n    </a>\n    <a href=\"https://github.com/astral-sh/ruff\">\n        <img\n            alt=\"mainpy - ruff\"\n            src=\"https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json\"\n        />\n    </a>\n</p>\n\n---\n\n## Basic Examples\n\nWith `mainpy`, there's no need to write `if __name__ == '__main__'` the\nboilerplate anymore:\n\n<table>\n<tr>\n<th width=\"415px\">without <code>mainpy</code></th>\n<th width=\"415px\">with <code>mainpy</code></th>\n</tr>\n<tr>\n<td width=\"415px\">\n\n```python\nif __name__ == '__main__':\n    app()\n\ndef app(): ...\n```\n\n</td>\n<td width=\"415px\">\n\n```python\nfrom mainpy import main\n\n@main\ndef app(): ...\n```\n\n</td>\n</tr>\n</table>\n\nFor async apps, the improvement becomes even more obvious:\n\n<table>\n<tr>\n<th width=\"415px\">without <code>mainpy</code></th>\n<th width=\"415px\">with <code>mainpy</code></th>\n</tr>\n<tr>\n<td width=\"415px\">\n\n```python\nimport asyncio\n\nasync def async_app(): ...\n\nif __name__ == '__main__':\n    with asyncio.Runner() as runner:\n        runner.run(async_app())\n```\n\n</td>\n<td width=\"415px\">\n\n```python\nfrom mainpy import main\n\n@main\nasync def async_app(): ...\n```\n\n</td>\n</tr>\n</table>\n\n## External Libraries\n\nEven though `mainpy` requires no other dependencies than `typing_extensions`\n(on Python < 3.10), it has optional support for [`uvloop`][UVLOOP], and plays\nnicely with popular CLI libraries, e.g. [`click`][CLICK] and [`typer`][TYPER].\n\n### `uvloop`\n\nIf you have [uvloop][UVLOOP] installed, mainpy will automatically call\n`uvloop.install()` before running your async main function.\nThis can be disabled by setting `use_uvloop=False`, e.g.:\n\n```python\n@main(use_uvloop=False)\nasync def app(): ...\n```\n\n### Click\n\nWith [`click`][CLICK] you can simply add the decorator as usual.\n\n> [!IMPORTANT]\n> The `@mainpy.main` decorator must come *before* `@click.command()`.\n\n```python\nimport mainpy\nimport click\n\n@mainpy.main\n@click.command()\ndef click_command():\n    click.echo('Hello from click_command')\n```\n\nThe function that is decorated with `@mainpy.main` is executed immediately.\nBut a `@click.group` must be defined *before* the command function.\nIn this case, `mainpy.main` should be called *after* all has been setup:\n\n```python\nimport mainpy\nimport click\n\n@click.group()\ndef group(): ...\n\n@group.command()\ndef command(): ...\n\nmainpy.main(group)\n```\n\n### Typer\n\nA [`typer`][TYPER] internally does some initialization after a command\nhas been defined.\nInstead of using `@mainpy.main` on the command itself, you should use\n`mainpy.main()` manually:\n\n```python\nimport mainpy\nimport typer\n\napp = typer.Typer()\n\n@app.command()\ndef command():\n    typer.echo('typer.Typer()')\n\nmainpy.main(command)\n```\n\n## Debug mode\n\nOptionally, Python's [development mode][DEVMODE] can be emulated by passing\n`debug=True` to `mainpy.main`. This does three things:\n\n- Enable the [faulthandler][FAULTHANDLER]\n- Configure [`warnings`][WARNINGS] to display all warnings\n- Runs `async` functions in [debug mode][ADEBUG]\n\n```python\n@main(debug=True)\ndef app(): ...\n```\n\n## Installation\n\nThe `mainpy` package is available on [pypi][PYPI] for Python $\\ge 3.8$:\n\n```shell\npip install mainpy\n```\n\nAdditionally, you can install the [`uvloop`][UVLOOP] extra which will install\n`uvloop>=0.14` (unless you're on windows):\n\n```shell\npip install mainpy[uvloop]\n```\n\n[PYPI]: https://pypi.org/project/mainpy/\n[UVLOOP]: https://github.com/MagicStack/uvloop\n[CLICK]: https://github.com/pallets/click\n[TYPER]: https://github.com/tiangolo/typer\n[DEVMODE]: https://docs.python.org/3/library/devmode.html\n[FAULTHANDLER]: https://docs.python.org/3/library/faulthandler.html\n[WARNINGS]: https://docs.python.org/3/library/warnings.html\n[ADEBUG]: https://docs.python.org/3/library/asyncio-dev.html#asyncio-debug-mode\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Simplify your project entrypoint with @main",
    "version": "1.4.0",
    "project_urls": {
        "Bug Tracker": "https://github.com/jorenham/mainpy/issues",
        "Changelog": "https://github.com/jorenham/mainpy/releases",
        "Documentation": "https://github.com/jorenham/mainpy?tab=readme-ov-file#mainpy",
        "Homepage": "https://github.com/jorenham/mainpy",
        "Repository": "https://github.com/jorenham/mainpy"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "c1d85991d85365a9f4c8208497b6a24db55d3d5804d2737dda4a06b43d383e44",
                "md5": "4e6e5bb47f132a5942d84b59f12d3773",
                "sha256": "5c2ea0cf65767f58bb053044e95b05998cdb5f44214783eff6a9dcaf05ecbeba"
            },
            "downloads": -1,
            "filename": "mainpy-1.4.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "4e6e5bb47f132a5942d84b59f12d3773",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "<4.0,>=3.8",
            "size": 5698,
            "upload_time": "2024-09-02T13:27:06",
            "upload_time_iso_8601": "2024-09-02T13:27:06.294492Z",
            "url": "https://files.pythonhosted.org/packages/c1/d8/5991d85365a9f4c8208497b6a24db55d3d5804d2737dda4a06b43d383e44/mainpy-1.4.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "420260b572ff3587599bff94f9cf87aa75f9ae8c0399a3c02fca17a445e21855",
                "md5": "6d61053e567f000218a17eff89dc514f",
                "sha256": "8b4763df867a20daef5226f7477a5b3a56d9f79ef9511f7e54d1f7be06a32de5"
            },
            "downloads": -1,
            "filename": "mainpy-1.4.0.tar.gz",
            "has_sig": false,
            "md5_digest": "6d61053e567f000218a17eff89dc514f",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "<4.0,>=3.8",
            "size": 7099,
            "upload_time": "2024-09-02T13:27:07",
            "upload_time_iso_8601": "2024-09-02T13:27:07.823498Z",
            "url": "https://files.pythonhosted.org/packages/42/02/60b572ff3587599bff94f9cf87aa75f9ae8c0399a3c02fca17a445e21855/mainpy-1.4.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-09-02 13:27:07",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "jorenham",
    "github_project": "mainpy",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "mainpy"
}
        
Elapsed time: 1.05391s