Imported Upstream version 62.3.4 upstream/62.3.4
authorJinWang An <jinwang.an@samsung.com>
Mon, 27 Mar 2023 08:02:50 +0000 (17:02 +0900)
committerJinWang An <jinwang.an@samsung.com>
Mon, 27 Mar 2023 08:02:50 +0000 (17:02 +0900)
.bumpversion.cfg
CHANGES.rst
docs/conf.py
docs/references/keywords.rst
docs/userguide/datafiles.rst
docs/userguide/declarative_config.rst
docs/userguide/entry_point.rst
setup.cfg
setuptools/command/build_py.py

index 987e30e62afeda1b9a9a122add8409e712e472cc..fb327835b22de1baffed1298f45900b955c20aa3 100644 (file)
@@ -1,5 +1,5 @@
 [bumpversion]
-current_version = 62.3.3
+current_version = 62.3.4
 commit = True
 tag = True
 
index 4d9c973efb0a17f9bbcbe57669982c54750a912d..70c9897d880425e93c8c43e11b53a236b85cb470 100644 (file)
@@ -1,3 +1,18 @@
+v62.3.4
+-------
+
+
+Documentation changes
+^^^^^^^^^^^^^^^^^^^^^
+* #3349: Fixed two small issues preventing docs from building locally -- by :user:`codeandfire`
+* #3350: Added note explaining ``package_data`` glob pattern matching for dotfiles -- by :user:`comabrewer`
+* #3358: Clarify the role of the ``package_dir`` configuration.
+
+Misc
+^^^^
+* #3354: Improve clarity in warning about unlisted namespace packages.
+
+
 v62.3.3
 -------
 
index 1023539c62f01ee302bab9c1ad87397906fe6506..902869163b4d529f59f5ab72575a37c479bff4d8 100644 (file)
@@ -103,7 +103,7 @@ github_repo_slug = f'{github_repo_org}/{github_repo_name}'
 github_repo_url = f'{github_url}/{github_repo_slug}'
 github_sponsors_url = f'{github_url}/sponsors'
 extlinks = {
-    'user': (f'{github_sponsors_url}/%s', '@'),  # noqa: WPS323
+    'user': (f'{github_sponsors_url}/%s', '@%s'),  # noqa: WPS323
     'pypi': ('https://pypi.org/project/%s', '%s'),  # noqa: WPS323
     'wiki': ('https://wikipedia.org/wiki/%s', '%s'),  # noqa: WPS323
 }
index d36630000f2c2bcef0f2394dc09ed06213cb3530..a66d503ea6e289e706ead1f524792171cc1356cd 100644 (file)
@@ -194,7 +194,46 @@ extensions).
 .. _keyword/package_dir:
 
 ``package_dir``
-    A dictionary providing a mapping of package to directory names.
+    A dictionary that maps package names (as they will be
+    imported by the end-users) into directory paths (that actually exist in the
+    project's source tree). This configuration has two main purposes:
+
+    1. To effectively "rename" paths when building your package.
+       For example, ``package_dir={"mypkg": "dir1/dir2/code_for_mypkg"}``
+       will instruct setuptools to copy the ``dir1/dir2/code_for_mypkg/...`` files
+       as ``mypkg/...`` when building the final :term:`wheel distribution <Wheel>`.
+
+       .. attention::
+          While it is *possible* to specify arbitrary mappings, developers are
+          **STRONGLY ADVISED AGAINST** that. They should try as much as possible
+          to keep the directory names and hierarchy identical to the way they will
+          appear in the final wheel, only deviating when absolutely necessary.
+
+    2. To indicate that the relevant code is entirely contained inside
+       a specific directory (instead of directly placed under the project's root).
+       In this case, a special key is required (the empty string, ``""``),
+       for example: ``package_dir={"": "<name of the container directory>"}``.
+       All the directories inside the container directory will be copied
+       directly into the final :term:`wheel distribution <Wheel>`, but the
+       container directory itself will not.
+
+       This practice is very common in the community to help separate the
+       package implementation from auxiliary files (e.g. CI configuration files),
+       and is referred to as :ref:`src-layout`, because the container
+       directory is commonly named ``src``.
+
+    All paths in ``package_dir`` must be relative to the project root directory
+    and use a forward slash (``/``) as path separator regardless of the
+    operating system.
+
+    .. tip::
+       When using :doc:`package discovery </userguide/package_discovery>`
+       together with :doc:`setup.cfg </userguide/declarative_config>` or
+       :doc:`pyproject.toml </userguide/pyproject_config>`, it is very likely
+       that you don't need to specify a value for ``package_dir``.  Please have
+       a look at the definitions of :ref:`src-layout` and :ref:`flat-layout` to
+       learn common practices on how to design a project's directory structure
+       and minimise the amount of configuration that is needed.
 
 .. _keyword/requires:
 
index 8622b6c447b4c1e7ba4a73302eccf2c42884780b..3a2ffbdf0520071fac81243542b1b41c0bf8654e 100644 (file)
@@ -157,6 +157,11 @@ require to be added by a revision control system plugin.
         the path separator, even if you are on Windows.  Setuptools automatically
         converts slashes to appropriate platform-specific separators at build time.
 
+.. note::
+        Glob patterns do not automatically match dotfiles (directory or file names
+        starting with a dot (``.``)). To include such files, you must explicitly start
+        the pattern with a dot, e.g. ``.*`` to match ``.gitignore``.
+
 If you have multiple top-level packages and a common pattern of data files for all these
 packages, for example::
 
@@ -243,8 +248,8 @@ Sometimes, the ``include_package_data`` or ``package_data`` options alone
 aren't sufficient to precisely define what files you want included. For example,
 consider a scenario where you have ``include_package_data=True``, and you are using
 a revision control system with an appropriate plugin.
-Sometimes developers add directory-specific marker files (such as `.gitignore`,
-`.gitkeep`, `.gitattributes`, or `.hgignore`), these files are probably being
+Sometimes developers add directory-specific marker files (such as ``.gitignore``,
+``.gitkeep``, ``.gitattributes``, or ``.hgignore``), these files are probably being
 tracked by the revision control system, and therefore by default they will be
 included when the package is installed.
 
index 2a65e6e36779743219fda8c976e097e021218c97..aa8bc7ea16b3fb9349dc2a815e39210acae6cc98 100644 (file)
@@ -62,8 +62,8 @@ boilerplate code in some cases.
 
 Metadata and options are set in the config sections of the same name.
 
-* Keys are the same as the keyword arguments one provides to the ``setup()``
-  function.
+* Keys are the same as the :doc:`keyword arguments </references/keywords>` one
+  provides to the ``setup()`` function.
 
 * Complex values can be written comma-separated or placed one per line
   in *dangling* config values. The following are equivalent:
@@ -90,7 +90,7 @@ Metadata and options are set in the config sections of the same name.
 Using a ``src/`` layout
 =======================
 
-One commonly used package configuration has all the module source code in a
+One commonly used configuration has all the Python source code in a
 subdirectory (often called the ``src/`` layout), like this::
 
     ├── src
@@ -101,7 +101,7 @@ subdirectory (often called the ``src/`` layout), like this::
     └── setup.cfg
 
 You can set up your ``setup.cfg`` to automatically find all your packages in
-the subdirectory like this:
+the subdirectory, using :ref:`package_dir <keyword/package_dir>`, like this:
 
 .. code-block:: ini
 
@@ -116,6 +116,22 @@ the subdirectory like this:
     [options.packages.find]
     where=src
 
+In this example, the value for the :ref:`package_dir <keyword/package_dir>`
+configuration (i.e. ``=src``) is parsed as ``{"": "src"}``.
+The ``""`` key has a special meaning in this context, and indicates that all the
+packages are contained inside the given directory.
+Also note that the value for ``[options.packages.find] where`` matches the
+value associated with ``""`` in the ``package_dir`` dictionary.
+
+..
+   TODO: Add the following tip once the auto-discovery is no longer experimental:
+
+   Starting in version 61, ``setuptools`` can automatically infer the
+   configurations for both ``packages`` and ``package_dir`` for projects using
+   a ``src/`` layout (as long as no value is specified for ``py_modules``).
+   Please see :doc:`package discovery </userguide/package_discovery>` for more
+   details.
+
 Specifying values
 =================
 
@@ -127,7 +143,10 @@ Type names used below:
 * ``list-comma`` - dangling list or string of comma-separated values
 * ``list-semi`` - dangling list or string of semicolon-separated values
 * ``bool`` - ``True`` is 1, yes, true
-* ``dict`` - list-comma where keys are separated from values by ``=``
+* ``dict`` - list-comma where each entry corresponds to a key/value pair,
+  with keys separated from values by ``=``.
+  If an entry starts with ``=``, the key is assumed to be an empty string
+  (e.g. ``=src`` is parsed as ``{"": "src"}``).
 * ``section`` - values are read from a dedicated (sub)section
 
 
@@ -143,15 +162,15 @@ Special directives:
 
 * ``file:`` - Value is read from a list of files and then concatenated
 
-  .. note::
-      The ``file:`` directive is sandboxed and won't reach anything outside
-      the directory containing ``setup.py``.
+  .. important::
+      The ``file:`` directive is sandboxed and won't reach anything outside the
+      project directory (i.e. the directory containing ``setup.cfg``/``pyproject.toml``).
 
 
 Metadata
 --------
 
-.. note::
+.. attention::
     The aliases given below are supported for compatibility reasons,
     but their use is not advised.
 
index b97419c474477ffcad74c63dc3345143d3f758df..9dca38956de2b45ff64d64bfb5cf2fef1dce1ea6 100644 (file)
@@ -14,15 +14,14 @@ Console Scripts
 ===============
 
 First consider an example without entry points. Imagine a package
-defined thus:
+defined thus::
 
-.. code-block:: bash
-
-    timmins/
-        timmins/__init__.py
-        timmins/__main__.py
-        setup.cfg # or setup.py
-        #other necessary files
+    project_root_directory
+    ├── setup.py        # and/or setup.cfg, pyproject.toml
+    └── src
+        └── timmins
+            ├── __init__.py
+            └── ...
 
 with ``__init__.py`` as:
 
@@ -31,7 +30,10 @@ with ``__init__.py`` as:
     def hello_world():
         print("Hello world")
 
-and ``__main__.py`` providing a hook:
+Now, suppose that we would like to provide some way of executing the
+function ``hello_world()`` from the command-line. One way to do this
+is to create a file ``src/timmins/__main__.py`` providing a hook as
+follows:
 
 .. code-block:: python
 
@@ -40,19 +42,20 @@ and ``__main__.py`` providing a hook:
     if __name__ == '__main__':
         hello_world()
 
-After installing the package, the function may be invoked through the
-`runpy <https://docs.python.org/3/library/runpy.html>`_ module:
+Then, after installing the package ``timmins``, we may invoke the ``hello_world()``
+function as follows, through the `runpy <https://docs.python.org/3/library/runpy.html>`_
+module:
 
 .. code-block:: bash
 
-    python -m timmins
+    $ python -m timmins
+    Hello world
 
-Adding a console script entry point allows the package to define a
-user-friendly name for installers of the package to execute. Installers
-like pip will create wrapper scripts to execute a function. In the
-above example, to create a command ``hello-world`` that invokes
-``timmins.hello_world``, add a console script entry point to
-``setup.cfg``:
+Instead of this approach using ``__main__.py``, you can also create a
+user-friendly CLI executable that can be called directly without ``python -m``.
+In the above example, to create a command ``hello-world`` that invokes
+``timmins.hello_world``, add a console script entry point to your
+configuration:
 
 .. tab:: setup.cfg
 
@@ -69,20 +72,35 @@ above example, to create a command ``hello-world`` that invokes
         from setuptools import setup
 
         setup(
-            name='timmins',
-            version='0.0.1',
-            packages=['timmins'],
-                       # ...
+            # ...,
             entry_points={
-                               'console_scripts': [
-                                       'hello-world=timmins:hello_world',
-                               ]
-                       }
+                'console_scripts': [
+                    'hello-world=timmins:hello_world',
+                ]
+            }
         )
 
+.. tab:: pyproject.toml (**EXPERIMENTAL**) [#experimental]_
+
+   .. code-block:: toml
+
+        [project.scripts]
+        hello-world = "timmins:hello_world"
+
 
 After installing the package, a user may invoke that function by simply calling
-``hello-world`` on the command line.
+``hello-world`` on the command line:
+
+.. code-block:: bash
+
+   $ hello-world
+   Hello world
+
+Note that any function configured as a console script, i.e. ``hello_world()`` in
+this example, should not accept any arguments. If your function requires any input
+from the user, you can use regular command-line argument parsing utilities like
+`argparse <https://docs.python.org/3/library/argparse.html>`_ within the body of
+the function to parse user input given via :obj:`sys.argv`.
 
 The syntax for entry points is specified as follows:
 
@@ -94,16 +112,99 @@ where ``name`` is the name for the script you want to create, the left hand
 side of ``:`` is the module that contains your function and the right hand
 side is the object you want to invoke (e.g. a function).
 
+GUI Scripts
+===========
+
 In addition to ``console_scripts``, Setuptools supports ``gui_scripts``, which
 will launch a GUI application without running in a terminal window.
 
+For example, if we have a project with the same directory structure as before,
+with an ``__init__.py`` file containing the following:
+
+.. code-block:: python
+
+    import PySimpleGUI as sg
+
+    def hello_world():
+        sg.Window(title="Hello world", layout=[[]], margins=(100, 50)).read()
+
+Then, we can add a GUI script entry point:
+
+.. tab:: setup.cfg
+
+    .. code-block:: ini
+
+        [options.entry_points]
+        gui_scripts =
+            hello-world = timmins:hello_world
+
+.. tab:: setup.py
+
+    .. code-block:: python
+       
+        from setuptools import setup
+
+        setup(
+            # ...,
+            entry_points={
+                'gui_scripts': [
+                    'hello-world=timmins:hello_world',
+                ]
+            }
+        )
+
+.. tab:: pyproject.toml (**EXPERIMENTAL**) [#experimental]_
+
+   .. code-block:: toml
+
+        [project.gui-scripts]
+        hello-world = "timmins:hello_world"
+
+.. note::
+   To be able to import ``PySimpleGUI``, you need to add ``pysimplegui`` to your package dependencies.
+   See :doc:`/userguide/dependency_management` for more information.
+
+Now, running:
+
+.. code-block:: bash
+
+   $ hello-world
+
+will open a small application window with the title 'Hello world'.
+
+Note that just as with console scripts, any function configured as a GUI script
+should not accept any arguments, and any user input can be parsed within the
+body of the function.
+
+.. note::
+
+    The difference between ``console_scripts`` and ``gui_scripts`` only affects
+    Windows systems. [#use_for_scripts]_ ``console_scripts`` are wrapped in a console
+    executable, so they are attached to a console and can use ``sys.stdin``,
+    ``sys.stdout`` and ``sys.stderr`` for input and output. ``gui_scripts`` are
+    wrapped in a GUI executable, so they can be started without a console, but
+    cannot use standard streams unless application code redirects them. Other
+    platforms do not have the same distinction.
+
+.. note::
+
+    Console and GUI scripts work because behind the scenes, installers like :pypi:`pip`
+    create wrapper scripts around the function(s) being invoked. For example,
+    the ``hello-world`` entry point in the above two examples would create a
+    command ``hello-world`` launching a script like this: [#use_for_scripts]_
+
+    .. code-block:: python
+
+        import sys
+        from timmins import hello_world
+        sys.exit(hello_world())
 
 .. _dynamic discovery of services and plugins:
 
 Advertising Behavior
 ====================
 
-Console scripts are one use of the more general concept of entry points. Entry
+Console/GUI scripts are one use of the more general concept of entry points. Entry
 points more generally allow a packager to advertise behavior for discovery by
 other libraries and applications. This feature enables "plug-in"-like
 functionality, where one library solicits entry points and any number of other
@@ -114,48 +215,277 @@ A good example of this plug-in behavior can be seen in
 where pytest is a test framework that allows other libraries to extend
 or modify its functionality through the ``pytest11`` entry point.
 
-The console scripts work similarly, where libraries advertise their commands
+The console/GUI scripts work similarly, where libraries advertise their commands
 and tools like ``pip`` create wrapper scripts that invoke those commands.
 
-For a project wishing to solicit entry points, Setuptools recommends the
-`importlib.metadata <https://docs.python.org/3/library/importlib.metadata.html>`_
-module (part of stdlib since Python 3.8) or its backport,
-:pypi:`importlib_metadata`.
+Entry Points for Plugins
+========================
 
-For example, to find the console script entry points from the example above:
+Let us consider a simple example to understand how we can implement entry points
+corresponding to plugins. Say we have a package ``timmins`` with the following
+directory structure::
 
-.. code-block:: pycon
+    timmins
+    ├── setup.py        # and/or setup.cfg, pyproject.toml
+    └── src
+        └── timmins
+            └── __init__.py
 
-    >>> from importlib import metadata
-    >>> eps = metadata.entry_points()['console_scripts']
+and in ``src/timmins/__init__.py`` we have the following code:
 
-``eps`` is now a list of ``EntryPoint`` objects, one of which corresponds
-to the ``hello-world = timmins:hello_world`` defined above. Each ``EntryPoint``
-contains the ``name``, ``group``, and ``value``. It also supplies a ``.load()``
-method to import and load that entry point (module or object).
+.. code-block:: python
 
-.. code-block:: ini
+   def hello_world():
+       print('Hello world')
 
-    [options.entry_points]
-    my.plugins =
-        hello-world = timmins:hello_world
+Basically, we have defined a ``hello_world()`` function which will print the text
+'Hello world'. Now, let us say we want to print the text 'Hello world' in different
+ways. The current function just prints the text as it is - let us say we want another
+style in which the text is enclosed within exclamation marks::
+
+    !!! Hello world !!!
+
+Let us see how this can be done using plugins. First, let us separate the style of
+printing the text from the text itself. In other words, we can change the code in
+``src/timmins/__init__.py`` to something like this:
+
+.. code-block:: python
+
+   def display(text):
+       print(text)
+
+   def hello_world():
+       display('Hello world')
+
+Here, the ``display()`` function controls the style of printing the text, and the
+``hello_world()`` function calls the ``display()`` function to print the text 'Hello
+world`.
+
+Right now the ``display()`` function just prints the text as it is. In order to be able
+to customize it, we can do the following. Let us introduce a new *group* of entry points
+named ``timmins.display``, and expect plugin packages implementing this entry point
+to supply a ``display()``-like function. Next, to be able to automatically discover plugin
+packages that implement this entry point, we can use the
+:mod:`importlib.metadata` module,
+as follows:
+
+.. code-block:: python
+
+   from importlib.metadata import entry_points
+   display_eps = entry_points(group='timmins.display')
+
+.. note::
+   Each ``importlib.metadata.EntryPoint`` object is an object containing a ``name``, a
+   ``group``, and a ``value``. For example, after setting up the plugin package as
+   described below, ``display_eps`` in the above code will look like this: [#package_metadata]_
 
-Then, a different project wishing to load 'my.plugins' plugins could run
-the following routine to load (and invoke) such plugins:
+    .. code-block:: python
+
+        (
+            EntryPoint(name='excl', value='timmins_plugin_fancy:excl_display', group='timmins.display'),
+            ...,
+        )
+
+``display_eps`` will now be a list of ``EntryPoint`` objects, each referring to ``display()``-like
+functions defined by one or more installed plugin packages. Then, to import a specific
+``display()``-like function - let us choose the one corresponding to the first discovered
+entry point - we can use the ``load()`` method as follows:
+
+.. code-block:: python
+
+   display = display_eps[0].load()
+
+Finally, a sensible behaviour would be that if we cannot find any plugin packages customizing
+the ``display()`` function, we should fall back to our default implementation which prints
+the text as it is. With this behaviour included, the code in ``src/timmins/__init__.py``
+finally becomes:
+
+.. code-block:: python
+
+   from importlib.metadata import entry_points
+   display_eps = entry_points(group='timmins.display')
+   try:
+       display = display_eps[0].load()
+   except IndexError:
+       def display(text):
+           print(text)
+
+   def hello_world():
+       display('Hello world')
+
+That finishes the setup on ``timmins``'s side. Next, we need to implement a plugin
+which implements the entry point ``timmins.display``. Let us name this plugin
+``timmins-plugin-fancy``, and set it up with the following directory structure::
+
+    timmins-plugin-fancy
+    ├── setup.py        # and/or setup.cfg, pyproject.toml
+    └── src
+        └── timmins_plugin_fancy
+            └── __init__.py
+
+And then, inside ``src/timmins_plugin_fancy/__init__.py``, we can put a function
+named ``excl_display()`` that prints the given text surrounded by exclamation marks:
+
+.. code-block:: python
+
+   def excl_display(text):
+       print('!!!', text, '!!!')
+
+This is the ``display()``-like function that we are looking to supply to the
+``timmins`` package. We can do that by adding the following in the configuration
+of ``timmins-plugin-fancy``:
+
+.. tab:: setup.cfg
+
+   .. code-block:: ini
+
+        [options.entry_points]
+        timmins.display =
+                excl = timmins_plugin_fancy:excl_display
+
+.. tab:: setup.py
+
+   .. code-block:: python
+
+        from setuptools import setup
+
+        setup(
+            # ...,
+            entry_points = {
+                'timmins.display' = [
+                    'excl=timmins_plugin_fancy:excl_display'
+                ]
+            }
+        )
+
+.. tab:: pyproject.toml (**EXPERIMENTAL**) [#experimental]_
+
+   .. code-block:: toml
+
+        [project.entry-points."timmins.display"]
+        excl = "timmins_plugin_fancy:excl_display"
+
+Basically, this configuration states that we are a supplying an entry point
+under the group ``timmins.display``. The entry point is named ``excl`` and it
+refers to the function ``excl_display`` defined by the package ``timmins_plugin_fancy``.
+
+Now, if we install both ``timmins`` and ``timmins_plugin_fancy``, we should get
+the following:
 
 .. code-block:: pycon
 
-    >>> from importlib import metadata
-    >>> eps = metadata.entry_points()['my.plugins']
-    >>> for ep in eps:
-    ...     plugin = ep.load()
-    ...     plugin()
-    ...
+   >>> from timmins import hello_world
+   >>> hello_world()
+   !!! Hello world !!!
+
+whereas if we only install ``timmins`` and not ``timmins_plugin_fancy``, we should
+get the following:
+
+.. code-block:: pycon
+
+   >>> from timmins import hello_world
+   >>> hello_world()
+   Hello world
+
+Therefore, our plugin works.
+
+Our plugin could have also defined multiple entry points under the group ``timmins.display``.
+For example, in ``src/timmins_plugin_fancy/__init__.py`` we could have two ``display()``-like
+functions, as follows:
+
+.. code-block:: python
+
+   def excl_display(text):
+       print('!!!', text, '!!!')
 
-The project soliciting the entry points needs not to have any dependency
-or prior knowledge about the libraries implementing the entry points, and
+   def lined_display(text):
+       print(''.join(['-' for _ in text]))
+       print(text)
+       print(''.join(['-' for _ in text]))
+
+The configuration of ``timmins-plugin-fancy`` would then change to:
+
+.. tab:: setup.cfg
+
+   .. code-block:: ini
+
+        [options.entry_points]
+        timmins.display =
+                excl = timmins_plugin_fancy:excl_display
+                lined = timmins_plugin_fancy:lined_display
+
+.. tab:: setup.py
+
+   .. code-block:: python
+
+        from setuptools import setup
+
+        setup(
+            # ...,
+            entry_points = {
+                'timmins.display' = [
+                    'excl=timmins_plugin_fancy:excl_display',
+                    'lined=timmins_plugin_fancy:lined_display',
+                ]
+            }
+        )
+
+.. tab:: pyproject.toml (**EXPERIMENTAL**) [#experimental]_
+
+   .. code-block:: toml
+
+        [project.entry-points."timmins.display"]
+        excl = "timmins_plugin_fancy:excl_display"
+        lined = "timmins_plugin_fancy:lined_display"
+
+On the ``timmins`` side, we can also use a different strategy of loading entry
+points. For example, we can search for a specific display style:
+
+.. code-block:: python
+
+   display_eps = entry_points(group='timmins.display')
+   try:
+       display = display_eps['lined'].load()
+   except KeyError:
+       # if the 'lined' display is not available, use something else
+       ...
+
+Or we can also load all plugins under the given group. Though this might not
+be of much use in our current example, there are several scenarios in which this
+is useful:
+
+.. code-block:: python
+
+   display_eps = entry_points(group='timmins.display')
+   for ep in display_eps:
+       display = ep.load()
+       # do something with display
+       ...
+
+importlib.metadata
+------------------
+
+The recommended approach for loading and importing entry points is the
+:mod:`importlib.metadata` module,
+which is a part of the standard library since Python 3.8. For older versions of
+Python, its backport :pypi:`importlib_metadata` should be used. While using the
+backport, the only change that has to be made is to replace ``importlib.metadata``
+with ``importlib_metadata``, i.e.
+
+.. code-block:: python
+
+   from importlib_metadata import entry_points
+   ...
+
+Summary
+-------
+
+In summary, entry points allow a package to open its functionalities for
+customization via plugins.
+The package soliciting the entry points need not have any dependency
+or prior knowledge about the plugins implementing the entry points, and
 downstream users are able to compose functionality by pulling together
-libraries implementing the entry points.
+plugins implementing the entry points.
 
 
 Dependency Management
@@ -179,3 +509,16 @@ In this case, the ``hello-world`` script is only viable if the ``pretty-printer`
 extra is indicated, and so a plugin host might exclude that entry point
 (i.e. not install a console script) if the relevant extra dependencies are not
 installed.
+
+----
+
+.. [#experimental]
+   Support for specifying package metadata and build configuration options via
+   ``pyproject.toml`` is experimental and might change
+   in the future. See :doc:`/userguide/pyproject_config`.
+
+.. [#use_for_scripts]
+   Reference: https://packaging.python.org/en/latest/specifications/entry-points/#use-for-scripts
+
+.. [#package_metadata]
+   Reference: https://packaging.python.org/en/latest/guides/creating-and-discovering-plugins/#using-package-metadata
index c2551357e653fcfdbc2b34327f020487b5139e8d..e1037d612cd64fe4855b06f710e87064ac11eb94 100644 (file)
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,6 +1,6 @@
 [metadata]
 name = setuptools
-version = 62.3.3
+version = 62.3.4
 author = Python Packaging Authority
 author_email = distutils-sig@python.org
 description = Easily download, build, install, upgrade, and uninstall Python packages
index 86847f07821c472609e6000630a237d97ab361ab..2fced3d6d57b74a9976628a2d850a00b9200d777 100644 (file)
@@ -263,9 +263,10 @@ class _IncludePackageDataAbuse:
     ############################
     Python recognizes {importable!r} as an importable package,
     but it is not listed in the `packages` configuration of setuptools.
-    Currently {importable!r} is only added to the distribution because it may
-    contain data files, but this behavior is likely to change in future
-    versions of setuptools (and therefore is considered deprecated).
+
+    {importable!r} has been automatically added to the distribution only
+    because it may contain data files, but this behavior is likely to change
+    in future versions of setuptools (and therefore is considered deprecated).
 
     Please make sure that {importable!r} is included as a package by using
     the `packages` configuration field or the proper discovery methods