# Packaging

Packaging is bundling up your python library so that it can be easily `pip install` by others.

Typically this involves:

1. Bundling the code into a Built Distribution (wheel) and/or Source Distribution (sdist).

2. Uploading (publishing) the distribution(s) to python package repository, like PyPI.

This section is a brief bootcamp on package configuration for a CLI application. This is not intended to be a complete tutorial on python packaging and publishing. In this tutorial, replace all instances of `mypackage` with your own project name.

## __main__.py

In python, if you have a module `mypackage/__main__.py`, it will be executed with the bash command `python -m mypackage`.

A pretty bare-bones Cyclopts `mypackage/__main__.py` will look like:

    # mypackage/__main__.py

    import cyclopts

    app = cyclopts.App()

    @app.command
    def foo(name: str):
        print(f"Hello {name}!")

    def main():
        app()

    if __name__ == "__main__":
        main()

    $ python -m mypackage World
    Hello World!

In the current state, the `main()` function is an unnecessary extra level of indirection (could just directly call `app`), but it can sometimes offer you additional flexibility in the future if you need it.

## Entrypoints

If you want your application to be callable like a standard bash executable (i.e. `my-package` instead of `python -m mypackage`), we'll need to add an entrypoint. We'll investigate the setuptools solution, and the poetry solution.

### Setuptools

`setup.py` is a script at the root of your project that gets executed upon installation. `setup.cfg` and `pyproject.toml` are two other alternatives that are supported.

The following are all equivalent, but should not be used at the same time. It is important that the function specified takes no arguments.

    # setup.py

    from setuptools import setup

    setup(
        # There should be a lot more fields populated here.
        entry_points={
            "console_scripts": [
                "my-package = mypackage.__main__:main",
            ]
        },
    )

    # pyproject.toml
    [project.scripts]
    my-package = "mypackage.__main__:main"

    # setup.cfg
    [options.entry_points]
    console_scripts =
        my-package = mypackage.__main__:main

All of these represent the same thing: create an executable named `my-package` that executes function `main` (from the right of the colon) from the python module `mypackage.__main__`. Note that this configuration is independent of any special naming, like `__main__` or `main`. The setuptools entrypoint documentation goes into further detail.

### Poetry

Poetry is a tool for dependency management and packaging in Python (and what Cyclopts uses). The syntax is very similar to setuptools:

    # pyproject.toml

    [tool.poetry.scripts]
    my-package = "mypackage.__main__:main"