https://github.com/jorenham/mainpy
Simplify your project's main entrypoint definition with @main
https://github.com/jorenham/mainpy
asyncio python python-3
Last synced: about 1 year ago
JSON representation
Simplify your project's main entrypoint definition with @main
- Host: GitHub
- URL: https://github.com/jorenham/mainpy
- Owner: jorenham
- License: mit
- Created: 2022-04-02T20:44:57.000Z (about 4 years ago)
- Default Branch: main
- Last Pushed: 2024-10-03T12:36:08.000Z (over 1 year ago)
- Last Synced: 2024-10-12T00:34:58.419Z (over 1 year ago)
- Topics: asyncio, python, python-3
- Language: Python
- Homepage: https://pypi.org/project/mainpy/
- Size: 308 KB
- Stars: 6
- Watchers: 4
- Forks: 2
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Security: SECURITY.md
Awesome Lists containing this project
README
@main.py
---
## Basic Examples
With `mainpy`, there's no need to write `if __name__ == '__main__'` the
boilerplate anymore:
without mainpy
with mainpy
```python
if __name__ == '__main__':
app()
def app(): ...
```
```python
from mainpy import main
@main
def app(): ...
```
For async apps, the improvement becomes even more obvious:
without mainpy
with mainpy
```python
import asyncio
async def async_app(): ...
if __name__ == '__main__':
with asyncio.Runner() as runner:
runner.run(async_app())
```
```python
from mainpy import main
@main
async def async_app(): ...
```
## 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.9$:
```shell
pip install mainpy
```
Additionally, you can install the [`uvloop`][UVLOOP] extra which will install
`uvloop>=0.15.2` (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