Skip to content

Instantly share code, notes, and snippets.

@jorenham
Last active March 29, 2022 14:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jorenham/98bc8bfe16482a1c1b25ea2512e7d993 to your computer and use it in GitHub Desktop.
Save jorenham/98bc8bfe16482a1c1b25ea2512e7d993 to your computer and use it in GitHub Desktop.
`@main` decorator as alternative to `if __name__ == '__main__': ...`
import asyncio
from run import main
@main(debug=True)
async def __amain__():
await asyncio.sleep(0.1)
fp = open(__file__)
nlines = len(fp.readlines())
print(nlines, __file__)
/usr/lib/python3.9/asyncio/events.py:80: ResourceWarning: unclosed file <_io.TextIOWrapper name='/example.py' mode='r' encoding='UTF-8'>
self._context.run(self._callback, *self._args)
ResourceWarning: Enable tracemalloc to get the object allocation traceback
12 /example.py
from __future__ import annotations
__all__ = ('run', 'main')
import asyncio
import functools
import inspect
import os
import sys
from typing import Any, Callable, NoReturn, overload, TypeVar
_F = TypeVar('_F', bound=Callable)
def run(fn: _F, *, debug: bool = False) -> NoReturn:
args = tuple(sys.argv[1:])
env = os.environ
flags = sys.flags
if debug or flags.debug or flags.dev_mode:
if not env.get('PYTHONWARNINGS'):
import warnings
warnings.simplefilter('default')
if not (env.get('PYTHONDEVMODE') or env.get('PYTHONFAULTHANDLER')):
import faulthandler
faulthandler.enable()
try:
functools.partial(fn, *args)
except TypeError:
args = ()
res = fn()
if inspect.isawaitable(res):
aio_debug = bool(int(env.get('PYTHONASYNCIODEBUG', debug)))
res = asyncio.run(res, debug=aio_debug)
sys.exit(res or 0)
@overload
def main(fn: None = ..., **kwargs: Any) -> Callable[[_F], _F]: ...
@overload
def main(fn: _F, **kwargs: Any) -> NoReturn: ...
def main(fn: _F | None = None, **kwargs) -> Callable[[_F], _F] | NoReturn:
if fn is None:
def _main(_fn: _F) -> NoReturn:
run(_fn, **kwargs)
return _main
if fn.__module__ == '__main__':
run(fn, **kwargs)
if not callable(fn):
raise TypeError(f'expected a callable, got {type(fn).__name__}')
return fn
@main
def __main():
# this should never run
assert False
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment