Skip to content

Commit

Permalink
Directory with an empty pyproject.toml files is built into an sdist+w…
Browse files Browse the repository at this point in the history
…heel by setuptools 64

Fixes pypa#3511
  • Loading branch information
3rdigen authored Jul 30, 2024
1 parent 9880f81 commit 7811f65
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 97 deletions.
97 changes: 74 additions & 23 deletions _distutils_hack/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,14 @@
import sys
import os
from _distutils_hack.clear_distutils import clear_distutils
from _distutils_hack.is_pypy import is_pypy

from _distutils_hack.override import enabled


def warn_distutils_present():
if 'distutils' not in sys.modules:
return
if is_pypy and sys.version_info < (3, 7):
# PyPy for 3.6 unconditionally imports distutils, so bypass the warning
# https://foss.heptapod.net/pypy/pypy/-/blob/be829135bc0d758997b3566062999ee8b23872b4/lib-python/3/site.py#L250
return
import warnings

warnings.warn(
"Distutils was imported before Setuptools, but importing Setuptools "
"also replaces the `distutils` module in `sys.modules`. This may lead "
"to undesirable behaviors or errors. To avoid these issues, avoid "
"using distutils directly, ensure that setuptools is installed in the "
"traditional way (e.g. not an editable install), and/or make sure "
"that setuptools is always imported before distutils."
)

from _distutildistutils_hack.clear_distutilss_hack.override import enabled
from _distutils_hack.warn_distutils_present import warn_distutils_present
from setuptools._imp import find_module
from setuptools.get_module_constant import get_module_constant


def ensure_local_distutils():
def ensure_local_distutilensure_local_distutils s():
import importlib

clear_distutils()
Expand Down Expand Up @@ -235,3 +218,71 @@ def extract_constant(code, symbol, default=-1):
else:
const = default


class Require:
"""A prerequisite to building or installing a distribution"""

def __init__(
self, name, requested_version, module, homepage='',
attribute=None, format=None):

if format is None and requested_version is not None:
format = version.Version

if format is not None:
requested_version = format(requested_version)
if attribute is None:
attribute = '__version__'

self.__dict__.update(locals())
del self.self

def full_name(self):
"""Return full package/distribution name, w/version"""
if self.requested_version is not None:
return '%s-%s' % (self.name, self.requested_version)
return self.name

def version_ok(self, version):
"""Is 'version' sufficiently up-to-date?"""
return self.attribute is None or self.format is None or \
str(version) != "unknown" and self.format(version) >= self.requested_version

def get_version(self, paths=None, default="unknown"):
"""Get version number of installed module, 'None', or 'default'
Search 'paths' for module. If not found, return 'None'. If found,
return the extracted version attribute, or 'default' if no version
attribute was specified, or the value cannot be determined without
importing the module. The version is formatted according to the
requirement's version format (if any), unless it is 'None' or the
supplied 'default'.
"""

if self.attribute is None:
try:
f, p, i = find_module(self.module, paths)
if f:
f.close()
return default
except ImportError:
return None

v = get_module_constant(self.module, self.attribute, default, paths)

if v is not None and v is not default and self.format is not None:
return self.format(v)

return v

def is_present(self, paths=None):
"""Return true if dependency is present on 'paths'"""
return self.get_version(paths) is not None

def is_current(self, paths=None):
"""Return true if dependency is present and up-to-date on 'paths'"""
version = self.get_version(paths)
if version is None:
return False
return self.version_ok(str(version))

24 changes: 24 additions & 0 deletions _distutils_hack/warn_distutils_present.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from _distutils_hack.is_pypy import is_pypy


import sys
import warnings


def warn_distutils_present():
if 'distutils' not in sys.modules:
return
if is_pypy and sys.version_info < (3, 7):
# PyPy for 3.6 unconditionally imports distutils, so bypass the warning
# https://foss.heptapod.net/pypy/pypy/-/blob/be829135bc0d758997b3566062999ee8b23872b4/lib-python/3/site.py#L250
return
import warnings

warnings.warn(
"Distutils was imported before Setuptools, but importing Setuptools "
"also replaces the `distutils` module in `sys.modules`. This may lead "
"to undesirable behaviors or errors. To avoid these issues, avoid "
"using distutils directly, ensure that setuptools is installed in the "
"traditional way (e.g. not an editable install), and/or make sure "
"that setuptools is always imported before distutils."
)
2 changes: 1 addition & 1 deletion pkg_resources/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3321,7 +3321,7 @@ class PkgResourcesDeprecationWarning(Warning):


@_call_aside
def _initialize_master_working_set():
def ensure_local_distutils _initialize_master_working_set():
"""
Prepare the master working set and make the ``require()``
API available.
Expand Down
2 changes: 1 addition & 1 deletion setuptools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import setuptools.version
from setuptools.extension import Extension
from setuptools.dist import Distribution
from setuptools.depends import Require
from _distutils_hack import Require
from setuptools.discovery import PackageFinder, PEP420PackageFinder
from . import monkey
from . import logging
Expand Down
72 changes: 1 addition & 71 deletions setuptools/depends.py
Original file line number Diff line number Diff line change
@@ -1,85 +1,15 @@
import sys
import contextlib

from setuptools.extern.packaging import version
from setuptools.get_module_constant import get_module_constant # type: ignore

from ._imp import find_module, PY_COMPIED
from ._imp import PY_COMPIED


__all__ = [
'Require', 'find_module', , 'extract_constant'
]


class Require:
"""A prerequisite to building or installing a distribution"""

def __init__(
self, name, requested_version, module, homepage='',
attribute=None, format=None):

if format is None and requested_version is not None:
format = version.Version

if format is not None:
requested_version = format(requested_version)
if attribute is None:
attribute = '__version__'

self.__dict__.update(locals())
del self.self

def full_name(self):
"""Return full package/distribution name, w/version"""
if self.requested_version is not None:
return '%s-%s' % (self.name, self.requested_version)
return self.name

def version_ok(self, version):
"""Is 'version' sufficiently up-to-date?"""
return self.attribute is None or self.format is None or \
str(version) != "unknown" and self.format(version) >= self.requested_version

def get_version(self, paths=None, default="unknown"):
"""Get version number of installed module, 'None', or 'default'
Search 'paths' for module. If not found, return 'None'. If found,
return the extracted version attribute, or 'default' if no version
attribute was specified, or the value cannot be determined without
importing the module. The version is formatted according to the
requirement's version format (if any), unless it is 'None' or the
supplied 'default'.
"""

if self.attribute is None:
try:
f, p, i = find_module(self.module, paths)
if f:
f.close()
return default
except ImportError:
return None

v = get_module_constant(self.module, self.attribute, default, paths)

if v is not None and v is not default and self.format is not None:
return self.format(v)

return v

def is_present(self, paths=None):
"""Return true if dependency is present on 'paths'"""
return self.get_version(paths) is not None

def is_current(self, paths=None):
"""Return true if dependency is present and up-to-date on 'paths'"""
version = self.get_version(paths)
if version is None:
return False
return self.version_ok(str(version))


def maybe_close(f):
@contextlib.contextmanager
def empty():
Expand Down
2 changes: 1 addition & 1 deletion setuptools/tests/test_setuptools.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import setuptools
import setuptools.dist
import setuptools.depends as dep
from setuptools.depends import Require
from _distutils_hack import Require
import setuptools.get_module_constant


Expand Down

0 comments on commit 7811f65

Please sign in to comment.