[bumpversion]
-current_version = 67.1.0
+current_version = 67.2.0
commit = True
tag = True
+v67.2.0
+-------
+
+
+Changes
+^^^^^^^
+* #3809: Merge with distutils@8c3c3d29, including fix for ``sysconfig.get_python_inc()`` (pypa/distutils#178), fix for segfault on MinGW (pypa/distutils#196), and better ``has_function`` support (pypa/distutils#195).
+
+
v67.1.0
-------
[metadata]
name = setuptools
-version = 67.1.0
+version = 67.2.0
author = Python Packaging Authority
author_email = distutils-sig@python.org
description = Easily download, build, install, upgrade, and uninstall Python packages
return (sorted_keys[RangeMap.first_item], sorted_keys[RangeMap.last_item])
# some special values for the RangeMap
- undefined_value = type(str('RangeValueUndefined'), (), {})()
+ undefined_value = type('RangeValueUndefined', (), {})()
class Item(int):
"RangeMap Item"
extra_postargs=None,
depends=None,
):
-
if not self.initialized:
self.initialize()
compile_info = self._setup_compile(
args = [self.cc] + compile_opts + pp_opts
if add_cpp_opts:
args.append('/EHsc')
- args.append(input_opt)
- args.append("/Fo" + obj)
+ args.extend((input_opt, "/Fo" + obj))
args.extend(extra_postargs)
try:
def create_static_lib(
self, objects, output_libname, output_dir=None, debug=0, target_lang=None
):
-
if not self.initialized:
self.initialize()
objects, output_dir = self._fix_object_args(objects, output_dir)
build_temp=None,
target_lang=None,
):
-
if not self.initialized:
self.initialize()
objects, output_dir = self._fix_object_args(objects, output_dir)
exe_extension = '.exe'
def __init__(self, verbose=0, dry_run=0, force=0):
-
super().__init__(verbose, dry_run, force)
# These executables are assumed to all be in the path.
extra_postargs=None,
depends=None,
):
-
macros, objects, extra_postargs, pp_opts, build = self._setup_compile(
output_dir, macros, include_dirs, sources, depends, extra_postargs
)
def create_static_lib(
self, objects, output_libname, output_dir=None, debug=0, target_lang=None
):
-
(objects, output_dir) = self._fix_object_args(objects, output_dir)
output_filename = self.library_filename(output_libname, output_dir=output_dir)
build_temp=None,
target_lang=None,
):
-
# XXX this ignores 'build_temp'! should follow the lead of
# msvccompiler.py
output_filename = os.path.join(output_dir, output_filename)
if self._need_link(objects, output_filename):
-
# Figure out linker args based on type of target.
if target_desc == CCompiler.EXECUTABLE:
startup_obj = 'c0w32'
ld_args.append(libfile)
# some default libraries
- ld_args.append('import32')
- ld_args.append('cw32mt')
+ ld_args.extend(('import32', 'cw32mt'))
# def file for export symbols
ld_args.extend([',', def_file])
extra_preargs=None,
extra_postargs=None,
):
-
(_, macros, include_dirs) = self._fix_compile_args(None, macros, include_dirs)
pp_opts = gen_preprocess_options(macros, include_dirs)
pp_args = ['cpp32.exe'] + pp_opts
import sys
import os
import re
+import warnings
from .errors import (
CompileError,
raise TypeError("'macros' (if supplied) must be a list of tuples")
if include_dirs is None:
- include_dirs = self.include_dirs
+ include_dirs = list(self.include_dirs)
elif isinstance(include_dirs, (list, tuple)):
include_dirs = list(include_dirs) + (self.include_dirs or [])
else:
libraries=None,
library_dirs=None,
):
- """Return a boolean indicating whether funcname is supported on
- the current platform. The optional arguments can be used to
- augment the compilation environment.
+ """Return a boolean indicating whether funcname is provided as
+ a symbol on the current platform. The optional arguments can
+ be used to augment the compilation environment.
+
+ The libraries argument is a list of flags to be passed to the
+ linker to make additional symbol definitions available for
+ linking.
+
+ The includes and include_dirs arguments are deprecated.
+ Usually, supplying include files with function declarations
+ will cause function detection to fail even in cases where the
+ symbol is available for linking.
+
"""
# this can't be included at module scope because it tries to
# import math which might not be available at that point - maybe
if includes is None:
includes = []
+ else:
+ warnings.warn("includes is deprecated", DeprecationWarning)
if include_dirs is None:
include_dirs = []
+ else:
+ warnings.warn("include_dirs is deprecated", DeprecationWarning)
if libraries is None:
libraries = []
if library_dirs is None:
f = os.fdopen(fd, "w")
try:
for incl in includes:
- f.write("""#include "%s"\n""" % incl)
+ f.write("""#include %s\n""" % incl)
+ if not includes:
+ # Use "char func(void);" as the prototype to follow
+ # what autoconf does. This prototype does not match
+ # any well-known function the compiler might recognize
+ # as a builtin, so this ends up as a true link test.
+ # Without a fake prototype, the test would need to
+ # know the exact argument types, and the has_function
+ # interface does not provide that level of information.
+ f.write(
+ """\
+#ifdef __cplusplus
+extern "C"
+#endif
+char %s(void);
+"""
+ % funcname
+ )
f.write(
"""\
int main (int argc, char **argv) {
except (LinkError, TypeError):
return False
else:
- os.remove(os.path.join(self.output_dir or '', "a.out"))
+ os.remove(
+ self.executable_filename("a.out", output_dir=self.output_dir or '')
+ )
finally:
for fn in objects:
os.remove(fn)
header = "command options for '%s':" % self.get_command_name()
self.announce(indent + header, level=logging.INFO)
indent = indent + " "
- for (option, _, _) in self.user_options:
+ for option, _, _ in self.user_options:
option = option.translate(longopt_xlate)
if option[-1] == "=":
option = option[:-1]
# Option_pairs: list of (src_option, dst_option) tuples
src_cmd_obj = self.distribution.get_command_obj(src_cmd)
src_cmd_obj.ensure_finalized()
- for (src_option, dst_option) in option_pairs:
+ for src_option, dst_option in option_pairs:
if getattr(self, dst_option) is None:
setattr(self, dst_option, getattr(src_cmd_obj, src_option))
run for the current distribution. Return a list of command names.
"""
commands = []
- for (cmd_name, method) in self.sub_commands:
+ for cmd_name, method in self.sub_commands:
if method is None or method(self):
commands.append(cmd_name)
return commands
class bdist(Command):
-
description = "create a built (binary) distribution"
user_options = [
class bdist_dumb(Command):
-
description = "create a \"dumb\" built distribution"
user_options = [
class bdist_rpm(Command):
-
description = "create an RPM distribution"
user_options = [
('postun', 'post_uninstall', None),
]
- for (rpm_opt, attr, default) in script_options:
+ for rpm_opt, attr, default in script_options:
# Insert contents of file referred to, if no file is referred to
# use 'default' as contents of script
val = getattr(self, attr)
class build(Command):
-
description = "build everything needed to install"
user_options = [
class build_clib(Command):
-
description = "build C/C++ libraries used by Python extensions"
user_options = [
self.compiler.set_include_dirs(self.include_dirs)
if self.define is not None:
# 'define' option is a list of (name,value) tuples
- for (name, value) in self.define:
+ for name, value in self.define:
self.compiler.define_macro(name, value)
if self.undef is not None:
for macro in self.undef:
return None
lib_names = []
- for (lib_name, build_info) in self.libraries:
+ for lib_name, build_info in self.libraries:
lib_names.append(lib_name)
return lib_names
def get_source_files(self):
self.check_library_list(self.libraries)
filenames = []
- for (lib_name, build_info) in self.libraries:
+ for lib_name, build_info in self.libraries:
sources = build_info.get('sources')
if sources is None or not isinstance(sources, (list, tuple)):
raise DistutilsSetupError(
return filenames
def build_libraries(self, libraries):
- for (lib_name, build_info) in libraries:
+ for lib_name, build_info in libraries:
sources = build_info.get('sources')
if sources is None or not isinstance(sources, (list, tuple)):
raise DistutilsSetupError(
class build_ext(Command):
-
description = "build C/C++ extensions (compile/link to build directory)"
# XXX thoughts on how to deal with complex command-line options like
self.compiler.set_include_dirs(self.include_dirs)
if self.define is not None:
# 'define' option is a list of (name,value) tuples
- for (name, value) in self.define:
+ for name, value in self.define:
self.compiler.define_macro(name, value)
if self.undef is not None:
for macro in self.undef:
name = ext.name.split('.')[-1]
try:
# Unicode module name support as defined in PEP-489
- # https://www.python.org/dev/peps/pep-0489/#export-hook-name
+ # https://peps.python.org/pep-0489/#export-hook-name
name.encode('ascii')
except UnicodeEncodeError:
suffix = 'U_' + name.encode('punycode').replace(b'-', b'_').decode('ascii')
class build_py(Command):
-
description = "\"build\" pure Python modules (copy to build directory)"
user_options = [
def get_outputs(self, include_bytecode=1):
modules = self.find_all_modules()
outputs = []
- for (package, module, module_file) in modules:
+ for package, module, module_file in modules:
package = package.split('.')
filename = self.get_module_outfile(self.build_lib, package, module)
outputs.append(filename)
def build_modules(self):
modules = self.find_modules()
- for (package, module, module_file) in modules:
+ for package, module, module_file in modules:
# Now "build" the module -- ie. copy the source file to
# self.build_lib (the build directory for Python source).
# (Actually, it gets copied to the directory for this package
# Now loop over the modules we found, "building" each one (just
# copy it to self.build_lib).
- for (package_, module, module_file) in modules:
+ for package_, module, module_file in modules:
assert package == package_
self.build_module(module, module_file, package)
class build_scripts(Command):
-
description = "\"build\" scripts (copy and fixup #! line)"
user_options = [
class clean(Command):
-
description = "clean up temporary files from 'build' command"
user_options = [
('build-base=', 'b', "base build directory (default: 'build.build-base')"),
class config(Command):
-
description = "prepare to build"
user_options = [
class install(Command):
-
description = "install everything from build directory"
user_options = [
for attr in attrs:
val = getattr(self, attr)
if val is not None:
- if os.name == 'posix' or os.name == 'nt':
+ if os.name in ('posix', 'nt'):
val = os.path.expanduser(val)
val = subst_vars(val, self.config_vars)
setattr(self, attr, val)
class install_data(Command):
-
description = "install data files"
user_options = [
# XXX force is never used
class install_headers(Command):
-
description = "install C/C++ header files"
user_options = [
class install_lib(Command):
-
description = "install all Python modules (extensions and pure Python)"
# The byte-compilation options are a tad confusing. Here are the
class install_scripts(Command):
-
description = "install scripts (Python or otherwise)"
user_options = [
class register(PyPIRCCommand):
-
description = "register the distribution with the Python package index"
user_options = PyPIRCCommand.user_options + [
('list-classifiers', None, 'list the valid Trove classifiers'),
class sdist(Command):
-
description = "create a source distribution (tarball, zip file, etc.)"
def checking_metadata(self):
"""Add all the default files to self.filelist:
- README or README.txt
- setup.py
- - test/test*.py
+ - tests/test*.py and test/test*.py
- all pure Python modules mentioned in setup script
- all files pointed by package_data (build_py)
- all files defined in data_files.
self.warn("standard file '%s' not found" % fn)
def _add_defaults_optional(self):
- optional = ['test/test*.py', 'setup.cfg']
+ optional = ['tests/test*.py', 'test/test*.py', 'setup.cfg']
for pattern in optional:
files = filter(os.path.isfile, glob(pattern))
self.filelist.extend(files)
class upload(PyPIRCCommand):
-
description = "upload binary package to PyPI"
user_options = PyPIRCCommand.user_options + [
# our Distribution (see below).
klass = attrs.get('distclass')
if klass:
- del attrs['distclass']
+ attrs.pop('distclass')
else:
klass = Distribution
# VS2013 / MSVC 12.0
1800: ['msvcr120'],
# VS2015 / MSVC 14.0
- 1900: ['ucrt', 'vcruntime140'],
+ 1900: ['vcruntime140'],
2000: RangeMap.undefined_value,
},
)
exe_extension = ".exe"
def __init__(self, verbose=0, dry_run=0, force=0):
-
super().__init__(verbose, dry_run, force)
status, details = check_config_h()
@property
def gcc_version(self):
- # Older numpy dependend on this existing to check for ancient
+ # Older numpy depended on this existing to check for ancient
# gcc versions. This doesn't make much sense with clang etc so
# just hardcode to something recent.
# https://github.com/numpy/numpy/pull/20333
def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
"""Compiles the source by spawning GCC and windres if needed."""
- if ext == '.rc' or ext == '.res':
+ if ext in ('.rc', '.res'):
# gcc needs '.res' and '.rc' compiled to object files !!!
try:
self.spawn(["windres", "-i", src, "-o", obj])
compiler_type = 'mingw32'
def __init__(self, verbose=0, dry_run=0, force=0):
-
super().__init__(verbose, dry_run, force)
shared_option = "-shared"
# remove dir from cache if it's already there
abspath = os.path.abspath(cmd[1])
if abspath in _path_created:
- del _path_created[abspath]
+ _path_created.pop(abspath)
except OSError as exc:
log.warning("error removing %s: %s", directory, exc)
options = attrs.get('options')
if options is not None:
del attrs['options']
- for (command, cmd_options) in options.items():
+ for command, cmd_options in options.items():
opt_dict = self.get_option_dict(command)
- for (opt, val) in cmd_options.items():
+ for opt, val in cmd_options.items():
opt_dict[opt] = ("setup script", val)
if 'licence' in attrs:
# Now work on the rest of the attributes. Any attribute that's
# not already defined is invalid!
- for (key, val) in attrs.items():
+ for key, val in attrs.items():
if hasattr(self.metadata, "set_" + key):
getattr(self.metadata, "set_" + key)(val)
elif hasattr(self.metadata, key):
# to set Distribution options.
if 'global' in self.command_options:
- for (opt, (src, val)) in self.command_options['global'].items():
+ for opt, (src, val) in self.command_options['global'].items():
alias = self.negative_opt.get(opt)
try:
if alias:
cmd_class.help_options, list
):
help_option_found = 0
- for (help_option, short, desc, func) in cmd_class.help_options:
+ for help_option, short, desc, func in cmd_class.help_options:
if hasattr(opts, parser.get_attr_name(help_option)):
help_option_found = 1
if callable(func):
# Put the options from the command-line into their official
# holding pen, the 'command_options' dictionary.
opt_dict = self.get_option_dict(command)
- for (name, value) in vars(opts).items():
+ for name, value in vars(opts).items():
opt_dict[name] = ("command line", value)
return args
for option in self.display_options:
is_display_option[option[0]] = 1
- for (opt, val) in option_order:
+ for opt, val in option_order:
if val and is_display_option.get(opt):
opt = translate_longopt(opt)
value = getattr(self.metadata, "get_" + opt)()
- if opt in ['keywords', 'platforms']:
+ if opt in ('keywords', 'platforms'):
print(','.join(value))
elif opt in ('classifiers', 'provides', 'requires', 'obsoletes'):
print('\n'.join(value))
if DEBUG:
self.announce(" setting options for '%s' command:" % command_name)
- for (option, (source, value)) in option_dict.items():
+ for option, (source, value) in option_dict.items():
if DEBUG:
self.announce(" {} = {} (from {})".format(option, value, source))
try:
def _check_alias_dict(self, aliases, what):
assert isinstance(aliases, dict)
- for (alias, opt) in aliases.items():
+ for alias, opt in aliases.items():
if alias not in self.option_index:
raise DistutilsGetoptError(
("invalid %s '%s': " "option '%s' not defined")
# XXX I suspect this is Unix-specific -- need porting help!
def move_file(src, dst, verbose=1, dry_run=0): # noqa: C901
-
"""Move a file 'src' to 'dst'. If 'dst' is a directory, the file will
be moved into it with the same name; otherwise, 'src' is just renamed
to 'dst'. Return the new full name of the file.
# to cross compile, you use 'x86_amd64'.
# On AMD64, 'vcvars32.bat amd64' is a native build env; to cross
# compile use 'x86' (ie, it runs the x86 compiler directly)
- if plat_name == get_platform() or plat_name == 'win32':
+ if plat_name in (get_platform(), 'win32'):
# native build or cross-compile to win32
plat_spec = PLAT_TO_VCVARS[plat_name]
else:
extra_postargs=None,
depends=None,
):
-
if not self.initialized:
self.initialize()
compile_info = self._setup_compile(
def create_static_lib(
self, objects, output_libname, output_dir=None, debug=0, target_lang=None
):
-
if not self.initialized:
self.initialize()
(objects, output_dir) = self._fix_object_args(objects, output_dir)
build_temp=None,
target_lang=None,
):
-
if not self.initialized:
self.initialize()
(objects, output_dir) = self._fix_object_args(objects, output_dir)
extra_postargs=None,
depends=None,
):
-
if not self.initialized:
self.initialize()
compile_info = self._setup_compile(
def create_static_lib(
self, objects, output_libname, output_dir=None, debug=0, target_lang=None
):
-
if not self.initialized:
self.initialize()
(objects, output_dir) = self._fix_object_args(objects, output_dir)
build_temp=None,
target_lang=None,
):
-
if not self.initialized:
self.initialize()
(objects, output_dir) = self._fix_object_args(objects, output_dir)
return getter(resolved_prefix, prefix, plat_specific)
+@pass_none
+def _extant(path):
+ """
+ Replace path with None if it doesn't exist.
+ """
+ return path if os.path.exists(path) else None
+
+
def _get_python_inc_posix(prefix, spec_prefix, plat_specific):
if IS_PYPY and sys.version_info < (3, 8):
return os.path.join(prefix, 'include')
return (
_get_python_inc_posix_python(plat_specific)
- or _get_python_inc_from_config(plat_specific, spec_prefix)
+ or _extant(_get_python_inc_from_config(plat_specific, spec_prefix))
or _get_python_inc_posix_prefix(prefix)
)
del notdone[name]
if name.startswith('PY_') and name[3:] in renamed_variables:
-
name = name[3:]
if name not in done:
done[name] = value
pass
assert os.getcwd() == current_dir
finally:
- del ARCHIVE_FORMATS['xxx']
+ ARCHIVE_FORMATS.pop('xxx')
def test_make_archive_tar(self):
base_dir = self._create_files()
):
@pytest.mark.usefixtures('needs_zlib')
def test_simple_built(self):
-
# let's create a simple package
tmp_dir = self.mkdtemp()
pkg_dir = os.path.join(tmp_dir, 'foo')
assert cmd.get_source_files() == ['a', 'b', 'c', 'd']
def test_build_libraries(self):
-
pkg_dir, dist = self.create_dist()
cmd = build_clib(dist)
cmd = self.build_ext(dist)
# making sure the user option is there
- options = [name for name, short, lable in cmd.user_options]
+ options = [name for name, short, label in cmd.user_options]
assert 'user' in options
# setting a value
assert incl in cmd.include_dirs
def test_optional_extension(self):
-
# this extension will fail, but let's ignore this failure
# with the optional argument.
modules = [Extension('foo', ['xxx'], optional=False)]
# do it again, setting include dirs after any initialization
compiler.set_include_dirs([python])
compiler.compile(_make_strs([c_file]))
+
+
+def test_has_function_prototype():
+ # Issue https://github.com/pypa/setuptools/issues/3648
+ # Test prototype-generating behavior.
+
+ compiler = ccompiler.new_compiler()
+
+ # Every C implementation should have these.
+ assert compiler.has_function('abort')
+ assert compiler.has_function('exit')
+ with pytest.deprecated_call(match='includes is deprecated'):
+ # abort() is a valid expression with the <stdlib.h> prototype.
+ assert compiler.has_function('abort', includes=['<stdlib.h>'])
+ with pytest.deprecated_call(match='includes is deprecated'):
+ # But exit() is not valid with the actual prototype in scope.
+ assert not compiler.has_function('exit', includes=['<stdlib.h>'])
+ # And setuptools_does_not_exist is not declared or defined at all.
+ assert not compiler.has_function('setuptools_does_not_exist')
+ with pytest.deprecated_call(match='includes is deprecated'):
+ assert not compiler.has_function(
+ 'setuptools_does_not_exist', includes=['<stdio.h>']
+ )
+
+
+def test_include_dirs_after_multiple_compile_calls(c_file):
+ """
+ Calling compile multiple times should not change the include dirs
+ (regression test for setuptools issue #3591).
+ """
+ compiler = ccompiler.new_compiler()
+ python = sysconfig.get_paths()['include']
+ compiler.set_include_dirs([python])
+ compiler.compile(_make_strs([c_file]))
+ assert compiler.include_dirs == [python]
+ compiler.compile(_make_strs([c_file]))
+ assert compiler.include_dirs == [python]
pytest.importorskip('docutils')
# Don't fail if there is a `code` or `code-block` directive
- example_rst_docs = []
- example_rst_docs.append(
+ example_rst_docs = [
textwrap.dedent(
"""\
Here's some code:
def foo():
pass
"""
- )
- )
- example_rst_docs.append(
+ ),
textwrap.dedent(
"""\
Here's some code:
def foo():
pass
"""
- )
- )
+ ),
+ ]
for rest_with_code in example_rst_docs:
pkg_info, dist = self.create_dist(long_description=rest_with_code)
cmd.make_file(infiles='in', outfile='out', func='func', args=())
def test_dump_options(self, cmd):
-
msgs = []
def _announce(msg, level):
assert compiler.runtime_library_dir_option('/foo') == []
def test_check_config_h(self):
-
# check_config_h looks for "GCC" in sys.version first
# returns CONFIG_H_OK if found
sys.version = (
assert check_config_h()[0] == CONFIG_H_OK
def test_get_msvcr(self):
-
# none
sys.version = (
'2.6.1 (r261:67515, Dec 6 2008, 16:42:21) '
'3.10.0 (tags/v3.10.0:b494f59, Oct 4 2021, 18:46:30) '
'[MSC v.1929 32 bit (Intel)]'
)
- assert get_msvcr() == ['ucrt', 'vcruntime140']
+ assert get_msvcr() == ['vcruntime140']
# unknown
sys.version = (
class TestDepUtil(support.TempdirManager):
def test_newer(self):
-
tmpdir = self.mkdtemp()
new_file = os.path.join(tmpdir, 'new')
old_file = os.path.abspath(__file__)
assert stat.S_IMODE(os.stat(self.target2).st_mode) == 0o555 & ~umask
def test_create_tree_verbosity(self, caplog):
-
create_tree(self.root_target, ['one', 'two', 'three'], verbose=0)
assert caplog.messages == []
remove_tree(self.root_target, verbose=0)
remove_tree(self.root_target, verbose=0)
def test_copy_tree_verbosity(self, caplog):
-
mkpath(self.target, verbose=0)
copy_tree(self.target, self.target2, verbose=0)
result_dict.keys()
)
- for (key, value) in d.command_options.get('install').items():
+ for key, value in d.command_options.get('install').items():
assert value == result_dict[key]
# Test case: In a Virtual Environment
cmd = install(dist)
# making sure the user option is there
- options = [name for name, short, lable in cmd.user_options]
+ options = [name for name, short, label in cmd.user_options]
assert 'user' in options
# setting a value
assert b'xxx' in self.conn.reqs[1].data
def test_password_not_in_file(self):
-
self.write_file(self.rc, PYPIRC_NOPASSWORD)
cmd = self._get_cmd()
cmd._set_config()
@pytest.mark.usefixtures('needs_zlib')
def test_add_defaults(self):
-
# http://bugs.python.org/issue2279
# add_default should also include
cmd, env={**os.environ, "PYTHONPATH": distutils_path}
)
assert out == "True"
+
+ def test_get_python_inc_missing_config_dir(self, monkeypatch):
+ """
+ In portable Python installations, the sysconfig will be broken,
+ pointing to the directories where the installation was built and
+ not where it currently is. In this case, ensure that the missing
+ directory isn't used for get_python_inc.
+
+ See pypa/distutils#178.
+ """
+
+ def override(name):
+ if name == 'INCLUDEPY':
+ return '/does-not-exist'
+ return sysconfig.get_config_var(name)
+
+ monkeypatch.setattr(sysconfig, 'get_config_var', override)
+
+ assert os.path.exists(sysconfig.get_python_inc())
# FileNotFoundError: [Errno 2] No such file or directory: 'a.out'
self.cc.output_dir = 'scratch'
os.chdir(self.mkdtemp())
- self.cc.has_function('abort', includes=['stdlib.h'])
+ self.cc.has_function('abort')
return self.last_open
def test_finalize_options(self):
-
# new format
self.write_file(self.rc, PYPIRC)
dist = Distribution()
line = None
if self.strip_comments and line:
-
# Look for the first "#" in the line. If none, never
# mind. If we find one and it's the first character, or
# is not preceded by "\", then it starts a comment --
# blank line (whether we rstrip'ed or not)? skip to next line
# if appropriate
- if (line == '' or line == '\n') and self.skip_blanks:
+ if line in ('', '\n') and self.skip_blanks:
continue
if self.join_lines:
class UnixCCompiler(CCompiler):
-
compiler_type = 'unix'
# These are used by CCompiler in two places: the constructor sets
import warnings
warnings.warn(
- "shell/Perl-style substitions are deprecated",
+ "shell/Perl-style substitutions are deprecated",
DeprecationWarning,
)
return repl
self.prerelease = None
def __str__(self):
-
if self.version[2] == 0:
vstring = '.'.join(map(str, self.version[0:2]))
else: