import sys
from typing import TYPE_CHECKING, List, Dict
from distutils.command.build import build as _build
from ..warnings import SetuptoolsDeprecationWarning
if sys.version_info >= (3, 8):
from typing import Protocol
elif TYPE_CHECKING:
from typing_extensions import Protocol
else:
from abc import ABC as Protocol
_ORIGINAL_SUBCOMMANDS = {"build_py", "build_clib", "build_ext", "build_scripts"}
class build(_build):
# copy to avoid sharing the object with parent class
sub_commands = _build.sub_commands[:]
def get_sub_commands(self):
subcommands = {cmd[0] for cmd in _build.sub_commands}
if subcommands - _ORIGINAL_SUBCOMMANDS:
SetuptoolsDeprecationWarning.emit(
"Direct usage of `distutils` commands",
"""
It seems that you are using `distutils.command.build` to add
new subcommands. Using `distutils` directly is considered deprecated,
please use `setuptools.command.build`.
""",
due_date=(2023, 12, 13), # Warning introduced in 13 Jun 2022.
see_url="https://peps.python.org/pep-0632/",
)
self.sub_commands = _build.sub_commands
return super().get_sub_commands()
class SubCommand(Protocol):
"""In order to support editable installations (see :pep:`660`) all
build subcommands **SHOULD** implement this protocol. They also **MUST** inherit
from ``setuptools.Command``.
When creating an :pep:`editable wheel <660>`, ``setuptools`` will try to evaluate
custom ``build`` subcommands using the following procedure:
1. ``setuptools`` will set the ``editable_mode`` attribute to ``True``
2. ``setuptools`` will execute the ``run()`` command.
.. important::
Subcommands **SHOULD** take advantage of ``editable_mode=True`` to adequate
its behaviour or perform optimisations.
For example, if a subcommand doesn't need to generate an extra file and
all it does is to copy a source file into the build directory,
``run()`` **SHOULD** simply "early return".
Similarly, if the subcommand creates files that would be placed alongside
Python files in the final distribution, during an editable install
the command **SHOULD** generate these files "in place" (i.e. write them to
the original source directory, instead of using the build directory).
Note that ``get_output_mapping()`` should reflect that and include mappings
for "in place" builds accordingly.
3. ``setuptools`` use any knowledge it can derive from the return values of
``get_outputs()`` and ``get_output_mapping()`` to create an editable wheel.
When relevant ``setuptools`` **MAY** attempt to use file links based on the value
of ``get_output_mapping()``. Alternatively, ``setuptools`` **MAY** attempt to use
:doc:`import hooks