Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: use modern package setup for example #817

Merged
merged 1 commit into from
Jan 29, 2021
Merged

Conversation

henryiii
Copy link
Contributor

@henryiii henryiii commented Jan 27, 2021

This is an attempt to modernize the suggestions in the packaging tutorial. Changes:

  • Include pyproject.toml
  • Use pypa/build for building the SDist & wheel, drop the --user recommendation (no longer needed and often harmful)
  • Update links to poetry

I've also rewrapped a few lines without changes that were ridiculously longer than 80 characters for consistency.

Closes #809.

@di
Copy link
Member

di commented Jan 28, 2021

Thanks!

I'm not sure we should recommend setup.cfg in light of pypa/setuptools#1688 (although it could be a while before that lands). At the very least, we might want to explore the "tabs" mentioned in that issue instead of removing the existing documentation entirely.

Everything else looks immediately mergeable though, could you break this into two PRs so we can land those changes immediately?

…rial. Changes:

* Include `pyproject.toml`
* Use `pypa/build` for building the SDist & wheel, drop the `--user` recommendation (no longer needed and often harmful)
* Update links to poetry

I've also rewrapped a few lines without changes that were ridiculously longer than 80 characters for consistency.
@henryiii
Copy link
Contributor Author

henryiii commented Jan 29, 2021

I've split out the setup.cfg changes. I still would highly recommend setup.cfg, because:

  • It is a static, easily parsable file, which is highly superior to a Python file - for example, cibuildwheel should soon gain support for reading the Requires-Python metadata from the PEP 621 location or from setup.cfg, but setup.py is impossible to reliably parse.
  • It avoids many common issues, like opening files without with, encoding issues, and issues with accessing the version.
  • It keeps setup.py as just logic, making it clear what's "dynamic" and what's just regular metadata.
  • It's actually readable, much less boilerplate
  • Less change of importing from distutils before setuptools
  • The PyPA projects, like twine, build, etc, use setup.cfg.
  • It's been supported since 2016
  • It's really easy to just say the fields are dynamically specifiable as keywords to setup than it is to say the keywords to setup might be in [options] or in [metadata] or in ...

While I'm really excited for PEP 621 support, that's quite some time away (looks like funding has not even been secured yet), and then there's another period for the tooling to mature and become common enough to be used, it won't ever support Python 2 / PyPy 2, etc, so I expect adoption to be slow. And setup.cfg is still not going away, with some tools strongly refusing (cough, flake8, cough cough) to ever add pyproject.toml support (MyPy is still setup.cfg only too).

If people are writing setup.cfg's, it will be much easier to transition to pyproject.toml than from setup.py.

For historical purposes (and because I can't easily make the PR since they would conflict), here is the content that I've removed:
Creating setup.cfg
------------------

:file:`setup.cfg` is the configuration file for :ref:`setuptools`. It tells
setuptools about your package (such as the name and version) as well as which
code files to include. Eventually much of this configuration may be able to move
to :file:`pyproject.toml`.

Open :file:`setup.py` and enter the following content. Update the package name
to include your username (for example, ``example-pkg-theacodes``), this ensures
that you have a unique package name and that your package doesn't conflict with
packages uploaded by other people following this tutorial.

.. code-block:: python

    [metadata]
    # replace with your username:
    name = example-pkg-YOUR-USERNAME-HERE
    version = 0.0.1
    url = https://github.com/pypa/sampleproject
    author = Example Author
    author_email = author@example.com
    classifiers =
        Programming Language :: Python :: 3
        License :: OSI Approved :: MIT License
        Operating System :: OS Independent
    description = A small example package
    long_description = file: README.md
    long_description_content_type = text/markdown

    [options]
    python_requires = >=3.6


There are a `variety of metadata and options
<https://setuptools.readthedocs.io/en/latest/userguide/declarative_config.html>`_
supported here. This is in configparser format; do not place quotes around values.
This example package uses a relatively minimal set of options:

- ``name`` is the *distribution name* of your package. This can be any name as
  long as only contains letters, numbers, ``_`` , and ``-``. It also must not
  already be taken on pypi.org. **Be sure to update this with your username,**
  as this ensures you won't try to upload a package with the same name as one
  which already exists when you upload the package.
- ``version`` is the package version see :pep:`440` for more details on
  versions. You can use ``file:`` or ``attr:`` directives to read from a file or
  package attribute (simple attributes do not require import).
- ``author`` and ``author_email`` are used to identify the author of the
  package.
- ``description`` is a short, one-sentence summary of the package.
- ``long_description`` is a detailed description of the package. This is
  shown on the package detail page on the Python Package Index. In
  this case, the long description is loaded from :file:`README.md` which is
  a common pattern, using the ``file:`` directive.
- ``long_description_content_type`` tells the index what type of markup is
  used for the long description. In this case, it's Markdown.
- ``url`` is the URL for the homepage of the project. For many projects, this
  will just be a link to GitHub, GitLab, Bitbucket, or similar code hosting
  service.
- ``packages`` is a list of all Python :term:`import packages <Import
  Package>` that should be included in the :term:`Distribution Package`.
  Instead of listing each package manually, we can use the ``find:`` directive
  to automatically discover all packages and subpackages. In this case, the
  list of packages will be ``example_pkg`` as that's the only package present.
- ``classifiers`` gives the index and :ref:`pip` some additional metadata
  about your package. In this case, the package is only compatible with Python
  3, is licensed under the MIT license, and is OS-independent. You should
  always include at least which version(s) of Python your package works on,
  which license your package is available under, and which operating systems
  your package will work on. For a complete list of classifiers, see
  https://pypi.org/classifiers/.

There are many more than the ones mentioned here. See
:doc:`/guides/distributing-packages-using-setuptools` for more details.

Creating setup.py (optional)
----------------------------

If you create a setup.py file, this will enable direct interaction with
:file:`setup.py` (which generally should be avoided), and editable installs. This file
used to be required, but can be omitted in modern setuptools.

Anything you set in setup.cfg can instead be set via keyword argument to
:func:`setup()`; this enables computed values to be used. You will also need
:func:`setup()` for setting up extension modules for compilation.

.. code-block:: python

    import setuptools

    setuptools.setup()

@di di merged commit c3d4b22 into pypa:main Jan 29, 2021
@henryiii henryiii deleted the chore/modern branch January 29, 2021 01:17
@di
Copy link
Member

di commented Jan 29, 2021

Agree w/ you on all fronts. Let's open a new PR w/ those changes and take the discussion there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Modernize packaging tutorial
2 participants