-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Closed
Labels
Description
setuptools version
74.0.0
Python version
3.9.18
OS
Ubuntu 22.04.4 x86-64
Additional environment information
The package to install has binary libraries that are already compiled.
pip==24.2, wheel==0.44.0, CPython 3.9.18 compiled with shared libraries option
It worked fine with setuptools<74.
The command is running in a Docker image.
Description
While building a legacy Python package using the command python setup.py install, the process crashed with the following error:
TypeError: object of type 'PosixPath' has no len()Expected behavior
The package build and install should be successfully completed.
How to Reproduce
This is the setup.py of the packages (with the package name changed). Please note that it is generated by SWIG from a C++ library.
# Builds the extensions with separate SWIG run-time support
# (see http://www.swig.org/Doc1.3/Modules.html) so as to
# share datatypes among different extensions.
import platform, os, sys
from pathlib import Path, PurePath
from setuptools import setup, Extension
from setuptools.command.build_ext import build_ext
if '--help' in str(sys.argv):
print("""
WARNING! It is no longer supported, neither by The Software nor by Python itself, to run setup.py directly.
Please use `python -m build` and `python -m pip .` for building and installing the Python wrapper instead.
Not specifying any of the options below is not guaranteed to work!
The Software specific options (always as first argument):
return_software_version
Example:
python setup.py return_software_version
will print something like:
2.49.0
""")
sys.exit()
if "THE_SOFTWARE_SOURCE_DIR" in os.environ:
the_software_dir = Path(os.environ['THE_SOFTWARE_SOURCE_DIR'])
elif "THE_SOFTWARE_DIR" in os.environ:
the_software_dir = Path(os.environ['THE_SOFTWARE_DIR'])
else:
print("Either 'THE_SOFTWARE_DIR' or 'THE_SOFTWARE_SOURCE_DIR' must be set!")
sys.exit(-1)
systemPlatform = platform.system()
if systemPlatform != "Linux" and systemPlatform != "Windows":
print("Could not determine system platform")
sys.exit(-1)
if "BUILDDIR_DN" in os.environ:
builddir_dn = Path(os.environ['BUILDDIR_DN'])
else:
builddir_dn = the_software_dir / r"LanguageBindings/Python/Output"
if systemPlatform == "Linux":
os.system("export BUILDDIR_DN={}".format(builddir_dn))
elif systemPlatform == "Windows":
os.system("set BUILDDIR_DN={}".format(builddir_dn))
version_file = the_software_dir / r"DriverBase/Include/softwareVersionInfo.h"
class SoftwareVersion(object):
def __init__(self):
class BuildNr(str):
def returnNr(self, key): # key is a str like 'THE_SOFTWARE_MAJOR_VERSION'
offset = self.find(key)
if offset == -1:
return '?'
offset += len(key)
while not self[offset].isdigit():
offset += 1
nr = self[offset]
while True:
offset += 1
if not self[offset].isdigit():
return nr
nr += self[offset]
version_all_h = open(version_file)
version = BuildNr(version_all_h.read())
version_all_h.close()
self.v_major = version.returnNr('#define THE_SOFTWARE_MAJOR_VERSION ')
self.v_minor = version.returnNr('#define THE_SOFTWARE_MINOR_VERSION ')
self.v_point = version.returnNr('#define THE_SOFTWARE_RELEASE_VERSION ')
self.v_build = version.returnNr('#define THE_SOFTWARE_BUILD_VERSION ')
def full(self):
return self.v_major + '.' + self.v_minor + '.' + self.v_point + '.' + self.v_build
software_version = SoftwareVersion()
if len(sys.argv) > 1:
if sys.argv[1] == 'return_software_version':
print('%s.%s.%s' % (software_version.v_major,
software_version.v_minor,
software_version.v_point))
sys.exit()
if systemPlatform == "Linux":
if( platform.architecture()[0] == "32bit" ):
bits = 32
elif( platform.architecture()[0] == "64bit" ):
bits = 64
else:
print("Error! Could not determine the systems CPU architecture!")
sys.exit(-1)
machine = platform.machine()
elif systemPlatform == "Windows":
bits = 64 if os.environ["PROCESSOR_ARCHITECTURE"] == "AMD64" else 32
macros = []
defines = os.getenv('DEFINES')
if defines is not None:
for dfn in defines.split():
macros += [(dfn[2:],'1')]
class dirlist(list):
"""You can define multiple directories in one environment variable"""
def addDir(self, d):
if type(d) is list:
for a in d:
self.addDir(Path(a)) # recurse
else:
d = Path(d)
if os.pathsep in str(d): # turn 'bar;foo' into ['bar', 'foo']
self.addDir(str(d).split(os.pathsep)) # recurse
else:
d = Path(str(d).replace('\ ', ' '))
if d.is_dir():
self.append(d)
def getList(self):
return list(self)
inc_dirs = dirlist()
lib_dirs = dirlist()
# inc_dirs : additional include directories
# lib_dirs : additional library directories
# macros : defined while building the extension
link_args = []
compile_args = []
# for debugging the Python extension library with Visual Studio on Windows set the variable in the next line to 'True'!
generateDebugInfo = False
installation_path = os.getenv('BUILD_FROM_INSTALLATION') # None if not set
if installation_path == '0': # '0' is explicit for 'not from installation'
installation_path = None # (like not specifying BUILD_FROM_INSTALLATION at all)
python_ver = '.'.join(str(x) for x in sys.version_info[:2])
if systemPlatform == "Linux":
if "THE_SOFTWARE_SOURCE_DIR" in os.environ:
if ("THE_SOFTWARE_BUILD_DIR" in os.environ):
lib_dirs.addDir(Path(os.environ["THE_SOFTWARE_BUILD_DIR"]) / Path('lib'))
else:
print()
print("ERROR: THE_SOFTWARE_SOURCE_DIR will be used but THE_SOFTWARE_BUILD_DIR is not set! The build directory thus cannot be found!")
sys.exit(-1)
else:
if ((machine == "armv7l") or (machine == "armv7")):
target_lib_sub_dir = Path('lib/armhf')
elif (machine == "i686" or machine == "x86_64") :
target_lib_sub_dir = Path('lib/x86_64')
elif ( machine == "aarch64") :
target_lib_sub_dir = Path('lib/arm64')
else:
print()
print("ERROR: Platform unsupported!")
sys.exit(-1)
lib_dirs.addDir(the_software_dir / target_lib_sub_dir)
compile_args = ['-Wno-unknown-pragmas', '-Wno-misleading-indentation', '-DCOMPILE_PYTHON']
if ((machine == "armv7l") or (machine == "armv7")):
compile_args += ['-O0']
link_args = ['-O0']
elif systemPlatform == "Windows":
compile_args = ['/GR','/bigobj', '/EHsc', '/DCOMPILE_PYTHON']
if generateDebugInfo:
compile_args += ['/Zi']
link_args += ['/DEBUG']
if "THE_SOFTWARE_SOURCE_DIR" in os.environ:
if bits == 32:
if ("THE_SOFTWARE_BUILD_X86_DIR" in os.environ) and ("THE_SOFTWARE_BUILD_CONFIGURATION" in os.environ):
build_lib_dir = Path(os.environ["THE_SOFTWARE_BUILD_X86_DIR"]) / r"lib\win\win32" / os.environ["THE_SOFTWARE_BUILD_CONFIGURATION"]
else:
print()
print("ERROR: THE_SOFTWARE_SOURCE_DIR will be used but THE_SOFTWARE_BUILD_X86_DIR is not set! The build directory thus cannot be found!")
sys.exit(-1)
else:
if ("THE_SOFTWARE_BUILD_X64_DIR" in os.environ) and ("THE_SOFTWARE_BUILD_CONFIGURATION" in os.environ):
build_lib_dir = Path(os.environ["THE_SOFTWARE_BUILD_X64_DIR"]) / r"lib\win\x64" / os.environ["THE_SOFTWARE_BUILD_CONFIGURATION"]
else:
print()
print("ERROR: THE_SOFTWARE_SOURCE_DIR will be used but THE_SOFTWARE_BUILD_X64_DIR is not set! The build directory thus cannot be found!")
sys.exit(-1)
lib_dirs.addDir(build_lib_dir)
link_args.append('/PDB:{}'.format(build_lib_dir / 'lib_the_software.pdb'))
else:
if bits == 32:
target_lib_sub_dir = Path('lib')
else:
target_lib_sub_dir = Path(r'lib\win\x64')
lib_dirs.addDir(the_software_dir / target_lib_sub_dir)
inc_dirs.addDir(the_software_dir)
inc_dirs.addDir(the_software_dir / 'theSofware_CPP')
if systemPlatform == "Windows":
inc_dirs.addDir(the_software_dir / 'softwareComponent' / 'Include')
build_options = {'build_base' : builddir_dn}
bdist_options = {'bdist_base' : builddir_dn, 'dist_dir' : builddir_dn}
# Create an 'Extension' object that describes how to build the Python extension.
def createExtension():
libs = ['softwareTool']
incl_dirs = inc_dirs.getList()
libr_dirs = lib_dirs.getList()
global installation_path
if installation_path is not None:
installation_path = Path(installation_path)
incl_dirs.insert(0, installation_path)
incl_dirs.insert(0, installation_path / 'softwareComponent' / 'Include')
incl_dirs.insert(0, installation_path / 'theSofware_CPP')
libr_dirs.insert(0, installation_path / 'lib')
else:
incl_dirs.insert(0, the_software_dir)
sources_fpns = [Path(builddir_dn) / 'software_wrap.cpp']
return Extension('lib_the_software',
sources = list(map(str, sources_fpns)),
include_dirs = list(map(str, incl_dirs)),
library_dirs = list(map(str, libr_dirs)),
define_macros = macros,
libraries = libs,
extra_compile_args = compile_args,
extra_link_args = link_args)
class build_ext_posix(build_ext):
# on Linux, once the lib has been built, dump a map, then strip the lib
def build_extensions(self):
self.check_extensions_list(self.extensions)
for ext in self.extensions:
self.build_extension(ext)
libName = str(Path(self.build_lib) / 'theSofware' / ext.name)
def getPlatform():
platformList = []
if systemPlatform == "Linux":
platformList.insert(0, os.system('ldconfig -p | grep softwareTool | cut -d \> -f 2 | grep -o "/lib/.*/" | cut -d/ -f 3'))
elif systemPlatform == "Windows":
platformList.insert(0, os.environ["PROCESSOR_ARCHITECTURE"])
return platformList
setup(
name = "TheSoftware", # remove this once we require setuptools 61.0.0 or above
version = software_version.full(),
platforms = getPlatform(),
description = 'The Software Python {} interface'.format(python_ver),
ext_package = 'theSofware', # all modules are in 'theSofware'
ext_modules = [createExtension()],
package_dir = {'theSofware' : 'Output'},
packages = ['theSofware', 'theSofware.Common'],
cmdclass = {'build_ext' : build_ext_posix if os.name == 'posix' else build_ext},
options = {'build' : build_options, 'bdist' : bdist_options}
)Output
$ python setup.py install
x86_64
x86_64
x86_64
running install
/home/user/.pyenv/versions/3.9.18/lib/python3.9/site-packages/setuptools/_distutils/cmd.py:66: SetuptoolsDeprecationWarning: setup.py install is deprecated.
!!
********************************************************************************
Please avoid running ``setup.py`` directly.
Instead, use pypa/build, pypa/installer or other
standards-based tools.
See https://blog.ganssle.io/articles/2021/10/setup-py-deprecated.html for details.
********************************************************************************
!!
self.initialize_options()
/home/user/.pyenv/versions/3.9.18/lib/python3.9/site-packages/setuptools/_distutils/cmd.py:66: EasyInstallDeprecationWarning: easy_install command is deprecated.
!!
********************************************************************************
Please avoid running ``setup.py`` and ``easy_install``.
Instead, use pypa/build, pypa/installer or other
standards-based tools.
See https://github.com/pypa/setuptools/issues/917 for details.
********************************************************************************
!!
self.initialize_options()
running bdist_egg
running egg_info
creating ThePackage.egg-info
writing ThePackage.egg-info/PKG-INFO
writing dependency_links to ThePackage.egg-info/dependency_links.txt
writing top-level names to ThePackage.egg-info/top_level.txt
writing manifest file 'ThePackage.egg-info/SOURCES.txt'
reading manifest file 'ThePackage.egg-info/SOURCES.txt'
Traceback (most recent call last):
File "/opt/ThePackage/LanguageBindings/Python/setup.py", line 240, in <module>
setup(
File "/home/user/.pyenv/versions/3.9.18/lib/python3.9/site-packages/setuptools/__init__.py", line 117, in setup
return distutils.core.setup(**attrs)
File "/home/user/.pyenv/versions/3.9.18/lib/python3.9/site-packages/setuptools/_distutils/core.py", line 184, in setup
return run_commands(dist)
File "/home/user/.pyenv/versions/3.9.18/lib/python3.9/site-packages/setuptools/_distutils/core.py", line 200, in run_commands
dist.run_commands()
File "/home/user/.pyenv/versions/3.9.18/lib/python3.9/site-packages/setuptools/_distutils/dist.py", line 953, in run_commands
self.run_command(cmd)
File "/home/user/.pyenv/versions/3.9.18/lib/python3.9/site-packages/setuptools/dist.py", line 950, in run_command
super().run_command(command)
File "/home/user/.pyenv/versions/3.9.18/lib/python3.9/site-packages/setuptools/_distutils/dist.py", line 972, in run_command
cmd_obj.run()
File "/home/user/.pyenv/versions/3.9.18/lib/python3.9/site-packages/setuptools/command/install.py", line 97, in run
self.do_egg_install()
File "/home/user/.pyenv/versions/3.9.18/lib/python3.9/site-packages/setuptools/command/install.py", line 149, in do_egg_install
self.run_command('bdist_egg')
File "/home/user/.pyenv/versions/3.9.18/lib/python3.9/site-packages/setuptools/_distutils/cmd.py", line 316, in run_command
self.distribution.run_command(command)
File "/home/user/.pyenv/versions/3.9.18/lib/python3.9/site-packages/setuptools/dist.py", line 950, in run_command
super().run_command(command)
File "/home/user/.pyenv/versions/3.9.18/lib/python3.9/site-packages/setuptools/_distutils/dist.py", line 972, in run_command
cmd_obj.run()
File "/home/user/.pyenv/versions/3.9.18/lib/python3.9/site-packages/setuptools/command/bdist_egg.py", line 159, in run
self.run_command("egg_info")
File "/home/user/.pyenv/versions/3.9.18/lib/python3.9/site-packages/setuptools/_distutils/cmd.py", line 316, in run_command
self.distribution.run_command(command)
File "/home/user/.pyenv/versions/3.9.18/lib/python3.9/site-packages/setuptools/dist.py", line 950, in run_command
super().run_command(command)
File "/home/user/.pyenv/versions/3.9.18/lib/python3.9/site-packages/setuptools/_distutils/dist.py", line 972, in run_command
cmd_obj.run()
File "/home/user/.pyenv/versions/3.9.18/lib/python3.9/site-packages/setuptools/command/egg_info.py", line 311, in run
self.find_sources()
File "/home/user/.pyenv/versions/3.9.18/lib/python3.9/site-packages/setuptools/command/egg_info.py", line 319, in find_sources
mm.run()
File "/home/user/.pyenv/versions/3.9.18/lib/python3.9/site-packages/setuptools/command/egg_info.py", line 545, in run
self.prune_file_list()
File "/home/user/.pyenv/versions/3.9.18/lib/python3.9/site-packages/setuptools/command/sdist.py", line 161, in prune_file_list
super().prune_file_list()
File "/home/user/.pyenv/versions/3.9.18/lib/python3.9/site-packages/setuptools/_distutils/command/sdist.py", line 394, in prune_file_list
self.filelist.exclude_pattern(None, prefix=build.build_base)
File "/home/user/.pyenv/versions/3.9.18/lib/python3.9/site-packages/setuptools/_distutils/filelist.py", line 249, in exclude_pattern
pattern_re = translate_pattern(pattern, anchor, prefix, is_regex)
File "/home/user/.pyenv/versions/3.9.18/lib/python3.9/site-packages/setuptools/_distutils/filelist.py", line 357, in translate_pattern
prefix_re = glob_to_re(prefix)
File "/home/user/.pyenv/versions/3.9.18/lib/python3.9/site-packages/setuptools/_distutils/filelist.py", line 318, in glob_to_re
pattern_re = fnmatch.translate(pattern)
File "/home/user/.pyenv/versions/3.9.18/lib/python3.9/fnmatch.py", line 89, in translate
i, n = 0, len(pat)
TypeError: object of type 'PosixPath' has no len()mbaumanndev