From e3f487d9168aa28a932509d65f97901e5668f883 Mon Sep 17 00:00:00 2001 From: Cadu Date: Sat, 7 Dec 2024 17:41:21 -0300 Subject: [PATCH 1/3] Change the function name to be able to be more easily imported (some IDEs actively avoid suggesting importing something named "main") --- README.md | 40 ++++++++++++++++++++++++++++++++++------ python_main/__init__.py | 15 ++++++++++----- tests/test_basic.py | 6 +++--- 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index e205973..2d478cb 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,16 @@ -# @main +# @python_main [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/python-main)](https://pypi.org/project/python-main/) [![PyPI - Version](https://img.shields.io/pypi/v/python-main)](https://pypi.org/project/python-main/) -`@main` decorator which runs the tagged function if the current module is being executed as a script. +`@python_main` is a decorator which: +- Automatically calls the function(s) tagged with it, if the current module is being **executed as a script**. +- Does nothing if the current module is being **imported**. -No more `if __name__ == "__main__":` all over the place. +It is, essentially, similar to the `if __name__ == "__main__":` block, but as a decorator. -That's it! +That's all it does. ### Installation @@ -20,14 +22,40 @@ poetry add python-main # ... ### Usage ```python -from python_main import main +from python_main import python_main A = 10 B = 20 -@main +@python_main def do_print(): """This will run if this module is executed.""" print(A + B) ``` + +You can also tag multiple functions with `@python_main` and they will all run if the module is executed, in the order they are defined. + +```python +from python_main import python_main + +A = 10 +B = 20 +C = 0 + +@python_main +def add_a_to_c(): + global C + C += A + +# ... other functions/ definitions ... + +@python_main +def add_b_to_c(): + global C + C += B + +# At this point: +# - C will be 30 if this module is executed as a script. +# - C will be untouched if this module is imported. +``` diff --git a/python_main/__init__.py b/python_main/__init__.py index 2b00fe9..9e42b3c 100644 --- a/python_main/__init__.py +++ b/python_main/__init__.py @@ -6,11 +6,16 @@ __MAIN_RETURN_TYPE = TypeVar("__MAIN_RETURN_TYPE") -def main(f: Callable[[], __MAIN_RETURN_TYPE]) -> Callable[[], __MAIN_RETURN_TYPE]: - if getattr(f, __CALLABLE_MODULE_PROP) == __RAN_AS_SCRIPT_MODULE: - f() - return f +def python_main( + main_function_to_be_called: Callable[[], __MAIN_RETURN_TYPE] +) -> Callable[[], __MAIN_RETURN_TYPE]: + if ( + getattr(main_function_to_be_called, __CALLABLE_MODULE_PROP) + == __RAN_AS_SCRIPT_MODULE + ): + main_function_to_be_called() + return main_function_to_be_called # Only export the main function -__all__ = ["main"] +__all__ = ["python_main"] diff --git a/tests/test_basic.py b/tests/test_basic.py index 21ae8d7..5fbab06 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -2,7 +2,7 @@ import pytest -from python_main import main +from python_main import python_main EXIT_CODE_RECEIVED = -1 @@ -44,7 +44,7 @@ def test_assert_function_actually_gets_called(mock_exit): __my_main_func.__module__ = "__main__" # Decorate it - main(__my_main_func) + python_main(__my_main_func) # Ensure that our main function was able to call mock_exit with the expected value. global EXIT_CODE_RECEIVED @@ -60,7 +60,7 @@ def test_assert_function_does_not_get_called(mock_exit): """ # Call the function, which is coming from a pytest execution and being imported as a module - function_returned = main(__my_main_func) + function_returned = python_main(__my_main_func) # Exit code will not have been set. global EXIT_CODE_RECEIVED From 83aa9f1d38c4a0cc56c66e054c5d932516464d96 Mon Sep 17 00:00:00 2001 From: Cadu Date: Sat, 7 Dec 2024 17:43:59 -0300 Subject: [PATCH 2/3] Wordsmithing. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2d478cb..d2fed21 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ - Automatically calls the function(s) tagged with it, if the current module is being **executed as a script**. - Does nothing if the current module is being **imported**. -It is, essentially, similar to the `if __name__ == "__main__":` block, but as a decorator. +It is, essentially, equivalent to the `if __name__ == "__main__":` construct, but as a decorator. That's all it does. From 59ca4c36eda2f3cf8d74c782b789b7fe0689c76f Mon Sep 17 00:00:00 2001 From: Cadu Date: Sat, 7 Dec 2024 17:44:56 -0300 Subject: [PATCH 3/3] Wordsmithing #2 --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index d2fed21..8756322 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,6 @@ from python_main import python_main A = 10 B = 20 - @python_main def do_print(): """This will run if this module is executed."""