[bumpversion]
-current_version = 54.1.0
+current_version = 54.1.1
commit = True
tag = True
--- /dev/null
+---
+name: 🐛 Bug report
+description: >-
+ Create a report to help us improve when
+ something is not working correctly
+title: '[BUG] '
+labels:
+- bug
+- Needs Triage
+issue_body: false # default: true, adds a classic WSYWIG textarea, if on
+
+body:
+- type: markdown
+ attributes:
+ value: >
+ **Thank you for wanting to report a bug in setuptools!**
+
+
+ ⚠
+ Verify first that your issue is not
+ [already reported on GitHub][issue search] and keep in mind and
+ keep in mind that we may have to keep the current behavior because
+ [every change breaks someone's workflow][XKCD 1172].
+ We try to be mindful about this.
+
+ Also test if the latest release and main branch are affected too.
+
+
+ If you are seeking community support, please consider
+ [starting a discussion][Discussions].
+
+
+ Thank you for your collaboration!
+
+
+ [Discussions]: https://github.com/pypa/setuptools/discussions
+
+ [issue search]: https://github.com/pypa/setuptools/search?q=is%3Aissue&type=issues
+
+ [XKCD 1172]: https://xkcd.com/1172/
+
+- type: markdown
+ attributes:
+ value: >-
+ **Environment**
+- type: input
+ attributes:
+ label: setuptools version
+ placeholder: For example, setuptools===60.4.2
+ validations:
+ required: true
+- type: input
+ attributes:
+ label: Python version
+ placeholder: For example, Python 3.10
+ validations:
+ required: true
+- type: input
+ attributes:
+ label: OS
+ placeholder: For example, Gentoo Linux, RHEL 8, Arch Linux, macOS etc.
+ validations:
+ required: true
+- type: textarea
+ attributes:
+ label: Additional environment information
+ description: >-
+ Feel free to add more information about your environment here.
+ placeholder: >-
+ This is only happening when I run setuptools on my fridge's patched firmware 🤯
+
+- type: textarea
+ attributes:
+ label: Description
+ description: >-
+ A clear and concise description of what the bug is.
+ placeholder: >-
+ I tried doing X and I expected it to result in Y because the docs
+ mentioned Z but what happened next what totally unexpected!
+ And here's why...
+ validations:
+ required: true
+
+- type: textarea
+ attributes:
+ label: Expected behavior
+ description: >-
+ A clear and concise description of what you expected to happen.
+ placeholder: >-
+ I tried doing X and I expected it to result in Y. I'm confused...
+ validations:
+ required: true
+
+- type: textarea
+ attributes:
+ label: How to Reproduce
+ description: >-
+ Describe the steps to reproduce this bug.
+ placeholder: |
+ 1. Integrate setuptools via '...'
+ 2. Then run '...'
+ 3. An error occurs.
+ validations:
+ required: true
+
+- type: textarea
+ attributes:
+ label: Output
+ description: >-
+ Paste the output of the steps above, including the commands
+ themselves and setuptools' output/traceback etc.
+ value: |
+ ```console
+
+ ```
+ validations:
+ required: true
+
+
+- type: checkboxes
+ attributes:
+ label: Code of Conduct
+ description: |
+ Read the [PSF Code of Conduct][CoC] first.
+
+ [CoC]: https://github.com/pypa/.github/blob/main/CODE_OF_CONDUCT.md
+ options:
+ - label: I agree to follow the PSF Code of Conduct
+ required: true
+...
--- /dev/null
+# Ref: https://help.github.com/en/github/building-a-strong-community/configuring-issue-templates-for-your-repository#configuring-the-template-chooser
+blank_issues_enabled: false # default: true
+contact_links:
+- name: 🤔 Have questions or need support?
+ url: https://github.com/pypa/setuptools/discussions
+ about: This is a place for the community to exchange ideas and recipes
+- name: 💬 Discourse
+ url: https://discuss.python.org/c/packaging
+ about: |
+ Please ask typical Q&A here: general ideas for Python packaging,
+ questions about structuring projects and so on
+- name: >-
+ 💬 IRC: #pypa @ Freenode
+ url: https://webchat.freenode.net/#pypa
+ about: Chat with devs
--- /dev/null
+---
+name: 📝 Documentation Report
+title: '[Docs] '
+description: Ask us about docs
+labels:
+- documentation
+- Needs Triage
+# NOTE: issue body is enabled to allow screenshots
+issue_body: true # default: true, adds a classic WSYWIG textarea, if on
+
+body:
+- type: markdown
+ attributes:
+ value: >
+ **Thank you for wanting to report a problem with setuptools
+ documentation!**
+
+
+ Please fill out your suggestions below. If the problem seems
+ straightforward, feel free to go ahead and
+ submit a pull request instead!
+
+
+ ⚠
+ Verify first that your issue is not [already reported on
+ GitHub][issue search].
+
+
+ If you are seeking community support, please consider
+ [starting a discussion][Discussions].
+
+
+ Thank you for your collaboration!
+
+
+ [issue search]: https://github.com/pypa/setuptools/search?q=is%3Aissue&type=issues
+
+ [Discussions]: https://github.com/pypa/setuptools/discussions
+
+- type: textarea
+ attributes:
+ label: Summary
+ description: >
+ Explain the problem briefly below, add suggestions to wording
+ or structure.
+
+
+ **HINT:** Did you know the documentation has a `View on GitHub`
+ link on every page? Feel free to use it to start a pull request
+ right from the GitHub UI!
+ placeholder: >-
+ I was reading the setuptools documentation of version X and I'm
+ having problems understanding Y. It would be very helpful if that
+ got rephrased as Z.
+ validations:
+ required: true
+
+- type: textarea
+ attributes:
+ label: OS / Environment
+ description: >-
+ Provide all relevant information below, e.g. OS version,
+ browser, etc.
+ placeholder: Fedora 33, Firefox etc.
+
+
+- type: checkboxes
+ attributes:
+ label: Code of Conduct
+ description: |
+ Read the [PSF Code of Conduct][CoC] first.
+
+ [CoC]: https://github.com/pypa/.github/blob/main/CODE_OF_CONDUCT.md
+ options:
+ - label: I agree to follow the PSF Code of Conduct
+ required: true
+
+
+- type: markdown
+ attributes:
+ value: >
+
+
+ ### Additional Information
+
+
+ Describe how this improves the documentation, e.g. before/after
+ situation or screenshots.
+
+
+ **HINT:** You can paste https://gist.github.com links for
+ larger files.
+...
--- /dev/null
+---
+name: ✨ Feature request
+description: Suggest an idea for setuptools
+title: '[FR] '
+labels:
+- enhancement
+- Needs Triage
+issue_body: false # default: true, adds a classic WSYWIG textarea, if on
+
+body:
+- type: markdown
+ attributes:
+ value: >
+ **Thank you for wanting to suggest a feature for setuptools!**
+
+
+ 💡
+ Before you go ahead with your request, please first consider if it
+ would be useful for majority of the setuptools users. As a general
+ rule of thumb, any feature that is only of interest to a small sub
+ group should be implemented in a third-party plugin or maybe even
+ just your project alone. Be mindful of the fact that the core
+ setuptools features have a broad impact.
+
+
+ <details>
+ <summary>
+ ❗ Every change breaks someone's workflow.
+ </summary>
+
+
+ [
+ ](https://xkcd.com/1172/)
+ </details>
+
+
+ ⚠
+ Verify first that your idea is not [already requested on GitHub][issue search].
+
+
+
+ [issue search]: https://github.com/pypa/setuptools/search?q=is%3Aissue&type=issues
+
+- type: textarea
+ attributes:
+ label: What's the problem this feature will solve?
+ description: >-
+ What are you trying to do, that you are unable to achieve
+ with setuptools as it currently stands?
+ placeholder: >-
+ I'm trying to do X and I'm missing feature Y for this to be
+ easily achievable.
+ validations:
+ required: true
+
+- type: textarea
+ attributes:
+ label: Describe the solution you'd like
+ description: >
+ Clear and concise description of what you want to happen.
+
+
+ Provide examples of real world use cases that this would enable
+ and how it solves the problem described above.
+ placeholder: >-
+ When I do X, I want to achieve Y in a situation when Z.
+ validations:
+ required: true
+
+- type: textarea
+ attributes:
+ label: Alternative Solutions
+ description: >-
+ Have you tried to workaround the problem using other tools? Or a
+ different approach to solving this issue? Please elaborate here.
+ placeholder: >-
+ I tried doing X, Y and Z. But they are subobpimal because of P.
+
+- type: textarea
+ attributes:
+ label: Additional context
+ description: >
+ Add any other context, links, etc. about the feature here.
+ Describe how the feature would be used, why it is needed and what
+ it would solve.
+
+
+ **HINT:** You can paste https://gist.github.com links for
+ larger files.
+ placeholder: >-
+ I asked on https://stackoverflow.com/.... and the community
+ advised me to do X, Y and Z.
+
+
+- type: checkboxes
+ attributes:
+ label: Code of Conduct
+ description: |
+ Read the [PSF Code of Conduct][CoC] first.
+
+ [CoC]: https://github.com/pypa/.github/blob/main/CODE_OF_CONDUCT.md
+ options:
+ - label: I agree to follow the PSF Code of Conduct
+ required: true
+...
+v54.1.1
+-------
+
+
+Documentation changes
+^^^^^^^^^^^^^^^^^^^^^
+* #2584: Added ``sphinx-inline-tabs`` extension to allow for comparison of ``setup.py`` and its equivalent ``setup.cfg`` -- by :user:`amy-lei`
+
+Misc
+^^^^
+* #2592: Made option keys in the ``[metadata]`` section of ``setup.cfg`` case-sensitive. Users having
+ uppercase option spellings will get a warning suggesting to make them to lowercase
+ -- by :user:`melissa-kun-li`
+
+
v54.1.0
-------
html_theme = 'alabaster'
templates_path = ['_templates']
html_sidebars = {'index': ['tidelift-sidebar.html']}
+
+# Add support for inline tabs
+extensions += ['sphinx_inline_tabs']
jaraco.packaging>=6.1
rst.linker>=1.9
pygments-github-lexers==0.0.5
+sphinx-inline-tabs
setuptools>=34
these dependencies when the package is installed. Although there is more
finess to it, let's start with a simple example.
-.. code-block:: ini
+.. tab:: setup.cfg
- [options]
- #...
- install_requires =
- docutils
- BazSpam ==1.1
+ .. code-block:: ini
+
+ [options]
+ #...
+ install_requires =
+ docutils
+ BazSpam ==1.1
+
+.. tab:: setup.py
-.. code-block:: python
+ .. code-block:: python
- setup(
- #...,
- install_requires = [
- 'docutils',
- 'BazSpam ==1.1'
- ]
- )
+ setup(
+ #...,
+ install_requires = [
+ 'docutils',
+ 'BazSpam ==1.1'
+ ]
+ )
When your project is installed (e.g. using pip), all of the dependencies not
3.4, therefore, package that depends on it can elect to install it only when
the Python version is older than 3.4. To accomplish this
-.. code-block:: ini
-
- [options]
- #...
- install_requires =
- enum34;python_version<'3.4'
+.. tab:: setup.cfg
-.. code-block:: python
+ .. code-block:: ini
- setup(
+ [options]
#...
- install_requires=[
- "enum34;python_version<'3.4'",]
- )
+ install_requires =
+ enum34;python_version<'3.4'
+
+.. tab:: setup.py
+
+ .. code-block:: python
+
+ setup(
+ #...
+ install_requires=[
+ "enum34;python_version<'3.4'",]
+ )
Similarly, if you also wish to declare ``pywin32`` with a minimal version of 1.0
and only install it if the user is using a Windows operating system:
-.. code-block:: ini
-
- [options]
- #...
- install_requires =
- enum34;python_version<'3.4'
- pywin32 >= 1.0;platform_system=='Windows'
+.. tab:: setup.cfg
-.. code-block:: python
+ .. code-block:: ini
- setup(
+ [options]
#...
- install_requires=[
- "enum34;python_version<'3.4'",
- "pywin32 >= 1.0;platform_system=='Windows'"
- ]
- )
+ install_requires =
+ enum34;python_version<'3.4'
+ pywin32 >= 1.0;platform_system=='Windows'
+
+.. tab:: setup.py
+
+ .. code-block:: python
+
+ setup(
+ #...
+ install_requires=[
+ "enum34;python_version<'3.4'",
+ "pywin32 >= 1.0;platform_system=='Windows'"
+ ]
+ )
The environmental markers that may be used for testing platform types are
detailed in `PEP 508 <https://www.python.org/dev/peps/pep-0508/>`_.
example, this will cause a search of the specified page for eggs or source
distributions, if the package's dependencies aren't already installed:
-.. code-block:: ini
-
- [options]
- #...
- dependency_links = http://peak.telecommunity.com/snapshots/
+.. tab:: setup.cfg
-.. code-block:: python
+ .. code-block:: ini
- setup(
+ [options]
#...
- dependency_links=[
- "http://peak.telecommunity.com/snapshots/"
- ],
- )
+ dependency_links = http://peak.telecommunity.com/snapshots/
+
+.. tab:: setup.py
+
+ .. code-block:: python
+
+ setup(
+ #...
+ dependency_links=[
+ "http://peak.telecommunity.com/snapshots/"
+ ],
+ )
Optional dependencies
For example, Package-A offers optional PDF support and requires two other
dependencies for it to work:
-.. code-block:: ini
+.. tab:: setup.cfg
- [metadata]
- name = Package-A
+ .. code-block:: ini
- [options.extras_require]
- PDF = ReportLab>=1.2; RXP
+ [metadata]
+ name = Package-A
+ [options.extras_require]
+ PDF = ReportLab>=1.2; RXP
-.. code-block:: python
- setup(
- name="Project-A",
- #...
- extras_require={
- "PDF": ["ReportLab>=1.2", "RXP"],
- }
- )
+.. tab:: setup.py
+
+ .. code-block:: python
+
+ setup(
+ name="Project-A",
+ #...
+ extras_require={
+ "PDF": ["ReportLab>=1.2", "RXP"],
+ }
+ )
The name ``PDF`` is an arbitary identifier of such a list of dependencies, to
which other components can refer and have them installed. There are two common
First is the console_scripts entry point:
-.. code-block:: ini
+.. tab:: setup.cfg
- [metadata]
- name = Project A
- #...
+ .. code-block:: ini
- [options]
- #...
- entry_points=
- [console_scripts]
- rst2pdf = project_a.tools.pdfgen [PDF]
- rst2html = project_a.tools.htmlgen
-
-.. code-block:: python
-
- setup(
- name = "Project-A"
- #...,
- entry_points={
- "console_scripts": [
- "rst2pdf = project_a.tools.pdfgen [PDF]",
- "rst2html = project_a.tools.htmlgen",
- ],
- }
- )
+ [metadata]
+ name = Project A
+ #...
+
+ [options]
+ #...
+ entry_points=
+ [console_scripts]
+ rst2pdf = project_a.tools.pdfgen [PDF]
+ rst2html = project_a.tools.htmlgen
+
+.. tab:: setup.py
+
+ .. code-block:: python
+
+ setup(
+ name = "Project-A"
+ #...,
+ entry_points={
+ "console_scripts": [
+ "rst2pdf = project_a.tools.pdfgen [PDF]",
+ "rst2html = project_a.tools.htmlgen",
+ ],
+ }
+ )
This syntax indicates that the entry point (in this case a console script)
is only valid when the PDF extra is installed. It is up to the installer
own dependencies. For example, if "Project-B" needs "project A" with PDF support
installed, it might declare the dependency like this:
-.. code-block:: ini
+.. tab:: setup.cfg
- [metadata]
- name = Project-B
- #...
+ .. code-block:: ini
- [options]
- #...
- install_requires =
- Project-A[PDF]
+ [metadata]
+ name = Project-B
+ #...
+
+ [options]
+ #...
+ install_requires =
+ Project-A[PDF]
+
+.. tab:: setup.py
-.. code-block:: python
+ .. code-block:: python
- setup(
- name="Project-B",
- install_requires=["Project-A[PDF]"],
- ...
- )
+ setup(
+ name="Project-B",
+ install_requires=["Project-A[PDF]"],
+ ...
+ )
This will cause ReportLab to be installed along with project A, if project B is
installed -- even if project A was already installed. In this way, a project
support for namespace package. Normally, you would specify the package to be
included manually in the following manner:
-.. code-block:: ini
-
- [options]
- #...
- packages =
- mypkg1
- mypkg2
+.. tab:: setup.cfg
-.. code-block:: python
+ .. code-block:: ini
- setup(
+ [options]
#...
- packages = ['mypkg1', 'mypkg2']
- )
+ packages =
+ mypkg1
+ mypkg2
+
+.. tab:: setup.py
+
+ .. code-block:: python
+
+ setup(
+ #...
+ packages = ['mypkg1', 'mypkg2']
+ )
This can get tiresome reallly quickly. To speed things up, we introduce two
functions provided by setuptools:
-.. code-block:: ini
+.. tab:: setup.cfg
- [options]
- packages = find:
- #or
- packages = find_namespace:
+ .. code-block:: ini
-.. code-block:: python
+ [options]
+ packages = find:
+ #or
+ packages = find_namespace:
- from setuptools import find_packages
- #or
- from setuptools import find_namespace_packages
+.. tab:: setup.py
+
+ .. code-block:: python
+
+ from setuptools import find_packages
+ #or
+ from setuptools import find_namespace_packages
Using ``find:`` or ``find_packages``
To have your setup.cfg or setup.py to automatically include packages found
in ``src`` that starts with the name ``pkg`` and not ``additional``:
-.. code-block:: ini
+.. tab:: setup.cfg
- [options]
- packages = find:
- package_dir =
- =src
+ .. code-block:: ini
- [options.packages.find]
- where = src
- include = pkg*
- exclude = additional
+ [options]
+ packages = find:
+ package_dir =
+ =src
-.. code-block:: python
+ [options.packages.find]
+ where = src
+ include = pkg*
+ exclude = additional
- setup(
- #...
- packages = find_packages(
- where = 'src',
- include = ['pkg*',],
- exclude = ['additional',]
- ),
- package_dir = {"":"src"}
- #...
- )
+.. tab:: setup.py
+
+ .. code-block:: python
+
+ setup(
+ #...
+ packages = find_packages(
+ where = 'src',
+ include = ['pkg*',],
+ exclude = ['additional',]
+ ),
+ package_dir = {"":"src"}
+ #...
+ )
.. _Namespace Packages:
And the ``namespace_packages`` keyword in your ``setup.cfg`` or ``setup.py``:
-.. code-block:: ini
+.. tab:: setup.cfg
- [options]
- namespace_packages = timmins
+ .. code-block:: ini
-.. code-block:: python
+ [options]
+ namespace_packages = timmins
+
+.. tab:: setup.py
+
+ .. code-block:: python
- setup(
- # ...
- namespace_packages = ['timmins']
- )
+ setup(
+ # ...
+ namespace_packages = ['timmins']
+ )
And your directory should look like this
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"
-Then, you will need a ``setup.cfg`` to specify your package information,
-such as metadata, contents, dependencies, etc. Here we demonstrate the minimum
+Then, you will need a ``setup.cfg`` or ``setup.py`` to specify your package
+information, such as metadata, contents, dependencies, etc. Here we demonstrate
+the minimum
-.. code-block:: ini
+.. tab:: setup.cfg
- [metadata]
- name = mypackage
- version = 0.0.1
+ .. code-block:: ini
- [options]
- packages = mypackage
- install_requires =
- requests
- importlib; python_version == "2.6"
+ [metadata]
+ name = mypackage
+ version = 0.0.1
+
+ [options]
+ packages = mypackage
+ install_requires =
+ requests
+ importlib; python_version == "2.6"
+
+.. tab:: setup.py
+
+ .. code-block:: python
+
+ from setuptools import setup
+
+ setup(
+ name='mypackage"'
+ version='0.0.1',
+ packages=['mypackage'],
+ install_requires=[
+ 'requests',
+ 'importlib; python_version == "2.6"',
+ ],
+ )
This is what your project would look like::
~/mypackage/
pyproject.toml
- setup.cfg
+ setup.cfg # or setup.py
mypackage/__init__.py
Then, you need an builder, such as :std:doc:`PyPA build <pypa-build:index>`
license_files =
LICENSE
name = setuptools
-version = 54.1.0
+version = 54.1.1
author = Python Packaging Authority
author_email = distutils-sig@python.org
description = Easily download, build, install, upgrade, and uninstall Python packages
sphinx
jaraco.packaging >= 8.2
rst.linker >= 1.9
+ sphinx-inline-tabs
# local
pygments-github-lexers==0.0.5
val = parser.get(section, opt)
opt = self.dash_to_underscore_warning(opt, section)
+ opt = self.make_option_lowercase(opt, section)
opt_dict[opt] = (filename, val)
# Make the ConfigParser forget everything (so we retain
% (opt, underscore_opt))
return underscore_opt
+ def make_option_lowercase(self, opt, section):
+ if section != 'metadata' or opt.islower():
+ return opt
+
+ lowercase_opt = opt.lower()
+ warnings.warn(
+ "Usage of uppercase key '%s' in '%s' will be deprecated in future "
+ "versions. Please use lowercase '%s' instead"
+ % (opt, section, lowercase_opt)
+ )
+ return lowercase_opt
+
# FIXME: 'Distribution._set_command_options' is too complex (14)
def _set_command_options(self, command_obj, option_dict=None): # noqa: C901
"""
assert metadata.author_email == 'test@test.com'
assert metadata.maintainer_email == 'foo@foo.com'
+ def test_uppercase_warning(self, tmpdir):
+ # remove this test and the method uppercase_warning() in setuptools.dist
+ # when no longer needed
+ fake_env(
+ tmpdir,
+ '[metadata]\n'
+ 'Name = foo\n'
+ 'description = Some description\n'
+ )
+ msg = ("Usage of uppercase key 'Name' in 'metadata' will be deprecated in "
+ "future versions. "
+ "Please use lowercase 'name' instead")
+ with pytest.warns(UserWarning, match=msg):
+ with get_dist(tmpdir) as dist:
+ metadata = dist.metadata
+
+ assert metadata.name == 'foo'
+ assert metadata.description == 'Some description'
+
class TestOptions: