Add files using upload-large-folder tool
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitattributes +2 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/ctypes/__pycache__/__init__.cpython-38.pyc +0 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/ctypes/__pycache__/_aix.cpython-38.pyc +0 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/ctypes/__pycache__/_endian.cpython-38.pyc +0 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/ctypes/__pycache__/util.cpython-38.pyc +0 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/ctypes/__pycache__/wintypes.cpython-38.pyc +0 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/ctypes/macholib/README.ctypes +7 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/ctypes/macholib/__init__.py +9 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/ctypes/macholib/__pycache__/__init__.cpython-38.pyc +0 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/ctypes/macholib/__pycache__/dyld.cpython-38.pyc +0 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/ctypes/macholib/__pycache__/dylib.cpython-38.pyc +0 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/ctypes/macholib/__pycache__/framework.cpython-38.pyc +0 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/ctypes/macholib/dyld.py +177 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/ctypes/macholib/dylib.py +63 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/ctypes/macholib/fetch_macholib +2 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/ctypes/macholib/fetch_macholib.bat +1 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/ctypes/macholib/framework.py +65 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/README +11 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/__init__.py +13 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/_msvccompiler.py +543 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/archive_util.py +256 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/bcppcompiler.py +393 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/ccompiler.py +1116 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/core.py +234 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/cygwinccompiler.py +412 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/debug.py +5 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/dep_util.py +92 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/dist.py +1256 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/errors.py +97 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/fancy_getopt.py +457 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/file_util.py +238 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/filelist.py +327 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/msvccompiler.py +643 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/spawn.py +203 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/unixccompiler.py +330 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/util.py +558 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/version.py +343 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/versionpredicate.py +166 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/encodings/__pycache__/iso8859_13.cpython-38.pyc +0 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/encodings/__pycache__/iso8859_9.cpython-38.pyc +0 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/encodings/__pycache__/mbcs.cpython-38.pyc +0 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/encodings/__pycache__/ptcp154.cpython-38.pyc +0 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/http/__pycache__/__init__.cpython-38.pyc +0 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/http/__pycache__/client.cpython-38.pyc +0 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/http/__pycache__/cookiejar.cpython-38.pyc +0 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/http/__pycache__/cookies.cpython-38.pyc +0 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/http/__pycache__/server.cpython-38.pyc +0 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/CREDITS.txt +37 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/NEWS.txt +1256 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/README.txt +251 -0
.gitattributes
CHANGED
|
@@ -173,3 +173,5 @@ my_container_sandbox/workspace/anaconda3/pkgs/ncurses-6.4-h6a678d5_0.conda filte
|
|
| 173 |
my_container_sandbox/workspace/anaconda3/pkgs/ca-certificates-2021.7.5-h06a4308_1.conda filter=lfs diff=lfs merge=lfs -text
|
| 174 |
my_container_sandbox/workspace/anaconda3/pkgs/conda-package-handling-2.2.0-pyh38be061_0.conda filter=lfs diff=lfs merge=lfs -text
|
| 175 |
my_container_sandbox/workspace/anaconda3/pkgs/sqlite-3.36.0-hc218d9a_0.conda filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
| 173 |
my_container_sandbox/workspace/anaconda3/pkgs/ca-certificates-2021.7.5-h06a4308_1.conda filter=lfs diff=lfs merge=lfs -text
|
| 174 |
my_container_sandbox/workspace/anaconda3/pkgs/conda-package-handling-2.2.0-pyh38be061_0.conda filter=lfs diff=lfs merge=lfs -text
|
| 175 |
my_container_sandbox/workspace/anaconda3/pkgs/sqlite-3.36.0-hc218d9a_0.conda filter=lfs diff=lfs merge=lfs -text
|
| 176 |
+
my_container_sandbox/workspace/anaconda3/pkgs/certifi-2021.5.30-py39h06a4308_0.conda filter=lfs diff=lfs merge=lfs -text
|
| 177 |
+
my_container_sandbox/workspace/anaconda3/pkgs/ncurses-6.2-he6710b0_1.conda filter=lfs diff=lfs merge=lfs -text
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/ctypes/__pycache__/__init__.cpython-38.pyc
ADDED
|
Binary file (16.4 kB). View file
|
|
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/ctypes/__pycache__/_aix.cpython-38.pyc
ADDED
|
Binary file (9.84 kB). View file
|
|
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/ctypes/__pycache__/_endian.cpython-38.pyc
ADDED
|
Binary file (1.92 kB). View file
|
|
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/ctypes/__pycache__/util.cpython-38.pyc
ADDED
|
Binary file (8.45 kB). View file
|
|
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/ctypes/__pycache__/wintypes.cpython-38.pyc
ADDED
|
Binary file (5.1 kB). View file
|
|
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/ctypes/macholib/README.ctypes
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Files in this directory come from Bob Ippolito's py2app.
|
| 2 |
+
|
| 3 |
+
License: Any components of the py2app suite may be distributed under
|
| 4 |
+
the MIT or PSF open source licenses.
|
| 5 |
+
|
| 6 |
+
This is version 1.0, SVN revision 789, from 2006/01/25.
|
| 7 |
+
The main repository is http://svn.red-bean.com/bob/macholib/trunk/macholib/
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/ctypes/macholib/__init__.py
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Enough Mach-O to make your head spin.
|
| 3 |
+
|
| 4 |
+
See the relevant header files in /usr/include/mach-o
|
| 5 |
+
|
| 6 |
+
And also Apple's documentation.
|
| 7 |
+
"""
|
| 8 |
+
|
| 9 |
+
__version__ = '1.0'
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/ctypes/macholib/__pycache__/__init__.cpython-38.pyc
ADDED
|
Binary file (294 Bytes). View file
|
|
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/ctypes/macholib/__pycache__/dyld.cpython-38.pyc
ADDED
|
Binary file (4.73 kB). View file
|
|
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/ctypes/macholib/__pycache__/dylib.cpython-38.pyc
ADDED
|
Binary file (1.91 kB). View file
|
|
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/ctypes/macholib/__pycache__/framework.cpython-38.pyc
ADDED
|
Binary file (2.19 kB). View file
|
|
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/ctypes/macholib/dyld.py
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
dyld emulation
|
| 3 |
+
"""
|
| 4 |
+
|
| 5 |
+
import os
|
| 6 |
+
from ctypes.macholib.framework import framework_info
|
| 7 |
+
from ctypes.macholib.dylib import dylib_info
|
| 8 |
+
from itertools import *
|
| 9 |
+
try:
|
| 10 |
+
from _ctypes import _dyld_shared_cache_contains_path
|
| 11 |
+
except ImportError:
|
| 12 |
+
def _dyld_shared_cache_contains_path(*args):
|
| 13 |
+
raise NotImplementedError
|
| 14 |
+
|
| 15 |
+
__all__ = [
|
| 16 |
+
'dyld_find', 'framework_find',
|
| 17 |
+
'framework_info', 'dylib_info',
|
| 18 |
+
]
|
| 19 |
+
|
| 20 |
+
# These are the defaults as per man dyld(1)
|
| 21 |
+
#
|
| 22 |
+
DEFAULT_FRAMEWORK_FALLBACK = [
|
| 23 |
+
os.path.expanduser("~/Library/Frameworks"),
|
| 24 |
+
"/Library/Frameworks",
|
| 25 |
+
"/Network/Library/Frameworks",
|
| 26 |
+
"/System/Library/Frameworks",
|
| 27 |
+
]
|
| 28 |
+
|
| 29 |
+
DEFAULT_LIBRARY_FALLBACK = [
|
| 30 |
+
os.path.expanduser("~/lib"),
|
| 31 |
+
"/usr/local/lib",
|
| 32 |
+
"/lib",
|
| 33 |
+
"/usr/lib",
|
| 34 |
+
]
|
| 35 |
+
|
| 36 |
+
def dyld_env(env, var):
|
| 37 |
+
if env is None:
|
| 38 |
+
env = os.environ
|
| 39 |
+
rval = env.get(var)
|
| 40 |
+
if rval is None:
|
| 41 |
+
return []
|
| 42 |
+
return rval.split(':')
|
| 43 |
+
|
| 44 |
+
def dyld_image_suffix(env=None):
|
| 45 |
+
if env is None:
|
| 46 |
+
env = os.environ
|
| 47 |
+
return env.get('DYLD_IMAGE_SUFFIX')
|
| 48 |
+
|
| 49 |
+
def dyld_framework_path(env=None):
|
| 50 |
+
return dyld_env(env, 'DYLD_FRAMEWORK_PATH')
|
| 51 |
+
|
| 52 |
+
def dyld_library_path(env=None):
|
| 53 |
+
return dyld_env(env, 'DYLD_LIBRARY_PATH')
|
| 54 |
+
|
| 55 |
+
def dyld_fallback_framework_path(env=None):
|
| 56 |
+
return dyld_env(env, 'DYLD_FALLBACK_FRAMEWORK_PATH')
|
| 57 |
+
|
| 58 |
+
def dyld_fallback_library_path(env=None):
|
| 59 |
+
return dyld_env(env, 'DYLD_FALLBACK_LIBRARY_PATH')
|
| 60 |
+
|
| 61 |
+
def dyld_image_suffix_search(iterator, env=None):
|
| 62 |
+
"""For a potential path iterator, add DYLD_IMAGE_SUFFIX semantics"""
|
| 63 |
+
suffix = dyld_image_suffix(env)
|
| 64 |
+
if suffix is None:
|
| 65 |
+
return iterator
|
| 66 |
+
def _inject(iterator=iterator, suffix=suffix):
|
| 67 |
+
for path in iterator:
|
| 68 |
+
if path.endswith('.dylib'):
|
| 69 |
+
yield path[:-len('.dylib')] + suffix + '.dylib'
|
| 70 |
+
else:
|
| 71 |
+
yield path + suffix
|
| 72 |
+
yield path
|
| 73 |
+
return _inject()
|
| 74 |
+
|
| 75 |
+
def dyld_override_search(name, env=None):
|
| 76 |
+
# If DYLD_FRAMEWORK_PATH is set and this dylib_name is a
|
| 77 |
+
# framework name, use the first file that exists in the framework
|
| 78 |
+
# path if any. If there is none go on to search the DYLD_LIBRARY_PATH
|
| 79 |
+
# if any.
|
| 80 |
+
|
| 81 |
+
framework = framework_info(name)
|
| 82 |
+
|
| 83 |
+
if framework is not None:
|
| 84 |
+
for path in dyld_framework_path(env):
|
| 85 |
+
yield os.path.join(path, framework['name'])
|
| 86 |
+
|
| 87 |
+
# If DYLD_LIBRARY_PATH is set then use the first file that exists
|
| 88 |
+
# in the path. If none use the original name.
|
| 89 |
+
for path in dyld_library_path(env):
|
| 90 |
+
yield os.path.join(path, os.path.basename(name))
|
| 91 |
+
|
| 92 |
+
def dyld_executable_path_search(name, executable_path=None):
|
| 93 |
+
# If we haven't done any searching and found a library and the
|
| 94 |
+
# dylib_name starts with "@executable_path/" then construct the
|
| 95 |
+
# library name.
|
| 96 |
+
if not executable_path:
|
| 97 |
+
import sys
|
| 98 |
+
if sys.prefix:
|
| 99 |
+
executable_path = os.path.join(sys.prefix, 'bin')
|
| 100 |
+
if name.startswith('@executable_path/') and executable_path is not None:
|
| 101 |
+
yield os.path.join(executable_path, name[len('@executable_path/'):])
|
| 102 |
+
|
| 103 |
+
def dyld_default_search(name, env=None):
|
| 104 |
+
yield name
|
| 105 |
+
|
| 106 |
+
framework = framework_info(name)
|
| 107 |
+
|
| 108 |
+
if framework is not None:
|
| 109 |
+
fallback_framework_path = dyld_fallback_framework_path(env)
|
| 110 |
+
for path in fallback_framework_path:
|
| 111 |
+
yield os.path.join(path, framework['name'])
|
| 112 |
+
|
| 113 |
+
fallback_library_path = dyld_fallback_library_path(env)
|
| 114 |
+
for path in fallback_library_path:
|
| 115 |
+
yield os.path.join(path, os.path.basename(name))
|
| 116 |
+
|
| 117 |
+
if framework is not None and not fallback_framework_path:
|
| 118 |
+
for path in DEFAULT_FRAMEWORK_FALLBACK:
|
| 119 |
+
yield os.path.join(path, framework['name'])
|
| 120 |
+
|
| 121 |
+
if not fallback_library_path:
|
| 122 |
+
for path in DEFAULT_LIBRARY_FALLBACK:
|
| 123 |
+
yield os.path.join(path, os.path.basename(name))
|
| 124 |
+
|
| 125 |
+
def dyld_find(name, executable_path=None, env=None):
|
| 126 |
+
"""
|
| 127 |
+
Find a library or framework using dyld semantics
|
| 128 |
+
"""
|
| 129 |
+
for path in dyld_image_suffix_search(chain(
|
| 130 |
+
dyld_override_search(name, env),
|
| 131 |
+
dyld_executable_path_search(name, executable_path),
|
| 132 |
+
dyld_default_search(name, env),
|
| 133 |
+
), env):
|
| 134 |
+
|
| 135 |
+
if os.path.isfile(path):
|
| 136 |
+
return path
|
| 137 |
+
try:
|
| 138 |
+
if _dyld_shared_cache_contains_path(path):
|
| 139 |
+
return path
|
| 140 |
+
except NotImplementedError:
|
| 141 |
+
pass
|
| 142 |
+
|
| 143 |
+
raise ValueError("dylib %s could not be found" % (name,))
|
| 144 |
+
|
| 145 |
+
def framework_find(fn, executable_path=None, env=None):
|
| 146 |
+
"""
|
| 147 |
+
Find a framework using dyld semantics in a very loose manner.
|
| 148 |
+
|
| 149 |
+
Will take input such as:
|
| 150 |
+
Python
|
| 151 |
+
Python.framework
|
| 152 |
+
Python.framework/Versions/Current
|
| 153 |
+
"""
|
| 154 |
+
error = None
|
| 155 |
+
try:
|
| 156 |
+
return dyld_find(fn, executable_path=executable_path, env=env)
|
| 157 |
+
except ValueError as e:
|
| 158 |
+
error = e
|
| 159 |
+
fmwk_index = fn.rfind('.framework')
|
| 160 |
+
if fmwk_index == -1:
|
| 161 |
+
fmwk_index = len(fn)
|
| 162 |
+
fn += '.framework'
|
| 163 |
+
fn = os.path.join(fn, os.path.basename(fn[:fmwk_index]))
|
| 164 |
+
try:
|
| 165 |
+
return dyld_find(fn, executable_path=executable_path, env=env)
|
| 166 |
+
except ValueError:
|
| 167 |
+
raise error
|
| 168 |
+
finally:
|
| 169 |
+
error = None
|
| 170 |
+
|
| 171 |
+
def test_dyld_find():
|
| 172 |
+
env = {}
|
| 173 |
+
assert dyld_find('libSystem.dylib') == '/usr/lib/libSystem.dylib'
|
| 174 |
+
assert dyld_find('System.framework/System') == '/System/Library/Frameworks/System.framework/System'
|
| 175 |
+
|
| 176 |
+
if __name__ == '__main__':
|
| 177 |
+
test_dyld_find()
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/ctypes/macholib/dylib.py
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Generic dylib path manipulation
|
| 3 |
+
"""
|
| 4 |
+
|
| 5 |
+
import re
|
| 6 |
+
|
| 7 |
+
__all__ = ['dylib_info']
|
| 8 |
+
|
| 9 |
+
DYLIB_RE = re.compile(r"""(?x)
|
| 10 |
+
(?P<location>^.*)(?:^|/)
|
| 11 |
+
(?P<name>
|
| 12 |
+
(?P<shortname>\w+?)
|
| 13 |
+
(?:\.(?P<version>[^._]+))?
|
| 14 |
+
(?:_(?P<suffix>[^._]+))?
|
| 15 |
+
\.dylib$
|
| 16 |
+
)
|
| 17 |
+
""")
|
| 18 |
+
|
| 19 |
+
def dylib_info(filename):
|
| 20 |
+
"""
|
| 21 |
+
A dylib name can take one of the following four forms:
|
| 22 |
+
Location/Name.SomeVersion_Suffix.dylib
|
| 23 |
+
Location/Name.SomeVersion.dylib
|
| 24 |
+
Location/Name_Suffix.dylib
|
| 25 |
+
Location/Name.dylib
|
| 26 |
+
|
| 27 |
+
returns None if not found or a mapping equivalent to:
|
| 28 |
+
dict(
|
| 29 |
+
location='Location',
|
| 30 |
+
name='Name.SomeVersion_Suffix.dylib',
|
| 31 |
+
shortname='Name',
|
| 32 |
+
version='SomeVersion',
|
| 33 |
+
suffix='Suffix',
|
| 34 |
+
)
|
| 35 |
+
|
| 36 |
+
Note that SomeVersion and Suffix are optional and may be None
|
| 37 |
+
if not present.
|
| 38 |
+
"""
|
| 39 |
+
is_dylib = DYLIB_RE.match(filename)
|
| 40 |
+
if not is_dylib:
|
| 41 |
+
return None
|
| 42 |
+
return is_dylib.groupdict()
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
def test_dylib_info():
|
| 46 |
+
def d(location=None, name=None, shortname=None, version=None, suffix=None):
|
| 47 |
+
return dict(
|
| 48 |
+
location=location,
|
| 49 |
+
name=name,
|
| 50 |
+
shortname=shortname,
|
| 51 |
+
version=version,
|
| 52 |
+
suffix=suffix
|
| 53 |
+
)
|
| 54 |
+
assert dylib_info('completely/invalid') is None
|
| 55 |
+
assert dylib_info('completely/invalide_debug') is None
|
| 56 |
+
assert dylib_info('P/Foo.dylib') == d('P', 'Foo.dylib', 'Foo')
|
| 57 |
+
assert dylib_info('P/Foo_debug.dylib') == d('P', 'Foo_debug.dylib', 'Foo', suffix='debug')
|
| 58 |
+
assert dylib_info('P/Foo.A.dylib') == d('P', 'Foo.A.dylib', 'Foo', 'A')
|
| 59 |
+
assert dylib_info('P/Foo_debug.A.dylib') == d('P', 'Foo_debug.A.dylib', 'Foo_debug', 'A')
|
| 60 |
+
assert dylib_info('P/Foo.A_debug.dylib') == d('P', 'Foo.A_debug.dylib', 'Foo', 'A', 'debug')
|
| 61 |
+
|
| 62 |
+
if __name__ == '__main__':
|
| 63 |
+
test_dylib_info()
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/ctypes/macholib/fetch_macholib
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/sh
|
| 2 |
+
svn export --force http://svn.red-bean.com/bob/macholib/trunk/macholib/ .
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/ctypes/macholib/fetch_macholib.bat
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
svn export --force http://svn.red-bean.com/bob/macholib/trunk/macholib/ .
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/ctypes/macholib/framework.py
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Generic framework path manipulation
|
| 3 |
+
"""
|
| 4 |
+
|
| 5 |
+
import re
|
| 6 |
+
|
| 7 |
+
__all__ = ['framework_info']
|
| 8 |
+
|
| 9 |
+
STRICT_FRAMEWORK_RE = re.compile(r"""(?x)
|
| 10 |
+
(?P<location>^.*)(?:^|/)
|
| 11 |
+
(?P<name>
|
| 12 |
+
(?P<shortname>\w+).framework/
|
| 13 |
+
(?:Versions/(?P<version>[^/]+)/)?
|
| 14 |
+
(?P=shortname)
|
| 15 |
+
(?:_(?P<suffix>[^_]+))?
|
| 16 |
+
)$
|
| 17 |
+
""")
|
| 18 |
+
|
| 19 |
+
def framework_info(filename):
|
| 20 |
+
"""
|
| 21 |
+
A framework name can take one of the following four forms:
|
| 22 |
+
Location/Name.framework/Versions/SomeVersion/Name_Suffix
|
| 23 |
+
Location/Name.framework/Versions/SomeVersion/Name
|
| 24 |
+
Location/Name.framework/Name_Suffix
|
| 25 |
+
Location/Name.framework/Name
|
| 26 |
+
|
| 27 |
+
returns None if not found, or a mapping equivalent to:
|
| 28 |
+
dict(
|
| 29 |
+
location='Location',
|
| 30 |
+
name='Name.framework/Versions/SomeVersion/Name_Suffix',
|
| 31 |
+
shortname='Name',
|
| 32 |
+
version='SomeVersion',
|
| 33 |
+
suffix='Suffix',
|
| 34 |
+
)
|
| 35 |
+
|
| 36 |
+
Note that SomeVersion and Suffix are optional and may be None
|
| 37 |
+
if not present
|
| 38 |
+
"""
|
| 39 |
+
is_framework = STRICT_FRAMEWORK_RE.match(filename)
|
| 40 |
+
if not is_framework:
|
| 41 |
+
return None
|
| 42 |
+
return is_framework.groupdict()
|
| 43 |
+
|
| 44 |
+
def test_framework_info():
|
| 45 |
+
def d(location=None, name=None, shortname=None, version=None, suffix=None):
|
| 46 |
+
return dict(
|
| 47 |
+
location=location,
|
| 48 |
+
name=name,
|
| 49 |
+
shortname=shortname,
|
| 50 |
+
version=version,
|
| 51 |
+
suffix=suffix
|
| 52 |
+
)
|
| 53 |
+
assert framework_info('completely/invalid') is None
|
| 54 |
+
assert framework_info('completely/invalid/_debug') is None
|
| 55 |
+
assert framework_info('P/F.framework') is None
|
| 56 |
+
assert framework_info('P/F.framework/_debug') is None
|
| 57 |
+
assert framework_info('P/F.framework/F') == d('P', 'F.framework/F', 'F')
|
| 58 |
+
assert framework_info('P/F.framework/F_debug') == d('P', 'F.framework/F_debug', 'F', suffix='debug')
|
| 59 |
+
assert framework_info('P/F.framework/Versions') is None
|
| 60 |
+
assert framework_info('P/F.framework/Versions/A') is None
|
| 61 |
+
assert framework_info('P/F.framework/Versions/A/F') == d('P', 'F.framework/Versions/A/F', 'F', 'A')
|
| 62 |
+
assert framework_info('P/F.framework/Versions/A/F_debug') == d('P', 'F.framework/Versions/A/F_debug', 'F', 'A', 'debug')
|
| 63 |
+
|
| 64 |
+
if __name__ == '__main__':
|
| 65 |
+
test_framework_info()
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/README
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
This directory contains the Distutils package.
|
| 2 |
+
|
| 3 |
+
There's a full documentation available at:
|
| 4 |
+
|
| 5 |
+
http://docs.python.org/distutils/
|
| 6 |
+
|
| 7 |
+
The Distutils-SIG web page is also a good starting point:
|
| 8 |
+
|
| 9 |
+
http://www.python.org/sigs/distutils-sig/
|
| 10 |
+
|
| 11 |
+
$Id$
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/__init__.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""distutils
|
| 2 |
+
|
| 3 |
+
The main package for the Python Module Distribution Utilities. Normally
|
| 4 |
+
used from a setup script as
|
| 5 |
+
|
| 6 |
+
from distutils.core import setup
|
| 7 |
+
|
| 8 |
+
setup (...)
|
| 9 |
+
"""
|
| 10 |
+
|
| 11 |
+
import sys
|
| 12 |
+
|
| 13 |
+
__version__ = sys.version[:sys.version.index(' ')]
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/_msvccompiler.py
ADDED
|
@@ -0,0 +1,543 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""distutils._msvccompiler
|
| 2 |
+
|
| 3 |
+
Contains MSVCCompiler, an implementation of the abstract CCompiler class
|
| 4 |
+
for Microsoft Visual Studio 2015.
|
| 5 |
+
|
| 6 |
+
The module is compatible with VS 2015 and later. You can find legacy support
|
| 7 |
+
for older versions in distutils.msvc9compiler and distutils.msvccompiler.
|
| 8 |
+
"""
|
| 9 |
+
|
| 10 |
+
# Written by Perry Stoll
|
| 11 |
+
# hacked by Robin Becker and Thomas Heller to do a better job of
|
| 12 |
+
# finding DevStudio (through the registry)
|
| 13 |
+
# ported to VS 2005 and VS 2008 by Christian Heimes
|
| 14 |
+
# ported to VS 2015 by Steve Dower
|
| 15 |
+
|
| 16 |
+
import os
|
| 17 |
+
import shutil
|
| 18 |
+
import stat
|
| 19 |
+
import subprocess
|
| 20 |
+
import winreg
|
| 21 |
+
|
| 22 |
+
from distutils.errors import DistutilsExecError, DistutilsPlatformError, \
|
| 23 |
+
CompileError, LibError, LinkError
|
| 24 |
+
from distutils.ccompiler import CCompiler, gen_lib_options
|
| 25 |
+
from distutils import log
|
| 26 |
+
from distutils.util import get_platform
|
| 27 |
+
|
| 28 |
+
from itertools import count
|
| 29 |
+
|
| 30 |
+
def _find_vc2015():
|
| 31 |
+
try:
|
| 32 |
+
key = winreg.OpenKeyEx(
|
| 33 |
+
winreg.HKEY_LOCAL_MACHINE,
|
| 34 |
+
r"Software\Microsoft\VisualStudio\SxS\VC7",
|
| 35 |
+
access=winreg.KEY_READ | winreg.KEY_WOW64_32KEY
|
| 36 |
+
)
|
| 37 |
+
except OSError:
|
| 38 |
+
log.debug("Visual C++ is not registered")
|
| 39 |
+
return None, None
|
| 40 |
+
|
| 41 |
+
best_version = 0
|
| 42 |
+
best_dir = None
|
| 43 |
+
with key:
|
| 44 |
+
for i in count():
|
| 45 |
+
try:
|
| 46 |
+
v, vc_dir, vt = winreg.EnumValue(key, i)
|
| 47 |
+
except OSError:
|
| 48 |
+
break
|
| 49 |
+
if v and vt == winreg.REG_SZ and os.path.isdir(vc_dir):
|
| 50 |
+
try:
|
| 51 |
+
version = int(float(v))
|
| 52 |
+
except (ValueError, TypeError):
|
| 53 |
+
continue
|
| 54 |
+
if version >= 14 and version > best_version:
|
| 55 |
+
best_version, best_dir = version, vc_dir
|
| 56 |
+
return best_version, best_dir
|
| 57 |
+
|
| 58 |
+
def _find_vc2017():
|
| 59 |
+
"""Returns "15, path" based on the result of invoking vswhere.exe
|
| 60 |
+
If no install is found, returns "None, None"
|
| 61 |
+
|
| 62 |
+
The version is returned to avoid unnecessarily changing the function
|
| 63 |
+
result. It may be ignored when the path is not None.
|
| 64 |
+
|
| 65 |
+
If vswhere.exe is not available, by definition, VS 2017 is not
|
| 66 |
+
installed.
|
| 67 |
+
"""
|
| 68 |
+
import json
|
| 69 |
+
|
| 70 |
+
root = os.environ.get("ProgramFiles(x86)") or os.environ.get("ProgramFiles")
|
| 71 |
+
if not root:
|
| 72 |
+
return None, None
|
| 73 |
+
|
| 74 |
+
try:
|
| 75 |
+
path = subprocess.check_output([
|
| 76 |
+
os.path.join(root, "Microsoft Visual Studio", "Installer", "vswhere.exe"),
|
| 77 |
+
"-latest",
|
| 78 |
+
"-prerelease",
|
| 79 |
+
"-requires", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64",
|
| 80 |
+
"-property", "installationPath",
|
| 81 |
+
"-products", "*",
|
| 82 |
+
], encoding="mbcs", errors="strict").strip()
|
| 83 |
+
except (subprocess.CalledProcessError, OSError, UnicodeDecodeError):
|
| 84 |
+
return None, None
|
| 85 |
+
|
| 86 |
+
path = os.path.join(path, "VC", "Auxiliary", "Build")
|
| 87 |
+
if os.path.isdir(path):
|
| 88 |
+
return 15, path
|
| 89 |
+
|
| 90 |
+
return None, None
|
| 91 |
+
|
| 92 |
+
PLAT_SPEC_TO_RUNTIME = {
|
| 93 |
+
'x86' : 'x86',
|
| 94 |
+
'x86_amd64' : 'x64',
|
| 95 |
+
'x86_arm' : 'arm',
|
| 96 |
+
'x86_arm64' : 'arm64'
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
def _find_vcvarsall(plat_spec):
|
| 100 |
+
# bpo-38597: Removed vcruntime return value
|
| 101 |
+
_, best_dir = _find_vc2017()
|
| 102 |
+
|
| 103 |
+
if not best_dir:
|
| 104 |
+
best_version, best_dir = _find_vc2015()
|
| 105 |
+
|
| 106 |
+
if not best_dir:
|
| 107 |
+
log.debug("No suitable Visual C++ version found")
|
| 108 |
+
return None, None
|
| 109 |
+
|
| 110 |
+
vcvarsall = os.path.join(best_dir, "vcvarsall.bat")
|
| 111 |
+
if not os.path.isfile(vcvarsall):
|
| 112 |
+
log.debug("%s cannot be found", vcvarsall)
|
| 113 |
+
return None, None
|
| 114 |
+
|
| 115 |
+
return vcvarsall, None
|
| 116 |
+
|
| 117 |
+
def _get_vc_env(plat_spec):
|
| 118 |
+
if os.getenv("DISTUTILS_USE_SDK"):
|
| 119 |
+
return {
|
| 120 |
+
key.lower(): value
|
| 121 |
+
for key, value in os.environ.items()
|
| 122 |
+
}
|
| 123 |
+
|
| 124 |
+
vcvarsall, _ = _find_vcvarsall(plat_spec)
|
| 125 |
+
if not vcvarsall:
|
| 126 |
+
raise DistutilsPlatformError("Unable to find vcvarsall.bat")
|
| 127 |
+
|
| 128 |
+
try:
|
| 129 |
+
out = subprocess.check_output(
|
| 130 |
+
'cmd /u /c "{}" {} && set'.format(vcvarsall, plat_spec),
|
| 131 |
+
stderr=subprocess.STDOUT,
|
| 132 |
+
).decode('utf-16le', errors='replace')
|
| 133 |
+
except subprocess.CalledProcessError as exc:
|
| 134 |
+
log.error(exc.output)
|
| 135 |
+
raise DistutilsPlatformError("Error executing {}"
|
| 136 |
+
.format(exc.cmd))
|
| 137 |
+
|
| 138 |
+
env = {
|
| 139 |
+
key.lower(): value
|
| 140 |
+
for key, _, value in
|
| 141 |
+
(line.partition('=') for line in out.splitlines())
|
| 142 |
+
if key and value
|
| 143 |
+
}
|
| 144 |
+
|
| 145 |
+
return env
|
| 146 |
+
|
| 147 |
+
def _find_exe(exe, paths=None):
|
| 148 |
+
"""Return path to an MSVC executable program.
|
| 149 |
+
|
| 150 |
+
Tries to find the program in several places: first, one of the
|
| 151 |
+
MSVC program search paths from the registry; next, the directories
|
| 152 |
+
in the PATH environment variable. If any of those work, return an
|
| 153 |
+
absolute path that is known to exist. If none of them work, just
|
| 154 |
+
return the original program name, 'exe'.
|
| 155 |
+
"""
|
| 156 |
+
if not paths:
|
| 157 |
+
paths = os.getenv('path').split(os.pathsep)
|
| 158 |
+
for p in paths:
|
| 159 |
+
fn = os.path.join(os.path.abspath(p), exe)
|
| 160 |
+
if os.path.isfile(fn):
|
| 161 |
+
return fn
|
| 162 |
+
return exe
|
| 163 |
+
|
| 164 |
+
# A map keyed by get_platform() return values to values accepted by
|
| 165 |
+
# 'vcvarsall.bat'. Always cross-compile from x86 to work with the
|
| 166 |
+
# lighter-weight MSVC installs that do not include native 64-bit tools.
|
| 167 |
+
PLAT_TO_VCVARS = {
|
| 168 |
+
'win32' : 'x86',
|
| 169 |
+
'win-amd64' : 'x86_amd64',
|
| 170 |
+
'win-arm32' : 'x86_arm',
|
| 171 |
+
'win-arm64' : 'x86_arm64'
|
| 172 |
+
}
|
| 173 |
+
|
| 174 |
+
class MSVCCompiler(CCompiler) :
|
| 175 |
+
"""Concrete class that implements an interface to Microsoft Visual C++,
|
| 176 |
+
as defined by the CCompiler abstract class."""
|
| 177 |
+
|
| 178 |
+
compiler_type = 'msvc'
|
| 179 |
+
|
| 180 |
+
# Just set this so CCompiler's constructor doesn't barf. We currently
|
| 181 |
+
# don't use the 'set_executables()' bureaucracy provided by CCompiler,
|
| 182 |
+
# as it really isn't necessary for this sort of single-compiler class.
|
| 183 |
+
# Would be nice to have a consistent interface with UnixCCompiler,
|
| 184 |
+
# though, so it's worth thinking about.
|
| 185 |
+
executables = {}
|
| 186 |
+
|
| 187 |
+
# Private class data (need to distinguish C from C++ source for compiler)
|
| 188 |
+
_c_extensions = ['.c']
|
| 189 |
+
_cpp_extensions = ['.cc', '.cpp', '.cxx']
|
| 190 |
+
_rc_extensions = ['.rc']
|
| 191 |
+
_mc_extensions = ['.mc']
|
| 192 |
+
|
| 193 |
+
# Needed for the filename generation methods provided by the
|
| 194 |
+
# base class, CCompiler.
|
| 195 |
+
src_extensions = (_c_extensions + _cpp_extensions +
|
| 196 |
+
_rc_extensions + _mc_extensions)
|
| 197 |
+
res_extension = '.res'
|
| 198 |
+
obj_extension = '.obj'
|
| 199 |
+
static_lib_extension = '.lib'
|
| 200 |
+
shared_lib_extension = '.dll'
|
| 201 |
+
static_lib_format = shared_lib_format = '%s%s'
|
| 202 |
+
exe_extension = '.exe'
|
| 203 |
+
|
| 204 |
+
|
| 205 |
+
def __init__(self, verbose=0, dry_run=0, force=0):
|
| 206 |
+
CCompiler.__init__ (self, verbose, dry_run, force)
|
| 207 |
+
# target platform (.plat_name is consistent with 'bdist')
|
| 208 |
+
self.plat_name = None
|
| 209 |
+
self.initialized = False
|
| 210 |
+
|
| 211 |
+
def initialize(self, plat_name=None):
|
| 212 |
+
# multi-init means we would need to check platform same each time...
|
| 213 |
+
assert not self.initialized, "don't init multiple times"
|
| 214 |
+
if plat_name is None:
|
| 215 |
+
plat_name = get_platform()
|
| 216 |
+
# sanity check for platforms to prevent obscure errors later.
|
| 217 |
+
if plat_name not in PLAT_TO_VCVARS:
|
| 218 |
+
raise DistutilsPlatformError("--plat-name must be one of {}"
|
| 219 |
+
.format(tuple(PLAT_TO_VCVARS)))
|
| 220 |
+
|
| 221 |
+
# Get the vcvarsall.bat spec for the requested platform.
|
| 222 |
+
plat_spec = PLAT_TO_VCVARS[plat_name]
|
| 223 |
+
|
| 224 |
+
vc_env = _get_vc_env(plat_spec)
|
| 225 |
+
if not vc_env:
|
| 226 |
+
raise DistutilsPlatformError("Unable to find a compatible "
|
| 227 |
+
"Visual Studio installation.")
|
| 228 |
+
|
| 229 |
+
self._paths = vc_env.get('path', '')
|
| 230 |
+
paths = self._paths.split(os.pathsep)
|
| 231 |
+
self.cc = _find_exe("cl.exe", paths)
|
| 232 |
+
self.linker = _find_exe("link.exe", paths)
|
| 233 |
+
self.lib = _find_exe("lib.exe", paths)
|
| 234 |
+
self.rc = _find_exe("rc.exe", paths) # resource compiler
|
| 235 |
+
self.mc = _find_exe("mc.exe", paths) # message compiler
|
| 236 |
+
self.mt = _find_exe("mt.exe", paths) # message compiler
|
| 237 |
+
|
| 238 |
+
for dir in vc_env.get('include', '').split(os.pathsep):
|
| 239 |
+
if dir:
|
| 240 |
+
self.add_include_dir(dir.rstrip(os.sep))
|
| 241 |
+
|
| 242 |
+
for dir in vc_env.get('lib', '').split(os.pathsep):
|
| 243 |
+
if dir:
|
| 244 |
+
self.add_library_dir(dir.rstrip(os.sep))
|
| 245 |
+
|
| 246 |
+
self.preprocess_options = None
|
| 247 |
+
# bpo-38597: Always compile with dynamic linking
|
| 248 |
+
# Future releases of Python 3.x will include all past
|
| 249 |
+
# versions of vcruntime*.dll for compatibility.
|
| 250 |
+
self.compile_options = [
|
| 251 |
+
'/nologo', '/Ox', '/W3', '/GL', '/DNDEBUG', '/MD'
|
| 252 |
+
]
|
| 253 |
+
|
| 254 |
+
self.compile_options_debug = [
|
| 255 |
+
'/nologo', '/Od', '/MDd', '/Zi', '/W3', '/D_DEBUG'
|
| 256 |
+
]
|
| 257 |
+
|
| 258 |
+
ldflags = [
|
| 259 |
+
'/nologo', '/INCREMENTAL:NO', '/LTCG'
|
| 260 |
+
]
|
| 261 |
+
|
| 262 |
+
ldflags_debug = [
|
| 263 |
+
'/nologo', '/INCREMENTAL:NO', '/LTCG', '/DEBUG:FULL'
|
| 264 |
+
]
|
| 265 |
+
|
| 266 |
+
self.ldflags_exe = [*ldflags, '/MANIFEST:EMBED,ID=1']
|
| 267 |
+
self.ldflags_exe_debug = [*ldflags_debug, '/MANIFEST:EMBED,ID=1']
|
| 268 |
+
self.ldflags_shared = [*ldflags, '/DLL', '/MANIFEST:EMBED,ID=2', '/MANIFESTUAC:NO']
|
| 269 |
+
self.ldflags_shared_debug = [*ldflags_debug, '/DLL', '/MANIFEST:EMBED,ID=2', '/MANIFESTUAC:NO']
|
| 270 |
+
self.ldflags_static = [*ldflags]
|
| 271 |
+
self.ldflags_static_debug = [*ldflags_debug]
|
| 272 |
+
|
| 273 |
+
self._ldflags = {
|
| 274 |
+
(CCompiler.EXECUTABLE, None): self.ldflags_exe,
|
| 275 |
+
(CCompiler.EXECUTABLE, False): self.ldflags_exe,
|
| 276 |
+
(CCompiler.EXECUTABLE, True): self.ldflags_exe_debug,
|
| 277 |
+
(CCompiler.SHARED_OBJECT, None): self.ldflags_shared,
|
| 278 |
+
(CCompiler.SHARED_OBJECT, False): self.ldflags_shared,
|
| 279 |
+
(CCompiler.SHARED_OBJECT, True): self.ldflags_shared_debug,
|
| 280 |
+
(CCompiler.SHARED_LIBRARY, None): self.ldflags_static,
|
| 281 |
+
(CCompiler.SHARED_LIBRARY, False): self.ldflags_static,
|
| 282 |
+
(CCompiler.SHARED_LIBRARY, True): self.ldflags_static_debug,
|
| 283 |
+
}
|
| 284 |
+
|
| 285 |
+
self.initialized = True
|
| 286 |
+
|
| 287 |
+
# -- Worker methods ------------------------------------------------
|
| 288 |
+
|
| 289 |
+
def object_filenames(self,
|
| 290 |
+
source_filenames,
|
| 291 |
+
strip_dir=0,
|
| 292 |
+
output_dir=''):
|
| 293 |
+
ext_map = {
|
| 294 |
+
**{ext: self.obj_extension for ext in self.src_extensions},
|
| 295 |
+
**{ext: self.res_extension for ext in self._rc_extensions + self._mc_extensions},
|
| 296 |
+
}
|
| 297 |
+
|
| 298 |
+
output_dir = output_dir or ''
|
| 299 |
+
|
| 300 |
+
def make_out_path(p):
|
| 301 |
+
base, ext = os.path.splitext(p)
|
| 302 |
+
if strip_dir:
|
| 303 |
+
base = os.path.basename(base)
|
| 304 |
+
else:
|
| 305 |
+
_, base = os.path.splitdrive(base)
|
| 306 |
+
if base.startswith((os.path.sep, os.path.altsep)):
|
| 307 |
+
base = base[1:]
|
| 308 |
+
try:
|
| 309 |
+
# XXX: This may produce absurdly long paths. We should check
|
| 310 |
+
# the length of the result and trim base until we fit within
|
| 311 |
+
# 260 characters.
|
| 312 |
+
return os.path.join(output_dir, base + ext_map[ext])
|
| 313 |
+
except LookupError:
|
| 314 |
+
# Better to raise an exception instead of silently continuing
|
| 315 |
+
# and later complain about sources and targets having
|
| 316 |
+
# different lengths
|
| 317 |
+
raise CompileError("Don't know how to compile {}".format(p))
|
| 318 |
+
|
| 319 |
+
return list(map(make_out_path, source_filenames))
|
| 320 |
+
|
| 321 |
+
|
| 322 |
+
def compile(self, sources,
|
| 323 |
+
output_dir=None, macros=None, include_dirs=None, debug=0,
|
| 324 |
+
extra_preargs=None, extra_postargs=None, depends=None):
|
| 325 |
+
|
| 326 |
+
if not self.initialized:
|
| 327 |
+
self.initialize()
|
| 328 |
+
compile_info = self._setup_compile(output_dir, macros, include_dirs,
|
| 329 |
+
sources, depends, extra_postargs)
|
| 330 |
+
macros, objects, extra_postargs, pp_opts, build = compile_info
|
| 331 |
+
|
| 332 |
+
compile_opts = extra_preargs or []
|
| 333 |
+
compile_opts.append('/c')
|
| 334 |
+
if debug:
|
| 335 |
+
compile_opts.extend(self.compile_options_debug)
|
| 336 |
+
else:
|
| 337 |
+
compile_opts.extend(self.compile_options)
|
| 338 |
+
|
| 339 |
+
|
| 340 |
+
add_cpp_opts = False
|
| 341 |
+
|
| 342 |
+
for obj in objects:
|
| 343 |
+
try:
|
| 344 |
+
src, ext = build[obj]
|
| 345 |
+
except KeyError:
|
| 346 |
+
continue
|
| 347 |
+
if debug:
|
| 348 |
+
# pass the full pathname to MSVC in debug mode,
|
| 349 |
+
# this allows the debugger to find the source file
|
| 350 |
+
# without asking the user to browse for it
|
| 351 |
+
src = os.path.abspath(src)
|
| 352 |
+
|
| 353 |
+
if ext in self._c_extensions:
|
| 354 |
+
input_opt = "/Tc" + src
|
| 355 |
+
elif ext in self._cpp_extensions:
|
| 356 |
+
input_opt = "/Tp" + src
|
| 357 |
+
add_cpp_opts = True
|
| 358 |
+
elif ext in self._rc_extensions:
|
| 359 |
+
# compile .RC to .RES file
|
| 360 |
+
input_opt = src
|
| 361 |
+
output_opt = "/fo" + obj
|
| 362 |
+
try:
|
| 363 |
+
self.spawn([self.rc] + pp_opts + [output_opt, input_opt])
|
| 364 |
+
except DistutilsExecError as msg:
|
| 365 |
+
raise CompileError(msg)
|
| 366 |
+
continue
|
| 367 |
+
elif ext in self._mc_extensions:
|
| 368 |
+
# Compile .MC to .RC file to .RES file.
|
| 369 |
+
# * '-h dir' specifies the directory for the
|
| 370 |
+
# generated include file
|
| 371 |
+
# * '-r dir' specifies the target directory of the
|
| 372 |
+
# generated RC file and the binary message resource
|
| 373 |
+
# it includes
|
| 374 |
+
#
|
| 375 |
+
# For now (since there are no options to change this),
|
| 376 |
+
# we use the source-directory for the include file and
|
| 377 |
+
# the build directory for the RC file and message
|
| 378 |
+
# resources. This works at least for win32all.
|
| 379 |
+
h_dir = os.path.dirname(src)
|
| 380 |
+
rc_dir = os.path.dirname(obj)
|
| 381 |
+
try:
|
| 382 |
+
# first compile .MC to .RC and .H file
|
| 383 |
+
self.spawn([self.mc, '-h', h_dir, '-r', rc_dir, src])
|
| 384 |
+
base, _ = os.path.splitext(os.path.basename (src))
|
| 385 |
+
rc_file = os.path.join(rc_dir, base + '.rc')
|
| 386 |
+
# then compile .RC to .RES file
|
| 387 |
+
self.spawn([self.rc, "/fo" + obj, rc_file])
|
| 388 |
+
|
| 389 |
+
except DistutilsExecError as msg:
|
| 390 |
+
raise CompileError(msg)
|
| 391 |
+
continue
|
| 392 |
+
else:
|
| 393 |
+
# how to handle this file?
|
| 394 |
+
raise CompileError("Don't know how to compile {} to {}"
|
| 395 |
+
.format(src, obj))
|
| 396 |
+
|
| 397 |
+
args = [self.cc] + compile_opts + pp_opts
|
| 398 |
+
if add_cpp_opts:
|
| 399 |
+
args.append('/EHsc')
|
| 400 |
+
args.append(input_opt)
|
| 401 |
+
args.append("/Fo" + obj)
|
| 402 |
+
args.extend(extra_postargs)
|
| 403 |
+
|
| 404 |
+
try:
|
| 405 |
+
self.spawn(args)
|
| 406 |
+
except DistutilsExecError as msg:
|
| 407 |
+
raise CompileError(msg)
|
| 408 |
+
|
| 409 |
+
return objects
|
| 410 |
+
|
| 411 |
+
|
| 412 |
+
def create_static_lib(self,
|
| 413 |
+
objects,
|
| 414 |
+
output_libname,
|
| 415 |
+
output_dir=None,
|
| 416 |
+
debug=0,
|
| 417 |
+
target_lang=None):
|
| 418 |
+
|
| 419 |
+
if not self.initialized:
|
| 420 |
+
self.initialize()
|
| 421 |
+
objects, output_dir = self._fix_object_args(objects, output_dir)
|
| 422 |
+
output_filename = self.library_filename(output_libname,
|
| 423 |
+
output_dir=output_dir)
|
| 424 |
+
|
| 425 |
+
if self._need_link(objects, output_filename):
|
| 426 |
+
lib_args = objects + ['/OUT:' + output_filename]
|
| 427 |
+
if debug:
|
| 428 |
+
pass # XXX what goes here?
|
| 429 |
+
try:
|
| 430 |
+
log.debug('Executing "%s" %s', self.lib, ' '.join(lib_args))
|
| 431 |
+
self.spawn([self.lib] + lib_args)
|
| 432 |
+
except DistutilsExecError as msg:
|
| 433 |
+
raise LibError(msg)
|
| 434 |
+
else:
|
| 435 |
+
log.debug("skipping %s (up-to-date)", output_filename)
|
| 436 |
+
|
| 437 |
+
|
| 438 |
+
def link(self,
|
| 439 |
+
target_desc,
|
| 440 |
+
objects,
|
| 441 |
+
output_filename,
|
| 442 |
+
output_dir=None,
|
| 443 |
+
libraries=None,
|
| 444 |
+
library_dirs=None,
|
| 445 |
+
runtime_library_dirs=None,
|
| 446 |
+
export_symbols=None,
|
| 447 |
+
debug=0,
|
| 448 |
+
extra_preargs=None,
|
| 449 |
+
extra_postargs=None,
|
| 450 |
+
build_temp=None,
|
| 451 |
+
target_lang=None):
|
| 452 |
+
|
| 453 |
+
if not self.initialized:
|
| 454 |
+
self.initialize()
|
| 455 |
+
objects, output_dir = self._fix_object_args(objects, output_dir)
|
| 456 |
+
fixed_args = self._fix_lib_args(libraries, library_dirs,
|
| 457 |
+
runtime_library_dirs)
|
| 458 |
+
libraries, library_dirs, runtime_library_dirs = fixed_args
|
| 459 |
+
|
| 460 |
+
if runtime_library_dirs:
|
| 461 |
+
self.warn("I don't know what to do with 'runtime_library_dirs': "
|
| 462 |
+
+ str(runtime_library_dirs))
|
| 463 |
+
|
| 464 |
+
lib_opts = gen_lib_options(self,
|
| 465 |
+
library_dirs, runtime_library_dirs,
|
| 466 |
+
libraries)
|
| 467 |
+
if output_dir is not None:
|
| 468 |
+
output_filename = os.path.join(output_dir, output_filename)
|
| 469 |
+
|
| 470 |
+
if self._need_link(objects, output_filename):
|
| 471 |
+
ldflags = self._ldflags[target_desc, debug]
|
| 472 |
+
|
| 473 |
+
export_opts = ["/EXPORT:" + sym for sym in (export_symbols or [])]
|
| 474 |
+
|
| 475 |
+
ld_args = (ldflags + lib_opts + export_opts +
|
| 476 |
+
objects + ['/OUT:' + output_filename])
|
| 477 |
+
|
| 478 |
+
# The MSVC linker generates .lib and .exp files, which cannot be
|
| 479 |
+
# suppressed by any linker switches. The .lib files may even be
|
| 480 |
+
# needed! Make sure they are generated in the temporary build
|
| 481 |
+
# directory. Since they have different names for debug and release
|
| 482 |
+
# builds, they can go into the same directory.
|
| 483 |
+
build_temp = os.path.dirname(objects[0])
|
| 484 |
+
if export_symbols is not None:
|
| 485 |
+
(dll_name, dll_ext) = os.path.splitext(
|
| 486 |
+
os.path.basename(output_filename))
|
| 487 |
+
implib_file = os.path.join(
|
| 488 |
+
build_temp,
|
| 489 |
+
self.library_filename(dll_name))
|
| 490 |
+
ld_args.append ('/IMPLIB:' + implib_file)
|
| 491 |
+
|
| 492 |
+
if extra_preargs:
|
| 493 |
+
ld_args[:0] = extra_preargs
|
| 494 |
+
if extra_postargs:
|
| 495 |
+
ld_args.extend(extra_postargs)
|
| 496 |
+
|
| 497 |
+
output_dir = os.path.dirname(os.path.abspath(output_filename))
|
| 498 |
+
self.mkpath(output_dir)
|
| 499 |
+
try:
|
| 500 |
+
log.debug('Executing "%s" %s', self.linker, ' '.join(ld_args))
|
| 501 |
+
self.spawn([self.linker] + ld_args)
|
| 502 |
+
except DistutilsExecError as msg:
|
| 503 |
+
raise LinkError(msg)
|
| 504 |
+
else:
|
| 505 |
+
log.debug("skipping %s (up-to-date)", output_filename)
|
| 506 |
+
|
| 507 |
+
def spawn(self, cmd):
|
| 508 |
+
old_path = os.getenv('path')
|
| 509 |
+
try:
|
| 510 |
+
os.environ['path'] = self._paths
|
| 511 |
+
return super().spawn(cmd)
|
| 512 |
+
finally:
|
| 513 |
+
os.environ['path'] = old_path
|
| 514 |
+
|
| 515 |
+
# -- Miscellaneous methods -----------------------------------------
|
| 516 |
+
# These are all used by the 'gen_lib_options() function, in
|
| 517 |
+
# ccompiler.py.
|
| 518 |
+
|
| 519 |
+
def library_dir_option(self, dir):
|
| 520 |
+
return "/LIBPATH:" + dir
|
| 521 |
+
|
| 522 |
+
def runtime_library_dir_option(self, dir):
|
| 523 |
+
raise DistutilsPlatformError(
|
| 524 |
+
"don't know how to set runtime library search path for MSVC")
|
| 525 |
+
|
| 526 |
+
def library_option(self, lib):
|
| 527 |
+
return self.library_filename(lib)
|
| 528 |
+
|
| 529 |
+
def find_library_file(self, dirs, lib, debug=0):
|
| 530 |
+
# Prefer a debugging library if found (and requested), but deal
|
| 531 |
+
# with it if we don't have one.
|
| 532 |
+
if debug:
|
| 533 |
+
try_names = [lib + "_d", lib]
|
| 534 |
+
else:
|
| 535 |
+
try_names = [lib]
|
| 536 |
+
for dir in dirs:
|
| 537 |
+
for name in try_names:
|
| 538 |
+
libfile = os.path.join(dir, self.library_filename(name))
|
| 539 |
+
if os.path.isfile(libfile):
|
| 540 |
+
return libfile
|
| 541 |
+
else:
|
| 542 |
+
# Oops, didn't find it in *any* of 'dirs'
|
| 543 |
+
return None
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/archive_util.py
ADDED
|
@@ -0,0 +1,256 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""distutils.archive_util
|
| 2 |
+
|
| 3 |
+
Utility functions for creating archive files (tarballs, zip files,
|
| 4 |
+
that sort of thing)."""
|
| 5 |
+
|
| 6 |
+
import os
|
| 7 |
+
from warnings import warn
|
| 8 |
+
import sys
|
| 9 |
+
|
| 10 |
+
try:
|
| 11 |
+
import zipfile
|
| 12 |
+
except ImportError:
|
| 13 |
+
zipfile = None
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
from distutils.errors import DistutilsExecError
|
| 17 |
+
from distutils.spawn import spawn
|
| 18 |
+
from distutils.dir_util import mkpath
|
| 19 |
+
from distutils import log
|
| 20 |
+
|
| 21 |
+
try:
|
| 22 |
+
from pwd import getpwnam
|
| 23 |
+
except ImportError:
|
| 24 |
+
getpwnam = None
|
| 25 |
+
|
| 26 |
+
try:
|
| 27 |
+
from grp import getgrnam
|
| 28 |
+
except ImportError:
|
| 29 |
+
getgrnam = None
|
| 30 |
+
|
| 31 |
+
def _get_gid(name):
|
| 32 |
+
"""Returns a gid, given a group name."""
|
| 33 |
+
if getgrnam is None or name is None:
|
| 34 |
+
return None
|
| 35 |
+
try:
|
| 36 |
+
result = getgrnam(name)
|
| 37 |
+
except KeyError:
|
| 38 |
+
result = None
|
| 39 |
+
if result is not None:
|
| 40 |
+
return result[2]
|
| 41 |
+
return None
|
| 42 |
+
|
| 43 |
+
def _get_uid(name):
|
| 44 |
+
"""Returns an uid, given a user name."""
|
| 45 |
+
if getpwnam is None or name is None:
|
| 46 |
+
return None
|
| 47 |
+
try:
|
| 48 |
+
result = getpwnam(name)
|
| 49 |
+
except KeyError:
|
| 50 |
+
result = None
|
| 51 |
+
if result is not None:
|
| 52 |
+
return result[2]
|
| 53 |
+
return None
|
| 54 |
+
|
| 55 |
+
def make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0,
|
| 56 |
+
owner=None, group=None):
|
| 57 |
+
"""Create a (possibly compressed) tar file from all the files under
|
| 58 |
+
'base_dir'.
|
| 59 |
+
|
| 60 |
+
'compress' must be "gzip" (the default), "bzip2", "xz", "compress", or
|
| 61 |
+
None. ("compress" will be deprecated in Python 3.2)
|
| 62 |
+
|
| 63 |
+
'owner' and 'group' can be used to define an owner and a group for the
|
| 64 |
+
archive that is being built. If not provided, the current owner and group
|
| 65 |
+
will be used.
|
| 66 |
+
|
| 67 |
+
The output tar file will be named 'base_dir' + ".tar", possibly plus
|
| 68 |
+
the appropriate compression extension (".gz", ".bz2", ".xz" or ".Z").
|
| 69 |
+
|
| 70 |
+
Returns the output filename.
|
| 71 |
+
"""
|
| 72 |
+
tar_compression = {'gzip': 'gz', 'bzip2': 'bz2', 'xz': 'xz', None: '',
|
| 73 |
+
'compress': ''}
|
| 74 |
+
compress_ext = {'gzip': '.gz', 'bzip2': '.bz2', 'xz': '.xz',
|
| 75 |
+
'compress': '.Z'}
|
| 76 |
+
|
| 77 |
+
# flags for compression program, each element of list will be an argument
|
| 78 |
+
if compress is not None and compress not in compress_ext.keys():
|
| 79 |
+
raise ValueError(
|
| 80 |
+
"bad value for 'compress': must be None, 'gzip', 'bzip2', "
|
| 81 |
+
"'xz' or 'compress'")
|
| 82 |
+
|
| 83 |
+
archive_name = base_name + '.tar'
|
| 84 |
+
if compress != 'compress':
|
| 85 |
+
archive_name += compress_ext.get(compress, '')
|
| 86 |
+
|
| 87 |
+
mkpath(os.path.dirname(archive_name), dry_run=dry_run)
|
| 88 |
+
|
| 89 |
+
# creating the tarball
|
| 90 |
+
import tarfile # late import so Python build itself doesn't break
|
| 91 |
+
|
| 92 |
+
log.info('Creating tar archive')
|
| 93 |
+
|
| 94 |
+
uid = _get_uid(owner)
|
| 95 |
+
gid = _get_gid(group)
|
| 96 |
+
|
| 97 |
+
def _set_uid_gid(tarinfo):
|
| 98 |
+
if gid is not None:
|
| 99 |
+
tarinfo.gid = gid
|
| 100 |
+
tarinfo.gname = group
|
| 101 |
+
if uid is not None:
|
| 102 |
+
tarinfo.uid = uid
|
| 103 |
+
tarinfo.uname = owner
|
| 104 |
+
return tarinfo
|
| 105 |
+
|
| 106 |
+
if not dry_run:
|
| 107 |
+
tar = tarfile.open(archive_name, 'w|%s' % tar_compression[compress])
|
| 108 |
+
try:
|
| 109 |
+
tar.add(base_dir, filter=_set_uid_gid)
|
| 110 |
+
finally:
|
| 111 |
+
tar.close()
|
| 112 |
+
|
| 113 |
+
# compression using `compress`
|
| 114 |
+
if compress == 'compress':
|
| 115 |
+
warn("'compress' will be deprecated.", PendingDeprecationWarning)
|
| 116 |
+
# the option varies depending on the platform
|
| 117 |
+
compressed_name = archive_name + compress_ext[compress]
|
| 118 |
+
if sys.platform == 'win32':
|
| 119 |
+
cmd = [compress, archive_name, compressed_name]
|
| 120 |
+
else:
|
| 121 |
+
cmd = [compress, '-f', archive_name]
|
| 122 |
+
spawn(cmd, dry_run=dry_run)
|
| 123 |
+
return compressed_name
|
| 124 |
+
|
| 125 |
+
return archive_name
|
| 126 |
+
|
| 127 |
+
def make_zipfile(base_name, base_dir, verbose=0, dry_run=0):
|
| 128 |
+
"""Create a zip file from all the files under 'base_dir'.
|
| 129 |
+
|
| 130 |
+
The output zip file will be named 'base_name' + ".zip". Uses either the
|
| 131 |
+
"zipfile" Python module (if available) or the InfoZIP "zip" utility
|
| 132 |
+
(if installed and found on the default search path). If neither tool is
|
| 133 |
+
available, raises DistutilsExecError. Returns the name of the output zip
|
| 134 |
+
file.
|
| 135 |
+
"""
|
| 136 |
+
zip_filename = base_name + ".zip"
|
| 137 |
+
mkpath(os.path.dirname(zip_filename), dry_run=dry_run)
|
| 138 |
+
|
| 139 |
+
# If zipfile module is not available, try spawning an external
|
| 140 |
+
# 'zip' command.
|
| 141 |
+
if zipfile is None:
|
| 142 |
+
if verbose:
|
| 143 |
+
zipoptions = "-r"
|
| 144 |
+
else:
|
| 145 |
+
zipoptions = "-rq"
|
| 146 |
+
|
| 147 |
+
try:
|
| 148 |
+
spawn(["zip", zipoptions, zip_filename, base_dir],
|
| 149 |
+
dry_run=dry_run)
|
| 150 |
+
except DistutilsExecError:
|
| 151 |
+
# XXX really should distinguish between "couldn't find
|
| 152 |
+
# external 'zip' command" and "zip failed".
|
| 153 |
+
raise DistutilsExecError(("unable to create zip file '%s': "
|
| 154 |
+
"could neither import the 'zipfile' module nor "
|
| 155 |
+
"find a standalone zip utility") % zip_filename)
|
| 156 |
+
|
| 157 |
+
else:
|
| 158 |
+
log.info("creating '%s' and adding '%s' to it",
|
| 159 |
+
zip_filename, base_dir)
|
| 160 |
+
|
| 161 |
+
if not dry_run:
|
| 162 |
+
try:
|
| 163 |
+
zip = zipfile.ZipFile(zip_filename, "w",
|
| 164 |
+
compression=zipfile.ZIP_DEFLATED)
|
| 165 |
+
except RuntimeError:
|
| 166 |
+
zip = zipfile.ZipFile(zip_filename, "w",
|
| 167 |
+
compression=zipfile.ZIP_STORED)
|
| 168 |
+
|
| 169 |
+
with zip:
|
| 170 |
+
if base_dir != os.curdir:
|
| 171 |
+
path = os.path.normpath(os.path.join(base_dir, ''))
|
| 172 |
+
zip.write(path, path)
|
| 173 |
+
log.info("adding '%s'", path)
|
| 174 |
+
for dirpath, dirnames, filenames in os.walk(base_dir):
|
| 175 |
+
for name in dirnames:
|
| 176 |
+
path = os.path.normpath(os.path.join(dirpath, name, ''))
|
| 177 |
+
zip.write(path, path)
|
| 178 |
+
log.info("adding '%s'", path)
|
| 179 |
+
for name in filenames:
|
| 180 |
+
path = os.path.normpath(os.path.join(dirpath, name))
|
| 181 |
+
if os.path.isfile(path):
|
| 182 |
+
zip.write(path, path)
|
| 183 |
+
log.info("adding '%s'", path)
|
| 184 |
+
|
| 185 |
+
return zip_filename
|
| 186 |
+
|
| 187 |
+
ARCHIVE_FORMATS = {
|
| 188 |
+
'gztar': (make_tarball, [('compress', 'gzip')], "gzip'ed tar-file"),
|
| 189 |
+
'bztar': (make_tarball, [('compress', 'bzip2')], "bzip2'ed tar-file"),
|
| 190 |
+
'xztar': (make_tarball, [('compress', 'xz')], "xz'ed tar-file"),
|
| 191 |
+
'ztar': (make_tarball, [('compress', 'compress')], "compressed tar file"),
|
| 192 |
+
'tar': (make_tarball, [('compress', None)], "uncompressed tar file"),
|
| 193 |
+
'zip': (make_zipfile, [],"ZIP file")
|
| 194 |
+
}
|
| 195 |
+
|
| 196 |
+
def check_archive_formats(formats):
|
| 197 |
+
"""Returns the first format from the 'format' list that is unknown.
|
| 198 |
+
|
| 199 |
+
If all formats are known, returns None
|
| 200 |
+
"""
|
| 201 |
+
for format in formats:
|
| 202 |
+
if format not in ARCHIVE_FORMATS:
|
| 203 |
+
return format
|
| 204 |
+
return None
|
| 205 |
+
|
| 206 |
+
def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
|
| 207 |
+
dry_run=0, owner=None, group=None):
|
| 208 |
+
"""Create an archive file (eg. zip or tar).
|
| 209 |
+
|
| 210 |
+
'base_name' is the name of the file to create, minus any format-specific
|
| 211 |
+
extension; 'format' is the archive format: one of "zip", "tar", "gztar",
|
| 212 |
+
"bztar", "xztar", or "ztar".
|
| 213 |
+
|
| 214 |
+
'root_dir' is a directory that will be the root directory of the
|
| 215 |
+
archive; ie. we typically chdir into 'root_dir' before creating the
|
| 216 |
+
archive. 'base_dir' is the directory where we start archiving from;
|
| 217 |
+
ie. 'base_dir' will be the common prefix of all files and
|
| 218 |
+
directories in the archive. 'root_dir' and 'base_dir' both default
|
| 219 |
+
to the current directory. Returns the name of the archive file.
|
| 220 |
+
|
| 221 |
+
'owner' and 'group' are used when creating a tar archive. By default,
|
| 222 |
+
uses the current owner and group.
|
| 223 |
+
"""
|
| 224 |
+
save_cwd = os.getcwd()
|
| 225 |
+
if root_dir is not None:
|
| 226 |
+
log.debug("changing into '%s'", root_dir)
|
| 227 |
+
base_name = os.path.abspath(base_name)
|
| 228 |
+
if not dry_run:
|
| 229 |
+
os.chdir(root_dir)
|
| 230 |
+
|
| 231 |
+
if base_dir is None:
|
| 232 |
+
base_dir = os.curdir
|
| 233 |
+
|
| 234 |
+
kwargs = {'dry_run': dry_run}
|
| 235 |
+
|
| 236 |
+
try:
|
| 237 |
+
format_info = ARCHIVE_FORMATS[format]
|
| 238 |
+
except KeyError:
|
| 239 |
+
raise ValueError("unknown archive format '%s'" % format)
|
| 240 |
+
|
| 241 |
+
func = format_info[0]
|
| 242 |
+
for arg, val in format_info[1]:
|
| 243 |
+
kwargs[arg] = val
|
| 244 |
+
|
| 245 |
+
if format != 'zip':
|
| 246 |
+
kwargs['owner'] = owner
|
| 247 |
+
kwargs['group'] = group
|
| 248 |
+
|
| 249 |
+
try:
|
| 250 |
+
filename = func(base_name, base_dir, **kwargs)
|
| 251 |
+
finally:
|
| 252 |
+
if root_dir is not None:
|
| 253 |
+
log.debug("changing back to '%s'", save_cwd)
|
| 254 |
+
os.chdir(save_cwd)
|
| 255 |
+
|
| 256 |
+
return filename
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/bcppcompiler.py
ADDED
|
@@ -0,0 +1,393 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""distutils.bcppcompiler
|
| 2 |
+
|
| 3 |
+
Contains BorlandCCompiler, an implementation of the abstract CCompiler class
|
| 4 |
+
for the Borland C++ compiler.
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
# This implementation by Lyle Johnson, based on the original msvccompiler.py
|
| 8 |
+
# module and using the directions originally published by Gordon Williams.
|
| 9 |
+
|
| 10 |
+
# XXX looks like there's a LOT of overlap between these two classes:
|
| 11 |
+
# someone should sit down and factor out the common code as
|
| 12 |
+
# WindowsCCompiler! --GPW
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
import os
|
| 16 |
+
from distutils.errors import \
|
| 17 |
+
DistutilsExecError, DistutilsPlatformError, \
|
| 18 |
+
CompileError, LibError, LinkError, UnknownFileError
|
| 19 |
+
from distutils.ccompiler import \
|
| 20 |
+
CCompiler, gen_preprocess_options, gen_lib_options
|
| 21 |
+
from distutils.file_util import write_file
|
| 22 |
+
from distutils.dep_util import newer
|
| 23 |
+
from distutils import log
|
| 24 |
+
|
| 25 |
+
class BCPPCompiler(CCompiler) :
|
| 26 |
+
"""Concrete class that implements an interface to the Borland C/C++
|
| 27 |
+
compiler, as defined by the CCompiler abstract class.
|
| 28 |
+
"""
|
| 29 |
+
|
| 30 |
+
compiler_type = 'bcpp'
|
| 31 |
+
|
| 32 |
+
# Just set this so CCompiler's constructor doesn't barf. We currently
|
| 33 |
+
# don't use the 'set_executables()' bureaucracy provided by CCompiler,
|
| 34 |
+
# as it really isn't necessary for this sort of single-compiler class.
|
| 35 |
+
# Would be nice to have a consistent interface with UnixCCompiler,
|
| 36 |
+
# though, so it's worth thinking about.
|
| 37 |
+
executables = {}
|
| 38 |
+
|
| 39 |
+
# Private class data (need to distinguish C from C++ source for compiler)
|
| 40 |
+
_c_extensions = ['.c']
|
| 41 |
+
_cpp_extensions = ['.cc', '.cpp', '.cxx']
|
| 42 |
+
|
| 43 |
+
# Needed for the filename generation methods provided by the
|
| 44 |
+
# base class, CCompiler.
|
| 45 |
+
src_extensions = _c_extensions + _cpp_extensions
|
| 46 |
+
obj_extension = '.obj'
|
| 47 |
+
static_lib_extension = '.lib'
|
| 48 |
+
shared_lib_extension = '.dll'
|
| 49 |
+
static_lib_format = shared_lib_format = '%s%s'
|
| 50 |
+
exe_extension = '.exe'
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
def __init__ (self,
|
| 54 |
+
verbose=0,
|
| 55 |
+
dry_run=0,
|
| 56 |
+
force=0):
|
| 57 |
+
|
| 58 |
+
CCompiler.__init__ (self, verbose, dry_run, force)
|
| 59 |
+
|
| 60 |
+
# These executables are assumed to all be in the path.
|
| 61 |
+
# Borland doesn't seem to use any special registry settings to
|
| 62 |
+
# indicate their installation locations.
|
| 63 |
+
|
| 64 |
+
self.cc = "bcc32.exe"
|
| 65 |
+
self.linker = "ilink32.exe"
|
| 66 |
+
self.lib = "tlib.exe"
|
| 67 |
+
|
| 68 |
+
self.preprocess_options = None
|
| 69 |
+
self.compile_options = ['/tWM', '/O2', '/q', '/g0']
|
| 70 |
+
self.compile_options_debug = ['/tWM', '/Od', '/q', '/g0']
|
| 71 |
+
|
| 72 |
+
self.ldflags_shared = ['/Tpd', '/Gn', '/q', '/x']
|
| 73 |
+
self.ldflags_shared_debug = ['/Tpd', '/Gn', '/q', '/x']
|
| 74 |
+
self.ldflags_static = []
|
| 75 |
+
self.ldflags_exe = ['/Gn', '/q', '/x']
|
| 76 |
+
self.ldflags_exe_debug = ['/Gn', '/q', '/x','/r']
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
# -- Worker methods ------------------------------------------------
|
| 80 |
+
|
| 81 |
+
def compile(self, sources,
|
| 82 |
+
output_dir=None, macros=None, include_dirs=None, debug=0,
|
| 83 |
+
extra_preargs=None, extra_postargs=None, depends=None):
|
| 84 |
+
|
| 85 |
+
macros, objects, extra_postargs, pp_opts, build = \
|
| 86 |
+
self._setup_compile(output_dir, macros, include_dirs, sources,
|
| 87 |
+
depends, extra_postargs)
|
| 88 |
+
compile_opts = extra_preargs or []
|
| 89 |
+
compile_opts.append ('-c')
|
| 90 |
+
if debug:
|
| 91 |
+
compile_opts.extend (self.compile_options_debug)
|
| 92 |
+
else:
|
| 93 |
+
compile_opts.extend (self.compile_options)
|
| 94 |
+
|
| 95 |
+
for obj in objects:
|
| 96 |
+
try:
|
| 97 |
+
src, ext = build[obj]
|
| 98 |
+
except KeyError:
|
| 99 |
+
continue
|
| 100 |
+
# XXX why do the normpath here?
|
| 101 |
+
src = os.path.normpath(src)
|
| 102 |
+
obj = os.path.normpath(obj)
|
| 103 |
+
# XXX _setup_compile() did a mkpath() too but before the normpath.
|
| 104 |
+
# Is it possible to skip the normpath?
|
| 105 |
+
self.mkpath(os.path.dirname(obj))
|
| 106 |
+
|
| 107 |
+
if ext == '.res':
|
| 108 |
+
# This is already a binary file -- skip it.
|
| 109 |
+
continue # the 'for' loop
|
| 110 |
+
if ext == '.rc':
|
| 111 |
+
# This needs to be compiled to a .res file -- do it now.
|
| 112 |
+
try:
|
| 113 |
+
self.spawn (["brcc32", "-fo", obj, src])
|
| 114 |
+
except DistutilsExecError as msg:
|
| 115 |
+
raise CompileError(msg)
|
| 116 |
+
continue # the 'for' loop
|
| 117 |
+
|
| 118 |
+
# The next two are both for the real compiler.
|
| 119 |
+
if ext in self._c_extensions:
|
| 120 |
+
input_opt = ""
|
| 121 |
+
elif ext in self._cpp_extensions:
|
| 122 |
+
input_opt = "-P"
|
| 123 |
+
else:
|
| 124 |
+
# Unknown file type -- no extra options. The compiler
|
| 125 |
+
# will probably fail, but let it just in case this is a
|
| 126 |
+
# file the compiler recognizes even if we don't.
|
| 127 |
+
input_opt = ""
|
| 128 |
+
|
| 129 |
+
output_opt = "-o" + obj
|
| 130 |
+
|
| 131 |
+
# Compiler command line syntax is: "bcc32 [options] file(s)".
|
| 132 |
+
# Note that the source file names must appear at the end of
|
| 133 |
+
# the command line.
|
| 134 |
+
try:
|
| 135 |
+
self.spawn ([self.cc] + compile_opts + pp_opts +
|
| 136 |
+
[input_opt, output_opt] +
|
| 137 |
+
extra_postargs + [src])
|
| 138 |
+
except DistutilsExecError as msg:
|
| 139 |
+
raise CompileError(msg)
|
| 140 |
+
|
| 141 |
+
return objects
|
| 142 |
+
|
| 143 |
+
# compile ()
|
| 144 |
+
|
| 145 |
+
|
| 146 |
+
def create_static_lib (self,
|
| 147 |
+
objects,
|
| 148 |
+
output_libname,
|
| 149 |
+
output_dir=None,
|
| 150 |
+
debug=0,
|
| 151 |
+
target_lang=None):
|
| 152 |
+
|
| 153 |
+
(objects, output_dir) = self._fix_object_args (objects, output_dir)
|
| 154 |
+
output_filename = \
|
| 155 |
+
self.library_filename (output_libname, output_dir=output_dir)
|
| 156 |
+
|
| 157 |
+
if self._need_link (objects, output_filename):
|
| 158 |
+
lib_args = [output_filename, '/u'] + objects
|
| 159 |
+
if debug:
|
| 160 |
+
pass # XXX what goes here?
|
| 161 |
+
try:
|
| 162 |
+
self.spawn ([self.lib] + lib_args)
|
| 163 |
+
except DistutilsExecError as msg:
|
| 164 |
+
raise LibError(msg)
|
| 165 |
+
else:
|
| 166 |
+
log.debug("skipping %s (up-to-date)", output_filename)
|
| 167 |
+
|
| 168 |
+
# create_static_lib ()
|
| 169 |
+
|
| 170 |
+
|
| 171 |
+
def link (self,
|
| 172 |
+
target_desc,
|
| 173 |
+
objects,
|
| 174 |
+
output_filename,
|
| 175 |
+
output_dir=None,
|
| 176 |
+
libraries=None,
|
| 177 |
+
library_dirs=None,
|
| 178 |
+
runtime_library_dirs=None,
|
| 179 |
+
export_symbols=None,
|
| 180 |
+
debug=0,
|
| 181 |
+
extra_preargs=None,
|
| 182 |
+
extra_postargs=None,
|
| 183 |
+
build_temp=None,
|
| 184 |
+
target_lang=None):
|
| 185 |
+
|
| 186 |
+
# XXX this ignores 'build_temp'! should follow the lead of
|
| 187 |
+
# msvccompiler.py
|
| 188 |
+
|
| 189 |
+
(objects, output_dir) = self._fix_object_args (objects, output_dir)
|
| 190 |
+
(libraries, library_dirs, runtime_library_dirs) = \
|
| 191 |
+
self._fix_lib_args (libraries, library_dirs, runtime_library_dirs)
|
| 192 |
+
|
| 193 |
+
if runtime_library_dirs:
|
| 194 |
+
log.warn("I don't know what to do with 'runtime_library_dirs': %s",
|
| 195 |
+
str(runtime_library_dirs))
|
| 196 |
+
|
| 197 |
+
if output_dir is not None:
|
| 198 |
+
output_filename = os.path.join (output_dir, output_filename)
|
| 199 |
+
|
| 200 |
+
if self._need_link (objects, output_filename):
|
| 201 |
+
|
| 202 |
+
# Figure out linker args based on type of target.
|
| 203 |
+
if target_desc == CCompiler.EXECUTABLE:
|
| 204 |
+
startup_obj = 'c0w32'
|
| 205 |
+
if debug:
|
| 206 |
+
ld_args = self.ldflags_exe_debug[:]
|
| 207 |
+
else:
|
| 208 |
+
ld_args = self.ldflags_exe[:]
|
| 209 |
+
else:
|
| 210 |
+
startup_obj = 'c0d32'
|
| 211 |
+
if debug:
|
| 212 |
+
ld_args = self.ldflags_shared_debug[:]
|
| 213 |
+
else:
|
| 214 |
+
ld_args = self.ldflags_shared[:]
|
| 215 |
+
|
| 216 |
+
|
| 217 |
+
# Create a temporary exports file for use by the linker
|
| 218 |
+
if export_symbols is None:
|
| 219 |
+
def_file = ''
|
| 220 |
+
else:
|
| 221 |
+
head, tail = os.path.split (output_filename)
|
| 222 |
+
modname, ext = os.path.splitext (tail)
|
| 223 |
+
temp_dir = os.path.dirname(objects[0]) # preserve tree structure
|
| 224 |
+
def_file = os.path.join (temp_dir, '%s.def' % modname)
|
| 225 |
+
contents = ['EXPORTS']
|
| 226 |
+
for sym in (export_symbols or []):
|
| 227 |
+
contents.append(' %s=_%s' % (sym, sym))
|
| 228 |
+
self.execute(write_file, (def_file, contents),
|
| 229 |
+
"writing %s" % def_file)
|
| 230 |
+
|
| 231 |
+
# Borland C++ has problems with '/' in paths
|
| 232 |
+
objects2 = map(os.path.normpath, objects)
|
| 233 |
+
# split objects in .obj and .res files
|
| 234 |
+
# Borland C++ needs them at different positions in the command line
|
| 235 |
+
objects = [startup_obj]
|
| 236 |
+
resources = []
|
| 237 |
+
for file in objects2:
|
| 238 |
+
(base, ext) = os.path.splitext(os.path.normcase(file))
|
| 239 |
+
if ext == '.res':
|
| 240 |
+
resources.append(file)
|
| 241 |
+
else:
|
| 242 |
+
objects.append(file)
|
| 243 |
+
|
| 244 |
+
|
| 245 |
+
for l in library_dirs:
|
| 246 |
+
ld_args.append("/L%s" % os.path.normpath(l))
|
| 247 |
+
ld_args.append("/L.") # we sometimes use relative paths
|
| 248 |
+
|
| 249 |
+
# list of object files
|
| 250 |
+
ld_args.extend(objects)
|
| 251 |
+
|
| 252 |
+
# XXX the command-line syntax for Borland C++ is a bit wonky;
|
| 253 |
+
# certain filenames are jammed together in one big string, but
|
| 254 |
+
# comma-delimited. This doesn't mesh too well with the
|
| 255 |
+
# Unix-centric attitude (with a DOS/Windows quoting hack) of
|
| 256 |
+
# 'spawn()', so constructing the argument list is a bit
|
| 257 |
+
# awkward. Note that doing the obvious thing and jamming all
|
| 258 |
+
# the filenames and commas into one argument would be wrong,
|
| 259 |
+
# because 'spawn()' would quote any filenames with spaces in
|
| 260 |
+
# them. Arghghh!. Apparently it works fine as coded...
|
| 261 |
+
|
| 262 |
+
# name of dll/exe file
|
| 263 |
+
ld_args.extend([',',output_filename])
|
| 264 |
+
# no map file and start libraries
|
| 265 |
+
ld_args.append(',,')
|
| 266 |
+
|
| 267 |
+
for lib in libraries:
|
| 268 |
+
# see if we find it and if there is a bcpp specific lib
|
| 269 |
+
# (xxx_bcpp.lib)
|
| 270 |
+
libfile = self.find_library_file(library_dirs, lib, debug)
|
| 271 |
+
if libfile is None:
|
| 272 |
+
ld_args.append(lib)
|
| 273 |
+
# probably a BCPP internal library -- don't warn
|
| 274 |
+
else:
|
| 275 |
+
# full name which prefers bcpp_xxx.lib over xxx.lib
|
| 276 |
+
ld_args.append(libfile)
|
| 277 |
+
|
| 278 |
+
# some default libraries
|
| 279 |
+
ld_args.append ('import32')
|
| 280 |
+
ld_args.append ('cw32mt')
|
| 281 |
+
|
| 282 |
+
# def file for export symbols
|
| 283 |
+
ld_args.extend([',',def_file])
|
| 284 |
+
# add resource files
|
| 285 |
+
ld_args.append(',')
|
| 286 |
+
ld_args.extend(resources)
|
| 287 |
+
|
| 288 |
+
|
| 289 |
+
if extra_preargs:
|
| 290 |
+
ld_args[:0] = extra_preargs
|
| 291 |
+
if extra_postargs:
|
| 292 |
+
ld_args.extend(extra_postargs)
|
| 293 |
+
|
| 294 |
+
self.mkpath (os.path.dirname (output_filename))
|
| 295 |
+
try:
|
| 296 |
+
self.spawn ([self.linker] + ld_args)
|
| 297 |
+
except DistutilsExecError as msg:
|
| 298 |
+
raise LinkError(msg)
|
| 299 |
+
|
| 300 |
+
else:
|
| 301 |
+
log.debug("skipping %s (up-to-date)", output_filename)
|
| 302 |
+
|
| 303 |
+
# link ()
|
| 304 |
+
|
| 305 |
+
# -- Miscellaneous methods -----------------------------------------
|
| 306 |
+
|
| 307 |
+
|
| 308 |
+
def find_library_file (self, dirs, lib, debug=0):
|
| 309 |
+
# List of effective library names to try, in order of preference:
|
| 310 |
+
# xxx_bcpp.lib is better than xxx.lib
|
| 311 |
+
# and xxx_d.lib is better than xxx.lib if debug is set
|
| 312 |
+
#
|
| 313 |
+
# The "_bcpp" suffix is to handle a Python installation for people
|
| 314 |
+
# with multiple compilers (primarily Distutils hackers, I suspect
|
| 315 |
+
# ;-). The idea is they'd have one static library for each
|
| 316 |
+
# compiler they care about, since (almost?) every Windows compiler
|
| 317 |
+
# seems to have a different format for static libraries.
|
| 318 |
+
if debug:
|
| 319 |
+
dlib = (lib + "_d")
|
| 320 |
+
try_names = (dlib + "_bcpp", lib + "_bcpp", dlib, lib)
|
| 321 |
+
else:
|
| 322 |
+
try_names = (lib + "_bcpp", lib)
|
| 323 |
+
|
| 324 |
+
for dir in dirs:
|
| 325 |
+
for name in try_names:
|
| 326 |
+
libfile = os.path.join(dir, self.library_filename(name))
|
| 327 |
+
if os.path.exists(libfile):
|
| 328 |
+
return libfile
|
| 329 |
+
else:
|
| 330 |
+
# Oops, didn't find it in *any* of 'dirs'
|
| 331 |
+
return None
|
| 332 |
+
|
| 333 |
+
# overwrite the one from CCompiler to support rc and res-files
|
| 334 |
+
def object_filenames (self,
|
| 335 |
+
source_filenames,
|
| 336 |
+
strip_dir=0,
|
| 337 |
+
output_dir=''):
|
| 338 |
+
if output_dir is None: output_dir = ''
|
| 339 |
+
obj_names = []
|
| 340 |
+
for src_name in source_filenames:
|
| 341 |
+
# use normcase to make sure '.rc' is really '.rc' and not '.RC'
|
| 342 |
+
(base, ext) = os.path.splitext (os.path.normcase(src_name))
|
| 343 |
+
if ext not in (self.src_extensions + ['.rc','.res']):
|
| 344 |
+
raise UnknownFileError("unknown file type '%s' (from '%s')" % \
|
| 345 |
+
(ext, src_name))
|
| 346 |
+
if strip_dir:
|
| 347 |
+
base = os.path.basename (base)
|
| 348 |
+
if ext == '.res':
|
| 349 |
+
# these can go unchanged
|
| 350 |
+
obj_names.append (os.path.join (output_dir, base + ext))
|
| 351 |
+
elif ext == '.rc':
|
| 352 |
+
# these need to be compiled to .res-files
|
| 353 |
+
obj_names.append (os.path.join (output_dir, base + '.res'))
|
| 354 |
+
else:
|
| 355 |
+
obj_names.append (os.path.join (output_dir,
|
| 356 |
+
base + self.obj_extension))
|
| 357 |
+
return obj_names
|
| 358 |
+
|
| 359 |
+
# object_filenames ()
|
| 360 |
+
|
| 361 |
+
def preprocess (self,
|
| 362 |
+
source,
|
| 363 |
+
output_file=None,
|
| 364 |
+
macros=None,
|
| 365 |
+
include_dirs=None,
|
| 366 |
+
extra_preargs=None,
|
| 367 |
+
extra_postargs=None):
|
| 368 |
+
|
| 369 |
+
(_, macros, include_dirs) = \
|
| 370 |
+
self._fix_compile_args(None, macros, include_dirs)
|
| 371 |
+
pp_opts = gen_preprocess_options(macros, include_dirs)
|
| 372 |
+
pp_args = ['cpp32.exe'] + pp_opts
|
| 373 |
+
if output_file is not None:
|
| 374 |
+
pp_args.append('-o' + output_file)
|
| 375 |
+
if extra_preargs:
|
| 376 |
+
pp_args[:0] = extra_preargs
|
| 377 |
+
if extra_postargs:
|
| 378 |
+
pp_args.extend(extra_postargs)
|
| 379 |
+
pp_args.append(source)
|
| 380 |
+
|
| 381 |
+
# We need to preprocess: either we're being forced to, or the
|
| 382 |
+
# source file is newer than the target (or the target doesn't
|
| 383 |
+
# exist).
|
| 384 |
+
if self.force or output_file is None or newer(source, output_file):
|
| 385 |
+
if output_file:
|
| 386 |
+
self.mkpath(os.path.dirname(output_file))
|
| 387 |
+
try:
|
| 388 |
+
self.spawn(pp_args)
|
| 389 |
+
except DistutilsExecError as msg:
|
| 390 |
+
print(msg)
|
| 391 |
+
raise CompileError(msg)
|
| 392 |
+
|
| 393 |
+
# preprocess()
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/ccompiler.py
ADDED
|
@@ -0,0 +1,1116 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""distutils.ccompiler
|
| 2 |
+
|
| 3 |
+
Contains CCompiler, an abstract base class that defines the interface
|
| 4 |
+
for the Distutils compiler abstraction model."""
|
| 5 |
+
|
| 6 |
+
import sys, os, re
|
| 7 |
+
from distutils.errors import *
|
| 8 |
+
from distutils.spawn import spawn
|
| 9 |
+
from distutils.file_util import move_file
|
| 10 |
+
from distutils.dir_util import mkpath
|
| 11 |
+
from distutils.dep_util import newer_pairwise, newer_group
|
| 12 |
+
from distutils.util import split_quoted, execute
|
| 13 |
+
from distutils import log
|
| 14 |
+
|
| 15 |
+
class CCompiler:
|
| 16 |
+
"""Abstract base class to define the interface that must be implemented
|
| 17 |
+
by real compiler classes. Also has some utility methods used by
|
| 18 |
+
several compiler classes.
|
| 19 |
+
|
| 20 |
+
The basic idea behind a compiler abstraction class is that each
|
| 21 |
+
instance can be used for all the compile/link steps in building a
|
| 22 |
+
single project. Thus, attributes common to all of those compile and
|
| 23 |
+
link steps -- include directories, macros to define, libraries to link
|
| 24 |
+
against, etc. -- are attributes of the compiler instance. To allow for
|
| 25 |
+
variability in how individual files are treated, most of those
|
| 26 |
+
attributes may be varied on a per-compilation or per-link basis.
|
| 27 |
+
"""
|
| 28 |
+
|
| 29 |
+
# 'compiler_type' is a class attribute that identifies this class. It
|
| 30 |
+
# keeps code that wants to know what kind of compiler it's dealing with
|
| 31 |
+
# from having to import all possible compiler classes just to do an
|
| 32 |
+
# 'isinstance'. In concrete CCompiler subclasses, 'compiler_type'
|
| 33 |
+
# should really, really be one of the keys of the 'compiler_class'
|
| 34 |
+
# dictionary (see below -- used by the 'new_compiler()' factory
|
| 35 |
+
# function) -- authors of new compiler interface classes are
|
| 36 |
+
# responsible for updating 'compiler_class'!
|
| 37 |
+
compiler_type = None
|
| 38 |
+
|
| 39 |
+
# XXX things not handled by this compiler abstraction model:
|
| 40 |
+
# * client can't provide additional options for a compiler,
|
| 41 |
+
# e.g. warning, optimization, debugging flags. Perhaps this
|
| 42 |
+
# should be the domain of concrete compiler abstraction classes
|
| 43 |
+
# (UnixCCompiler, MSVCCompiler, etc.) -- or perhaps the base
|
| 44 |
+
# class should have methods for the common ones.
|
| 45 |
+
# * can't completely override the include or library searchg
|
| 46 |
+
# path, ie. no "cc -I -Idir1 -Idir2" or "cc -L -Ldir1 -Ldir2".
|
| 47 |
+
# I'm not sure how widely supported this is even by Unix
|
| 48 |
+
# compilers, much less on other platforms. And I'm even less
|
| 49 |
+
# sure how useful it is; maybe for cross-compiling, but
|
| 50 |
+
# support for that is a ways off. (And anyways, cross
|
| 51 |
+
# compilers probably have a dedicated binary with the
|
| 52 |
+
# right paths compiled in. I hope.)
|
| 53 |
+
# * can't do really freaky things with the library list/library
|
| 54 |
+
# dirs, e.g. "-Ldir1 -lfoo -Ldir2 -lfoo" to link against
|
| 55 |
+
# different versions of libfoo.a in different locations. I
|
| 56 |
+
# think this is useless without the ability to null out the
|
| 57 |
+
# library search path anyways.
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
# Subclasses that rely on the standard filename generation methods
|
| 61 |
+
# implemented below should override these; see the comment near
|
| 62 |
+
# those methods ('object_filenames()' et. al.) for details:
|
| 63 |
+
src_extensions = None # list of strings
|
| 64 |
+
obj_extension = None # string
|
| 65 |
+
static_lib_extension = None
|
| 66 |
+
shared_lib_extension = None # string
|
| 67 |
+
static_lib_format = None # format string
|
| 68 |
+
shared_lib_format = None # prob. same as static_lib_format
|
| 69 |
+
exe_extension = None # string
|
| 70 |
+
|
| 71 |
+
# Default language settings. language_map is used to detect a source
|
| 72 |
+
# file or Extension target language, checking source filenames.
|
| 73 |
+
# language_order is used to detect the language precedence, when deciding
|
| 74 |
+
# what language to use when mixing source types. For example, if some
|
| 75 |
+
# extension has two files with ".c" extension, and one with ".cpp", it
|
| 76 |
+
# is still linked as c++.
|
| 77 |
+
language_map = {".c" : "c",
|
| 78 |
+
".cc" : "c++",
|
| 79 |
+
".cpp" : "c++",
|
| 80 |
+
".cxx" : "c++",
|
| 81 |
+
".m" : "objc",
|
| 82 |
+
}
|
| 83 |
+
language_order = ["c++", "objc", "c"]
|
| 84 |
+
|
| 85 |
+
def __init__(self, verbose=0, dry_run=0, force=0):
|
| 86 |
+
self.dry_run = dry_run
|
| 87 |
+
self.force = force
|
| 88 |
+
self.verbose = verbose
|
| 89 |
+
|
| 90 |
+
# 'output_dir': a common output directory for object, library,
|
| 91 |
+
# shared object, and shared library files
|
| 92 |
+
self.output_dir = None
|
| 93 |
+
|
| 94 |
+
# 'macros': a list of macro definitions (or undefinitions). A
|
| 95 |
+
# macro definition is a 2-tuple (name, value), where the value is
|
| 96 |
+
# either a string or None (no explicit value). A macro
|
| 97 |
+
# undefinition is a 1-tuple (name,).
|
| 98 |
+
self.macros = []
|
| 99 |
+
|
| 100 |
+
# 'include_dirs': a list of directories to search for include files
|
| 101 |
+
self.include_dirs = []
|
| 102 |
+
|
| 103 |
+
# 'libraries': a list of libraries to include in any link
|
| 104 |
+
# (library names, not filenames: eg. "foo" not "libfoo.a")
|
| 105 |
+
self.libraries = []
|
| 106 |
+
|
| 107 |
+
# 'library_dirs': a list of directories to search for libraries
|
| 108 |
+
self.library_dirs = []
|
| 109 |
+
|
| 110 |
+
# 'runtime_library_dirs': a list of directories to search for
|
| 111 |
+
# shared libraries/objects at runtime
|
| 112 |
+
self.runtime_library_dirs = []
|
| 113 |
+
|
| 114 |
+
# 'objects': a list of object files (or similar, such as explicitly
|
| 115 |
+
# named library files) to include on any link
|
| 116 |
+
self.objects = []
|
| 117 |
+
|
| 118 |
+
for key in self.executables.keys():
|
| 119 |
+
self.set_executable(key, self.executables[key])
|
| 120 |
+
|
| 121 |
+
def set_executables(self, **kwargs):
|
| 122 |
+
"""Define the executables (and options for them) that will be run
|
| 123 |
+
to perform the various stages of compilation. The exact set of
|
| 124 |
+
executables that may be specified here depends on the compiler
|
| 125 |
+
class (via the 'executables' class attribute), but most will have:
|
| 126 |
+
compiler the C/C++ compiler
|
| 127 |
+
linker_so linker used to create shared objects and libraries
|
| 128 |
+
linker_exe linker used to create binary executables
|
| 129 |
+
archiver static library creator
|
| 130 |
+
|
| 131 |
+
On platforms with a command-line (Unix, DOS/Windows), each of these
|
| 132 |
+
is a string that will be split into executable name and (optional)
|
| 133 |
+
list of arguments. (Splitting the string is done similarly to how
|
| 134 |
+
Unix shells operate: words are delimited by spaces, but quotes and
|
| 135 |
+
backslashes can override this. See
|
| 136 |
+
'distutils.util.split_quoted()'.)
|
| 137 |
+
"""
|
| 138 |
+
|
| 139 |
+
# Note that some CCompiler implementation classes will define class
|
| 140 |
+
# attributes 'cpp', 'cc', etc. with hard-coded executable names;
|
| 141 |
+
# this is appropriate when a compiler class is for exactly one
|
| 142 |
+
# compiler/OS combination (eg. MSVCCompiler). Other compiler
|
| 143 |
+
# classes (UnixCCompiler, in particular) are driven by information
|
| 144 |
+
# discovered at run-time, since there are many different ways to do
|
| 145 |
+
# basically the same things with Unix C compilers.
|
| 146 |
+
|
| 147 |
+
for key in kwargs:
|
| 148 |
+
if key not in self.executables:
|
| 149 |
+
raise ValueError("unknown executable '%s' for class %s" %
|
| 150 |
+
(key, self.__class__.__name__))
|
| 151 |
+
self.set_executable(key, kwargs[key])
|
| 152 |
+
|
| 153 |
+
def set_executable(self, key, value):
|
| 154 |
+
if isinstance(value, str):
|
| 155 |
+
setattr(self, key, split_quoted(value))
|
| 156 |
+
else:
|
| 157 |
+
setattr(self, key, value)
|
| 158 |
+
|
| 159 |
+
def _find_macro(self, name):
|
| 160 |
+
i = 0
|
| 161 |
+
for defn in self.macros:
|
| 162 |
+
if defn[0] == name:
|
| 163 |
+
return i
|
| 164 |
+
i += 1
|
| 165 |
+
return None
|
| 166 |
+
|
| 167 |
+
def _check_macro_definitions(self, definitions):
|
| 168 |
+
"""Ensures that every element of 'definitions' is a valid macro
|
| 169 |
+
definition, ie. either (name,value) 2-tuple or a (name,) tuple. Do
|
| 170 |
+
nothing if all definitions are OK, raise TypeError otherwise.
|
| 171 |
+
"""
|
| 172 |
+
for defn in definitions:
|
| 173 |
+
if not (isinstance(defn, tuple) and
|
| 174 |
+
(len(defn) in (1, 2) and
|
| 175 |
+
(isinstance (defn[1], str) or defn[1] is None)) and
|
| 176 |
+
isinstance (defn[0], str)):
|
| 177 |
+
raise TypeError(("invalid macro definition '%s': " % defn) + \
|
| 178 |
+
"must be tuple (string,), (string, string), or " + \
|
| 179 |
+
"(string, None)")
|
| 180 |
+
|
| 181 |
+
|
| 182 |
+
# -- Bookkeeping methods -------------------------------------------
|
| 183 |
+
|
| 184 |
+
def define_macro(self, name, value=None):
|
| 185 |
+
"""Define a preprocessor macro for all compilations driven by this
|
| 186 |
+
compiler object. The optional parameter 'value' should be a
|
| 187 |
+
string; if it is not supplied, then the macro will be defined
|
| 188 |
+
without an explicit value and the exact outcome depends on the
|
| 189 |
+
compiler used (XXX true? does ANSI say anything about this?)
|
| 190 |
+
"""
|
| 191 |
+
# Delete from the list of macro definitions/undefinitions if
|
| 192 |
+
# already there (so that this one will take precedence).
|
| 193 |
+
i = self._find_macro (name)
|
| 194 |
+
if i is not None:
|
| 195 |
+
del self.macros[i]
|
| 196 |
+
|
| 197 |
+
self.macros.append((name, value))
|
| 198 |
+
|
| 199 |
+
def undefine_macro(self, name):
|
| 200 |
+
"""Undefine a preprocessor macro for all compilations driven by
|
| 201 |
+
this compiler object. If the same macro is defined by
|
| 202 |
+
'define_macro()' and undefined by 'undefine_macro()' the last call
|
| 203 |
+
takes precedence (including multiple redefinitions or
|
| 204 |
+
undefinitions). If the macro is redefined/undefined on a
|
| 205 |
+
per-compilation basis (ie. in the call to 'compile()'), then that
|
| 206 |
+
takes precedence.
|
| 207 |
+
"""
|
| 208 |
+
# Delete from the list of macro definitions/undefinitions if
|
| 209 |
+
# already there (so that this one will take precedence).
|
| 210 |
+
i = self._find_macro (name)
|
| 211 |
+
if i is not None:
|
| 212 |
+
del self.macros[i]
|
| 213 |
+
|
| 214 |
+
undefn = (name,)
|
| 215 |
+
self.macros.append(undefn)
|
| 216 |
+
|
| 217 |
+
def add_include_dir(self, dir):
|
| 218 |
+
"""Add 'dir' to the list of directories that will be searched for
|
| 219 |
+
header files. The compiler is instructed to search directories in
|
| 220 |
+
the order in which they are supplied by successive calls to
|
| 221 |
+
'add_include_dir()'.
|
| 222 |
+
"""
|
| 223 |
+
self.include_dirs.append(dir)
|
| 224 |
+
|
| 225 |
+
def set_include_dirs(self, dirs):
|
| 226 |
+
"""Set the list of directories that will be searched to 'dirs' (a
|
| 227 |
+
list of strings). Overrides any preceding calls to
|
| 228 |
+
'add_include_dir()'; subsequence calls to 'add_include_dir()' add
|
| 229 |
+
to the list passed to 'set_include_dirs()'. This does not affect
|
| 230 |
+
any list of standard include directories that the compiler may
|
| 231 |
+
search by default.
|
| 232 |
+
"""
|
| 233 |
+
self.include_dirs = dirs[:]
|
| 234 |
+
|
| 235 |
+
def add_library(self, libname):
|
| 236 |
+
"""Add 'libname' to the list of libraries that will be included in
|
| 237 |
+
all links driven by this compiler object. Note that 'libname'
|
| 238 |
+
should *not* be the name of a file containing a library, but the
|
| 239 |
+
name of the library itself: the actual filename will be inferred by
|
| 240 |
+
the linker, the compiler, or the compiler class (depending on the
|
| 241 |
+
platform).
|
| 242 |
+
|
| 243 |
+
The linker will be instructed to link against libraries in the
|
| 244 |
+
order they were supplied to 'add_library()' and/or
|
| 245 |
+
'set_libraries()'. It is perfectly valid to duplicate library
|
| 246 |
+
names; the linker will be instructed to link against libraries as
|
| 247 |
+
many times as they are mentioned.
|
| 248 |
+
"""
|
| 249 |
+
self.libraries.append(libname)
|
| 250 |
+
|
| 251 |
+
def set_libraries(self, libnames):
|
| 252 |
+
"""Set the list of libraries to be included in all links driven by
|
| 253 |
+
this compiler object to 'libnames' (a list of strings). This does
|
| 254 |
+
not affect any standard system libraries that the linker may
|
| 255 |
+
include by default.
|
| 256 |
+
"""
|
| 257 |
+
self.libraries = libnames[:]
|
| 258 |
+
|
| 259 |
+
def add_library_dir(self, dir):
|
| 260 |
+
"""Add 'dir' to the list of directories that will be searched for
|
| 261 |
+
libraries specified to 'add_library()' and 'set_libraries()'. The
|
| 262 |
+
linker will be instructed to search for libraries in the order they
|
| 263 |
+
are supplied to 'add_library_dir()' and/or 'set_library_dirs()'.
|
| 264 |
+
"""
|
| 265 |
+
self.library_dirs.append(dir)
|
| 266 |
+
|
| 267 |
+
def set_library_dirs(self, dirs):
|
| 268 |
+
"""Set the list of library search directories to 'dirs' (a list of
|
| 269 |
+
strings). This does not affect any standard library search path
|
| 270 |
+
that the linker may search by default.
|
| 271 |
+
"""
|
| 272 |
+
self.library_dirs = dirs[:]
|
| 273 |
+
|
| 274 |
+
def add_runtime_library_dir(self, dir):
|
| 275 |
+
"""Add 'dir' to the list of directories that will be searched for
|
| 276 |
+
shared libraries at runtime.
|
| 277 |
+
"""
|
| 278 |
+
self.runtime_library_dirs.append(dir)
|
| 279 |
+
|
| 280 |
+
def set_runtime_library_dirs(self, dirs):
|
| 281 |
+
"""Set the list of directories to search for shared libraries at
|
| 282 |
+
runtime to 'dirs' (a list of strings). This does not affect any
|
| 283 |
+
standard search path that the runtime linker may search by
|
| 284 |
+
default.
|
| 285 |
+
"""
|
| 286 |
+
self.runtime_library_dirs = dirs[:]
|
| 287 |
+
|
| 288 |
+
def add_link_object(self, object):
|
| 289 |
+
"""Add 'object' to the list of object files (or analogues, such as
|
| 290 |
+
explicitly named library files or the output of "resource
|
| 291 |
+
compilers") to be included in every link driven by this compiler
|
| 292 |
+
object.
|
| 293 |
+
"""
|
| 294 |
+
self.objects.append(object)
|
| 295 |
+
|
| 296 |
+
def set_link_objects(self, objects):
|
| 297 |
+
"""Set the list of object files (or analogues) to be included in
|
| 298 |
+
every link to 'objects'. This does not affect any standard object
|
| 299 |
+
files that the linker may include by default (such as system
|
| 300 |
+
libraries).
|
| 301 |
+
"""
|
| 302 |
+
self.objects = objects[:]
|
| 303 |
+
|
| 304 |
+
|
| 305 |
+
# -- Private utility methods --------------------------------------
|
| 306 |
+
# (here for the convenience of subclasses)
|
| 307 |
+
|
| 308 |
+
# Helper method to prep compiler in subclass compile() methods
|
| 309 |
+
|
| 310 |
+
def _setup_compile(self, outdir, macros, incdirs, sources, depends,
|
| 311 |
+
extra):
|
| 312 |
+
"""Process arguments and decide which source files to compile."""
|
| 313 |
+
if outdir is None:
|
| 314 |
+
outdir = self.output_dir
|
| 315 |
+
elif not isinstance(outdir, str):
|
| 316 |
+
raise TypeError("'output_dir' must be a string or None")
|
| 317 |
+
|
| 318 |
+
if macros is None:
|
| 319 |
+
macros = self.macros
|
| 320 |
+
elif isinstance(macros, list):
|
| 321 |
+
macros = macros + (self.macros or [])
|
| 322 |
+
else:
|
| 323 |
+
raise TypeError("'macros' (if supplied) must be a list of tuples")
|
| 324 |
+
|
| 325 |
+
if incdirs is None:
|
| 326 |
+
incdirs = self.include_dirs
|
| 327 |
+
elif isinstance(incdirs, (list, tuple)):
|
| 328 |
+
incdirs = list(incdirs) + (self.include_dirs or [])
|
| 329 |
+
else:
|
| 330 |
+
raise TypeError(
|
| 331 |
+
"'include_dirs' (if supplied) must be a list of strings")
|
| 332 |
+
|
| 333 |
+
if extra is None:
|
| 334 |
+
extra = []
|
| 335 |
+
|
| 336 |
+
# Get the list of expected output (object) files
|
| 337 |
+
objects = self.object_filenames(sources, strip_dir=0,
|
| 338 |
+
output_dir=outdir)
|
| 339 |
+
assert len(objects) == len(sources)
|
| 340 |
+
|
| 341 |
+
pp_opts = gen_preprocess_options(macros, incdirs)
|
| 342 |
+
|
| 343 |
+
build = {}
|
| 344 |
+
for i in range(len(sources)):
|
| 345 |
+
src = sources[i]
|
| 346 |
+
obj = objects[i]
|
| 347 |
+
ext = os.path.splitext(src)[1]
|
| 348 |
+
self.mkpath(os.path.dirname(obj))
|
| 349 |
+
build[obj] = (src, ext)
|
| 350 |
+
|
| 351 |
+
return macros, objects, extra, pp_opts, build
|
| 352 |
+
|
| 353 |
+
def _get_cc_args(self, pp_opts, debug, before):
|
| 354 |
+
# works for unixccompiler, cygwinccompiler
|
| 355 |
+
cc_args = pp_opts + ['-c']
|
| 356 |
+
if debug:
|
| 357 |
+
cc_args[:0] = ['-g']
|
| 358 |
+
if before:
|
| 359 |
+
cc_args[:0] = before
|
| 360 |
+
return cc_args
|
| 361 |
+
|
| 362 |
+
def _fix_compile_args(self, output_dir, macros, include_dirs):
|
| 363 |
+
"""Typecheck and fix-up some of the arguments to the 'compile()'
|
| 364 |
+
method, and return fixed-up values. Specifically: if 'output_dir'
|
| 365 |
+
is None, replaces it with 'self.output_dir'; ensures that 'macros'
|
| 366 |
+
is a list, and augments it with 'self.macros'; ensures that
|
| 367 |
+
'include_dirs' is a list, and augments it with 'self.include_dirs'.
|
| 368 |
+
Guarantees that the returned values are of the correct type,
|
| 369 |
+
i.e. for 'output_dir' either string or None, and for 'macros' and
|
| 370 |
+
'include_dirs' either list or None.
|
| 371 |
+
"""
|
| 372 |
+
if output_dir is None:
|
| 373 |
+
output_dir = self.output_dir
|
| 374 |
+
elif not isinstance(output_dir, str):
|
| 375 |
+
raise TypeError("'output_dir' must be a string or None")
|
| 376 |
+
|
| 377 |
+
if macros is None:
|
| 378 |
+
macros = self.macros
|
| 379 |
+
elif isinstance(macros, list):
|
| 380 |
+
macros = macros + (self.macros or [])
|
| 381 |
+
else:
|
| 382 |
+
raise TypeError("'macros' (if supplied) must be a list of tuples")
|
| 383 |
+
|
| 384 |
+
if include_dirs is None:
|
| 385 |
+
include_dirs = self.include_dirs
|
| 386 |
+
elif isinstance(include_dirs, (list, tuple)):
|
| 387 |
+
include_dirs = list(include_dirs) + (self.include_dirs or [])
|
| 388 |
+
else:
|
| 389 |
+
raise TypeError(
|
| 390 |
+
"'include_dirs' (if supplied) must be a list of strings")
|
| 391 |
+
|
| 392 |
+
return output_dir, macros, include_dirs
|
| 393 |
+
|
| 394 |
+
def _prep_compile(self, sources, output_dir, depends=None):
|
| 395 |
+
"""Decide which souce files must be recompiled.
|
| 396 |
+
|
| 397 |
+
Determine the list of object files corresponding to 'sources',
|
| 398 |
+
and figure out which ones really need to be recompiled.
|
| 399 |
+
Return a list of all object files and a dictionary telling
|
| 400 |
+
which source files can be skipped.
|
| 401 |
+
"""
|
| 402 |
+
# Get the list of expected output (object) files
|
| 403 |
+
objects = self.object_filenames(sources, output_dir=output_dir)
|
| 404 |
+
assert len(objects) == len(sources)
|
| 405 |
+
|
| 406 |
+
# Return an empty dict for the "which source files can be skipped"
|
| 407 |
+
# return value to preserve API compatibility.
|
| 408 |
+
return objects, {}
|
| 409 |
+
|
| 410 |
+
def _fix_object_args(self, objects, output_dir):
|
| 411 |
+
"""Typecheck and fix up some arguments supplied to various methods.
|
| 412 |
+
Specifically: ensure that 'objects' is a list; if output_dir is
|
| 413 |
+
None, replace with self.output_dir. Return fixed versions of
|
| 414 |
+
'objects' and 'output_dir'.
|
| 415 |
+
"""
|
| 416 |
+
if not isinstance(objects, (list, tuple)):
|
| 417 |
+
raise TypeError("'objects' must be a list or tuple of strings")
|
| 418 |
+
objects = list(objects)
|
| 419 |
+
|
| 420 |
+
if output_dir is None:
|
| 421 |
+
output_dir = self.output_dir
|
| 422 |
+
elif not isinstance(output_dir, str):
|
| 423 |
+
raise TypeError("'output_dir' must be a string or None")
|
| 424 |
+
|
| 425 |
+
return (objects, output_dir)
|
| 426 |
+
|
| 427 |
+
def _fix_lib_args(self, libraries, library_dirs, runtime_library_dirs):
|
| 428 |
+
"""Typecheck and fix up some of the arguments supplied to the
|
| 429 |
+
'link_*' methods. Specifically: ensure that all arguments are
|
| 430 |
+
lists, and augment them with their permanent versions
|
| 431 |
+
(eg. 'self.libraries' augments 'libraries'). Return a tuple with
|
| 432 |
+
fixed versions of all arguments.
|
| 433 |
+
"""
|
| 434 |
+
if libraries is None:
|
| 435 |
+
libraries = self.libraries
|
| 436 |
+
elif isinstance(libraries, (list, tuple)):
|
| 437 |
+
libraries = list (libraries) + (self.libraries or [])
|
| 438 |
+
else:
|
| 439 |
+
raise TypeError(
|
| 440 |
+
"'libraries' (if supplied) must be a list of strings")
|
| 441 |
+
|
| 442 |
+
if library_dirs is None:
|
| 443 |
+
library_dirs = self.library_dirs
|
| 444 |
+
elif isinstance(library_dirs, (list, tuple)):
|
| 445 |
+
library_dirs = list (library_dirs) + (self.library_dirs or [])
|
| 446 |
+
else:
|
| 447 |
+
raise TypeError(
|
| 448 |
+
"'library_dirs' (if supplied) must be a list of strings")
|
| 449 |
+
|
| 450 |
+
if runtime_library_dirs is None:
|
| 451 |
+
runtime_library_dirs = self.runtime_library_dirs
|
| 452 |
+
elif isinstance(runtime_library_dirs, (list, tuple)):
|
| 453 |
+
runtime_library_dirs = (list(runtime_library_dirs) +
|
| 454 |
+
(self.runtime_library_dirs or []))
|
| 455 |
+
else:
|
| 456 |
+
raise TypeError("'runtime_library_dirs' (if supplied) "
|
| 457 |
+
"must be a list of strings")
|
| 458 |
+
|
| 459 |
+
return (libraries, library_dirs, runtime_library_dirs)
|
| 460 |
+
|
| 461 |
+
def _need_link(self, objects, output_file):
|
| 462 |
+
"""Return true if we need to relink the files listed in 'objects'
|
| 463 |
+
to recreate 'output_file'.
|
| 464 |
+
"""
|
| 465 |
+
if self.force:
|
| 466 |
+
return True
|
| 467 |
+
else:
|
| 468 |
+
if self.dry_run:
|
| 469 |
+
newer = newer_group (objects, output_file, missing='newer')
|
| 470 |
+
else:
|
| 471 |
+
newer = newer_group (objects, output_file)
|
| 472 |
+
return newer
|
| 473 |
+
|
| 474 |
+
def detect_language(self, sources):
|
| 475 |
+
"""Detect the language of a given file, or list of files. Uses
|
| 476 |
+
language_map, and language_order to do the job.
|
| 477 |
+
"""
|
| 478 |
+
if not isinstance(sources, list):
|
| 479 |
+
sources = [sources]
|
| 480 |
+
lang = None
|
| 481 |
+
index = len(self.language_order)
|
| 482 |
+
for source in sources:
|
| 483 |
+
base, ext = os.path.splitext(source)
|
| 484 |
+
extlang = self.language_map.get(ext)
|
| 485 |
+
try:
|
| 486 |
+
extindex = self.language_order.index(extlang)
|
| 487 |
+
if extindex < index:
|
| 488 |
+
lang = extlang
|
| 489 |
+
index = extindex
|
| 490 |
+
except ValueError:
|
| 491 |
+
pass
|
| 492 |
+
return lang
|
| 493 |
+
|
| 494 |
+
|
| 495 |
+
# -- Worker methods ------------------------------------------------
|
| 496 |
+
# (must be implemented by subclasses)
|
| 497 |
+
|
| 498 |
+
def preprocess(self, source, output_file=None, macros=None,
|
| 499 |
+
include_dirs=None, extra_preargs=None, extra_postargs=None):
|
| 500 |
+
"""Preprocess a single C/C++ source file, named in 'source'.
|
| 501 |
+
Output will be written to file named 'output_file', or stdout if
|
| 502 |
+
'output_file' not supplied. 'macros' is a list of macro
|
| 503 |
+
definitions as for 'compile()', which will augment the macros set
|
| 504 |
+
with 'define_macro()' and 'undefine_macro()'. 'include_dirs' is a
|
| 505 |
+
list of directory names that will be added to the default list.
|
| 506 |
+
|
| 507 |
+
Raises PreprocessError on failure.
|
| 508 |
+
"""
|
| 509 |
+
pass
|
| 510 |
+
|
| 511 |
+
def compile(self, sources, output_dir=None, macros=None,
|
| 512 |
+
include_dirs=None, debug=0, extra_preargs=None,
|
| 513 |
+
extra_postargs=None, depends=None):
|
| 514 |
+
"""Compile one or more source files.
|
| 515 |
+
|
| 516 |
+
'sources' must be a list of filenames, most likely C/C++
|
| 517 |
+
files, but in reality anything that can be handled by a
|
| 518 |
+
particular compiler and compiler class (eg. MSVCCompiler can
|
| 519 |
+
handle resource files in 'sources'). Return a list of object
|
| 520 |
+
filenames, one per source filename in 'sources'. Depending on
|
| 521 |
+
the implementation, not all source files will necessarily be
|
| 522 |
+
compiled, but all corresponding object filenames will be
|
| 523 |
+
returned.
|
| 524 |
+
|
| 525 |
+
If 'output_dir' is given, object files will be put under it, while
|
| 526 |
+
retaining their original path component. That is, "foo/bar.c"
|
| 527 |
+
normally compiles to "foo/bar.o" (for a Unix implementation); if
|
| 528 |
+
'output_dir' is "build", then it would compile to
|
| 529 |
+
"build/foo/bar.o".
|
| 530 |
+
|
| 531 |
+
'macros', if given, must be a list of macro definitions. A macro
|
| 532 |
+
definition is either a (name, value) 2-tuple or a (name,) 1-tuple.
|
| 533 |
+
The former defines a macro; if the value is None, the macro is
|
| 534 |
+
defined without an explicit value. The 1-tuple case undefines a
|
| 535 |
+
macro. Later definitions/redefinitions/ undefinitions take
|
| 536 |
+
precedence.
|
| 537 |
+
|
| 538 |
+
'include_dirs', if given, must be a list of strings, the
|
| 539 |
+
directories to add to the default include file search path for this
|
| 540 |
+
compilation only.
|
| 541 |
+
|
| 542 |
+
'debug' is a boolean; if true, the compiler will be instructed to
|
| 543 |
+
output debug symbols in (or alongside) the object file(s).
|
| 544 |
+
|
| 545 |
+
'extra_preargs' and 'extra_postargs' are implementation- dependent.
|
| 546 |
+
On platforms that have the notion of a command-line (e.g. Unix,
|
| 547 |
+
DOS/Windows), they are most likely lists of strings: extra
|
| 548 |
+
command-line arguments to prepend/append to the compiler command
|
| 549 |
+
line. On other platforms, consult the implementation class
|
| 550 |
+
documentation. In any event, they are intended as an escape hatch
|
| 551 |
+
for those occasions when the abstract compiler framework doesn't
|
| 552 |
+
cut the mustard.
|
| 553 |
+
|
| 554 |
+
'depends', if given, is a list of filenames that all targets
|
| 555 |
+
depend on. If a source file is older than any file in
|
| 556 |
+
depends, then the source file will be recompiled. This
|
| 557 |
+
supports dependency tracking, but only at a coarse
|
| 558 |
+
granularity.
|
| 559 |
+
|
| 560 |
+
Raises CompileError on failure.
|
| 561 |
+
"""
|
| 562 |
+
# A concrete compiler class can either override this method
|
| 563 |
+
# entirely or implement _compile().
|
| 564 |
+
macros, objects, extra_postargs, pp_opts, build = \
|
| 565 |
+
self._setup_compile(output_dir, macros, include_dirs, sources,
|
| 566 |
+
depends, extra_postargs)
|
| 567 |
+
cc_args = self._get_cc_args(pp_opts, debug, extra_preargs)
|
| 568 |
+
|
| 569 |
+
for obj in objects:
|
| 570 |
+
try:
|
| 571 |
+
src, ext = build[obj]
|
| 572 |
+
except KeyError:
|
| 573 |
+
continue
|
| 574 |
+
self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts)
|
| 575 |
+
|
| 576 |
+
# Return *all* object filenames, not just the ones we just built.
|
| 577 |
+
return objects
|
| 578 |
+
|
| 579 |
+
def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
|
| 580 |
+
"""Compile 'src' to product 'obj'."""
|
| 581 |
+
# A concrete compiler class that does not override compile()
|
| 582 |
+
# should implement _compile().
|
| 583 |
+
pass
|
| 584 |
+
|
| 585 |
+
def create_static_lib(self, objects, output_libname, output_dir=None,
|
| 586 |
+
debug=0, target_lang=None):
|
| 587 |
+
"""Link a bunch of stuff together to create a static library file.
|
| 588 |
+
The "bunch of stuff" consists of the list of object files supplied
|
| 589 |
+
as 'objects', the extra object files supplied to
|
| 590 |
+
'add_link_object()' and/or 'set_link_objects()', the libraries
|
| 591 |
+
supplied to 'add_library()' and/or 'set_libraries()', and the
|
| 592 |
+
libraries supplied as 'libraries' (if any).
|
| 593 |
+
|
| 594 |
+
'output_libname' should be a library name, not a filename; the
|
| 595 |
+
filename will be inferred from the library name. 'output_dir' is
|
| 596 |
+
the directory where the library file will be put.
|
| 597 |
+
|
| 598 |
+
'debug' is a boolean; if true, debugging information will be
|
| 599 |
+
included in the library (note that on most platforms, it is the
|
| 600 |
+
compile step where this matters: the 'debug' flag is included here
|
| 601 |
+
just for consistency).
|
| 602 |
+
|
| 603 |
+
'target_lang' is the target language for which the given objects
|
| 604 |
+
are being compiled. This allows specific linkage time treatment of
|
| 605 |
+
certain languages.
|
| 606 |
+
|
| 607 |
+
Raises LibError on failure.
|
| 608 |
+
"""
|
| 609 |
+
pass
|
| 610 |
+
|
| 611 |
+
|
| 612 |
+
# values for target_desc parameter in link()
|
| 613 |
+
SHARED_OBJECT = "shared_object"
|
| 614 |
+
SHARED_LIBRARY = "shared_library"
|
| 615 |
+
EXECUTABLE = "executable"
|
| 616 |
+
|
| 617 |
+
def link(self,
|
| 618 |
+
target_desc,
|
| 619 |
+
objects,
|
| 620 |
+
output_filename,
|
| 621 |
+
output_dir=None,
|
| 622 |
+
libraries=None,
|
| 623 |
+
library_dirs=None,
|
| 624 |
+
runtime_library_dirs=None,
|
| 625 |
+
export_symbols=None,
|
| 626 |
+
debug=0,
|
| 627 |
+
extra_preargs=None,
|
| 628 |
+
extra_postargs=None,
|
| 629 |
+
build_temp=None,
|
| 630 |
+
target_lang=None):
|
| 631 |
+
"""Link a bunch of stuff together to create an executable or
|
| 632 |
+
shared library file.
|
| 633 |
+
|
| 634 |
+
The "bunch of stuff" consists of the list of object files supplied
|
| 635 |
+
as 'objects'. 'output_filename' should be a filename. If
|
| 636 |
+
'output_dir' is supplied, 'output_filename' is relative to it
|
| 637 |
+
(i.e. 'output_filename' can provide directory components if
|
| 638 |
+
needed).
|
| 639 |
+
|
| 640 |
+
'libraries' is a list of libraries to link against. These are
|
| 641 |
+
library names, not filenames, since they're translated into
|
| 642 |
+
filenames in a platform-specific way (eg. "foo" becomes "libfoo.a"
|
| 643 |
+
on Unix and "foo.lib" on DOS/Windows). However, they can include a
|
| 644 |
+
directory component, which means the linker will look in that
|
| 645 |
+
specific directory rather than searching all the normal locations.
|
| 646 |
+
|
| 647 |
+
'library_dirs', if supplied, should be a list of directories to
|
| 648 |
+
search for libraries that were specified as bare library names
|
| 649 |
+
(ie. no directory component). These are on top of the system
|
| 650 |
+
default and those supplied to 'add_library_dir()' and/or
|
| 651 |
+
'set_library_dirs()'. 'runtime_library_dirs' is a list of
|
| 652 |
+
directories that will be embedded into the shared library and used
|
| 653 |
+
to search for other shared libraries that *it* depends on at
|
| 654 |
+
run-time. (This may only be relevant on Unix.)
|
| 655 |
+
|
| 656 |
+
'export_symbols' is a list of symbols that the shared library will
|
| 657 |
+
export. (This appears to be relevant only on Windows.)
|
| 658 |
+
|
| 659 |
+
'debug' is as for 'compile()' and 'create_static_lib()', with the
|
| 660 |
+
slight distinction that it actually matters on most platforms (as
|
| 661 |
+
opposed to 'create_static_lib()', which includes a 'debug' flag
|
| 662 |
+
mostly for form's sake).
|
| 663 |
+
|
| 664 |
+
'extra_preargs' and 'extra_postargs' are as for 'compile()' (except
|
| 665 |
+
of course that they supply command-line arguments for the
|
| 666 |
+
particular linker being used).
|
| 667 |
+
|
| 668 |
+
'target_lang' is the target language for which the given objects
|
| 669 |
+
are being compiled. This allows specific linkage time treatment of
|
| 670 |
+
certain languages.
|
| 671 |
+
|
| 672 |
+
Raises LinkError on failure.
|
| 673 |
+
"""
|
| 674 |
+
raise NotImplementedError
|
| 675 |
+
|
| 676 |
+
|
| 677 |
+
# Old 'link_*()' methods, rewritten to use the new 'link()' method.
|
| 678 |
+
|
| 679 |
+
def link_shared_lib(self,
|
| 680 |
+
objects,
|
| 681 |
+
output_libname,
|
| 682 |
+
output_dir=None,
|
| 683 |
+
libraries=None,
|
| 684 |
+
library_dirs=None,
|
| 685 |
+
runtime_library_dirs=None,
|
| 686 |
+
export_symbols=None,
|
| 687 |
+
debug=0,
|
| 688 |
+
extra_preargs=None,
|
| 689 |
+
extra_postargs=None,
|
| 690 |
+
build_temp=None,
|
| 691 |
+
target_lang=None):
|
| 692 |
+
self.link(CCompiler.SHARED_LIBRARY, objects,
|
| 693 |
+
self.library_filename(output_libname, lib_type='shared'),
|
| 694 |
+
output_dir,
|
| 695 |
+
libraries, library_dirs, runtime_library_dirs,
|
| 696 |
+
export_symbols, debug,
|
| 697 |
+
extra_preargs, extra_postargs, build_temp, target_lang)
|
| 698 |
+
|
| 699 |
+
|
| 700 |
+
def link_shared_object(self,
|
| 701 |
+
objects,
|
| 702 |
+
output_filename,
|
| 703 |
+
output_dir=None,
|
| 704 |
+
libraries=None,
|
| 705 |
+
library_dirs=None,
|
| 706 |
+
runtime_library_dirs=None,
|
| 707 |
+
export_symbols=None,
|
| 708 |
+
debug=0,
|
| 709 |
+
extra_preargs=None,
|
| 710 |
+
extra_postargs=None,
|
| 711 |
+
build_temp=None,
|
| 712 |
+
target_lang=None):
|
| 713 |
+
self.link(CCompiler.SHARED_OBJECT, objects,
|
| 714 |
+
output_filename, output_dir,
|
| 715 |
+
libraries, library_dirs, runtime_library_dirs,
|
| 716 |
+
export_symbols, debug,
|
| 717 |
+
extra_preargs, extra_postargs, build_temp, target_lang)
|
| 718 |
+
|
| 719 |
+
|
| 720 |
+
def link_executable(self,
|
| 721 |
+
objects,
|
| 722 |
+
output_progname,
|
| 723 |
+
output_dir=None,
|
| 724 |
+
libraries=None,
|
| 725 |
+
library_dirs=None,
|
| 726 |
+
runtime_library_dirs=None,
|
| 727 |
+
debug=0,
|
| 728 |
+
extra_preargs=None,
|
| 729 |
+
extra_postargs=None,
|
| 730 |
+
target_lang=None):
|
| 731 |
+
self.link(CCompiler.EXECUTABLE, objects,
|
| 732 |
+
self.executable_filename(output_progname), output_dir,
|
| 733 |
+
libraries, library_dirs, runtime_library_dirs, None,
|
| 734 |
+
debug, extra_preargs, extra_postargs, None, target_lang)
|
| 735 |
+
|
| 736 |
+
|
| 737 |
+
# -- Miscellaneous methods -----------------------------------------
|
| 738 |
+
# These are all used by the 'gen_lib_options() function; there is
|
| 739 |
+
# no appropriate default implementation so subclasses should
|
| 740 |
+
# implement all of these.
|
| 741 |
+
|
| 742 |
+
def library_dir_option(self, dir):
|
| 743 |
+
"""Return the compiler option to add 'dir' to the list of
|
| 744 |
+
directories searched for libraries.
|
| 745 |
+
"""
|
| 746 |
+
raise NotImplementedError
|
| 747 |
+
|
| 748 |
+
def runtime_library_dir_option(self, dir):
|
| 749 |
+
"""Return the compiler option to add 'dir' to the list of
|
| 750 |
+
directories searched for runtime libraries.
|
| 751 |
+
"""
|
| 752 |
+
raise NotImplementedError
|
| 753 |
+
|
| 754 |
+
def library_option(self, lib):
|
| 755 |
+
"""Return the compiler option to add 'lib' to the list of libraries
|
| 756 |
+
linked into the shared library or executable.
|
| 757 |
+
"""
|
| 758 |
+
raise NotImplementedError
|
| 759 |
+
|
| 760 |
+
def has_function(self, funcname, includes=None, include_dirs=None,
|
| 761 |
+
libraries=None, library_dirs=None):
|
| 762 |
+
"""Return a boolean indicating whether funcname is supported on
|
| 763 |
+
the current platform. The optional arguments can be used to
|
| 764 |
+
augment the compilation environment.
|
| 765 |
+
"""
|
| 766 |
+
# this can't be included at module scope because it tries to
|
| 767 |
+
# import math which might not be available at that point - maybe
|
| 768 |
+
# the necessary logic should just be inlined?
|
| 769 |
+
import tempfile
|
| 770 |
+
if includes is None:
|
| 771 |
+
includes = []
|
| 772 |
+
if include_dirs is None:
|
| 773 |
+
include_dirs = []
|
| 774 |
+
if libraries is None:
|
| 775 |
+
libraries = []
|
| 776 |
+
if library_dirs is None:
|
| 777 |
+
library_dirs = []
|
| 778 |
+
fd, fname = tempfile.mkstemp(".c", funcname, text=True)
|
| 779 |
+
f = os.fdopen(fd, "w")
|
| 780 |
+
try:
|
| 781 |
+
for incl in includes:
|
| 782 |
+
f.write("""#include "%s"\n""" % incl)
|
| 783 |
+
f.write("""\
|
| 784 |
+
int main (int argc, char **argv) {
|
| 785 |
+
%s();
|
| 786 |
+
return 0;
|
| 787 |
+
}
|
| 788 |
+
""" % funcname)
|
| 789 |
+
finally:
|
| 790 |
+
f.close()
|
| 791 |
+
try:
|
| 792 |
+
objects = self.compile([fname], include_dirs=include_dirs)
|
| 793 |
+
except CompileError:
|
| 794 |
+
return False
|
| 795 |
+
|
| 796 |
+
try:
|
| 797 |
+
self.link_executable(objects, "a.out",
|
| 798 |
+
libraries=libraries,
|
| 799 |
+
library_dirs=library_dirs)
|
| 800 |
+
except (LinkError, TypeError):
|
| 801 |
+
return False
|
| 802 |
+
return True
|
| 803 |
+
|
| 804 |
+
def find_library_file (self, dirs, lib, debug=0):
|
| 805 |
+
"""Search the specified list of directories for a static or shared
|
| 806 |
+
library file 'lib' and return the full path to that file. If
|
| 807 |
+
'debug' true, look for a debugging version (if that makes sense on
|
| 808 |
+
the current platform). Return None if 'lib' wasn't found in any of
|
| 809 |
+
the specified directories.
|
| 810 |
+
"""
|
| 811 |
+
raise NotImplementedError
|
| 812 |
+
|
| 813 |
+
# -- Filename generation methods -----------------------------------
|
| 814 |
+
|
| 815 |
+
# The default implementation of the filename generating methods are
|
| 816 |
+
# prejudiced towards the Unix/DOS/Windows view of the world:
|
| 817 |
+
# * object files are named by replacing the source file extension
|
| 818 |
+
# (eg. .c/.cpp -> .o/.obj)
|
| 819 |
+
# * library files (shared or static) are named by plugging the
|
| 820 |
+
# library name and extension into a format string, eg.
|
| 821 |
+
# "lib%s.%s" % (lib_name, ".a") for Unix static libraries
|
| 822 |
+
# * executables are named by appending an extension (possibly
|
| 823 |
+
# empty) to the program name: eg. progname + ".exe" for
|
| 824 |
+
# Windows
|
| 825 |
+
#
|
| 826 |
+
# To reduce redundant code, these methods expect to find
|
| 827 |
+
# several attributes in the current object (presumably defined
|
| 828 |
+
# as class attributes):
|
| 829 |
+
# * src_extensions -
|
| 830 |
+
# list of C/C++ source file extensions, eg. ['.c', '.cpp']
|
| 831 |
+
# * obj_extension -
|
| 832 |
+
# object file extension, eg. '.o' or '.obj'
|
| 833 |
+
# * static_lib_extension -
|
| 834 |
+
# extension for static library files, eg. '.a' or '.lib'
|
| 835 |
+
# * shared_lib_extension -
|
| 836 |
+
# extension for shared library/object files, eg. '.so', '.dll'
|
| 837 |
+
# * static_lib_format -
|
| 838 |
+
# format string for generating static library filenames,
|
| 839 |
+
# eg. 'lib%s.%s' or '%s.%s'
|
| 840 |
+
# * shared_lib_format
|
| 841 |
+
# format string for generating shared library filenames
|
| 842 |
+
# (probably same as static_lib_format, since the extension
|
| 843 |
+
# is one of the intended parameters to the format string)
|
| 844 |
+
# * exe_extension -
|
| 845 |
+
# extension for executable files, eg. '' or '.exe'
|
| 846 |
+
|
| 847 |
+
def object_filenames(self, source_filenames, strip_dir=0, output_dir=''):
|
| 848 |
+
if output_dir is None:
|
| 849 |
+
output_dir = ''
|
| 850 |
+
obj_names = []
|
| 851 |
+
for src_name in source_filenames:
|
| 852 |
+
base, ext = os.path.splitext(src_name)
|
| 853 |
+
base = os.path.splitdrive(base)[1] # Chop off the drive
|
| 854 |
+
base = base[os.path.isabs(base):] # If abs, chop off leading /
|
| 855 |
+
if ext not in self.src_extensions:
|
| 856 |
+
raise UnknownFileError(
|
| 857 |
+
"unknown file type '%s' (from '%s')" % (ext, src_name))
|
| 858 |
+
if strip_dir:
|
| 859 |
+
base = os.path.basename(base)
|
| 860 |
+
obj_names.append(os.path.join(output_dir,
|
| 861 |
+
base + self.obj_extension))
|
| 862 |
+
return obj_names
|
| 863 |
+
|
| 864 |
+
def shared_object_filename(self, basename, strip_dir=0, output_dir=''):
|
| 865 |
+
assert output_dir is not None
|
| 866 |
+
if strip_dir:
|
| 867 |
+
basename = os.path.basename(basename)
|
| 868 |
+
return os.path.join(output_dir, basename + self.shared_lib_extension)
|
| 869 |
+
|
| 870 |
+
def executable_filename(self, basename, strip_dir=0, output_dir=''):
|
| 871 |
+
assert output_dir is not None
|
| 872 |
+
if strip_dir:
|
| 873 |
+
basename = os.path.basename(basename)
|
| 874 |
+
return os.path.join(output_dir, basename + (self.exe_extension or ''))
|
| 875 |
+
|
| 876 |
+
def library_filename(self, libname, lib_type='static', # or 'shared'
|
| 877 |
+
strip_dir=0, output_dir=''):
|
| 878 |
+
assert output_dir is not None
|
| 879 |
+
if lib_type not in ("static", "shared", "dylib", "xcode_stub"):
|
| 880 |
+
raise ValueError(
|
| 881 |
+
"'lib_type' must be \"static\", \"shared\", \"dylib\", or \"xcode_stub\"")
|
| 882 |
+
fmt = getattr(self, lib_type + "_lib_format")
|
| 883 |
+
ext = getattr(self, lib_type + "_lib_extension")
|
| 884 |
+
|
| 885 |
+
dir, base = os.path.split(libname)
|
| 886 |
+
filename = fmt % (base, ext)
|
| 887 |
+
if strip_dir:
|
| 888 |
+
dir = ''
|
| 889 |
+
|
| 890 |
+
return os.path.join(output_dir, dir, filename)
|
| 891 |
+
|
| 892 |
+
|
| 893 |
+
# -- Utility methods -----------------------------------------------
|
| 894 |
+
|
| 895 |
+
def announce(self, msg, level=1):
|
| 896 |
+
log.debug(msg)
|
| 897 |
+
|
| 898 |
+
def debug_print(self, msg):
|
| 899 |
+
from distutils.debug import DEBUG
|
| 900 |
+
if DEBUG:
|
| 901 |
+
print(msg)
|
| 902 |
+
|
| 903 |
+
def warn(self, msg):
|
| 904 |
+
sys.stderr.write("warning: %s\n" % msg)
|
| 905 |
+
|
| 906 |
+
def execute(self, func, args, msg=None, level=1):
|
| 907 |
+
execute(func, args, msg, self.dry_run)
|
| 908 |
+
|
| 909 |
+
def spawn(self, cmd):
|
| 910 |
+
spawn(cmd, dry_run=self.dry_run)
|
| 911 |
+
|
| 912 |
+
def move_file(self, src, dst):
|
| 913 |
+
return move_file(src, dst, dry_run=self.dry_run)
|
| 914 |
+
|
| 915 |
+
def mkpath (self, name, mode=0o777):
|
| 916 |
+
mkpath(name, mode, dry_run=self.dry_run)
|
| 917 |
+
|
| 918 |
+
|
| 919 |
+
# Map a sys.platform/os.name ('posix', 'nt') to the default compiler
|
| 920 |
+
# type for that platform. Keys are interpreted as re match
|
| 921 |
+
# patterns. Order is important; platform mappings are preferred over
|
| 922 |
+
# OS names.
|
| 923 |
+
_default_compilers = (
|
| 924 |
+
|
| 925 |
+
# Platform string mappings
|
| 926 |
+
|
| 927 |
+
# on a cygwin built python we can use gcc like an ordinary UNIXish
|
| 928 |
+
# compiler
|
| 929 |
+
('cygwin.*', 'unix'),
|
| 930 |
+
|
| 931 |
+
# OS name mappings
|
| 932 |
+
('posix', 'unix'),
|
| 933 |
+
('nt', 'msvc'),
|
| 934 |
+
|
| 935 |
+
)
|
| 936 |
+
|
| 937 |
+
def get_default_compiler(osname=None, platform=None):
|
| 938 |
+
"""Determine the default compiler to use for the given platform.
|
| 939 |
+
|
| 940 |
+
osname should be one of the standard Python OS names (i.e. the
|
| 941 |
+
ones returned by os.name) and platform the common value
|
| 942 |
+
returned by sys.platform for the platform in question.
|
| 943 |
+
|
| 944 |
+
The default values are os.name and sys.platform in case the
|
| 945 |
+
parameters are not given.
|
| 946 |
+
"""
|
| 947 |
+
if osname is None:
|
| 948 |
+
osname = os.name
|
| 949 |
+
if platform is None:
|
| 950 |
+
platform = sys.platform
|
| 951 |
+
for pattern, compiler in _default_compilers:
|
| 952 |
+
if re.match(pattern, platform) is not None or \
|
| 953 |
+
re.match(pattern, osname) is not None:
|
| 954 |
+
return compiler
|
| 955 |
+
# Default to Unix compiler
|
| 956 |
+
return 'unix'
|
| 957 |
+
|
| 958 |
+
# Map compiler types to (module_name, class_name) pairs -- ie. where to
|
| 959 |
+
# find the code that implements an interface to this compiler. (The module
|
| 960 |
+
# is assumed to be in the 'distutils' package.)
|
| 961 |
+
compiler_class = { 'unix': ('unixccompiler', 'UnixCCompiler',
|
| 962 |
+
"standard UNIX-style compiler"),
|
| 963 |
+
'msvc': ('_msvccompiler', 'MSVCCompiler',
|
| 964 |
+
"Microsoft Visual C++"),
|
| 965 |
+
'cygwin': ('cygwinccompiler', 'CygwinCCompiler',
|
| 966 |
+
"Cygwin port of GNU C Compiler for Win32"),
|
| 967 |
+
'mingw32': ('cygwinccompiler', 'Mingw32CCompiler',
|
| 968 |
+
"Mingw32 port of GNU C Compiler for Win32"),
|
| 969 |
+
'bcpp': ('bcppcompiler', 'BCPPCompiler',
|
| 970 |
+
"Borland C++ Compiler"),
|
| 971 |
+
}
|
| 972 |
+
|
| 973 |
+
def show_compilers():
|
| 974 |
+
"""Print list of available compilers (used by the "--help-compiler"
|
| 975 |
+
options to "build", "build_ext", "build_clib").
|
| 976 |
+
"""
|
| 977 |
+
# XXX this "knows" that the compiler option it's describing is
|
| 978 |
+
# "--compiler", which just happens to be the case for the three
|
| 979 |
+
# commands that use it.
|
| 980 |
+
from distutils.fancy_getopt import FancyGetopt
|
| 981 |
+
compilers = []
|
| 982 |
+
for compiler in compiler_class.keys():
|
| 983 |
+
compilers.append(("compiler="+compiler, None,
|
| 984 |
+
compiler_class[compiler][2]))
|
| 985 |
+
compilers.sort()
|
| 986 |
+
pretty_printer = FancyGetopt(compilers)
|
| 987 |
+
pretty_printer.print_help("List of available compilers:")
|
| 988 |
+
|
| 989 |
+
|
| 990 |
+
def new_compiler(plat=None, compiler=None, verbose=0, dry_run=0, force=0):
|
| 991 |
+
"""Generate an instance of some CCompiler subclass for the supplied
|
| 992 |
+
platform/compiler combination. 'plat' defaults to 'os.name'
|
| 993 |
+
(eg. 'posix', 'nt'), and 'compiler' defaults to the default compiler
|
| 994 |
+
for that platform. Currently only 'posix' and 'nt' are supported, and
|
| 995 |
+
the default compilers are "traditional Unix interface" (UnixCCompiler
|
| 996 |
+
class) and Visual C++ (MSVCCompiler class). Note that it's perfectly
|
| 997 |
+
possible to ask for a Unix compiler object under Windows, and a
|
| 998 |
+
Microsoft compiler object under Unix -- if you supply a value for
|
| 999 |
+
'compiler', 'plat' is ignored.
|
| 1000 |
+
"""
|
| 1001 |
+
if plat is None:
|
| 1002 |
+
plat = os.name
|
| 1003 |
+
|
| 1004 |
+
try:
|
| 1005 |
+
if compiler is None:
|
| 1006 |
+
compiler = get_default_compiler(plat)
|
| 1007 |
+
|
| 1008 |
+
(module_name, class_name, long_description) = compiler_class[compiler]
|
| 1009 |
+
except KeyError:
|
| 1010 |
+
msg = "don't know how to compile C/C++ code on platform '%s'" % plat
|
| 1011 |
+
if compiler is not None:
|
| 1012 |
+
msg = msg + " with '%s' compiler" % compiler
|
| 1013 |
+
raise DistutilsPlatformError(msg)
|
| 1014 |
+
|
| 1015 |
+
try:
|
| 1016 |
+
module_name = "distutils." + module_name
|
| 1017 |
+
__import__ (module_name)
|
| 1018 |
+
module = sys.modules[module_name]
|
| 1019 |
+
klass = vars(module)[class_name]
|
| 1020 |
+
except ImportError:
|
| 1021 |
+
raise DistutilsModuleError(
|
| 1022 |
+
"can't compile C/C++ code: unable to load module '%s'" % \
|
| 1023 |
+
module_name)
|
| 1024 |
+
except KeyError:
|
| 1025 |
+
raise DistutilsModuleError(
|
| 1026 |
+
"can't compile C/C++ code: unable to find class '%s' "
|
| 1027 |
+
"in module '%s'" % (class_name, module_name))
|
| 1028 |
+
|
| 1029 |
+
# XXX The None is necessary to preserve backwards compatibility
|
| 1030 |
+
# with classes that expect verbose to be the first positional
|
| 1031 |
+
# argument.
|
| 1032 |
+
return klass(None, dry_run, force)
|
| 1033 |
+
|
| 1034 |
+
|
| 1035 |
+
def gen_preprocess_options(macros, include_dirs):
|
| 1036 |
+
"""Generate C pre-processor options (-D, -U, -I) as used by at least
|
| 1037 |
+
two types of compilers: the typical Unix compiler and Visual C++.
|
| 1038 |
+
'macros' is the usual thing, a list of 1- or 2-tuples, where (name,)
|
| 1039 |
+
means undefine (-U) macro 'name', and (name,value) means define (-D)
|
| 1040 |
+
macro 'name' to 'value'. 'include_dirs' is just a list of directory
|
| 1041 |
+
names to be added to the header file search path (-I). Returns a list
|
| 1042 |
+
of command-line options suitable for either Unix compilers or Visual
|
| 1043 |
+
C++.
|
| 1044 |
+
"""
|
| 1045 |
+
# XXX it would be nice (mainly aesthetic, and so we don't generate
|
| 1046 |
+
# stupid-looking command lines) to go over 'macros' and eliminate
|
| 1047 |
+
# redundant definitions/undefinitions (ie. ensure that only the
|
| 1048 |
+
# latest mention of a particular macro winds up on the command
|
| 1049 |
+
# line). I don't think it's essential, though, since most (all?)
|
| 1050 |
+
# Unix C compilers only pay attention to the latest -D or -U
|
| 1051 |
+
# mention of a macro on their command line. Similar situation for
|
| 1052 |
+
# 'include_dirs'. I'm punting on both for now. Anyways, weeding out
|
| 1053 |
+
# redundancies like this should probably be the province of
|
| 1054 |
+
# CCompiler, since the data structures used are inherited from it
|
| 1055 |
+
# and therefore common to all CCompiler classes.
|
| 1056 |
+
pp_opts = []
|
| 1057 |
+
for macro in macros:
|
| 1058 |
+
if not (isinstance(macro, tuple) and 1 <= len(macro) <= 2):
|
| 1059 |
+
raise TypeError(
|
| 1060 |
+
"bad macro definition '%s': "
|
| 1061 |
+
"each element of 'macros' list must be a 1- or 2-tuple"
|
| 1062 |
+
% macro)
|
| 1063 |
+
|
| 1064 |
+
if len(macro) == 1: # undefine this macro
|
| 1065 |
+
pp_opts.append("-U%s" % macro[0])
|
| 1066 |
+
elif len(macro) == 2:
|
| 1067 |
+
if macro[1] is None: # define with no explicit value
|
| 1068 |
+
pp_opts.append("-D%s" % macro[0])
|
| 1069 |
+
else:
|
| 1070 |
+
# XXX *don't* need to be clever about quoting the
|
| 1071 |
+
# macro value here, because we're going to avoid the
|
| 1072 |
+
# shell at all costs when we spawn the command!
|
| 1073 |
+
pp_opts.append("-D%s=%s" % macro)
|
| 1074 |
+
|
| 1075 |
+
for dir in include_dirs:
|
| 1076 |
+
pp_opts.append("-I%s" % dir)
|
| 1077 |
+
return pp_opts
|
| 1078 |
+
|
| 1079 |
+
|
| 1080 |
+
def gen_lib_options (compiler, library_dirs, runtime_library_dirs, libraries):
|
| 1081 |
+
"""Generate linker options for searching library directories and
|
| 1082 |
+
linking with specific libraries. 'libraries' and 'library_dirs' are,
|
| 1083 |
+
respectively, lists of library names (not filenames!) and search
|
| 1084 |
+
directories. Returns a list of command-line options suitable for use
|
| 1085 |
+
with some compiler (depending on the two format strings passed in).
|
| 1086 |
+
"""
|
| 1087 |
+
lib_opts = []
|
| 1088 |
+
|
| 1089 |
+
for dir in library_dirs:
|
| 1090 |
+
lib_opts.append(compiler.library_dir_option(dir))
|
| 1091 |
+
|
| 1092 |
+
for dir in runtime_library_dirs:
|
| 1093 |
+
opt = compiler.runtime_library_dir_option(dir)
|
| 1094 |
+
if isinstance(opt, list):
|
| 1095 |
+
lib_opts = lib_opts + opt
|
| 1096 |
+
else:
|
| 1097 |
+
lib_opts.append(opt)
|
| 1098 |
+
|
| 1099 |
+
# XXX it's important that we *not* remove redundant library mentions!
|
| 1100 |
+
# sometimes you really do have to say "-lfoo -lbar -lfoo" in order to
|
| 1101 |
+
# resolve all symbols. I just hope we never have to say "-lfoo obj.o
|
| 1102 |
+
# -lbar" to get things to work -- that's certainly a possibility, but a
|
| 1103 |
+
# pretty nasty way to arrange your C code.
|
| 1104 |
+
|
| 1105 |
+
for lib in libraries:
|
| 1106 |
+
(lib_dir, lib_name) = os.path.split(lib)
|
| 1107 |
+
if lib_dir:
|
| 1108 |
+
lib_file = compiler.find_library_file([lib_dir], lib_name)
|
| 1109 |
+
if lib_file:
|
| 1110 |
+
lib_opts.append(lib_file)
|
| 1111 |
+
else:
|
| 1112 |
+
compiler.warn("no library file corresponding to "
|
| 1113 |
+
"'%s' found (skipping)" % lib)
|
| 1114 |
+
else:
|
| 1115 |
+
lib_opts.append(compiler.library_option (lib))
|
| 1116 |
+
return lib_opts
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/core.py
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""distutils.core
|
| 2 |
+
|
| 3 |
+
The only module that needs to be imported to use the Distutils; provides
|
| 4 |
+
the 'setup' function (which is to be called from the setup script). Also
|
| 5 |
+
indirectly provides the Distribution and Command classes, although they are
|
| 6 |
+
really defined in distutils.dist and distutils.cmd.
|
| 7 |
+
"""
|
| 8 |
+
|
| 9 |
+
import os
|
| 10 |
+
import sys
|
| 11 |
+
|
| 12 |
+
from distutils.debug import DEBUG
|
| 13 |
+
from distutils.errors import *
|
| 14 |
+
|
| 15 |
+
# Mainly import these so setup scripts can "from distutils.core import" them.
|
| 16 |
+
from distutils.dist import Distribution
|
| 17 |
+
from distutils.cmd import Command
|
| 18 |
+
from distutils.config import PyPIRCCommand
|
| 19 |
+
from distutils.extension import Extension
|
| 20 |
+
|
| 21 |
+
# This is a barebones help message generated displayed when the user
|
| 22 |
+
# runs the setup script with no arguments at all. More useful help
|
| 23 |
+
# is generated with various --help options: global help, list commands,
|
| 24 |
+
# and per-command help.
|
| 25 |
+
USAGE = """\
|
| 26 |
+
usage: %(script)s [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
|
| 27 |
+
or: %(script)s --help [cmd1 cmd2 ...]
|
| 28 |
+
or: %(script)s --help-commands
|
| 29 |
+
or: %(script)s cmd --help
|
| 30 |
+
"""
|
| 31 |
+
|
| 32 |
+
def gen_usage (script_name):
|
| 33 |
+
script = os.path.basename(script_name)
|
| 34 |
+
return USAGE % vars()
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
# Some mild magic to control the behaviour of 'setup()' from 'run_setup()'.
|
| 38 |
+
_setup_stop_after = None
|
| 39 |
+
_setup_distribution = None
|
| 40 |
+
|
| 41 |
+
# Legal keyword arguments for the setup() function
|
| 42 |
+
setup_keywords = ('distclass', 'script_name', 'script_args', 'options',
|
| 43 |
+
'name', 'version', 'author', 'author_email',
|
| 44 |
+
'maintainer', 'maintainer_email', 'url', 'license',
|
| 45 |
+
'description', 'long_description', 'keywords',
|
| 46 |
+
'platforms', 'classifiers', 'download_url',
|
| 47 |
+
'requires', 'provides', 'obsoletes',
|
| 48 |
+
)
|
| 49 |
+
|
| 50 |
+
# Legal keyword arguments for the Extension constructor
|
| 51 |
+
extension_keywords = ('name', 'sources', 'include_dirs',
|
| 52 |
+
'define_macros', 'undef_macros',
|
| 53 |
+
'library_dirs', 'libraries', 'runtime_library_dirs',
|
| 54 |
+
'extra_objects', 'extra_compile_args', 'extra_link_args',
|
| 55 |
+
'swig_opts', 'export_symbols', 'depends', 'language')
|
| 56 |
+
|
| 57 |
+
def setup (**attrs):
|
| 58 |
+
"""The gateway to the Distutils: do everything your setup script needs
|
| 59 |
+
to do, in a highly flexible and user-driven way. Briefly: create a
|
| 60 |
+
Distribution instance; find and parse config files; parse the command
|
| 61 |
+
line; run each Distutils command found there, customized by the options
|
| 62 |
+
supplied to 'setup()' (as keyword arguments), in config files, and on
|
| 63 |
+
the command line.
|
| 64 |
+
|
| 65 |
+
The Distribution instance might be an instance of a class supplied via
|
| 66 |
+
the 'distclass' keyword argument to 'setup'; if no such class is
|
| 67 |
+
supplied, then the Distribution class (in dist.py) is instantiated.
|
| 68 |
+
All other arguments to 'setup' (except for 'cmdclass') are used to set
|
| 69 |
+
attributes of the Distribution instance.
|
| 70 |
+
|
| 71 |
+
The 'cmdclass' argument, if supplied, is a dictionary mapping command
|
| 72 |
+
names to command classes. Each command encountered on the command line
|
| 73 |
+
will be turned into a command class, which is in turn instantiated; any
|
| 74 |
+
class found in 'cmdclass' is used in place of the default, which is
|
| 75 |
+
(for command 'foo_bar') class 'foo_bar' in module
|
| 76 |
+
'distutils.command.foo_bar'. The command class must provide a
|
| 77 |
+
'user_options' attribute which is a list of option specifiers for
|
| 78 |
+
'distutils.fancy_getopt'. Any command-line options between the current
|
| 79 |
+
and the next command are used to set attributes of the current command
|
| 80 |
+
object.
|
| 81 |
+
|
| 82 |
+
When the entire command-line has been successfully parsed, calls the
|
| 83 |
+
'run()' method on each command object in turn. This method will be
|
| 84 |
+
driven entirely by the Distribution object (which each command object
|
| 85 |
+
has a reference to, thanks to its constructor), and the
|
| 86 |
+
command-specific options that became attributes of each command
|
| 87 |
+
object.
|
| 88 |
+
"""
|
| 89 |
+
|
| 90 |
+
global _setup_stop_after, _setup_distribution
|
| 91 |
+
|
| 92 |
+
# Determine the distribution class -- either caller-supplied or
|
| 93 |
+
# our Distribution (see below).
|
| 94 |
+
klass = attrs.get('distclass')
|
| 95 |
+
if klass:
|
| 96 |
+
del attrs['distclass']
|
| 97 |
+
else:
|
| 98 |
+
klass = Distribution
|
| 99 |
+
|
| 100 |
+
if 'script_name' not in attrs:
|
| 101 |
+
attrs['script_name'] = os.path.basename(sys.argv[0])
|
| 102 |
+
if 'script_args' not in attrs:
|
| 103 |
+
attrs['script_args'] = sys.argv[1:]
|
| 104 |
+
|
| 105 |
+
# Create the Distribution instance, using the remaining arguments
|
| 106 |
+
# (ie. everything except distclass) to initialize it
|
| 107 |
+
try:
|
| 108 |
+
_setup_distribution = dist = klass(attrs)
|
| 109 |
+
except DistutilsSetupError as msg:
|
| 110 |
+
if 'name' not in attrs:
|
| 111 |
+
raise SystemExit("error in setup command: %s" % msg)
|
| 112 |
+
else:
|
| 113 |
+
raise SystemExit("error in %s setup command: %s" % \
|
| 114 |
+
(attrs['name'], msg))
|
| 115 |
+
|
| 116 |
+
if _setup_stop_after == "init":
|
| 117 |
+
return dist
|
| 118 |
+
|
| 119 |
+
# Find and parse the config file(s): they will override options from
|
| 120 |
+
# the setup script, but be overridden by the command line.
|
| 121 |
+
dist.parse_config_files()
|
| 122 |
+
|
| 123 |
+
if DEBUG:
|
| 124 |
+
print("options (after parsing config files):")
|
| 125 |
+
dist.dump_option_dicts()
|
| 126 |
+
|
| 127 |
+
if _setup_stop_after == "config":
|
| 128 |
+
return dist
|
| 129 |
+
|
| 130 |
+
# Parse the command line and override config files; any
|
| 131 |
+
# command-line errors are the end user's fault, so turn them into
|
| 132 |
+
# SystemExit to suppress tracebacks.
|
| 133 |
+
try:
|
| 134 |
+
ok = dist.parse_command_line()
|
| 135 |
+
except DistutilsArgError as msg:
|
| 136 |
+
raise SystemExit(gen_usage(dist.script_name) + "\nerror: %s" % msg)
|
| 137 |
+
|
| 138 |
+
if DEBUG:
|
| 139 |
+
print("options (after parsing command line):")
|
| 140 |
+
dist.dump_option_dicts()
|
| 141 |
+
|
| 142 |
+
if _setup_stop_after == "commandline":
|
| 143 |
+
return dist
|
| 144 |
+
|
| 145 |
+
# And finally, run all the commands found on the command line.
|
| 146 |
+
if ok:
|
| 147 |
+
try:
|
| 148 |
+
dist.run_commands()
|
| 149 |
+
except KeyboardInterrupt:
|
| 150 |
+
raise SystemExit("interrupted")
|
| 151 |
+
except OSError as exc:
|
| 152 |
+
if DEBUG:
|
| 153 |
+
sys.stderr.write("error: %s\n" % (exc,))
|
| 154 |
+
raise
|
| 155 |
+
else:
|
| 156 |
+
raise SystemExit("error: %s" % (exc,))
|
| 157 |
+
|
| 158 |
+
except (DistutilsError,
|
| 159 |
+
CCompilerError) as msg:
|
| 160 |
+
if DEBUG:
|
| 161 |
+
raise
|
| 162 |
+
else:
|
| 163 |
+
raise SystemExit("error: " + str(msg))
|
| 164 |
+
|
| 165 |
+
return dist
|
| 166 |
+
|
| 167 |
+
# setup ()
|
| 168 |
+
|
| 169 |
+
|
| 170 |
+
def run_setup (script_name, script_args=None, stop_after="run"):
|
| 171 |
+
"""Run a setup script in a somewhat controlled environment, and
|
| 172 |
+
return the Distribution instance that drives things. This is useful
|
| 173 |
+
if you need to find out the distribution meta-data (passed as
|
| 174 |
+
keyword args from 'script' to 'setup()', or the contents of the
|
| 175 |
+
config files or command-line.
|
| 176 |
+
|
| 177 |
+
'script_name' is a file that will be read and run with 'exec()';
|
| 178 |
+
'sys.argv[0]' will be replaced with 'script' for the duration of the
|
| 179 |
+
call. 'script_args' is a list of strings; if supplied,
|
| 180 |
+
'sys.argv[1:]' will be replaced by 'script_args' for the duration of
|
| 181 |
+
the call.
|
| 182 |
+
|
| 183 |
+
'stop_after' tells 'setup()' when to stop processing; possible
|
| 184 |
+
values:
|
| 185 |
+
init
|
| 186 |
+
stop after the Distribution instance has been created and
|
| 187 |
+
populated with the keyword arguments to 'setup()'
|
| 188 |
+
config
|
| 189 |
+
stop after config files have been parsed (and their data
|
| 190 |
+
stored in the Distribution instance)
|
| 191 |
+
commandline
|
| 192 |
+
stop after the command-line ('sys.argv[1:]' or 'script_args')
|
| 193 |
+
have been parsed (and the data stored in the Distribution)
|
| 194 |
+
run [default]
|
| 195 |
+
stop after all commands have been run (the same as if 'setup()'
|
| 196 |
+
had been called in the usual way
|
| 197 |
+
|
| 198 |
+
Returns the Distribution instance, which provides all information
|
| 199 |
+
used to drive the Distutils.
|
| 200 |
+
"""
|
| 201 |
+
if stop_after not in ('init', 'config', 'commandline', 'run'):
|
| 202 |
+
raise ValueError("invalid value for 'stop_after': %r" % (stop_after,))
|
| 203 |
+
|
| 204 |
+
global _setup_stop_after, _setup_distribution
|
| 205 |
+
_setup_stop_after = stop_after
|
| 206 |
+
|
| 207 |
+
save_argv = sys.argv.copy()
|
| 208 |
+
g = {'__file__': script_name}
|
| 209 |
+
try:
|
| 210 |
+
try:
|
| 211 |
+
sys.argv[0] = script_name
|
| 212 |
+
if script_args is not None:
|
| 213 |
+
sys.argv[1:] = script_args
|
| 214 |
+
with open(script_name, 'rb') as f:
|
| 215 |
+
exec(f.read(), g)
|
| 216 |
+
finally:
|
| 217 |
+
sys.argv = save_argv
|
| 218 |
+
_setup_stop_after = None
|
| 219 |
+
except SystemExit:
|
| 220 |
+
# Hmm, should we do something if exiting with a non-zero code
|
| 221 |
+
# (ie. error)?
|
| 222 |
+
pass
|
| 223 |
+
|
| 224 |
+
if _setup_distribution is None:
|
| 225 |
+
raise RuntimeError(("'distutils.core.setup()' was never called -- "
|
| 226 |
+
"perhaps '%s' is not a Distutils setup script?") % \
|
| 227 |
+
script_name)
|
| 228 |
+
|
| 229 |
+
# I wonder if the setup script's namespace -- g and l -- would be of
|
| 230 |
+
# any interest to callers?
|
| 231 |
+
#print "_setup_distribution:", _setup_distribution
|
| 232 |
+
return _setup_distribution
|
| 233 |
+
|
| 234 |
+
# run_setup ()
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/cygwinccompiler.py
ADDED
|
@@ -0,0 +1,412 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""distutils.cygwinccompiler
|
| 2 |
+
|
| 3 |
+
Provides the CygwinCCompiler class, a subclass of UnixCCompiler that
|
| 4 |
+
handles the Cygwin port of the GNU C compiler to Windows. It also contains
|
| 5 |
+
the Mingw32CCompiler class which handles the mingw32 port of GCC (same as
|
| 6 |
+
cygwin in no-cygwin mode).
|
| 7 |
+
"""
|
| 8 |
+
|
| 9 |
+
# problems:
|
| 10 |
+
#
|
| 11 |
+
# * if you use a msvc compiled python version (1.5.2)
|
| 12 |
+
# 1. you have to insert a __GNUC__ section in its config.h
|
| 13 |
+
# 2. you have to generate an import library for its dll
|
| 14 |
+
# - create a def-file for python??.dll
|
| 15 |
+
# - create an import library using
|
| 16 |
+
# dlltool --dllname python15.dll --def python15.def \
|
| 17 |
+
# --output-lib libpython15.a
|
| 18 |
+
#
|
| 19 |
+
# see also http://starship.python.net/crew/kernr/mingw32/Notes.html
|
| 20 |
+
#
|
| 21 |
+
# * We put export_symbols in a def-file, and don't use
|
| 22 |
+
# --export-all-symbols because it doesn't worked reliable in some
|
| 23 |
+
# tested configurations. And because other windows compilers also
|
| 24 |
+
# need their symbols specified this no serious problem.
|
| 25 |
+
#
|
| 26 |
+
# tested configurations:
|
| 27 |
+
#
|
| 28 |
+
# * cygwin gcc 2.91.57/ld 2.9.4/dllwrap 0.2.4 works
|
| 29 |
+
# (after patching python's config.h and for C++ some other include files)
|
| 30 |
+
# see also http://starship.python.net/crew/kernr/mingw32/Notes.html
|
| 31 |
+
# * mingw32 gcc 2.95.2/ld 2.9.4/dllwrap 0.2.4 works
|
| 32 |
+
# (ld doesn't support -shared, so we use dllwrap)
|
| 33 |
+
# * cygwin gcc 2.95.2/ld 2.10.90/dllwrap 2.10.90 works now
|
| 34 |
+
# - its dllwrap doesn't work, there is a bug in binutils 2.10.90
|
| 35 |
+
# see also http://sources.redhat.com/ml/cygwin/2000-06/msg01274.html
|
| 36 |
+
# - using gcc -mdll instead dllwrap doesn't work without -static because
|
| 37 |
+
# it tries to link against dlls instead their import libraries. (If
|
| 38 |
+
# it finds the dll first.)
|
| 39 |
+
# By specifying -static we force ld to link against the import libraries,
|
| 40 |
+
# this is windows standard and there are normally not the necessary symbols
|
| 41 |
+
# in the dlls.
|
| 42 |
+
# *** only the version of June 2000 shows these problems
|
| 43 |
+
# * cygwin gcc 3.2/ld 2.13.90 works
|
| 44 |
+
# (ld supports -shared)
|
| 45 |
+
# * mingw gcc 3.2/ld 2.13 works
|
| 46 |
+
# (ld supports -shared)
|
| 47 |
+
|
| 48 |
+
import os
|
| 49 |
+
import sys
|
| 50 |
+
import copy
|
| 51 |
+
from subprocess import Popen, PIPE, check_output
|
| 52 |
+
import re
|
| 53 |
+
|
| 54 |
+
from distutils.ccompiler import gen_preprocess_options, gen_lib_options
|
| 55 |
+
from distutils.unixccompiler import UnixCCompiler
|
| 56 |
+
from distutils.file_util import write_file
|
| 57 |
+
from distutils.errors import (DistutilsExecError, CCompilerError,
|
| 58 |
+
CompileError, UnknownFileError)
|
| 59 |
+
from distutils import log
|
| 60 |
+
from distutils.version import LooseVersion
|
| 61 |
+
from distutils.spawn import find_executable
|
| 62 |
+
|
| 63 |
+
def get_msvcr():
|
| 64 |
+
"""Include the appropriate MSVC runtime library if Python was built
|
| 65 |
+
with MSVC 7.0 or later.
|
| 66 |
+
"""
|
| 67 |
+
msc_pos = sys.version.find('MSC v.')
|
| 68 |
+
if msc_pos != -1:
|
| 69 |
+
msc_ver = sys.version[msc_pos+6:msc_pos+10]
|
| 70 |
+
if msc_ver == '1300':
|
| 71 |
+
# MSVC 7.0
|
| 72 |
+
return ['msvcr70']
|
| 73 |
+
elif msc_ver == '1310':
|
| 74 |
+
# MSVC 7.1
|
| 75 |
+
return ['msvcr71']
|
| 76 |
+
elif msc_ver == '1400':
|
| 77 |
+
# VS2005 / MSVC 8.0
|
| 78 |
+
return ['msvcr80']
|
| 79 |
+
elif msc_ver == '1500':
|
| 80 |
+
# VS2008 / MSVC 9.0
|
| 81 |
+
return ['msvcr90']
|
| 82 |
+
elif msc_ver == '1600':
|
| 83 |
+
# VS2010 / MSVC 10.0
|
| 84 |
+
return ['msvcr100']
|
| 85 |
+
elif int(msc_ver) >= 1900:
|
| 86 |
+
# VS2015 / MSVC 14.0
|
| 87 |
+
return ['msvcr140']
|
| 88 |
+
else:
|
| 89 |
+
raise ValueError("Unknown MS Compiler version %s " % msc_ver)
|
| 90 |
+
|
| 91 |
+
|
| 92 |
+
class CygwinCCompiler(UnixCCompiler):
|
| 93 |
+
""" Handles the Cygwin port of the GNU C compiler to Windows.
|
| 94 |
+
"""
|
| 95 |
+
compiler_type = 'cygwin'
|
| 96 |
+
obj_extension = ".o"
|
| 97 |
+
static_lib_extension = ".a"
|
| 98 |
+
shared_lib_extension = ".dll"
|
| 99 |
+
static_lib_format = "lib%s%s"
|
| 100 |
+
shared_lib_format = "%s%s"
|
| 101 |
+
exe_extension = ".exe"
|
| 102 |
+
|
| 103 |
+
def __init__(self, verbose=0, dry_run=0, force=0):
|
| 104 |
+
|
| 105 |
+
UnixCCompiler.__init__(self, verbose, dry_run, force)
|
| 106 |
+
|
| 107 |
+
status, details = check_config_h()
|
| 108 |
+
self.debug_print("Python's GCC status: %s (details: %s)" %
|
| 109 |
+
(status, details))
|
| 110 |
+
if status is not CONFIG_H_OK:
|
| 111 |
+
self.warn(
|
| 112 |
+
"Python's pyconfig.h doesn't seem to support your compiler. "
|
| 113 |
+
"Reason: %s. "
|
| 114 |
+
"Compiling may fail because of undefined preprocessor macros."
|
| 115 |
+
% details)
|
| 116 |
+
|
| 117 |
+
self.gcc_version, self.ld_version, self.dllwrap_version = \
|
| 118 |
+
get_versions()
|
| 119 |
+
self.debug_print(self.compiler_type + ": gcc %s, ld %s, dllwrap %s\n" %
|
| 120 |
+
(self.gcc_version,
|
| 121 |
+
self.ld_version,
|
| 122 |
+
self.dllwrap_version) )
|
| 123 |
+
|
| 124 |
+
# ld_version >= "2.10.90" and < "2.13" should also be able to use
|
| 125 |
+
# gcc -mdll instead of dllwrap
|
| 126 |
+
# Older dllwraps had own version numbers, newer ones use the
|
| 127 |
+
# same as the rest of binutils ( also ld )
|
| 128 |
+
# dllwrap 2.10.90 is buggy
|
| 129 |
+
if self.ld_version >= "2.10.90":
|
| 130 |
+
self.linker_dll = "gcc"
|
| 131 |
+
else:
|
| 132 |
+
self.linker_dll = "dllwrap"
|
| 133 |
+
|
| 134 |
+
# ld_version >= "2.13" support -shared so use it instead of
|
| 135 |
+
# -mdll -static
|
| 136 |
+
if self.ld_version >= "2.13":
|
| 137 |
+
shared_option = "-shared"
|
| 138 |
+
else:
|
| 139 |
+
shared_option = "-mdll -static"
|
| 140 |
+
|
| 141 |
+
# Hard-code GCC because that's what this is all about.
|
| 142 |
+
# XXX optimization, warnings etc. should be customizable.
|
| 143 |
+
self.set_executables(compiler='gcc -mcygwin -O -Wall',
|
| 144 |
+
compiler_so='gcc -mcygwin -mdll -O -Wall',
|
| 145 |
+
compiler_cxx='g++ -mcygwin -O -Wall',
|
| 146 |
+
linker_exe='gcc -mcygwin',
|
| 147 |
+
linker_so=('%s -mcygwin %s' %
|
| 148 |
+
(self.linker_dll, shared_option)))
|
| 149 |
+
|
| 150 |
+
# cygwin and mingw32 need different sets of libraries
|
| 151 |
+
if self.gcc_version == "2.91.57":
|
| 152 |
+
# cygwin shouldn't need msvcrt, but without the dlls will crash
|
| 153 |
+
# (gcc version 2.91.57) -- perhaps something about initialization
|
| 154 |
+
self.dll_libraries=["msvcrt"]
|
| 155 |
+
self.warn(
|
| 156 |
+
"Consider upgrading to a newer version of gcc")
|
| 157 |
+
else:
|
| 158 |
+
# Include the appropriate MSVC runtime library if Python was built
|
| 159 |
+
# with MSVC 7.0 or later.
|
| 160 |
+
self.dll_libraries = get_msvcr()
|
| 161 |
+
|
| 162 |
+
def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
|
| 163 |
+
"""Compiles the source by spawning GCC and windres if needed."""
|
| 164 |
+
if ext == '.rc' or ext == '.res':
|
| 165 |
+
# gcc needs '.res' and '.rc' compiled to object files !!!
|
| 166 |
+
try:
|
| 167 |
+
self.spawn(["windres", "-i", src, "-o", obj])
|
| 168 |
+
except DistutilsExecError as msg:
|
| 169 |
+
raise CompileError(msg)
|
| 170 |
+
else: # for other files use the C-compiler
|
| 171 |
+
try:
|
| 172 |
+
self.spawn(self.compiler_so + cc_args + [src, '-o', obj] +
|
| 173 |
+
extra_postargs)
|
| 174 |
+
except DistutilsExecError as msg:
|
| 175 |
+
raise CompileError(msg)
|
| 176 |
+
|
| 177 |
+
def link(self, target_desc, objects, output_filename, output_dir=None,
|
| 178 |
+
libraries=None, library_dirs=None, runtime_library_dirs=None,
|
| 179 |
+
export_symbols=None, debug=0, extra_preargs=None,
|
| 180 |
+
extra_postargs=None, build_temp=None, target_lang=None):
|
| 181 |
+
"""Link the objects."""
|
| 182 |
+
# use separate copies, so we can modify the lists
|
| 183 |
+
extra_preargs = copy.copy(extra_preargs or [])
|
| 184 |
+
libraries = copy.copy(libraries or [])
|
| 185 |
+
objects = copy.copy(objects or [])
|
| 186 |
+
|
| 187 |
+
# Additional libraries
|
| 188 |
+
libraries.extend(self.dll_libraries)
|
| 189 |
+
|
| 190 |
+
# handle export symbols by creating a def-file
|
| 191 |
+
# with executables this only works with gcc/ld as linker
|
| 192 |
+
if ((export_symbols is not None) and
|
| 193 |
+
(target_desc != self.EXECUTABLE or self.linker_dll == "gcc")):
|
| 194 |
+
# (The linker doesn't do anything if output is up-to-date.
|
| 195 |
+
# So it would probably better to check if we really need this,
|
| 196 |
+
# but for this we had to insert some unchanged parts of
|
| 197 |
+
# UnixCCompiler, and this is not what we want.)
|
| 198 |
+
|
| 199 |
+
# we want to put some files in the same directory as the
|
| 200 |
+
# object files are, build_temp doesn't help much
|
| 201 |
+
# where are the object files
|
| 202 |
+
temp_dir = os.path.dirname(objects[0])
|
| 203 |
+
# name of dll to give the helper files the same base name
|
| 204 |
+
(dll_name, dll_extension) = os.path.splitext(
|
| 205 |
+
os.path.basename(output_filename))
|
| 206 |
+
|
| 207 |
+
# generate the filenames for these files
|
| 208 |
+
def_file = os.path.join(temp_dir, dll_name + ".def")
|
| 209 |
+
lib_file = os.path.join(temp_dir, 'lib' + dll_name + ".a")
|
| 210 |
+
|
| 211 |
+
# Generate .def file
|
| 212 |
+
contents = [
|
| 213 |
+
"LIBRARY %s" % os.path.basename(output_filename),
|
| 214 |
+
"EXPORTS"]
|
| 215 |
+
for sym in export_symbols:
|
| 216 |
+
contents.append(sym)
|
| 217 |
+
self.execute(write_file, (def_file, contents),
|
| 218 |
+
"writing %s" % def_file)
|
| 219 |
+
|
| 220 |
+
# next add options for def-file and to creating import libraries
|
| 221 |
+
|
| 222 |
+
# dllwrap uses different options than gcc/ld
|
| 223 |
+
if self.linker_dll == "dllwrap":
|
| 224 |
+
extra_preargs.extend(["--output-lib", lib_file])
|
| 225 |
+
# for dllwrap we have to use a special option
|
| 226 |
+
extra_preargs.extend(["--def", def_file])
|
| 227 |
+
# we use gcc/ld here and can be sure ld is >= 2.9.10
|
| 228 |
+
else:
|
| 229 |
+
# doesn't work: bfd_close build\...\libfoo.a: Invalid operation
|
| 230 |
+
#extra_preargs.extend(["-Wl,--out-implib,%s" % lib_file])
|
| 231 |
+
# for gcc/ld the def-file is specified as any object files
|
| 232 |
+
objects.append(def_file)
|
| 233 |
+
|
| 234 |
+
#end: if ((export_symbols is not None) and
|
| 235 |
+
# (target_desc != self.EXECUTABLE or self.linker_dll == "gcc")):
|
| 236 |
+
|
| 237 |
+
# who wants symbols and a many times larger output file
|
| 238 |
+
# should explicitly switch the debug mode on
|
| 239 |
+
# otherwise we let dllwrap/ld strip the output file
|
| 240 |
+
# (On my machine: 10KiB < stripped_file < ??100KiB
|
| 241 |
+
# unstripped_file = stripped_file + XXX KiB
|
| 242 |
+
# ( XXX=254 for a typical python extension))
|
| 243 |
+
if not debug:
|
| 244 |
+
extra_preargs.append("-s")
|
| 245 |
+
|
| 246 |
+
UnixCCompiler.link(self, target_desc, objects, output_filename,
|
| 247 |
+
output_dir, libraries, library_dirs,
|
| 248 |
+
runtime_library_dirs,
|
| 249 |
+
None, # export_symbols, we do this in our def-file
|
| 250 |
+
debug, extra_preargs, extra_postargs, build_temp,
|
| 251 |
+
target_lang)
|
| 252 |
+
|
| 253 |
+
# -- Miscellaneous methods -----------------------------------------
|
| 254 |
+
|
| 255 |
+
def object_filenames(self, source_filenames, strip_dir=0, output_dir=''):
|
| 256 |
+
"""Adds supports for rc and res files."""
|
| 257 |
+
if output_dir is None:
|
| 258 |
+
output_dir = ''
|
| 259 |
+
obj_names = []
|
| 260 |
+
for src_name in source_filenames:
|
| 261 |
+
# use normcase to make sure '.rc' is really '.rc' and not '.RC'
|
| 262 |
+
base, ext = os.path.splitext(os.path.normcase(src_name))
|
| 263 |
+
if ext not in (self.src_extensions + ['.rc','.res']):
|
| 264 |
+
raise UnknownFileError("unknown file type '%s' (from '%s')" % \
|
| 265 |
+
(ext, src_name))
|
| 266 |
+
if strip_dir:
|
| 267 |
+
base = os.path.basename (base)
|
| 268 |
+
if ext in ('.res', '.rc'):
|
| 269 |
+
# these need to be compiled to object files
|
| 270 |
+
obj_names.append (os.path.join(output_dir,
|
| 271 |
+
base + ext + self.obj_extension))
|
| 272 |
+
else:
|
| 273 |
+
obj_names.append (os.path.join(output_dir,
|
| 274 |
+
base + self.obj_extension))
|
| 275 |
+
return obj_names
|
| 276 |
+
|
| 277 |
+
# the same as cygwin plus some additional parameters
|
| 278 |
+
class Mingw32CCompiler(CygwinCCompiler):
|
| 279 |
+
""" Handles the Mingw32 port of the GNU C compiler to Windows.
|
| 280 |
+
"""
|
| 281 |
+
compiler_type = 'mingw32'
|
| 282 |
+
|
| 283 |
+
def __init__(self, verbose=0, dry_run=0, force=0):
|
| 284 |
+
|
| 285 |
+
CygwinCCompiler.__init__ (self, verbose, dry_run, force)
|
| 286 |
+
|
| 287 |
+
# ld_version >= "2.13" support -shared so use it instead of
|
| 288 |
+
# -mdll -static
|
| 289 |
+
if self.ld_version >= "2.13":
|
| 290 |
+
shared_option = "-shared"
|
| 291 |
+
else:
|
| 292 |
+
shared_option = "-mdll -static"
|
| 293 |
+
|
| 294 |
+
# A real mingw32 doesn't need to specify a different entry point,
|
| 295 |
+
# but cygwin 2.91.57 in no-cygwin-mode needs it.
|
| 296 |
+
if self.gcc_version <= "2.91.57":
|
| 297 |
+
entry_point = '--entry _DllMain@12'
|
| 298 |
+
else:
|
| 299 |
+
entry_point = ''
|
| 300 |
+
|
| 301 |
+
if is_cygwingcc():
|
| 302 |
+
raise CCompilerError(
|
| 303 |
+
'Cygwin gcc cannot be used with --compiler=mingw32')
|
| 304 |
+
|
| 305 |
+
if sys.maxsize == 2**31 - 1:
|
| 306 |
+
ms_win=' -DMS_WIN32'
|
| 307 |
+
else:
|
| 308 |
+
ms_win=' -DMS_WIN64'
|
| 309 |
+
self.set_executables(compiler='gcc -O -Wall'+ms_win,
|
| 310 |
+
compiler_so='gcc -mdll -O -Wall'+ms_win,
|
| 311 |
+
compiler_cxx='g++ -O -Wall'+ms_win,
|
| 312 |
+
linker_exe='gcc',
|
| 313 |
+
linker_so='%s %s %s'
|
| 314 |
+
% (self.linker_dll, shared_option,
|
| 315 |
+
entry_point))
|
| 316 |
+
# Maybe we should also append -mthreads, but then the finished
|
| 317 |
+
# dlls need another dll (mingwm10.dll see Mingw32 docs)
|
| 318 |
+
# (-mthreads: Support thread-safe exception handling on `Mingw32')
|
| 319 |
+
|
| 320 |
+
# no additional libraries needed
|
| 321 |
+
self.dll_libraries=[]
|
| 322 |
+
|
| 323 |
+
# Include the appropriate MSVC runtime library if Python was built
|
| 324 |
+
# with MSVC 7.0 or later.
|
| 325 |
+
self.dll_libraries = get_msvcr()
|
| 326 |
+
|
| 327 |
+
# Because these compilers aren't configured in Python's pyconfig.h file by
|
| 328 |
+
# default, we should at least warn the user if he is using an unmodified
|
| 329 |
+
# version.
|
| 330 |
+
|
| 331 |
+
CONFIG_H_OK = "ok"
|
| 332 |
+
CONFIG_H_NOTOK = "not ok"
|
| 333 |
+
CONFIG_H_UNCERTAIN = "uncertain"
|
| 334 |
+
|
| 335 |
+
def check_config_h():
|
| 336 |
+
"""Check if the current Python installation appears amenable to building
|
| 337 |
+
extensions with GCC.
|
| 338 |
+
|
| 339 |
+
Returns a tuple (status, details), where 'status' is one of the following
|
| 340 |
+
constants:
|
| 341 |
+
|
| 342 |
+
- CONFIG_H_OK: all is well, go ahead and compile
|
| 343 |
+
- CONFIG_H_NOTOK: doesn't look good
|
| 344 |
+
- CONFIG_H_UNCERTAIN: not sure -- unable to read pyconfig.h
|
| 345 |
+
|
| 346 |
+
'details' is a human-readable string explaining the situation.
|
| 347 |
+
|
| 348 |
+
Note there are two ways to conclude "OK": either 'sys.version' contains
|
| 349 |
+
the string "GCC" (implying that this Python was built with GCC), or the
|
| 350 |
+
installed "pyconfig.h" contains the string "__GNUC__".
|
| 351 |
+
"""
|
| 352 |
+
|
| 353 |
+
# XXX since this function also checks sys.version, it's not strictly a
|
| 354 |
+
# "pyconfig.h" check -- should probably be renamed...
|
| 355 |
+
|
| 356 |
+
from distutils import sysconfig
|
| 357 |
+
|
| 358 |
+
# if sys.version contains GCC then python was compiled with GCC, and the
|
| 359 |
+
# pyconfig.h file should be OK
|
| 360 |
+
if "GCC" in sys.version:
|
| 361 |
+
return CONFIG_H_OK, "sys.version mentions 'GCC'"
|
| 362 |
+
|
| 363 |
+
# let's see if __GNUC__ is mentioned in python.h
|
| 364 |
+
fn = sysconfig.get_config_h_filename()
|
| 365 |
+
try:
|
| 366 |
+
config_h = open(fn)
|
| 367 |
+
try:
|
| 368 |
+
if "__GNUC__" in config_h.read():
|
| 369 |
+
return CONFIG_H_OK, "'%s' mentions '__GNUC__'" % fn
|
| 370 |
+
else:
|
| 371 |
+
return CONFIG_H_NOTOK, "'%s' does not mention '__GNUC__'" % fn
|
| 372 |
+
finally:
|
| 373 |
+
config_h.close()
|
| 374 |
+
except OSError as exc:
|
| 375 |
+
return (CONFIG_H_UNCERTAIN,
|
| 376 |
+
"couldn't read '%s': %s" % (fn, exc.strerror))
|
| 377 |
+
|
| 378 |
+
RE_VERSION = re.compile(br'(\d+\.\d+(\.\d+)*)')
|
| 379 |
+
|
| 380 |
+
def _find_exe_version(cmd):
|
| 381 |
+
"""Find the version of an executable by running `cmd` in the shell.
|
| 382 |
+
|
| 383 |
+
If the command is not found, or the output does not match
|
| 384 |
+
`RE_VERSION`, returns None.
|
| 385 |
+
"""
|
| 386 |
+
executable = cmd.split()[0]
|
| 387 |
+
if find_executable(executable) is None:
|
| 388 |
+
return None
|
| 389 |
+
out = Popen(cmd, shell=True, stdout=PIPE).stdout
|
| 390 |
+
try:
|
| 391 |
+
out_string = out.read()
|
| 392 |
+
finally:
|
| 393 |
+
out.close()
|
| 394 |
+
result = RE_VERSION.search(out_string)
|
| 395 |
+
if result is None:
|
| 396 |
+
return None
|
| 397 |
+
# LooseVersion works with strings
|
| 398 |
+
# so we need to decode our bytes
|
| 399 |
+
return LooseVersion(result.group(1).decode())
|
| 400 |
+
|
| 401 |
+
def get_versions():
|
| 402 |
+
""" Try to find out the versions of gcc, ld and dllwrap.
|
| 403 |
+
|
| 404 |
+
If not possible it returns None for it.
|
| 405 |
+
"""
|
| 406 |
+
commands = ['gcc -dumpversion', 'ld -v', 'dllwrap --version']
|
| 407 |
+
return tuple([_find_exe_version(cmd) for cmd in commands])
|
| 408 |
+
|
| 409 |
+
def is_cygwingcc():
|
| 410 |
+
'''Try to determine if the gcc that would be used is from cygwin.'''
|
| 411 |
+
out_string = check_output(['gcc', '-dumpmachine'])
|
| 412 |
+
return out_string.strip().endswith(b'cygwin')
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/debug.py
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
|
| 3 |
+
# If DISTUTILS_DEBUG is anything other than the empty string, we run in
|
| 4 |
+
# debug mode.
|
| 5 |
+
DEBUG = os.environ.get('DISTUTILS_DEBUG')
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/dep_util.py
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""distutils.dep_util
|
| 2 |
+
|
| 3 |
+
Utility functions for simple, timestamp-based dependency of files
|
| 4 |
+
and groups of files; also, function based entirely on such
|
| 5 |
+
timestamp dependency analysis."""
|
| 6 |
+
|
| 7 |
+
import os
|
| 8 |
+
from distutils.errors import DistutilsFileError
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
def newer (source, target):
|
| 12 |
+
"""Return true if 'source' exists and is more recently modified than
|
| 13 |
+
'target', or if 'source' exists and 'target' doesn't. Return false if
|
| 14 |
+
both exist and 'target' is the same age or younger than 'source'.
|
| 15 |
+
Raise DistutilsFileError if 'source' does not exist.
|
| 16 |
+
"""
|
| 17 |
+
if not os.path.exists(source):
|
| 18 |
+
raise DistutilsFileError("file '%s' does not exist" %
|
| 19 |
+
os.path.abspath(source))
|
| 20 |
+
if not os.path.exists(target):
|
| 21 |
+
return 1
|
| 22 |
+
|
| 23 |
+
from stat import ST_MTIME
|
| 24 |
+
mtime1 = os.stat(source)[ST_MTIME]
|
| 25 |
+
mtime2 = os.stat(target)[ST_MTIME]
|
| 26 |
+
|
| 27 |
+
return mtime1 > mtime2
|
| 28 |
+
|
| 29 |
+
# newer ()
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
def newer_pairwise (sources, targets):
|
| 33 |
+
"""Walk two filename lists in parallel, testing if each source is newer
|
| 34 |
+
than its corresponding target. Return a pair of lists (sources,
|
| 35 |
+
targets) where source is newer than target, according to the semantics
|
| 36 |
+
of 'newer()'.
|
| 37 |
+
"""
|
| 38 |
+
if len(sources) != len(targets):
|
| 39 |
+
raise ValueError("'sources' and 'targets' must be same length")
|
| 40 |
+
|
| 41 |
+
# build a pair of lists (sources, targets) where source is newer
|
| 42 |
+
n_sources = []
|
| 43 |
+
n_targets = []
|
| 44 |
+
for i in range(len(sources)):
|
| 45 |
+
if newer(sources[i], targets[i]):
|
| 46 |
+
n_sources.append(sources[i])
|
| 47 |
+
n_targets.append(targets[i])
|
| 48 |
+
|
| 49 |
+
return (n_sources, n_targets)
|
| 50 |
+
|
| 51 |
+
# newer_pairwise ()
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
def newer_group (sources, target, missing='error'):
|
| 55 |
+
"""Return true if 'target' is out-of-date with respect to any file
|
| 56 |
+
listed in 'sources'. In other words, if 'target' exists and is newer
|
| 57 |
+
than every file in 'sources', return false; otherwise return true.
|
| 58 |
+
'missing' controls what we do when a source file is missing; the
|
| 59 |
+
default ("error") is to blow up with an OSError from inside 'stat()';
|
| 60 |
+
if it is "ignore", we silently drop any missing source files; if it is
|
| 61 |
+
"newer", any missing source files make us assume that 'target' is
|
| 62 |
+
out-of-date (this is handy in "dry-run" mode: it'll make you pretend to
|
| 63 |
+
carry out commands that wouldn't work because inputs are missing, but
|
| 64 |
+
that doesn't matter because you're not actually going to run the
|
| 65 |
+
commands).
|
| 66 |
+
"""
|
| 67 |
+
# If the target doesn't even exist, then it's definitely out-of-date.
|
| 68 |
+
if not os.path.exists(target):
|
| 69 |
+
return 1
|
| 70 |
+
|
| 71 |
+
# Otherwise we have to find out the hard way: if *any* source file
|
| 72 |
+
# is more recent than 'target', then 'target' is out-of-date and
|
| 73 |
+
# we can immediately return true. If we fall through to the end
|
| 74 |
+
# of the loop, then 'target' is up-to-date and we return false.
|
| 75 |
+
from stat import ST_MTIME
|
| 76 |
+
target_mtime = os.stat(target)[ST_MTIME]
|
| 77 |
+
for source in sources:
|
| 78 |
+
if not os.path.exists(source):
|
| 79 |
+
if missing == 'error': # blow up when we stat() the file
|
| 80 |
+
pass
|
| 81 |
+
elif missing == 'ignore': # missing source dropped from
|
| 82 |
+
continue # target's dependency list
|
| 83 |
+
elif missing == 'newer': # missing source means target is
|
| 84 |
+
return 1 # out-of-date
|
| 85 |
+
|
| 86 |
+
source_mtime = os.stat(source)[ST_MTIME]
|
| 87 |
+
if source_mtime > target_mtime:
|
| 88 |
+
return 1
|
| 89 |
+
else:
|
| 90 |
+
return 0
|
| 91 |
+
|
| 92 |
+
# newer_group ()
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/dist.py
ADDED
|
@@ -0,0 +1,1256 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""distutils.dist
|
| 2 |
+
|
| 3 |
+
Provides the Distribution class, which represents the module distribution
|
| 4 |
+
being built/installed/distributed.
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
import sys
|
| 8 |
+
import os
|
| 9 |
+
import re
|
| 10 |
+
from email import message_from_file
|
| 11 |
+
|
| 12 |
+
try:
|
| 13 |
+
import warnings
|
| 14 |
+
except ImportError:
|
| 15 |
+
warnings = None
|
| 16 |
+
|
| 17 |
+
from distutils.errors import *
|
| 18 |
+
from distutils.fancy_getopt import FancyGetopt, translate_longopt
|
| 19 |
+
from distutils.util import check_environ, strtobool, rfc822_escape
|
| 20 |
+
from distutils import log
|
| 21 |
+
from distutils.debug import DEBUG
|
| 22 |
+
|
| 23 |
+
# Regex to define acceptable Distutils command names. This is not *quite*
|
| 24 |
+
# the same as a Python NAME -- I don't allow leading underscores. The fact
|
| 25 |
+
# that they're very similar is no coincidence; the default naming scheme is
|
| 26 |
+
# to look for a Python module named after the command.
|
| 27 |
+
command_re = re.compile(r'^[a-zA-Z]([a-zA-Z0-9_]*)$')
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
def _ensure_list(value, fieldname):
|
| 31 |
+
if isinstance(value, str):
|
| 32 |
+
# a string containing comma separated values is okay. It will
|
| 33 |
+
# be converted to a list by Distribution.finalize_options().
|
| 34 |
+
pass
|
| 35 |
+
elif not isinstance(value, list):
|
| 36 |
+
# passing a tuple or an iterator perhaps, warn and convert
|
| 37 |
+
typename = type(value).__name__
|
| 38 |
+
msg = f"Warning: '{fieldname}' should be a list, got type '{typename}'"
|
| 39 |
+
log.log(log.WARN, msg)
|
| 40 |
+
value = list(value)
|
| 41 |
+
return value
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
class Distribution:
|
| 45 |
+
"""The core of the Distutils. Most of the work hiding behind 'setup'
|
| 46 |
+
is really done within a Distribution instance, which farms the work out
|
| 47 |
+
to the Distutils commands specified on the command line.
|
| 48 |
+
|
| 49 |
+
Setup scripts will almost never instantiate Distribution directly,
|
| 50 |
+
unless the 'setup()' function is totally inadequate to their needs.
|
| 51 |
+
However, it is conceivable that a setup script might wish to subclass
|
| 52 |
+
Distribution for some specialized purpose, and then pass the subclass
|
| 53 |
+
to 'setup()' as the 'distclass' keyword argument. If so, it is
|
| 54 |
+
necessary to respect the expectations that 'setup' has of Distribution.
|
| 55 |
+
See the code for 'setup()', in core.py, for details.
|
| 56 |
+
"""
|
| 57 |
+
|
| 58 |
+
# 'global_options' describes the command-line options that may be
|
| 59 |
+
# supplied to the setup script prior to any actual commands.
|
| 60 |
+
# Eg. "./setup.py -n" or "./setup.py --quiet" both take advantage of
|
| 61 |
+
# these global options. This list should be kept to a bare minimum,
|
| 62 |
+
# since every global option is also valid as a command option -- and we
|
| 63 |
+
# don't want to pollute the commands with too many options that they
|
| 64 |
+
# have minimal control over.
|
| 65 |
+
# The fourth entry for verbose means that it can be repeated.
|
| 66 |
+
global_options = [
|
| 67 |
+
('verbose', 'v', "run verbosely (default)", 1),
|
| 68 |
+
('quiet', 'q', "run quietly (turns verbosity off)"),
|
| 69 |
+
('dry-run', 'n', "don't actually do anything"),
|
| 70 |
+
('help', 'h', "show detailed help message"),
|
| 71 |
+
('no-user-cfg', None,
|
| 72 |
+
'ignore pydistutils.cfg in your home directory'),
|
| 73 |
+
]
|
| 74 |
+
|
| 75 |
+
# 'common_usage' is a short (2-3 line) string describing the common
|
| 76 |
+
# usage of the setup script.
|
| 77 |
+
common_usage = """\
|
| 78 |
+
Common commands: (see '--help-commands' for more)
|
| 79 |
+
|
| 80 |
+
setup.py build will build the package underneath 'build/'
|
| 81 |
+
setup.py install will install the package
|
| 82 |
+
"""
|
| 83 |
+
|
| 84 |
+
# options that are not propagated to the commands
|
| 85 |
+
display_options = [
|
| 86 |
+
('help-commands', None,
|
| 87 |
+
"list all available commands"),
|
| 88 |
+
('name', None,
|
| 89 |
+
"print package name"),
|
| 90 |
+
('version', 'V',
|
| 91 |
+
"print package version"),
|
| 92 |
+
('fullname', None,
|
| 93 |
+
"print <package name>-<version>"),
|
| 94 |
+
('author', None,
|
| 95 |
+
"print the author's name"),
|
| 96 |
+
('author-email', None,
|
| 97 |
+
"print the author's email address"),
|
| 98 |
+
('maintainer', None,
|
| 99 |
+
"print the maintainer's name"),
|
| 100 |
+
('maintainer-email', None,
|
| 101 |
+
"print the maintainer's email address"),
|
| 102 |
+
('contact', None,
|
| 103 |
+
"print the maintainer's name if known, else the author's"),
|
| 104 |
+
('contact-email', None,
|
| 105 |
+
"print the maintainer's email address if known, else the author's"),
|
| 106 |
+
('url', None,
|
| 107 |
+
"print the URL for this package"),
|
| 108 |
+
('license', None,
|
| 109 |
+
"print the license of the package"),
|
| 110 |
+
('licence', None,
|
| 111 |
+
"alias for --license"),
|
| 112 |
+
('description', None,
|
| 113 |
+
"print the package description"),
|
| 114 |
+
('long-description', None,
|
| 115 |
+
"print the long package description"),
|
| 116 |
+
('platforms', None,
|
| 117 |
+
"print the list of platforms"),
|
| 118 |
+
('classifiers', None,
|
| 119 |
+
"print the list of classifiers"),
|
| 120 |
+
('keywords', None,
|
| 121 |
+
"print the list of keywords"),
|
| 122 |
+
('provides', None,
|
| 123 |
+
"print the list of packages/modules provided"),
|
| 124 |
+
('requires', None,
|
| 125 |
+
"print the list of packages/modules required"),
|
| 126 |
+
('obsoletes', None,
|
| 127 |
+
"print the list of packages/modules made obsolete")
|
| 128 |
+
]
|
| 129 |
+
display_option_names = [translate_longopt(x[0]) for x in display_options]
|
| 130 |
+
|
| 131 |
+
# negative options are options that exclude other options
|
| 132 |
+
negative_opt = {'quiet': 'verbose'}
|
| 133 |
+
|
| 134 |
+
# -- Creation/initialization methods -------------------------------
|
| 135 |
+
|
| 136 |
+
def __init__(self, attrs=None):
|
| 137 |
+
"""Construct a new Distribution instance: initialize all the
|
| 138 |
+
attributes of a Distribution, and then use 'attrs' (a dictionary
|
| 139 |
+
mapping attribute names to values) to assign some of those
|
| 140 |
+
attributes their "real" values. (Any attributes not mentioned in
|
| 141 |
+
'attrs' will be assigned to some null value: 0, None, an empty list
|
| 142 |
+
or dictionary, etc.) Most importantly, initialize the
|
| 143 |
+
'command_obj' attribute to the empty dictionary; this will be
|
| 144 |
+
filled in with real command objects by 'parse_command_line()'.
|
| 145 |
+
"""
|
| 146 |
+
|
| 147 |
+
# Default values for our command-line options
|
| 148 |
+
self.verbose = 1
|
| 149 |
+
self.dry_run = 0
|
| 150 |
+
self.help = 0
|
| 151 |
+
for attr in self.display_option_names:
|
| 152 |
+
setattr(self, attr, 0)
|
| 153 |
+
|
| 154 |
+
# Store the distribution meta-data (name, version, author, and so
|
| 155 |
+
# forth) in a separate object -- we're getting to have enough
|
| 156 |
+
# information here (and enough command-line options) that it's
|
| 157 |
+
# worth it. Also delegate 'get_XXX()' methods to the 'metadata'
|
| 158 |
+
# object in a sneaky and underhanded (but efficient!) way.
|
| 159 |
+
self.metadata = DistributionMetadata()
|
| 160 |
+
for basename in self.metadata._METHOD_BASENAMES:
|
| 161 |
+
method_name = "get_" + basename
|
| 162 |
+
setattr(self, method_name, getattr(self.metadata, method_name))
|
| 163 |
+
|
| 164 |
+
# 'cmdclass' maps command names to class objects, so we
|
| 165 |
+
# can 1) quickly figure out which class to instantiate when
|
| 166 |
+
# we need to create a new command object, and 2) have a way
|
| 167 |
+
# for the setup script to override command classes
|
| 168 |
+
self.cmdclass = {}
|
| 169 |
+
|
| 170 |
+
# 'command_packages' is a list of packages in which commands
|
| 171 |
+
# are searched for. The factory for command 'foo' is expected
|
| 172 |
+
# to be named 'foo' in the module 'foo' in one of the packages
|
| 173 |
+
# named here. This list is searched from the left; an error
|
| 174 |
+
# is raised if no named package provides the command being
|
| 175 |
+
# searched for. (Always access using get_command_packages().)
|
| 176 |
+
self.command_packages = None
|
| 177 |
+
|
| 178 |
+
# 'script_name' and 'script_args' are usually set to sys.argv[0]
|
| 179 |
+
# and sys.argv[1:], but they can be overridden when the caller is
|
| 180 |
+
# not necessarily a setup script run from the command-line.
|
| 181 |
+
self.script_name = None
|
| 182 |
+
self.script_args = None
|
| 183 |
+
|
| 184 |
+
# 'command_options' is where we store command options between
|
| 185 |
+
# parsing them (from config files, the command-line, etc.) and when
|
| 186 |
+
# they are actually needed -- ie. when the command in question is
|
| 187 |
+
# instantiated. It is a dictionary of dictionaries of 2-tuples:
|
| 188 |
+
# command_options = { command_name : { option : (source, value) } }
|
| 189 |
+
self.command_options = {}
|
| 190 |
+
|
| 191 |
+
# 'dist_files' is the list of (command, pyversion, file) that
|
| 192 |
+
# have been created by any dist commands run so far. This is
|
| 193 |
+
# filled regardless of whether the run is dry or not. pyversion
|
| 194 |
+
# gives sysconfig.get_python_version() if the dist file is
|
| 195 |
+
# specific to a Python version, 'any' if it is good for all
|
| 196 |
+
# Python versions on the target platform, and '' for a source
|
| 197 |
+
# file. pyversion should not be used to specify minimum or
|
| 198 |
+
# maximum required Python versions; use the metainfo for that
|
| 199 |
+
# instead.
|
| 200 |
+
self.dist_files = []
|
| 201 |
+
|
| 202 |
+
# These options are really the business of various commands, rather
|
| 203 |
+
# than of the Distribution itself. We provide aliases for them in
|
| 204 |
+
# Distribution as a convenience to the developer.
|
| 205 |
+
self.packages = None
|
| 206 |
+
self.package_data = {}
|
| 207 |
+
self.package_dir = None
|
| 208 |
+
self.py_modules = None
|
| 209 |
+
self.libraries = None
|
| 210 |
+
self.headers = None
|
| 211 |
+
self.ext_modules = None
|
| 212 |
+
self.ext_package = None
|
| 213 |
+
self.include_dirs = None
|
| 214 |
+
self.extra_path = None
|
| 215 |
+
self.scripts = None
|
| 216 |
+
self.data_files = None
|
| 217 |
+
self.password = ''
|
| 218 |
+
|
| 219 |
+
# And now initialize bookkeeping stuff that can't be supplied by
|
| 220 |
+
# the caller at all. 'command_obj' maps command names to
|
| 221 |
+
# Command instances -- that's how we enforce that every command
|
| 222 |
+
# class is a singleton.
|
| 223 |
+
self.command_obj = {}
|
| 224 |
+
|
| 225 |
+
# 'have_run' maps command names to boolean values; it keeps track
|
| 226 |
+
# of whether we have actually run a particular command, to make it
|
| 227 |
+
# cheap to "run" a command whenever we think we might need to -- if
|
| 228 |
+
# it's already been done, no need for expensive filesystem
|
| 229 |
+
# operations, we just check the 'have_run' dictionary and carry on.
|
| 230 |
+
# It's only safe to query 'have_run' for a command class that has
|
| 231 |
+
# been instantiated -- a false value will be inserted when the
|
| 232 |
+
# command object is created, and replaced with a true value when
|
| 233 |
+
# the command is successfully run. Thus it's probably best to use
|
| 234 |
+
# '.get()' rather than a straight lookup.
|
| 235 |
+
self.have_run = {}
|
| 236 |
+
|
| 237 |
+
# Now we'll use the attrs dictionary (ultimately, keyword args from
|
| 238 |
+
# the setup script) to possibly override any or all of these
|
| 239 |
+
# distribution options.
|
| 240 |
+
|
| 241 |
+
if attrs:
|
| 242 |
+
# Pull out the set of command options and work on them
|
| 243 |
+
# specifically. Note that this order guarantees that aliased
|
| 244 |
+
# command options will override any supplied redundantly
|
| 245 |
+
# through the general options dictionary.
|
| 246 |
+
options = attrs.get('options')
|
| 247 |
+
if options is not None:
|
| 248 |
+
del attrs['options']
|
| 249 |
+
for (command, cmd_options) in options.items():
|
| 250 |
+
opt_dict = self.get_option_dict(command)
|
| 251 |
+
for (opt, val) in cmd_options.items():
|
| 252 |
+
opt_dict[opt] = ("setup script", val)
|
| 253 |
+
|
| 254 |
+
if 'licence' in attrs:
|
| 255 |
+
attrs['license'] = attrs['licence']
|
| 256 |
+
del attrs['licence']
|
| 257 |
+
msg = "'licence' distribution option is deprecated; use 'license'"
|
| 258 |
+
if warnings is not None:
|
| 259 |
+
warnings.warn(msg)
|
| 260 |
+
else:
|
| 261 |
+
sys.stderr.write(msg + "\n")
|
| 262 |
+
|
| 263 |
+
# Now work on the rest of the attributes. Any attribute that's
|
| 264 |
+
# not already defined is invalid!
|
| 265 |
+
for (key, val) in attrs.items():
|
| 266 |
+
if hasattr(self.metadata, "set_" + key):
|
| 267 |
+
getattr(self.metadata, "set_" + key)(val)
|
| 268 |
+
elif hasattr(self.metadata, key):
|
| 269 |
+
setattr(self.metadata, key, val)
|
| 270 |
+
elif hasattr(self, key):
|
| 271 |
+
setattr(self, key, val)
|
| 272 |
+
else:
|
| 273 |
+
msg = "Unknown distribution option: %s" % repr(key)
|
| 274 |
+
warnings.warn(msg)
|
| 275 |
+
|
| 276 |
+
# no-user-cfg is handled before other command line args
|
| 277 |
+
# because other args override the config files, and this
|
| 278 |
+
# one is needed before we can load the config files.
|
| 279 |
+
# If attrs['script_args'] wasn't passed, assume false.
|
| 280 |
+
#
|
| 281 |
+
# This also make sure we just look at the global options
|
| 282 |
+
self.want_user_cfg = True
|
| 283 |
+
|
| 284 |
+
if self.script_args is not None:
|
| 285 |
+
for arg in self.script_args:
|
| 286 |
+
if not arg.startswith('-'):
|
| 287 |
+
break
|
| 288 |
+
if arg == '--no-user-cfg':
|
| 289 |
+
self.want_user_cfg = False
|
| 290 |
+
break
|
| 291 |
+
|
| 292 |
+
self.finalize_options()
|
| 293 |
+
|
| 294 |
+
def get_option_dict(self, command):
|
| 295 |
+
"""Get the option dictionary for a given command. If that
|
| 296 |
+
command's option dictionary hasn't been created yet, then create it
|
| 297 |
+
and return the new dictionary; otherwise, return the existing
|
| 298 |
+
option dictionary.
|
| 299 |
+
"""
|
| 300 |
+
dict = self.command_options.get(command)
|
| 301 |
+
if dict is None:
|
| 302 |
+
dict = self.command_options[command] = {}
|
| 303 |
+
return dict
|
| 304 |
+
|
| 305 |
+
def dump_option_dicts(self, header=None, commands=None, indent=""):
|
| 306 |
+
from pprint import pformat
|
| 307 |
+
|
| 308 |
+
if commands is None: # dump all command option dicts
|
| 309 |
+
commands = sorted(self.command_options.keys())
|
| 310 |
+
|
| 311 |
+
if header is not None:
|
| 312 |
+
self.announce(indent + header)
|
| 313 |
+
indent = indent + " "
|
| 314 |
+
|
| 315 |
+
if not commands:
|
| 316 |
+
self.announce(indent + "no commands known yet")
|
| 317 |
+
return
|
| 318 |
+
|
| 319 |
+
for cmd_name in commands:
|
| 320 |
+
opt_dict = self.command_options.get(cmd_name)
|
| 321 |
+
if opt_dict is None:
|
| 322 |
+
self.announce(indent +
|
| 323 |
+
"no option dict for '%s' command" % cmd_name)
|
| 324 |
+
else:
|
| 325 |
+
self.announce(indent +
|
| 326 |
+
"option dict for '%s' command:" % cmd_name)
|
| 327 |
+
out = pformat(opt_dict)
|
| 328 |
+
for line in out.split('\n'):
|
| 329 |
+
self.announce(indent + " " + line)
|
| 330 |
+
|
| 331 |
+
# -- Config file finding/parsing methods ---------------------------
|
| 332 |
+
|
| 333 |
+
def find_config_files(self):
|
| 334 |
+
"""Find as many configuration files as should be processed for this
|
| 335 |
+
platform, and return a list of filenames in the order in which they
|
| 336 |
+
should be parsed. The filenames returned are guaranteed to exist
|
| 337 |
+
(modulo nasty race conditions).
|
| 338 |
+
|
| 339 |
+
There are three possible config files: distutils.cfg in the
|
| 340 |
+
Distutils installation directory (ie. where the top-level
|
| 341 |
+
Distutils __inst__.py file lives), a file in the user's home
|
| 342 |
+
directory named .pydistutils.cfg on Unix and pydistutils.cfg
|
| 343 |
+
on Windows/Mac; and setup.cfg in the current directory.
|
| 344 |
+
|
| 345 |
+
The file in the user's home directory can be disabled with the
|
| 346 |
+
--no-user-cfg option.
|
| 347 |
+
"""
|
| 348 |
+
files = []
|
| 349 |
+
check_environ()
|
| 350 |
+
|
| 351 |
+
# Where to look for the system-wide Distutils config file
|
| 352 |
+
sys_dir = os.path.dirname(sys.modules['distutils'].__file__)
|
| 353 |
+
|
| 354 |
+
# Look for the system config file
|
| 355 |
+
sys_file = os.path.join(sys_dir, "distutils.cfg")
|
| 356 |
+
if os.path.isfile(sys_file):
|
| 357 |
+
files.append(sys_file)
|
| 358 |
+
|
| 359 |
+
# What to call the per-user config file
|
| 360 |
+
if os.name == 'posix':
|
| 361 |
+
user_filename = ".pydistutils.cfg"
|
| 362 |
+
else:
|
| 363 |
+
user_filename = "pydistutils.cfg"
|
| 364 |
+
|
| 365 |
+
# And look for the user config file
|
| 366 |
+
if self.want_user_cfg:
|
| 367 |
+
user_file = os.path.join(os.path.expanduser('~'), user_filename)
|
| 368 |
+
if os.path.isfile(user_file):
|
| 369 |
+
files.append(user_file)
|
| 370 |
+
|
| 371 |
+
# All platforms support local setup.cfg
|
| 372 |
+
local_file = "setup.cfg"
|
| 373 |
+
if os.path.isfile(local_file):
|
| 374 |
+
files.append(local_file)
|
| 375 |
+
|
| 376 |
+
if DEBUG:
|
| 377 |
+
self.announce("using config files: %s" % ', '.join(files))
|
| 378 |
+
|
| 379 |
+
return files
|
| 380 |
+
|
| 381 |
+
def parse_config_files(self, filenames=None):
|
| 382 |
+
from configparser import ConfigParser
|
| 383 |
+
|
| 384 |
+
# Ignore install directory options if we have a venv
|
| 385 |
+
if sys.prefix != sys.base_prefix:
|
| 386 |
+
ignore_options = [
|
| 387 |
+
'install-base', 'install-platbase', 'install-lib',
|
| 388 |
+
'install-platlib', 'install-purelib', 'install-headers',
|
| 389 |
+
'install-scripts', 'install-data', 'prefix', 'exec-prefix',
|
| 390 |
+
'home', 'user', 'root']
|
| 391 |
+
else:
|
| 392 |
+
ignore_options = []
|
| 393 |
+
|
| 394 |
+
ignore_options = frozenset(ignore_options)
|
| 395 |
+
|
| 396 |
+
if filenames is None:
|
| 397 |
+
filenames = self.find_config_files()
|
| 398 |
+
|
| 399 |
+
if DEBUG:
|
| 400 |
+
self.announce("Distribution.parse_config_files():")
|
| 401 |
+
|
| 402 |
+
parser = ConfigParser()
|
| 403 |
+
for filename in filenames:
|
| 404 |
+
if DEBUG:
|
| 405 |
+
self.announce(" reading %s" % filename)
|
| 406 |
+
parser.read(filename)
|
| 407 |
+
for section in parser.sections():
|
| 408 |
+
options = parser.options(section)
|
| 409 |
+
opt_dict = self.get_option_dict(section)
|
| 410 |
+
|
| 411 |
+
for opt in options:
|
| 412 |
+
if opt != '__name__' and opt not in ignore_options:
|
| 413 |
+
val = parser.get(section,opt)
|
| 414 |
+
opt = opt.replace('-', '_')
|
| 415 |
+
opt_dict[opt] = (filename, val)
|
| 416 |
+
|
| 417 |
+
# Make the ConfigParser forget everything (so we retain
|
| 418 |
+
# the original filenames that options come from)
|
| 419 |
+
parser.__init__()
|
| 420 |
+
|
| 421 |
+
# If there was a "global" section in the config file, use it
|
| 422 |
+
# to set Distribution options.
|
| 423 |
+
|
| 424 |
+
if 'global' in self.command_options:
|
| 425 |
+
for (opt, (src, val)) in self.command_options['global'].items():
|
| 426 |
+
alias = self.negative_opt.get(opt)
|
| 427 |
+
try:
|
| 428 |
+
if alias:
|
| 429 |
+
setattr(self, alias, not strtobool(val))
|
| 430 |
+
elif opt in ('verbose', 'dry_run'): # ugh!
|
| 431 |
+
setattr(self, opt, strtobool(val))
|
| 432 |
+
else:
|
| 433 |
+
setattr(self, opt, val)
|
| 434 |
+
except ValueError as msg:
|
| 435 |
+
raise DistutilsOptionError(msg)
|
| 436 |
+
|
| 437 |
+
# -- Command-line parsing methods ----------------------------------
|
| 438 |
+
|
| 439 |
+
def parse_command_line(self):
|
| 440 |
+
"""Parse the setup script's command line, taken from the
|
| 441 |
+
'script_args' instance attribute (which defaults to 'sys.argv[1:]'
|
| 442 |
+
-- see 'setup()' in core.py). This list is first processed for
|
| 443 |
+
"global options" -- options that set attributes of the Distribution
|
| 444 |
+
instance. Then, it is alternately scanned for Distutils commands
|
| 445 |
+
and options for that command. Each new command terminates the
|
| 446 |
+
options for the previous command. The allowed options for a
|
| 447 |
+
command are determined by the 'user_options' attribute of the
|
| 448 |
+
command class -- thus, we have to be able to load command classes
|
| 449 |
+
in order to parse the command line. Any error in that 'options'
|
| 450 |
+
attribute raises DistutilsGetoptError; any error on the
|
| 451 |
+
command-line raises DistutilsArgError. If no Distutils commands
|
| 452 |
+
were found on the command line, raises DistutilsArgError. Return
|
| 453 |
+
true if command-line was successfully parsed and we should carry
|
| 454 |
+
on with executing commands; false if no errors but we shouldn't
|
| 455 |
+
execute commands (currently, this only happens if user asks for
|
| 456 |
+
help).
|
| 457 |
+
"""
|
| 458 |
+
#
|
| 459 |
+
# We now have enough information to show the Macintosh dialog
|
| 460 |
+
# that allows the user to interactively specify the "command line".
|
| 461 |
+
#
|
| 462 |
+
toplevel_options = self._get_toplevel_options()
|
| 463 |
+
|
| 464 |
+
# We have to parse the command line a bit at a time -- global
|
| 465 |
+
# options, then the first command, then its options, and so on --
|
| 466 |
+
# because each command will be handled by a different class, and
|
| 467 |
+
# the options that are valid for a particular class aren't known
|
| 468 |
+
# until we have loaded the command class, which doesn't happen
|
| 469 |
+
# until we know what the command is.
|
| 470 |
+
|
| 471 |
+
self.commands = []
|
| 472 |
+
parser = FancyGetopt(toplevel_options + self.display_options)
|
| 473 |
+
parser.set_negative_aliases(self.negative_opt)
|
| 474 |
+
parser.set_aliases({'licence': 'license'})
|
| 475 |
+
args = parser.getopt(args=self.script_args, object=self)
|
| 476 |
+
option_order = parser.get_option_order()
|
| 477 |
+
log.set_verbosity(self.verbose)
|
| 478 |
+
|
| 479 |
+
# for display options we return immediately
|
| 480 |
+
if self.handle_display_options(option_order):
|
| 481 |
+
return
|
| 482 |
+
while args:
|
| 483 |
+
args = self._parse_command_opts(parser, args)
|
| 484 |
+
if args is None: # user asked for help (and got it)
|
| 485 |
+
return
|
| 486 |
+
|
| 487 |
+
# Handle the cases of --help as a "global" option, ie.
|
| 488 |
+
# "setup.py --help" and "setup.py --help command ...". For the
|
| 489 |
+
# former, we show global options (--verbose, --dry-run, etc.)
|
| 490 |
+
# and display-only options (--name, --version, etc.); for the
|
| 491 |
+
# latter, we omit the display-only options and show help for
|
| 492 |
+
# each command listed on the command line.
|
| 493 |
+
if self.help:
|
| 494 |
+
self._show_help(parser,
|
| 495 |
+
display_options=len(self.commands) == 0,
|
| 496 |
+
commands=self.commands)
|
| 497 |
+
return
|
| 498 |
+
|
| 499 |
+
# Oops, no commands found -- an end-user error
|
| 500 |
+
if not self.commands:
|
| 501 |
+
raise DistutilsArgError("no commands supplied")
|
| 502 |
+
|
| 503 |
+
# All is well: return true
|
| 504 |
+
return True
|
| 505 |
+
|
| 506 |
+
def _get_toplevel_options(self):
|
| 507 |
+
"""Return the non-display options recognized at the top level.
|
| 508 |
+
|
| 509 |
+
This includes options that are recognized *only* at the top
|
| 510 |
+
level as well as options recognized for commands.
|
| 511 |
+
"""
|
| 512 |
+
return self.global_options + [
|
| 513 |
+
("command-packages=", None,
|
| 514 |
+
"list of packages that provide distutils commands"),
|
| 515 |
+
]
|
| 516 |
+
|
| 517 |
+
def _parse_command_opts(self, parser, args):
|
| 518 |
+
"""Parse the command-line options for a single command.
|
| 519 |
+
'parser' must be a FancyGetopt instance; 'args' must be the list
|
| 520 |
+
of arguments, starting with the current command (whose options
|
| 521 |
+
we are about to parse). Returns a new version of 'args' with
|
| 522 |
+
the next command at the front of the list; will be the empty
|
| 523 |
+
list if there are no more commands on the command line. Returns
|
| 524 |
+
None if the user asked for help on this command.
|
| 525 |
+
"""
|
| 526 |
+
# late import because of mutual dependence between these modules
|
| 527 |
+
from distutils.cmd import Command
|
| 528 |
+
|
| 529 |
+
# Pull the current command from the head of the command line
|
| 530 |
+
command = args[0]
|
| 531 |
+
if not command_re.match(command):
|
| 532 |
+
raise SystemExit("invalid command name '%s'" % command)
|
| 533 |
+
self.commands.append(command)
|
| 534 |
+
|
| 535 |
+
# Dig up the command class that implements this command, so we
|
| 536 |
+
# 1) know that it's a valid command, and 2) know which options
|
| 537 |
+
# it takes.
|
| 538 |
+
try:
|
| 539 |
+
cmd_class = self.get_command_class(command)
|
| 540 |
+
except DistutilsModuleError as msg:
|
| 541 |
+
raise DistutilsArgError(msg)
|
| 542 |
+
|
| 543 |
+
# Require that the command class be derived from Command -- want
|
| 544 |
+
# to be sure that the basic "command" interface is implemented.
|
| 545 |
+
if not issubclass(cmd_class, Command):
|
| 546 |
+
raise DistutilsClassError(
|
| 547 |
+
"command class %s must subclass Command" % cmd_class)
|
| 548 |
+
|
| 549 |
+
# Also make sure that the command object provides a list of its
|
| 550 |
+
# known options.
|
| 551 |
+
if not (hasattr(cmd_class, 'user_options') and
|
| 552 |
+
isinstance(cmd_class.user_options, list)):
|
| 553 |
+
msg = ("command class %s must provide "
|
| 554 |
+
"'user_options' attribute (a list of tuples)")
|
| 555 |
+
raise DistutilsClassError(msg % cmd_class)
|
| 556 |
+
|
| 557 |
+
# If the command class has a list of negative alias options,
|
| 558 |
+
# merge it in with the global negative aliases.
|
| 559 |
+
negative_opt = self.negative_opt
|
| 560 |
+
if hasattr(cmd_class, 'negative_opt'):
|
| 561 |
+
negative_opt = negative_opt.copy()
|
| 562 |
+
negative_opt.update(cmd_class.negative_opt)
|
| 563 |
+
|
| 564 |
+
# Check for help_options in command class. They have a different
|
| 565 |
+
# format (tuple of four) so we need to preprocess them here.
|
| 566 |
+
if (hasattr(cmd_class, 'help_options') and
|
| 567 |
+
isinstance(cmd_class.help_options, list)):
|
| 568 |
+
help_options = fix_help_options(cmd_class.help_options)
|
| 569 |
+
else:
|
| 570 |
+
help_options = []
|
| 571 |
+
|
| 572 |
+
# All commands support the global options too, just by adding
|
| 573 |
+
# in 'global_options'.
|
| 574 |
+
parser.set_option_table(self.global_options +
|
| 575 |
+
cmd_class.user_options +
|
| 576 |
+
help_options)
|
| 577 |
+
parser.set_negative_aliases(negative_opt)
|
| 578 |
+
(args, opts) = parser.getopt(args[1:])
|
| 579 |
+
if hasattr(opts, 'help') and opts.help:
|
| 580 |
+
self._show_help(parser, display_options=0, commands=[cmd_class])
|
| 581 |
+
return
|
| 582 |
+
|
| 583 |
+
if (hasattr(cmd_class, 'help_options') and
|
| 584 |
+
isinstance(cmd_class.help_options, list)):
|
| 585 |
+
help_option_found=0
|
| 586 |
+
for (help_option, short, desc, func) in cmd_class.help_options:
|
| 587 |
+
if hasattr(opts, parser.get_attr_name(help_option)):
|
| 588 |
+
help_option_found=1
|
| 589 |
+
if callable(func):
|
| 590 |
+
func()
|
| 591 |
+
else:
|
| 592 |
+
raise DistutilsClassError(
|
| 593 |
+
"invalid help function %r for help option '%s': "
|
| 594 |
+
"must be a callable object (function, etc.)"
|
| 595 |
+
% (func, help_option))
|
| 596 |
+
|
| 597 |
+
if help_option_found:
|
| 598 |
+
return
|
| 599 |
+
|
| 600 |
+
# Put the options from the command-line into their official
|
| 601 |
+
# holding pen, the 'command_options' dictionary.
|
| 602 |
+
opt_dict = self.get_option_dict(command)
|
| 603 |
+
for (name, value) in vars(opts).items():
|
| 604 |
+
opt_dict[name] = ("command line", value)
|
| 605 |
+
|
| 606 |
+
return args
|
| 607 |
+
|
| 608 |
+
def finalize_options(self):
|
| 609 |
+
"""Set final values for all the options on the Distribution
|
| 610 |
+
instance, analogous to the .finalize_options() method of Command
|
| 611 |
+
objects.
|
| 612 |
+
"""
|
| 613 |
+
for attr in ('keywords', 'platforms'):
|
| 614 |
+
value = getattr(self.metadata, attr)
|
| 615 |
+
if value is None:
|
| 616 |
+
continue
|
| 617 |
+
if isinstance(value, str):
|
| 618 |
+
value = [elm.strip() for elm in value.split(',')]
|
| 619 |
+
setattr(self.metadata, attr, value)
|
| 620 |
+
|
| 621 |
+
def _show_help(self, parser, global_options=1, display_options=1,
|
| 622 |
+
commands=[]):
|
| 623 |
+
"""Show help for the setup script command-line in the form of
|
| 624 |
+
several lists of command-line options. 'parser' should be a
|
| 625 |
+
FancyGetopt instance; do not expect it to be returned in the
|
| 626 |
+
same state, as its option table will be reset to make it
|
| 627 |
+
generate the correct help text.
|
| 628 |
+
|
| 629 |
+
If 'global_options' is true, lists the global options:
|
| 630 |
+
--verbose, --dry-run, etc. If 'display_options' is true, lists
|
| 631 |
+
the "display-only" options: --name, --version, etc. Finally,
|
| 632 |
+
lists per-command help for every command name or command class
|
| 633 |
+
in 'commands'.
|
| 634 |
+
"""
|
| 635 |
+
# late import because of mutual dependence between these modules
|
| 636 |
+
from distutils.core import gen_usage
|
| 637 |
+
from distutils.cmd import Command
|
| 638 |
+
|
| 639 |
+
if global_options:
|
| 640 |
+
if display_options:
|
| 641 |
+
options = self._get_toplevel_options()
|
| 642 |
+
else:
|
| 643 |
+
options = self.global_options
|
| 644 |
+
parser.set_option_table(options)
|
| 645 |
+
parser.print_help(self.common_usage + "\nGlobal options:")
|
| 646 |
+
print('')
|
| 647 |
+
|
| 648 |
+
if display_options:
|
| 649 |
+
parser.set_option_table(self.display_options)
|
| 650 |
+
parser.print_help(
|
| 651 |
+
"Information display options (just display " +
|
| 652 |
+
"information, ignore any commands)")
|
| 653 |
+
print('')
|
| 654 |
+
|
| 655 |
+
for command in self.commands:
|
| 656 |
+
if isinstance(command, type) and issubclass(command, Command):
|
| 657 |
+
klass = command
|
| 658 |
+
else:
|
| 659 |
+
klass = self.get_command_class(command)
|
| 660 |
+
if (hasattr(klass, 'help_options') and
|
| 661 |
+
isinstance(klass.help_options, list)):
|
| 662 |
+
parser.set_option_table(klass.user_options +
|
| 663 |
+
fix_help_options(klass.help_options))
|
| 664 |
+
else:
|
| 665 |
+
parser.set_option_table(klass.user_options)
|
| 666 |
+
parser.print_help("Options for '%s' command:" % klass.__name__)
|
| 667 |
+
print('')
|
| 668 |
+
|
| 669 |
+
print(gen_usage(self.script_name))
|
| 670 |
+
|
| 671 |
+
def handle_display_options(self, option_order):
|
| 672 |
+
"""If there were any non-global "display-only" options
|
| 673 |
+
(--help-commands or the metadata display options) on the command
|
| 674 |
+
line, display the requested info and return true; else return
|
| 675 |
+
false.
|
| 676 |
+
"""
|
| 677 |
+
from distutils.core import gen_usage
|
| 678 |
+
|
| 679 |
+
# User just wants a list of commands -- we'll print it out and stop
|
| 680 |
+
# processing now (ie. if they ran "setup --help-commands foo bar",
|
| 681 |
+
# we ignore "foo bar").
|
| 682 |
+
if self.help_commands:
|
| 683 |
+
self.print_commands()
|
| 684 |
+
print('')
|
| 685 |
+
print(gen_usage(self.script_name))
|
| 686 |
+
return 1
|
| 687 |
+
|
| 688 |
+
# If user supplied any of the "display metadata" options, then
|
| 689 |
+
# display that metadata in the order in which the user supplied the
|
| 690 |
+
# metadata options.
|
| 691 |
+
any_display_options = 0
|
| 692 |
+
is_display_option = {}
|
| 693 |
+
for option in self.display_options:
|
| 694 |
+
is_display_option[option[0]] = 1
|
| 695 |
+
|
| 696 |
+
for (opt, val) in option_order:
|
| 697 |
+
if val and is_display_option.get(opt):
|
| 698 |
+
opt = translate_longopt(opt)
|
| 699 |
+
value = getattr(self.metadata, "get_"+opt)()
|
| 700 |
+
if opt in ['keywords', 'platforms']:
|
| 701 |
+
print(','.join(value))
|
| 702 |
+
elif opt in ('classifiers', 'provides', 'requires',
|
| 703 |
+
'obsoletes'):
|
| 704 |
+
print('\n'.join(value))
|
| 705 |
+
else:
|
| 706 |
+
print(value)
|
| 707 |
+
any_display_options = 1
|
| 708 |
+
|
| 709 |
+
return any_display_options
|
| 710 |
+
|
| 711 |
+
def print_command_list(self, commands, header, max_length):
|
| 712 |
+
"""Print a subset of the list of all commands -- used by
|
| 713 |
+
'print_commands()'.
|
| 714 |
+
"""
|
| 715 |
+
print(header + ":")
|
| 716 |
+
|
| 717 |
+
for cmd in commands:
|
| 718 |
+
klass = self.cmdclass.get(cmd)
|
| 719 |
+
if not klass:
|
| 720 |
+
klass = self.get_command_class(cmd)
|
| 721 |
+
try:
|
| 722 |
+
description = klass.description
|
| 723 |
+
except AttributeError:
|
| 724 |
+
description = "(no description available)"
|
| 725 |
+
|
| 726 |
+
print(" %-*s %s" % (max_length, cmd, description))
|
| 727 |
+
|
| 728 |
+
def print_commands(self):
|
| 729 |
+
"""Print out a help message listing all available commands with a
|
| 730 |
+
description of each. The list is divided into "standard commands"
|
| 731 |
+
(listed in distutils.command.__all__) and "extra commands"
|
| 732 |
+
(mentioned in self.cmdclass, but not a standard command). The
|
| 733 |
+
descriptions come from the command class attribute
|
| 734 |
+
'description'.
|
| 735 |
+
"""
|
| 736 |
+
import distutils.command
|
| 737 |
+
std_commands = distutils.command.__all__
|
| 738 |
+
is_std = {}
|
| 739 |
+
for cmd in std_commands:
|
| 740 |
+
is_std[cmd] = 1
|
| 741 |
+
|
| 742 |
+
extra_commands = []
|
| 743 |
+
for cmd in self.cmdclass.keys():
|
| 744 |
+
if not is_std.get(cmd):
|
| 745 |
+
extra_commands.append(cmd)
|
| 746 |
+
|
| 747 |
+
max_length = 0
|
| 748 |
+
for cmd in (std_commands + extra_commands):
|
| 749 |
+
if len(cmd) > max_length:
|
| 750 |
+
max_length = len(cmd)
|
| 751 |
+
|
| 752 |
+
self.print_command_list(std_commands,
|
| 753 |
+
"Standard commands",
|
| 754 |
+
max_length)
|
| 755 |
+
if extra_commands:
|
| 756 |
+
print()
|
| 757 |
+
self.print_command_list(extra_commands,
|
| 758 |
+
"Extra commands",
|
| 759 |
+
max_length)
|
| 760 |
+
|
| 761 |
+
def get_command_list(self):
|
| 762 |
+
"""Get a list of (command, description) tuples.
|
| 763 |
+
The list is divided into "standard commands" (listed in
|
| 764 |
+
distutils.command.__all__) and "extra commands" (mentioned in
|
| 765 |
+
self.cmdclass, but not a standard command). The descriptions come
|
| 766 |
+
from the command class attribute 'description'.
|
| 767 |
+
"""
|
| 768 |
+
# Currently this is only used on Mac OS, for the Mac-only GUI
|
| 769 |
+
# Distutils interface (by Jack Jansen)
|
| 770 |
+
import distutils.command
|
| 771 |
+
std_commands = distutils.command.__all__
|
| 772 |
+
is_std = {}
|
| 773 |
+
for cmd in std_commands:
|
| 774 |
+
is_std[cmd] = 1
|
| 775 |
+
|
| 776 |
+
extra_commands = []
|
| 777 |
+
for cmd in self.cmdclass.keys():
|
| 778 |
+
if not is_std.get(cmd):
|
| 779 |
+
extra_commands.append(cmd)
|
| 780 |
+
|
| 781 |
+
rv = []
|
| 782 |
+
for cmd in (std_commands + extra_commands):
|
| 783 |
+
klass = self.cmdclass.get(cmd)
|
| 784 |
+
if not klass:
|
| 785 |
+
klass = self.get_command_class(cmd)
|
| 786 |
+
try:
|
| 787 |
+
description = klass.description
|
| 788 |
+
except AttributeError:
|
| 789 |
+
description = "(no description available)"
|
| 790 |
+
rv.append((cmd, description))
|
| 791 |
+
return rv
|
| 792 |
+
|
| 793 |
+
# -- Command class/object methods ----------------------------------
|
| 794 |
+
|
| 795 |
+
def get_command_packages(self):
|
| 796 |
+
"""Return a list of packages from which commands are loaded."""
|
| 797 |
+
pkgs = self.command_packages
|
| 798 |
+
if not isinstance(pkgs, list):
|
| 799 |
+
if pkgs is None:
|
| 800 |
+
pkgs = ''
|
| 801 |
+
pkgs = [pkg.strip() for pkg in pkgs.split(',') if pkg != '']
|
| 802 |
+
if "distutils.command" not in pkgs:
|
| 803 |
+
pkgs.insert(0, "distutils.command")
|
| 804 |
+
self.command_packages = pkgs
|
| 805 |
+
return pkgs
|
| 806 |
+
|
| 807 |
+
def get_command_class(self, command):
|
| 808 |
+
"""Return the class that implements the Distutils command named by
|
| 809 |
+
'command'. First we check the 'cmdclass' dictionary; if the
|
| 810 |
+
command is mentioned there, we fetch the class object from the
|
| 811 |
+
dictionary and return it. Otherwise we load the command module
|
| 812 |
+
("distutils.command." + command) and fetch the command class from
|
| 813 |
+
the module. The loaded class is also stored in 'cmdclass'
|
| 814 |
+
to speed future calls to 'get_command_class()'.
|
| 815 |
+
|
| 816 |
+
Raises DistutilsModuleError if the expected module could not be
|
| 817 |
+
found, or if that module does not define the expected class.
|
| 818 |
+
"""
|
| 819 |
+
klass = self.cmdclass.get(command)
|
| 820 |
+
if klass:
|
| 821 |
+
return klass
|
| 822 |
+
|
| 823 |
+
for pkgname in self.get_command_packages():
|
| 824 |
+
module_name = "%s.%s" % (pkgname, command)
|
| 825 |
+
klass_name = command
|
| 826 |
+
|
| 827 |
+
try:
|
| 828 |
+
__import__(module_name)
|
| 829 |
+
module = sys.modules[module_name]
|
| 830 |
+
except ImportError:
|
| 831 |
+
continue
|
| 832 |
+
|
| 833 |
+
try:
|
| 834 |
+
klass = getattr(module, klass_name)
|
| 835 |
+
except AttributeError:
|
| 836 |
+
raise DistutilsModuleError(
|
| 837 |
+
"invalid command '%s' (no class '%s' in module '%s')"
|
| 838 |
+
% (command, klass_name, module_name))
|
| 839 |
+
|
| 840 |
+
self.cmdclass[command] = klass
|
| 841 |
+
return klass
|
| 842 |
+
|
| 843 |
+
raise DistutilsModuleError("invalid command '%s'" % command)
|
| 844 |
+
|
| 845 |
+
def get_command_obj(self, command, create=1):
|
| 846 |
+
"""Return the command object for 'command'. Normally this object
|
| 847 |
+
is cached on a previous call to 'get_command_obj()'; if no command
|
| 848 |
+
object for 'command' is in the cache, then we either create and
|
| 849 |
+
return it (if 'create' is true) or return None.
|
| 850 |
+
"""
|
| 851 |
+
cmd_obj = self.command_obj.get(command)
|
| 852 |
+
if not cmd_obj and create:
|
| 853 |
+
if DEBUG:
|
| 854 |
+
self.announce("Distribution.get_command_obj(): "
|
| 855 |
+
"creating '%s' command object" % command)
|
| 856 |
+
|
| 857 |
+
klass = self.get_command_class(command)
|
| 858 |
+
cmd_obj = self.command_obj[command] = klass(self)
|
| 859 |
+
self.have_run[command] = 0
|
| 860 |
+
|
| 861 |
+
# Set any options that were supplied in config files
|
| 862 |
+
# or on the command line. (NB. support for error
|
| 863 |
+
# reporting is lame here: any errors aren't reported
|
| 864 |
+
# until 'finalize_options()' is called, which means
|
| 865 |
+
# we won't report the source of the error.)
|
| 866 |
+
options = self.command_options.get(command)
|
| 867 |
+
if options:
|
| 868 |
+
self._set_command_options(cmd_obj, options)
|
| 869 |
+
|
| 870 |
+
return cmd_obj
|
| 871 |
+
|
| 872 |
+
def _set_command_options(self, command_obj, option_dict=None):
|
| 873 |
+
"""Set the options for 'command_obj' from 'option_dict'. Basically
|
| 874 |
+
this means copying elements of a dictionary ('option_dict') to
|
| 875 |
+
attributes of an instance ('command').
|
| 876 |
+
|
| 877 |
+
'command_obj' must be a Command instance. If 'option_dict' is not
|
| 878 |
+
supplied, uses the standard option dictionary for this command
|
| 879 |
+
(from 'self.command_options').
|
| 880 |
+
"""
|
| 881 |
+
command_name = command_obj.get_command_name()
|
| 882 |
+
if option_dict is None:
|
| 883 |
+
option_dict = self.get_option_dict(command_name)
|
| 884 |
+
|
| 885 |
+
if DEBUG:
|
| 886 |
+
self.announce(" setting options for '%s' command:" % command_name)
|
| 887 |
+
for (option, (source, value)) in option_dict.items():
|
| 888 |
+
if DEBUG:
|
| 889 |
+
self.announce(" %s = %s (from %s)" % (option, value,
|
| 890 |
+
source))
|
| 891 |
+
try:
|
| 892 |
+
bool_opts = [translate_longopt(o)
|
| 893 |
+
for o in command_obj.boolean_options]
|
| 894 |
+
except AttributeError:
|
| 895 |
+
bool_opts = []
|
| 896 |
+
try:
|
| 897 |
+
neg_opt = command_obj.negative_opt
|
| 898 |
+
except AttributeError:
|
| 899 |
+
neg_opt = {}
|
| 900 |
+
|
| 901 |
+
try:
|
| 902 |
+
is_string = isinstance(value, str)
|
| 903 |
+
if option in neg_opt and is_string:
|
| 904 |
+
setattr(command_obj, neg_opt[option], not strtobool(value))
|
| 905 |
+
elif option in bool_opts and is_string:
|
| 906 |
+
setattr(command_obj, option, strtobool(value))
|
| 907 |
+
elif hasattr(command_obj, option):
|
| 908 |
+
setattr(command_obj, option, value)
|
| 909 |
+
else:
|
| 910 |
+
raise DistutilsOptionError(
|
| 911 |
+
"error in %s: command '%s' has no such option '%s'"
|
| 912 |
+
% (source, command_name, option))
|
| 913 |
+
except ValueError as msg:
|
| 914 |
+
raise DistutilsOptionError(msg)
|
| 915 |
+
|
| 916 |
+
def reinitialize_command(self, command, reinit_subcommands=0):
|
| 917 |
+
"""Reinitializes a command to the state it was in when first
|
| 918 |
+
returned by 'get_command_obj()': ie., initialized but not yet
|
| 919 |
+
finalized. This provides the opportunity to sneak option
|
| 920 |
+
values in programmatically, overriding or supplementing
|
| 921 |
+
user-supplied values from the config files and command line.
|
| 922 |
+
You'll have to re-finalize the command object (by calling
|
| 923 |
+
'finalize_options()' or 'ensure_finalized()') before using it for
|
| 924 |
+
real.
|
| 925 |
+
|
| 926 |
+
'command' should be a command name (string) or command object. If
|
| 927 |
+
'reinit_subcommands' is true, also reinitializes the command's
|
| 928 |
+
sub-commands, as declared by the 'sub_commands' class attribute (if
|
| 929 |
+
it has one). See the "install" command for an example. Only
|
| 930 |
+
reinitializes the sub-commands that actually matter, ie. those
|
| 931 |
+
whose test predicates return true.
|
| 932 |
+
|
| 933 |
+
Returns the reinitialized command object.
|
| 934 |
+
"""
|
| 935 |
+
from distutils.cmd import Command
|
| 936 |
+
if not isinstance(command, Command):
|
| 937 |
+
command_name = command
|
| 938 |
+
command = self.get_command_obj(command_name)
|
| 939 |
+
else:
|
| 940 |
+
command_name = command.get_command_name()
|
| 941 |
+
|
| 942 |
+
if not command.finalized:
|
| 943 |
+
return command
|
| 944 |
+
command.initialize_options()
|
| 945 |
+
command.finalized = 0
|
| 946 |
+
self.have_run[command_name] = 0
|
| 947 |
+
self._set_command_options(command)
|
| 948 |
+
|
| 949 |
+
if reinit_subcommands:
|
| 950 |
+
for sub in command.get_sub_commands():
|
| 951 |
+
self.reinitialize_command(sub, reinit_subcommands)
|
| 952 |
+
|
| 953 |
+
return command
|
| 954 |
+
|
| 955 |
+
# -- Methods that operate on the Distribution ----------------------
|
| 956 |
+
|
| 957 |
+
def announce(self, msg, level=log.INFO):
|
| 958 |
+
log.log(level, msg)
|
| 959 |
+
|
| 960 |
+
def run_commands(self):
|
| 961 |
+
"""Run each command that was seen on the setup script command line.
|
| 962 |
+
Uses the list of commands found and cache of command objects
|
| 963 |
+
created by 'get_command_obj()'.
|
| 964 |
+
"""
|
| 965 |
+
for cmd in self.commands:
|
| 966 |
+
self.run_command(cmd)
|
| 967 |
+
|
| 968 |
+
# -- Methods that operate on its Commands --------------------------
|
| 969 |
+
|
| 970 |
+
def run_command(self, command):
|
| 971 |
+
"""Do whatever it takes to run a command (including nothing at all,
|
| 972 |
+
if the command has already been run). Specifically: if we have
|
| 973 |
+
already created and run the command named by 'command', return
|
| 974 |
+
silently without doing anything. If the command named by 'command'
|
| 975 |
+
doesn't even have a command object yet, create one. Then invoke
|
| 976 |
+
'run()' on that command object (or an existing one).
|
| 977 |
+
"""
|
| 978 |
+
# Already been here, done that? then return silently.
|
| 979 |
+
if self.have_run.get(command):
|
| 980 |
+
return
|
| 981 |
+
|
| 982 |
+
log.info("running %s", command)
|
| 983 |
+
cmd_obj = self.get_command_obj(command)
|
| 984 |
+
cmd_obj.ensure_finalized()
|
| 985 |
+
cmd_obj.run()
|
| 986 |
+
self.have_run[command] = 1
|
| 987 |
+
|
| 988 |
+
# -- Distribution query methods ------------------------------------
|
| 989 |
+
|
| 990 |
+
def has_pure_modules(self):
|
| 991 |
+
return len(self.packages or self.py_modules or []) > 0
|
| 992 |
+
|
| 993 |
+
def has_ext_modules(self):
|
| 994 |
+
return self.ext_modules and len(self.ext_modules) > 0
|
| 995 |
+
|
| 996 |
+
def has_c_libraries(self):
|
| 997 |
+
return self.libraries and len(self.libraries) > 0
|
| 998 |
+
|
| 999 |
+
def has_modules(self):
|
| 1000 |
+
return self.has_pure_modules() or self.has_ext_modules()
|
| 1001 |
+
|
| 1002 |
+
def has_headers(self):
|
| 1003 |
+
return self.headers and len(self.headers) > 0
|
| 1004 |
+
|
| 1005 |
+
def has_scripts(self):
|
| 1006 |
+
return self.scripts and len(self.scripts) > 0
|
| 1007 |
+
|
| 1008 |
+
def has_data_files(self):
|
| 1009 |
+
return self.data_files and len(self.data_files) > 0
|
| 1010 |
+
|
| 1011 |
+
def is_pure(self):
|
| 1012 |
+
return (self.has_pure_modules() and
|
| 1013 |
+
not self.has_ext_modules() and
|
| 1014 |
+
not self.has_c_libraries())
|
| 1015 |
+
|
| 1016 |
+
# -- Metadata query methods ----------------------------------------
|
| 1017 |
+
|
| 1018 |
+
# If you're looking for 'get_name()', 'get_version()', and so forth,
|
| 1019 |
+
# they are defined in a sneaky way: the constructor binds self.get_XXX
|
| 1020 |
+
# to self.metadata.get_XXX. The actual code is in the
|
| 1021 |
+
# DistributionMetadata class, below.
|
| 1022 |
+
|
| 1023 |
+
class DistributionMetadata:
|
| 1024 |
+
"""Dummy class to hold the distribution meta-data: name, version,
|
| 1025 |
+
author, and so forth.
|
| 1026 |
+
"""
|
| 1027 |
+
|
| 1028 |
+
_METHOD_BASENAMES = ("name", "version", "author", "author_email",
|
| 1029 |
+
"maintainer", "maintainer_email", "url",
|
| 1030 |
+
"license", "description", "long_description",
|
| 1031 |
+
"keywords", "platforms", "fullname", "contact",
|
| 1032 |
+
"contact_email", "classifiers", "download_url",
|
| 1033 |
+
# PEP 314
|
| 1034 |
+
"provides", "requires", "obsoletes",
|
| 1035 |
+
)
|
| 1036 |
+
|
| 1037 |
+
def __init__(self, path=None):
|
| 1038 |
+
if path is not None:
|
| 1039 |
+
self.read_pkg_file(open(path))
|
| 1040 |
+
else:
|
| 1041 |
+
self.name = None
|
| 1042 |
+
self.version = None
|
| 1043 |
+
self.author = None
|
| 1044 |
+
self.author_email = None
|
| 1045 |
+
self.maintainer = None
|
| 1046 |
+
self.maintainer_email = None
|
| 1047 |
+
self.url = None
|
| 1048 |
+
self.license = None
|
| 1049 |
+
self.description = None
|
| 1050 |
+
self.long_description = None
|
| 1051 |
+
self.keywords = None
|
| 1052 |
+
self.platforms = None
|
| 1053 |
+
self.classifiers = None
|
| 1054 |
+
self.download_url = None
|
| 1055 |
+
# PEP 314
|
| 1056 |
+
self.provides = None
|
| 1057 |
+
self.requires = None
|
| 1058 |
+
self.obsoletes = None
|
| 1059 |
+
|
| 1060 |
+
def read_pkg_file(self, file):
|
| 1061 |
+
"""Reads the metadata values from a file object."""
|
| 1062 |
+
msg = message_from_file(file)
|
| 1063 |
+
|
| 1064 |
+
def _read_field(name):
|
| 1065 |
+
value = msg[name]
|
| 1066 |
+
if value == 'UNKNOWN':
|
| 1067 |
+
return None
|
| 1068 |
+
return value
|
| 1069 |
+
|
| 1070 |
+
def _read_list(name):
|
| 1071 |
+
values = msg.get_all(name, None)
|
| 1072 |
+
if values == []:
|
| 1073 |
+
return None
|
| 1074 |
+
return values
|
| 1075 |
+
|
| 1076 |
+
metadata_version = msg['metadata-version']
|
| 1077 |
+
self.name = _read_field('name')
|
| 1078 |
+
self.version = _read_field('version')
|
| 1079 |
+
self.description = _read_field('summary')
|
| 1080 |
+
# we are filling author only.
|
| 1081 |
+
self.author = _read_field('author')
|
| 1082 |
+
self.maintainer = None
|
| 1083 |
+
self.author_email = _read_field('author-email')
|
| 1084 |
+
self.maintainer_email = None
|
| 1085 |
+
self.url = _read_field('home-page')
|
| 1086 |
+
self.license = _read_field('license')
|
| 1087 |
+
|
| 1088 |
+
if 'download-url' in msg:
|
| 1089 |
+
self.download_url = _read_field('download-url')
|
| 1090 |
+
else:
|
| 1091 |
+
self.download_url = None
|
| 1092 |
+
|
| 1093 |
+
self.long_description = _read_field('description')
|
| 1094 |
+
self.description = _read_field('summary')
|
| 1095 |
+
|
| 1096 |
+
if 'keywords' in msg:
|
| 1097 |
+
self.keywords = _read_field('keywords').split(',')
|
| 1098 |
+
|
| 1099 |
+
self.platforms = _read_list('platform')
|
| 1100 |
+
self.classifiers = _read_list('classifier')
|
| 1101 |
+
|
| 1102 |
+
# PEP 314 - these fields only exist in 1.1
|
| 1103 |
+
if metadata_version == '1.1':
|
| 1104 |
+
self.requires = _read_list('requires')
|
| 1105 |
+
self.provides = _read_list('provides')
|
| 1106 |
+
self.obsoletes = _read_list('obsoletes')
|
| 1107 |
+
else:
|
| 1108 |
+
self.requires = None
|
| 1109 |
+
self.provides = None
|
| 1110 |
+
self.obsoletes = None
|
| 1111 |
+
|
| 1112 |
+
def write_pkg_info(self, base_dir):
|
| 1113 |
+
"""Write the PKG-INFO file into the release tree.
|
| 1114 |
+
"""
|
| 1115 |
+
with open(os.path.join(base_dir, 'PKG-INFO'), 'w',
|
| 1116 |
+
encoding='UTF-8') as pkg_info:
|
| 1117 |
+
self.write_pkg_file(pkg_info)
|
| 1118 |
+
|
| 1119 |
+
def write_pkg_file(self, file):
|
| 1120 |
+
"""Write the PKG-INFO format data to a file object.
|
| 1121 |
+
"""
|
| 1122 |
+
version = '1.0'
|
| 1123 |
+
if (self.provides or self.requires or self.obsoletes or
|
| 1124 |
+
self.classifiers or self.download_url):
|
| 1125 |
+
version = '1.1'
|
| 1126 |
+
|
| 1127 |
+
file.write('Metadata-Version: %s\n' % version)
|
| 1128 |
+
file.write('Name: %s\n' % self.get_name())
|
| 1129 |
+
file.write('Version: %s\n' % self.get_version())
|
| 1130 |
+
file.write('Summary: %s\n' % self.get_description())
|
| 1131 |
+
file.write('Home-page: %s\n' % self.get_url())
|
| 1132 |
+
file.write('Author: %s\n' % self.get_contact())
|
| 1133 |
+
file.write('Author-email: %s\n' % self.get_contact_email())
|
| 1134 |
+
file.write('License: %s\n' % self.get_license())
|
| 1135 |
+
if self.download_url:
|
| 1136 |
+
file.write('Download-URL: %s\n' % self.download_url)
|
| 1137 |
+
|
| 1138 |
+
long_desc = rfc822_escape(self.get_long_description())
|
| 1139 |
+
file.write('Description: %s\n' % long_desc)
|
| 1140 |
+
|
| 1141 |
+
keywords = ','.join(self.get_keywords())
|
| 1142 |
+
if keywords:
|
| 1143 |
+
file.write('Keywords: %s\n' % keywords)
|
| 1144 |
+
|
| 1145 |
+
self._write_list(file, 'Platform', self.get_platforms())
|
| 1146 |
+
self._write_list(file, 'Classifier', self.get_classifiers())
|
| 1147 |
+
|
| 1148 |
+
# PEP 314
|
| 1149 |
+
self._write_list(file, 'Requires', self.get_requires())
|
| 1150 |
+
self._write_list(file, 'Provides', self.get_provides())
|
| 1151 |
+
self._write_list(file, 'Obsoletes', self.get_obsoletes())
|
| 1152 |
+
|
| 1153 |
+
def _write_list(self, file, name, values):
|
| 1154 |
+
for value in values:
|
| 1155 |
+
file.write('%s: %s\n' % (name, value))
|
| 1156 |
+
|
| 1157 |
+
# -- Metadata query methods ----------------------------------------
|
| 1158 |
+
|
| 1159 |
+
def get_name(self):
|
| 1160 |
+
return self.name or "UNKNOWN"
|
| 1161 |
+
|
| 1162 |
+
def get_version(self):
|
| 1163 |
+
return self.version or "0.0.0"
|
| 1164 |
+
|
| 1165 |
+
def get_fullname(self):
|
| 1166 |
+
return "%s-%s" % (self.get_name(), self.get_version())
|
| 1167 |
+
|
| 1168 |
+
def get_author(self):
|
| 1169 |
+
return self.author or "UNKNOWN"
|
| 1170 |
+
|
| 1171 |
+
def get_author_email(self):
|
| 1172 |
+
return self.author_email or "UNKNOWN"
|
| 1173 |
+
|
| 1174 |
+
def get_maintainer(self):
|
| 1175 |
+
return self.maintainer or "UNKNOWN"
|
| 1176 |
+
|
| 1177 |
+
def get_maintainer_email(self):
|
| 1178 |
+
return self.maintainer_email or "UNKNOWN"
|
| 1179 |
+
|
| 1180 |
+
def get_contact(self):
|
| 1181 |
+
return self.maintainer or self.author or "UNKNOWN"
|
| 1182 |
+
|
| 1183 |
+
def get_contact_email(self):
|
| 1184 |
+
return self.maintainer_email or self.author_email or "UNKNOWN"
|
| 1185 |
+
|
| 1186 |
+
def get_url(self):
|
| 1187 |
+
return self.url or "UNKNOWN"
|
| 1188 |
+
|
| 1189 |
+
def get_license(self):
|
| 1190 |
+
return self.license or "UNKNOWN"
|
| 1191 |
+
get_licence = get_license
|
| 1192 |
+
|
| 1193 |
+
def get_description(self):
|
| 1194 |
+
return self.description or "UNKNOWN"
|
| 1195 |
+
|
| 1196 |
+
def get_long_description(self):
|
| 1197 |
+
return self.long_description or "UNKNOWN"
|
| 1198 |
+
|
| 1199 |
+
def get_keywords(self):
|
| 1200 |
+
return self.keywords or []
|
| 1201 |
+
|
| 1202 |
+
def set_keywords(self, value):
|
| 1203 |
+
self.keywords = _ensure_list(value, 'keywords')
|
| 1204 |
+
|
| 1205 |
+
def get_platforms(self):
|
| 1206 |
+
return self.platforms or ["UNKNOWN"]
|
| 1207 |
+
|
| 1208 |
+
def set_platforms(self, value):
|
| 1209 |
+
self.platforms = _ensure_list(value, 'platforms')
|
| 1210 |
+
|
| 1211 |
+
def get_classifiers(self):
|
| 1212 |
+
return self.classifiers or []
|
| 1213 |
+
|
| 1214 |
+
def set_classifiers(self, value):
|
| 1215 |
+
self.classifiers = _ensure_list(value, 'classifiers')
|
| 1216 |
+
|
| 1217 |
+
def get_download_url(self):
|
| 1218 |
+
return self.download_url or "UNKNOWN"
|
| 1219 |
+
|
| 1220 |
+
# PEP 314
|
| 1221 |
+
def get_requires(self):
|
| 1222 |
+
return self.requires or []
|
| 1223 |
+
|
| 1224 |
+
def set_requires(self, value):
|
| 1225 |
+
import distutils.versionpredicate
|
| 1226 |
+
for v in value:
|
| 1227 |
+
distutils.versionpredicate.VersionPredicate(v)
|
| 1228 |
+
self.requires = list(value)
|
| 1229 |
+
|
| 1230 |
+
def get_provides(self):
|
| 1231 |
+
return self.provides or []
|
| 1232 |
+
|
| 1233 |
+
def set_provides(self, value):
|
| 1234 |
+
value = [v.strip() for v in value]
|
| 1235 |
+
for v in value:
|
| 1236 |
+
import distutils.versionpredicate
|
| 1237 |
+
distutils.versionpredicate.split_provision(v)
|
| 1238 |
+
self.provides = value
|
| 1239 |
+
|
| 1240 |
+
def get_obsoletes(self):
|
| 1241 |
+
return self.obsoletes or []
|
| 1242 |
+
|
| 1243 |
+
def set_obsoletes(self, value):
|
| 1244 |
+
import distutils.versionpredicate
|
| 1245 |
+
for v in value:
|
| 1246 |
+
distutils.versionpredicate.VersionPredicate(v)
|
| 1247 |
+
self.obsoletes = list(value)
|
| 1248 |
+
|
| 1249 |
+
def fix_help_options(options):
|
| 1250 |
+
"""Convert a 4-tuple 'help_options' list as found in various command
|
| 1251 |
+
classes to the 3-tuple form required by FancyGetopt.
|
| 1252 |
+
"""
|
| 1253 |
+
new_options = []
|
| 1254 |
+
for help_tuple in options:
|
| 1255 |
+
new_options.append(help_tuple[0:3])
|
| 1256 |
+
return new_options
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/errors.py
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""distutils.errors
|
| 2 |
+
|
| 3 |
+
Provides exceptions used by the Distutils modules. Note that Distutils
|
| 4 |
+
modules may raise standard exceptions; in particular, SystemExit is
|
| 5 |
+
usually raised for errors that are obviously the end-user's fault
|
| 6 |
+
(eg. bad command-line arguments).
|
| 7 |
+
|
| 8 |
+
This module is safe to use in "from ... import *" mode; it only exports
|
| 9 |
+
symbols whose names start with "Distutils" and end with "Error"."""
|
| 10 |
+
|
| 11 |
+
class DistutilsError (Exception):
|
| 12 |
+
"""The root of all Distutils evil."""
|
| 13 |
+
pass
|
| 14 |
+
|
| 15 |
+
class DistutilsModuleError (DistutilsError):
|
| 16 |
+
"""Unable to load an expected module, or to find an expected class
|
| 17 |
+
within some module (in particular, command modules and classes)."""
|
| 18 |
+
pass
|
| 19 |
+
|
| 20 |
+
class DistutilsClassError (DistutilsError):
|
| 21 |
+
"""Some command class (or possibly distribution class, if anyone
|
| 22 |
+
feels a need to subclass Distribution) is found not to be holding
|
| 23 |
+
up its end of the bargain, ie. implementing some part of the
|
| 24 |
+
"command "interface."""
|
| 25 |
+
pass
|
| 26 |
+
|
| 27 |
+
class DistutilsGetoptError (DistutilsError):
|
| 28 |
+
"""The option table provided to 'fancy_getopt()' is bogus."""
|
| 29 |
+
pass
|
| 30 |
+
|
| 31 |
+
class DistutilsArgError (DistutilsError):
|
| 32 |
+
"""Raised by fancy_getopt in response to getopt.error -- ie. an
|
| 33 |
+
error in the command line usage."""
|
| 34 |
+
pass
|
| 35 |
+
|
| 36 |
+
class DistutilsFileError (DistutilsError):
|
| 37 |
+
"""Any problems in the filesystem: expected file not found, etc.
|
| 38 |
+
Typically this is for problems that we detect before OSError
|
| 39 |
+
could be raised."""
|
| 40 |
+
pass
|
| 41 |
+
|
| 42 |
+
class DistutilsOptionError (DistutilsError):
|
| 43 |
+
"""Syntactic/semantic errors in command options, such as use of
|
| 44 |
+
mutually conflicting options, or inconsistent options,
|
| 45 |
+
badly-spelled values, etc. No distinction is made between option
|
| 46 |
+
values originating in the setup script, the command line, config
|
| 47 |
+
files, or what-have-you -- but if we *know* something originated in
|
| 48 |
+
the setup script, we'll raise DistutilsSetupError instead."""
|
| 49 |
+
pass
|
| 50 |
+
|
| 51 |
+
class DistutilsSetupError (DistutilsError):
|
| 52 |
+
"""For errors that can be definitely blamed on the setup script,
|
| 53 |
+
such as invalid keyword arguments to 'setup()'."""
|
| 54 |
+
pass
|
| 55 |
+
|
| 56 |
+
class DistutilsPlatformError (DistutilsError):
|
| 57 |
+
"""We don't know how to do something on the current platform (but
|
| 58 |
+
we do know how to do it on some platform) -- eg. trying to compile
|
| 59 |
+
C files on a platform not supported by a CCompiler subclass."""
|
| 60 |
+
pass
|
| 61 |
+
|
| 62 |
+
class DistutilsExecError (DistutilsError):
|
| 63 |
+
"""Any problems executing an external program (such as the C
|
| 64 |
+
compiler, when compiling C files)."""
|
| 65 |
+
pass
|
| 66 |
+
|
| 67 |
+
class DistutilsInternalError (DistutilsError):
|
| 68 |
+
"""Internal inconsistencies or impossibilities (obviously, this
|
| 69 |
+
should never be seen if the code is working!)."""
|
| 70 |
+
pass
|
| 71 |
+
|
| 72 |
+
class DistutilsTemplateError (DistutilsError):
|
| 73 |
+
"""Syntax error in a file list template."""
|
| 74 |
+
|
| 75 |
+
class DistutilsByteCompileError(DistutilsError):
|
| 76 |
+
"""Byte compile error."""
|
| 77 |
+
|
| 78 |
+
# Exception classes used by the CCompiler implementation classes
|
| 79 |
+
class CCompilerError (Exception):
|
| 80 |
+
"""Some compile/link operation failed."""
|
| 81 |
+
|
| 82 |
+
class PreprocessError (CCompilerError):
|
| 83 |
+
"""Failure to preprocess one or more C/C++ files."""
|
| 84 |
+
|
| 85 |
+
class CompileError (CCompilerError):
|
| 86 |
+
"""Failure to compile one or more C/C++ source files."""
|
| 87 |
+
|
| 88 |
+
class LibError (CCompilerError):
|
| 89 |
+
"""Failure to create a static library from one or more C/C++ object
|
| 90 |
+
files."""
|
| 91 |
+
|
| 92 |
+
class LinkError (CCompilerError):
|
| 93 |
+
"""Failure to link one or more C/C++ object files into an executable
|
| 94 |
+
or shared library file."""
|
| 95 |
+
|
| 96 |
+
class UnknownFileError (CCompilerError):
|
| 97 |
+
"""Attempt to process an unknown file type."""
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/fancy_getopt.py
ADDED
|
@@ -0,0 +1,457 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""distutils.fancy_getopt
|
| 2 |
+
|
| 3 |
+
Wrapper around the standard getopt module that provides the following
|
| 4 |
+
additional features:
|
| 5 |
+
* short and long options are tied together
|
| 6 |
+
* options have help strings, so fancy_getopt could potentially
|
| 7 |
+
create a complete usage summary
|
| 8 |
+
* options set attributes of a passed-in object
|
| 9 |
+
"""
|
| 10 |
+
|
| 11 |
+
import sys, string, re
|
| 12 |
+
import getopt
|
| 13 |
+
from distutils.errors import *
|
| 14 |
+
|
| 15 |
+
# Much like command_re in distutils.core, this is close to but not quite
|
| 16 |
+
# the same as a Python NAME -- except, in the spirit of most GNU
|
| 17 |
+
# utilities, we use '-' in place of '_'. (The spirit of LISP lives on!)
|
| 18 |
+
# The similarities to NAME are again not a coincidence...
|
| 19 |
+
longopt_pat = r'[a-zA-Z](?:[a-zA-Z0-9-]*)'
|
| 20 |
+
longopt_re = re.compile(r'^%s$' % longopt_pat)
|
| 21 |
+
|
| 22 |
+
# For recognizing "negative alias" options, eg. "quiet=!verbose"
|
| 23 |
+
neg_alias_re = re.compile("^(%s)=!(%s)$" % (longopt_pat, longopt_pat))
|
| 24 |
+
|
| 25 |
+
# This is used to translate long options to legitimate Python identifiers
|
| 26 |
+
# (for use as attributes of some object).
|
| 27 |
+
longopt_xlate = str.maketrans('-', '_')
|
| 28 |
+
|
| 29 |
+
class FancyGetopt:
|
| 30 |
+
"""Wrapper around the standard 'getopt()' module that provides some
|
| 31 |
+
handy extra functionality:
|
| 32 |
+
* short and long options are tied together
|
| 33 |
+
* options have help strings, and help text can be assembled
|
| 34 |
+
from them
|
| 35 |
+
* options set attributes of a passed-in object
|
| 36 |
+
* boolean options can have "negative aliases" -- eg. if
|
| 37 |
+
--quiet is the "negative alias" of --verbose, then "--quiet"
|
| 38 |
+
on the command line sets 'verbose' to false
|
| 39 |
+
"""
|
| 40 |
+
|
| 41 |
+
def __init__(self, option_table=None):
|
| 42 |
+
# The option table is (currently) a list of tuples. The
|
| 43 |
+
# tuples may have 3 or four values:
|
| 44 |
+
# (long_option, short_option, help_string [, repeatable])
|
| 45 |
+
# if an option takes an argument, its long_option should have '='
|
| 46 |
+
# appended; short_option should just be a single character, no ':'
|
| 47 |
+
# in any case. If a long_option doesn't have a corresponding
|
| 48 |
+
# short_option, short_option should be None. All option tuples
|
| 49 |
+
# must have long options.
|
| 50 |
+
self.option_table = option_table
|
| 51 |
+
|
| 52 |
+
# 'option_index' maps long option names to entries in the option
|
| 53 |
+
# table (ie. those 3-tuples).
|
| 54 |
+
self.option_index = {}
|
| 55 |
+
if self.option_table:
|
| 56 |
+
self._build_index()
|
| 57 |
+
|
| 58 |
+
# 'alias' records (duh) alias options; {'foo': 'bar'} means
|
| 59 |
+
# --foo is an alias for --bar
|
| 60 |
+
self.alias = {}
|
| 61 |
+
|
| 62 |
+
# 'negative_alias' keeps track of options that are the boolean
|
| 63 |
+
# opposite of some other option
|
| 64 |
+
self.negative_alias = {}
|
| 65 |
+
|
| 66 |
+
# These keep track of the information in the option table. We
|
| 67 |
+
# don't actually populate these structures until we're ready to
|
| 68 |
+
# parse the command-line, since the 'option_table' passed in here
|
| 69 |
+
# isn't necessarily the final word.
|
| 70 |
+
self.short_opts = []
|
| 71 |
+
self.long_opts = []
|
| 72 |
+
self.short2long = {}
|
| 73 |
+
self.attr_name = {}
|
| 74 |
+
self.takes_arg = {}
|
| 75 |
+
|
| 76 |
+
# And 'option_order' is filled up in 'getopt()'; it records the
|
| 77 |
+
# original order of options (and their values) on the command-line,
|
| 78 |
+
# but expands short options, converts aliases, etc.
|
| 79 |
+
self.option_order = []
|
| 80 |
+
|
| 81 |
+
def _build_index(self):
|
| 82 |
+
self.option_index.clear()
|
| 83 |
+
for option in self.option_table:
|
| 84 |
+
self.option_index[option[0]] = option
|
| 85 |
+
|
| 86 |
+
def set_option_table(self, option_table):
|
| 87 |
+
self.option_table = option_table
|
| 88 |
+
self._build_index()
|
| 89 |
+
|
| 90 |
+
def add_option(self, long_option, short_option=None, help_string=None):
|
| 91 |
+
if long_option in self.option_index:
|
| 92 |
+
raise DistutilsGetoptError(
|
| 93 |
+
"option conflict: already an option '%s'" % long_option)
|
| 94 |
+
else:
|
| 95 |
+
option = (long_option, short_option, help_string)
|
| 96 |
+
self.option_table.append(option)
|
| 97 |
+
self.option_index[long_option] = option
|
| 98 |
+
|
| 99 |
+
def has_option(self, long_option):
|
| 100 |
+
"""Return true if the option table for this parser has an
|
| 101 |
+
option with long name 'long_option'."""
|
| 102 |
+
return long_option in self.option_index
|
| 103 |
+
|
| 104 |
+
def get_attr_name(self, long_option):
|
| 105 |
+
"""Translate long option name 'long_option' to the form it
|
| 106 |
+
has as an attribute of some object: ie., translate hyphens
|
| 107 |
+
to underscores."""
|
| 108 |
+
return long_option.translate(longopt_xlate)
|
| 109 |
+
|
| 110 |
+
def _check_alias_dict(self, aliases, what):
|
| 111 |
+
assert isinstance(aliases, dict)
|
| 112 |
+
for (alias, opt) in aliases.items():
|
| 113 |
+
if alias not in self.option_index:
|
| 114 |
+
raise DistutilsGetoptError(("invalid %s '%s': "
|
| 115 |
+
"option '%s' not defined") % (what, alias, alias))
|
| 116 |
+
if opt not in self.option_index:
|
| 117 |
+
raise DistutilsGetoptError(("invalid %s '%s': "
|
| 118 |
+
"aliased option '%s' not defined") % (what, alias, opt))
|
| 119 |
+
|
| 120 |
+
def set_aliases(self, alias):
|
| 121 |
+
"""Set the aliases for this option parser."""
|
| 122 |
+
self._check_alias_dict(alias, "alias")
|
| 123 |
+
self.alias = alias
|
| 124 |
+
|
| 125 |
+
def set_negative_aliases(self, negative_alias):
|
| 126 |
+
"""Set the negative aliases for this option parser.
|
| 127 |
+
'negative_alias' should be a dictionary mapping option names to
|
| 128 |
+
option names, both the key and value must already be defined
|
| 129 |
+
in the option table."""
|
| 130 |
+
self._check_alias_dict(negative_alias, "negative alias")
|
| 131 |
+
self.negative_alias = negative_alias
|
| 132 |
+
|
| 133 |
+
def _grok_option_table(self):
|
| 134 |
+
"""Populate the various data structures that keep tabs on the
|
| 135 |
+
option table. Called by 'getopt()' before it can do anything
|
| 136 |
+
worthwhile.
|
| 137 |
+
"""
|
| 138 |
+
self.long_opts = []
|
| 139 |
+
self.short_opts = []
|
| 140 |
+
self.short2long.clear()
|
| 141 |
+
self.repeat = {}
|
| 142 |
+
|
| 143 |
+
for option in self.option_table:
|
| 144 |
+
if len(option) == 3:
|
| 145 |
+
long, short, help = option
|
| 146 |
+
repeat = 0
|
| 147 |
+
elif len(option) == 4:
|
| 148 |
+
long, short, help, repeat = option
|
| 149 |
+
else:
|
| 150 |
+
# the option table is part of the code, so simply
|
| 151 |
+
# assert that it is correct
|
| 152 |
+
raise ValueError("invalid option tuple: %r" % (option,))
|
| 153 |
+
|
| 154 |
+
# Type- and value-check the option names
|
| 155 |
+
if not isinstance(long, str) or len(long) < 2:
|
| 156 |
+
raise DistutilsGetoptError(("invalid long option '%s': "
|
| 157 |
+
"must be a string of length >= 2") % long)
|
| 158 |
+
|
| 159 |
+
if (not ((short is None) or
|
| 160 |
+
(isinstance(short, str) and len(short) == 1))):
|
| 161 |
+
raise DistutilsGetoptError("invalid short option '%s': "
|
| 162 |
+
"must a single character or None" % short)
|
| 163 |
+
|
| 164 |
+
self.repeat[long] = repeat
|
| 165 |
+
self.long_opts.append(long)
|
| 166 |
+
|
| 167 |
+
if long[-1] == '=': # option takes an argument?
|
| 168 |
+
if short: short = short + ':'
|
| 169 |
+
long = long[0:-1]
|
| 170 |
+
self.takes_arg[long] = 1
|
| 171 |
+
else:
|
| 172 |
+
# Is option is a "negative alias" for some other option (eg.
|
| 173 |
+
# "quiet" == "!verbose")?
|
| 174 |
+
alias_to = self.negative_alias.get(long)
|
| 175 |
+
if alias_to is not None:
|
| 176 |
+
if self.takes_arg[alias_to]:
|
| 177 |
+
raise DistutilsGetoptError(
|
| 178 |
+
"invalid negative alias '%s': "
|
| 179 |
+
"aliased option '%s' takes a value"
|
| 180 |
+
% (long, alias_to))
|
| 181 |
+
|
| 182 |
+
self.long_opts[-1] = long # XXX redundant?!
|
| 183 |
+
self.takes_arg[long] = 0
|
| 184 |
+
|
| 185 |
+
# If this is an alias option, make sure its "takes arg" flag is
|
| 186 |
+
# the same as the option it's aliased to.
|
| 187 |
+
alias_to = self.alias.get(long)
|
| 188 |
+
if alias_to is not None:
|
| 189 |
+
if self.takes_arg[long] != self.takes_arg[alias_to]:
|
| 190 |
+
raise DistutilsGetoptError(
|
| 191 |
+
"invalid alias '%s': inconsistent with "
|
| 192 |
+
"aliased option '%s' (one of them takes a value, "
|
| 193 |
+
"the other doesn't"
|
| 194 |
+
% (long, alias_to))
|
| 195 |
+
|
| 196 |
+
# Now enforce some bondage on the long option name, so we can
|
| 197 |
+
# later translate it to an attribute name on some object. Have
|
| 198 |
+
# to do this a bit late to make sure we've removed any trailing
|
| 199 |
+
# '='.
|
| 200 |
+
if not longopt_re.match(long):
|
| 201 |
+
raise DistutilsGetoptError(
|
| 202 |
+
"invalid long option name '%s' "
|
| 203 |
+
"(must be letters, numbers, hyphens only" % long)
|
| 204 |
+
|
| 205 |
+
self.attr_name[long] = self.get_attr_name(long)
|
| 206 |
+
if short:
|
| 207 |
+
self.short_opts.append(short)
|
| 208 |
+
self.short2long[short[0]] = long
|
| 209 |
+
|
| 210 |
+
def getopt(self, args=None, object=None):
|
| 211 |
+
"""Parse command-line options in args. Store as attributes on object.
|
| 212 |
+
|
| 213 |
+
If 'args' is None or not supplied, uses 'sys.argv[1:]'. If
|
| 214 |
+
'object' is None or not supplied, creates a new OptionDummy
|
| 215 |
+
object, stores option values there, and returns a tuple (args,
|
| 216 |
+
object). If 'object' is supplied, it is modified in place and
|
| 217 |
+
'getopt()' just returns 'args'; in both cases, the returned
|
| 218 |
+
'args' is a modified copy of the passed-in 'args' list, which
|
| 219 |
+
is left untouched.
|
| 220 |
+
"""
|
| 221 |
+
if args is None:
|
| 222 |
+
args = sys.argv[1:]
|
| 223 |
+
if object is None:
|
| 224 |
+
object = OptionDummy()
|
| 225 |
+
created_object = True
|
| 226 |
+
else:
|
| 227 |
+
created_object = False
|
| 228 |
+
|
| 229 |
+
self._grok_option_table()
|
| 230 |
+
|
| 231 |
+
short_opts = ' '.join(self.short_opts)
|
| 232 |
+
try:
|
| 233 |
+
opts, args = getopt.getopt(args, short_opts, self.long_opts)
|
| 234 |
+
except getopt.error as msg:
|
| 235 |
+
raise DistutilsArgError(msg)
|
| 236 |
+
|
| 237 |
+
for opt, val in opts:
|
| 238 |
+
if len(opt) == 2 and opt[0] == '-': # it's a short option
|
| 239 |
+
opt = self.short2long[opt[1]]
|
| 240 |
+
else:
|
| 241 |
+
assert len(opt) > 2 and opt[:2] == '--'
|
| 242 |
+
opt = opt[2:]
|
| 243 |
+
|
| 244 |
+
alias = self.alias.get(opt)
|
| 245 |
+
if alias:
|
| 246 |
+
opt = alias
|
| 247 |
+
|
| 248 |
+
if not self.takes_arg[opt]: # boolean option?
|
| 249 |
+
assert val == '', "boolean option can't have value"
|
| 250 |
+
alias = self.negative_alias.get(opt)
|
| 251 |
+
if alias:
|
| 252 |
+
opt = alias
|
| 253 |
+
val = 0
|
| 254 |
+
else:
|
| 255 |
+
val = 1
|
| 256 |
+
|
| 257 |
+
attr = self.attr_name[opt]
|
| 258 |
+
# The only repeating option at the moment is 'verbose'.
|
| 259 |
+
# It has a negative option -q quiet, which should set verbose = 0.
|
| 260 |
+
if val and self.repeat.get(attr) is not None:
|
| 261 |
+
val = getattr(object, attr, 0) + 1
|
| 262 |
+
setattr(object, attr, val)
|
| 263 |
+
self.option_order.append((opt, val))
|
| 264 |
+
|
| 265 |
+
# for opts
|
| 266 |
+
if created_object:
|
| 267 |
+
return args, object
|
| 268 |
+
else:
|
| 269 |
+
return args
|
| 270 |
+
|
| 271 |
+
def get_option_order(self):
|
| 272 |
+
"""Returns the list of (option, value) tuples processed by the
|
| 273 |
+
previous run of 'getopt()'. Raises RuntimeError if
|
| 274 |
+
'getopt()' hasn't been called yet.
|
| 275 |
+
"""
|
| 276 |
+
if self.option_order is None:
|
| 277 |
+
raise RuntimeError("'getopt()' hasn't been called yet")
|
| 278 |
+
else:
|
| 279 |
+
return self.option_order
|
| 280 |
+
|
| 281 |
+
def generate_help(self, header=None):
|
| 282 |
+
"""Generate help text (a list of strings, one per suggested line of
|
| 283 |
+
output) from the option table for this FancyGetopt object.
|
| 284 |
+
"""
|
| 285 |
+
# Blithely assume the option table is good: probably wouldn't call
|
| 286 |
+
# 'generate_help()' unless you've already called 'getopt()'.
|
| 287 |
+
|
| 288 |
+
# First pass: determine maximum length of long option names
|
| 289 |
+
max_opt = 0
|
| 290 |
+
for option in self.option_table:
|
| 291 |
+
long = option[0]
|
| 292 |
+
short = option[1]
|
| 293 |
+
l = len(long)
|
| 294 |
+
if long[-1] == '=':
|
| 295 |
+
l = l - 1
|
| 296 |
+
if short is not None:
|
| 297 |
+
l = l + 5 # " (-x)" where short == 'x'
|
| 298 |
+
if l > max_opt:
|
| 299 |
+
max_opt = l
|
| 300 |
+
|
| 301 |
+
opt_width = max_opt + 2 + 2 + 2 # room for indent + dashes + gutter
|
| 302 |
+
|
| 303 |
+
# Typical help block looks like this:
|
| 304 |
+
# --foo controls foonabulation
|
| 305 |
+
# Help block for longest option looks like this:
|
| 306 |
+
# --flimflam set the flim-flam level
|
| 307 |
+
# and with wrapped text:
|
| 308 |
+
# --flimflam set the flim-flam level (must be between
|
| 309 |
+
# 0 and 100, except on Tuesdays)
|
| 310 |
+
# Options with short names will have the short name shown (but
|
| 311 |
+
# it doesn't contribute to max_opt):
|
| 312 |
+
# --foo (-f) controls foonabulation
|
| 313 |
+
# If adding the short option would make the left column too wide,
|
| 314 |
+
# we push the explanation off to the next line
|
| 315 |
+
# --flimflam (-l)
|
| 316 |
+
# set the flim-flam level
|
| 317 |
+
# Important parameters:
|
| 318 |
+
# - 2 spaces before option block start lines
|
| 319 |
+
# - 2 dashes for each long option name
|
| 320 |
+
# - min. 2 spaces between option and explanation (gutter)
|
| 321 |
+
# - 5 characters (incl. space) for short option name
|
| 322 |
+
|
| 323 |
+
# Now generate lines of help text. (If 80 columns were good enough
|
| 324 |
+
# for Jesus, then 78 columns are good enough for me!)
|
| 325 |
+
line_width = 78
|
| 326 |
+
text_width = line_width - opt_width
|
| 327 |
+
big_indent = ' ' * opt_width
|
| 328 |
+
if header:
|
| 329 |
+
lines = [header]
|
| 330 |
+
else:
|
| 331 |
+
lines = ['Option summary:']
|
| 332 |
+
|
| 333 |
+
for option in self.option_table:
|
| 334 |
+
long, short, help = option[:3]
|
| 335 |
+
text = wrap_text(help, text_width)
|
| 336 |
+
if long[-1] == '=':
|
| 337 |
+
long = long[0:-1]
|
| 338 |
+
|
| 339 |
+
# Case 1: no short option at all (makes life easy)
|
| 340 |
+
if short is None:
|
| 341 |
+
if text:
|
| 342 |
+
lines.append(" --%-*s %s" % (max_opt, long, text[0]))
|
| 343 |
+
else:
|
| 344 |
+
lines.append(" --%-*s " % (max_opt, long))
|
| 345 |
+
|
| 346 |
+
# Case 2: we have a short option, so we have to include it
|
| 347 |
+
# just after the long option
|
| 348 |
+
else:
|
| 349 |
+
opt_names = "%s (-%s)" % (long, short)
|
| 350 |
+
if text:
|
| 351 |
+
lines.append(" --%-*s %s" %
|
| 352 |
+
(max_opt, opt_names, text[0]))
|
| 353 |
+
else:
|
| 354 |
+
lines.append(" --%-*s" % opt_names)
|
| 355 |
+
|
| 356 |
+
for l in text[1:]:
|
| 357 |
+
lines.append(big_indent + l)
|
| 358 |
+
return lines
|
| 359 |
+
|
| 360 |
+
def print_help(self, header=None, file=None):
|
| 361 |
+
if file is None:
|
| 362 |
+
file = sys.stdout
|
| 363 |
+
for line in self.generate_help(header):
|
| 364 |
+
file.write(line + "\n")
|
| 365 |
+
|
| 366 |
+
|
| 367 |
+
def fancy_getopt(options, negative_opt, object, args):
|
| 368 |
+
parser = FancyGetopt(options)
|
| 369 |
+
parser.set_negative_aliases(negative_opt)
|
| 370 |
+
return parser.getopt(args, object)
|
| 371 |
+
|
| 372 |
+
|
| 373 |
+
WS_TRANS = {ord(_wschar) : ' ' for _wschar in string.whitespace}
|
| 374 |
+
|
| 375 |
+
def wrap_text(text, width):
|
| 376 |
+
"""wrap_text(text : string, width : int) -> [string]
|
| 377 |
+
|
| 378 |
+
Split 'text' into multiple lines of no more than 'width' characters
|
| 379 |
+
each, and return the list of strings that results.
|
| 380 |
+
"""
|
| 381 |
+
if text is None:
|
| 382 |
+
return []
|
| 383 |
+
if len(text) <= width:
|
| 384 |
+
return [text]
|
| 385 |
+
|
| 386 |
+
text = text.expandtabs()
|
| 387 |
+
text = text.translate(WS_TRANS)
|
| 388 |
+
chunks = re.split(r'( +|-+)', text)
|
| 389 |
+
chunks = [ch for ch in chunks if ch] # ' - ' results in empty strings
|
| 390 |
+
lines = []
|
| 391 |
+
|
| 392 |
+
while chunks:
|
| 393 |
+
cur_line = [] # list of chunks (to-be-joined)
|
| 394 |
+
cur_len = 0 # length of current line
|
| 395 |
+
|
| 396 |
+
while chunks:
|
| 397 |
+
l = len(chunks[0])
|
| 398 |
+
if cur_len + l <= width: # can squeeze (at least) this chunk in
|
| 399 |
+
cur_line.append(chunks[0])
|
| 400 |
+
del chunks[0]
|
| 401 |
+
cur_len = cur_len + l
|
| 402 |
+
else: # this line is full
|
| 403 |
+
# drop last chunk if all space
|
| 404 |
+
if cur_line and cur_line[-1][0] == ' ':
|
| 405 |
+
del cur_line[-1]
|
| 406 |
+
break
|
| 407 |
+
|
| 408 |
+
if chunks: # any chunks left to process?
|
| 409 |
+
# if the current line is still empty, then we had a single
|
| 410 |
+
# chunk that's too big too fit on a line -- so we break
|
| 411 |
+
# down and break it up at the line width
|
| 412 |
+
if cur_len == 0:
|
| 413 |
+
cur_line.append(chunks[0][0:width])
|
| 414 |
+
chunks[0] = chunks[0][width:]
|
| 415 |
+
|
| 416 |
+
# all-whitespace chunks at the end of a line can be discarded
|
| 417 |
+
# (and we know from the re.split above that if a chunk has
|
| 418 |
+
# *any* whitespace, it is *all* whitespace)
|
| 419 |
+
if chunks[0][0] == ' ':
|
| 420 |
+
del chunks[0]
|
| 421 |
+
|
| 422 |
+
# and store this line in the list-of-all-lines -- as a single
|
| 423 |
+
# string, of course!
|
| 424 |
+
lines.append(''.join(cur_line))
|
| 425 |
+
|
| 426 |
+
return lines
|
| 427 |
+
|
| 428 |
+
|
| 429 |
+
def translate_longopt(opt):
|
| 430 |
+
"""Convert a long option name to a valid Python identifier by
|
| 431 |
+
changing "-" to "_".
|
| 432 |
+
"""
|
| 433 |
+
return opt.translate(longopt_xlate)
|
| 434 |
+
|
| 435 |
+
|
| 436 |
+
class OptionDummy:
|
| 437 |
+
"""Dummy class just used as a place to hold command-line option
|
| 438 |
+
values as instance attributes."""
|
| 439 |
+
|
| 440 |
+
def __init__(self, options=[]):
|
| 441 |
+
"""Create a new OptionDummy instance. The attributes listed in
|
| 442 |
+
'options' will be initialized to None."""
|
| 443 |
+
for opt in options:
|
| 444 |
+
setattr(self, opt, None)
|
| 445 |
+
|
| 446 |
+
|
| 447 |
+
if __name__ == "__main__":
|
| 448 |
+
text = """\
|
| 449 |
+
Tra-la-la, supercalifragilisticexpialidocious.
|
| 450 |
+
How *do* you spell that odd word, anyways?
|
| 451 |
+
(Someone ask Mary -- she'll know [or she'll
|
| 452 |
+
say, "How should I know?"].)"""
|
| 453 |
+
|
| 454 |
+
for w in (10, 20, 30, 40):
|
| 455 |
+
print("width: %d" % w)
|
| 456 |
+
print("\n".join(wrap_text(text, w)))
|
| 457 |
+
print()
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/file_util.py
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""distutils.file_util
|
| 2 |
+
|
| 3 |
+
Utility functions for operating on single files.
|
| 4 |
+
"""
|
| 5 |
+
|
| 6 |
+
import os
|
| 7 |
+
from distutils.errors import DistutilsFileError
|
| 8 |
+
from distutils import log
|
| 9 |
+
|
| 10 |
+
# for generating verbose output in 'copy_file()'
|
| 11 |
+
_copy_action = { None: 'copying',
|
| 12 |
+
'hard': 'hard linking',
|
| 13 |
+
'sym': 'symbolically linking' }
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
def _copy_file_contents(src, dst, buffer_size=16*1024):
|
| 17 |
+
"""Copy the file 'src' to 'dst'; both must be filenames. Any error
|
| 18 |
+
opening either file, reading from 'src', or writing to 'dst', raises
|
| 19 |
+
DistutilsFileError. Data is read/written in chunks of 'buffer_size'
|
| 20 |
+
bytes (default 16k). No attempt is made to handle anything apart from
|
| 21 |
+
regular files.
|
| 22 |
+
"""
|
| 23 |
+
# Stolen from shutil module in the standard library, but with
|
| 24 |
+
# custom error-handling added.
|
| 25 |
+
fsrc = None
|
| 26 |
+
fdst = None
|
| 27 |
+
try:
|
| 28 |
+
try:
|
| 29 |
+
fsrc = open(src, 'rb')
|
| 30 |
+
except OSError as e:
|
| 31 |
+
raise DistutilsFileError("could not open '%s': %s" % (src, e.strerror))
|
| 32 |
+
|
| 33 |
+
if os.path.exists(dst):
|
| 34 |
+
try:
|
| 35 |
+
os.unlink(dst)
|
| 36 |
+
except OSError as e:
|
| 37 |
+
raise DistutilsFileError(
|
| 38 |
+
"could not delete '%s': %s" % (dst, e.strerror))
|
| 39 |
+
|
| 40 |
+
try:
|
| 41 |
+
fdst = open(dst, 'wb')
|
| 42 |
+
except OSError as e:
|
| 43 |
+
raise DistutilsFileError(
|
| 44 |
+
"could not create '%s': %s" % (dst, e.strerror))
|
| 45 |
+
|
| 46 |
+
while True:
|
| 47 |
+
try:
|
| 48 |
+
buf = fsrc.read(buffer_size)
|
| 49 |
+
except OSError as e:
|
| 50 |
+
raise DistutilsFileError(
|
| 51 |
+
"could not read from '%s': %s" % (src, e.strerror))
|
| 52 |
+
|
| 53 |
+
if not buf:
|
| 54 |
+
break
|
| 55 |
+
|
| 56 |
+
try:
|
| 57 |
+
fdst.write(buf)
|
| 58 |
+
except OSError as e:
|
| 59 |
+
raise DistutilsFileError(
|
| 60 |
+
"could not write to '%s': %s" % (dst, e.strerror))
|
| 61 |
+
finally:
|
| 62 |
+
if fdst:
|
| 63 |
+
fdst.close()
|
| 64 |
+
if fsrc:
|
| 65 |
+
fsrc.close()
|
| 66 |
+
|
| 67 |
+
def copy_file(src, dst, preserve_mode=1, preserve_times=1, update=0,
|
| 68 |
+
link=None, verbose=1, dry_run=0):
|
| 69 |
+
"""Copy a file 'src' to 'dst'. If 'dst' is a directory, then 'src' is
|
| 70 |
+
copied there with the same name; otherwise, it must be a filename. (If
|
| 71 |
+
the file exists, it will be ruthlessly clobbered.) If 'preserve_mode'
|
| 72 |
+
is true (the default), the file's mode (type and permission bits, or
|
| 73 |
+
whatever is analogous on the current platform) is copied. If
|
| 74 |
+
'preserve_times' is true (the default), the last-modified and
|
| 75 |
+
last-access times are copied as well. If 'update' is true, 'src' will
|
| 76 |
+
only be copied if 'dst' does not exist, or if 'dst' does exist but is
|
| 77 |
+
older than 'src'.
|
| 78 |
+
|
| 79 |
+
'link' allows you to make hard links (os.link) or symbolic links
|
| 80 |
+
(os.symlink) instead of copying: set it to "hard" or "sym"; if it is
|
| 81 |
+
None (the default), files are copied. Don't set 'link' on systems that
|
| 82 |
+
don't support it: 'copy_file()' doesn't check if hard or symbolic
|
| 83 |
+
linking is available. If hardlink fails, falls back to
|
| 84 |
+
_copy_file_contents().
|
| 85 |
+
|
| 86 |
+
Under Mac OS, uses the native file copy function in macostools; on
|
| 87 |
+
other systems, uses '_copy_file_contents()' to copy file contents.
|
| 88 |
+
|
| 89 |
+
Return a tuple (dest_name, copied): 'dest_name' is the actual name of
|
| 90 |
+
the output file, and 'copied' is true if the file was copied (or would
|
| 91 |
+
have been copied, if 'dry_run' true).
|
| 92 |
+
"""
|
| 93 |
+
# XXX if the destination file already exists, we clobber it if
|
| 94 |
+
# copying, but blow up if linking. Hmmm. And I don't know what
|
| 95 |
+
# macostools.copyfile() does. Should definitely be consistent, and
|
| 96 |
+
# should probably blow up if destination exists and we would be
|
| 97 |
+
# changing it (ie. it's not already a hard/soft link to src OR
|
| 98 |
+
# (not update) and (src newer than dst).
|
| 99 |
+
|
| 100 |
+
from distutils.dep_util import newer
|
| 101 |
+
from stat import ST_ATIME, ST_MTIME, ST_MODE, S_IMODE
|
| 102 |
+
|
| 103 |
+
if not os.path.isfile(src):
|
| 104 |
+
raise DistutilsFileError(
|
| 105 |
+
"can't copy '%s': doesn't exist or not a regular file" % src)
|
| 106 |
+
|
| 107 |
+
if os.path.isdir(dst):
|
| 108 |
+
dir = dst
|
| 109 |
+
dst = os.path.join(dst, os.path.basename(src))
|
| 110 |
+
else:
|
| 111 |
+
dir = os.path.dirname(dst)
|
| 112 |
+
|
| 113 |
+
if update and not newer(src, dst):
|
| 114 |
+
if verbose >= 1:
|
| 115 |
+
log.debug("not copying %s (output up-to-date)", src)
|
| 116 |
+
return (dst, 0)
|
| 117 |
+
|
| 118 |
+
try:
|
| 119 |
+
action = _copy_action[link]
|
| 120 |
+
except KeyError:
|
| 121 |
+
raise ValueError("invalid value '%s' for 'link' argument" % link)
|
| 122 |
+
|
| 123 |
+
if verbose >= 1:
|
| 124 |
+
if os.path.basename(dst) == os.path.basename(src):
|
| 125 |
+
log.info("%s %s -> %s", action, src, dir)
|
| 126 |
+
else:
|
| 127 |
+
log.info("%s %s -> %s", action, src, dst)
|
| 128 |
+
|
| 129 |
+
if dry_run:
|
| 130 |
+
return (dst, 1)
|
| 131 |
+
|
| 132 |
+
# If linking (hard or symbolic), use the appropriate system call
|
| 133 |
+
# (Unix only, of course, but that's the caller's responsibility)
|
| 134 |
+
elif link == 'hard':
|
| 135 |
+
if not (os.path.exists(dst) and os.path.samefile(src, dst)):
|
| 136 |
+
try:
|
| 137 |
+
os.link(src, dst)
|
| 138 |
+
return (dst, 1)
|
| 139 |
+
except OSError:
|
| 140 |
+
# If hard linking fails, fall back on copying file
|
| 141 |
+
# (some special filesystems don't support hard linking
|
| 142 |
+
# even under Unix, see issue #8876).
|
| 143 |
+
pass
|
| 144 |
+
elif link == 'sym':
|
| 145 |
+
if not (os.path.exists(dst) and os.path.samefile(src, dst)):
|
| 146 |
+
os.symlink(src, dst)
|
| 147 |
+
return (dst, 1)
|
| 148 |
+
|
| 149 |
+
# Otherwise (non-Mac, not linking), copy the file contents and
|
| 150 |
+
# (optionally) copy the times and mode.
|
| 151 |
+
_copy_file_contents(src, dst)
|
| 152 |
+
if preserve_mode or preserve_times:
|
| 153 |
+
st = os.stat(src)
|
| 154 |
+
|
| 155 |
+
# According to David Ascher <da@ski.org>, utime() should be done
|
| 156 |
+
# before chmod() (at least under NT).
|
| 157 |
+
if preserve_times:
|
| 158 |
+
os.utime(dst, (st[ST_ATIME], st[ST_MTIME]))
|
| 159 |
+
if preserve_mode:
|
| 160 |
+
os.chmod(dst, S_IMODE(st[ST_MODE]))
|
| 161 |
+
|
| 162 |
+
return (dst, 1)
|
| 163 |
+
|
| 164 |
+
|
| 165 |
+
# XXX I suspect this is Unix-specific -- need porting help!
|
| 166 |
+
def move_file (src, dst,
|
| 167 |
+
verbose=1,
|
| 168 |
+
dry_run=0):
|
| 169 |
+
|
| 170 |
+
"""Move a file 'src' to 'dst'. If 'dst' is a directory, the file will
|
| 171 |
+
be moved into it with the same name; otherwise, 'src' is just renamed
|
| 172 |
+
to 'dst'. Return the new full name of the file.
|
| 173 |
+
|
| 174 |
+
Handles cross-device moves on Unix using 'copy_file()'. What about
|
| 175 |
+
other systems???
|
| 176 |
+
"""
|
| 177 |
+
from os.path import exists, isfile, isdir, basename, dirname
|
| 178 |
+
import errno
|
| 179 |
+
|
| 180 |
+
if verbose >= 1:
|
| 181 |
+
log.info("moving %s -> %s", src, dst)
|
| 182 |
+
|
| 183 |
+
if dry_run:
|
| 184 |
+
return dst
|
| 185 |
+
|
| 186 |
+
if not isfile(src):
|
| 187 |
+
raise DistutilsFileError("can't move '%s': not a regular file" % src)
|
| 188 |
+
|
| 189 |
+
if isdir(dst):
|
| 190 |
+
dst = os.path.join(dst, basename(src))
|
| 191 |
+
elif exists(dst):
|
| 192 |
+
raise DistutilsFileError(
|
| 193 |
+
"can't move '%s': destination '%s' already exists" %
|
| 194 |
+
(src, dst))
|
| 195 |
+
|
| 196 |
+
if not isdir(dirname(dst)):
|
| 197 |
+
raise DistutilsFileError(
|
| 198 |
+
"can't move '%s': destination '%s' not a valid path" %
|
| 199 |
+
(src, dst))
|
| 200 |
+
|
| 201 |
+
copy_it = False
|
| 202 |
+
try:
|
| 203 |
+
os.rename(src, dst)
|
| 204 |
+
except OSError as e:
|
| 205 |
+
(num, msg) = e.args
|
| 206 |
+
if num == errno.EXDEV:
|
| 207 |
+
copy_it = True
|
| 208 |
+
else:
|
| 209 |
+
raise DistutilsFileError(
|
| 210 |
+
"couldn't move '%s' to '%s': %s" % (src, dst, msg))
|
| 211 |
+
|
| 212 |
+
if copy_it:
|
| 213 |
+
copy_file(src, dst, verbose=verbose)
|
| 214 |
+
try:
|
| 215 |
+
os.unlink(src)
|
| 216 |
+
except OSError as e:
|
| 217 |
+
(num, msg) = e.args
|
| 218 |
+
try:
|
| 219 |
+
os.unlink(dst)
|
| 220 |
+
except OSError:
|
| 221 |
+
pass
|
| 222 |
+
raise DistutilsFileError(
|
| 223 |
+
"couldn't move '%s' to '%s' by copy/delete: "
|
| 224 |
+
"delete '%s' failed: %s"
|
| 225 |
+
% (src, dst, src, msg))
|
| 226 |
+
return dst
|
| 227 |
+
|
| 228 |
+
|
| 229 |
+
def write_file (filename, contents):
|
| 230 |
+
"""Create a file with the specified name and write 'contents' (a
|
| 231 |
+
sequence of strings without line terminators) to it.
|
| 232 |
+
"""
|
| 233 |
+
f = open(filename, "w")
|
| 234 |
+
try:
|
| 235 |
+
for line in contents:
|
| 236 |
+
f.write(line + "\n")
|
| 237 |
+
finally:
|
| 238 |
+
f.close()
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/filelist.py
ADDED
|
@@ -0,0 +1,327 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""distutils.filelist
|
| 2 |
+
|
| 3 |
+
Provides the FileList class, used for poking about the filesystem
|
| 4 |
+
and building lists of files.
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
import os, re
|
| 8 |
+
import fnmatch
|
| 9 |
+
import functools
|
| 10 |
+
from distutils.util import convert_path
|
| 11 |
+
from distutils.errors import DistutilsTemplateError, DistutilsInternalError
|
| 12 |
+
from distutils import log
|
| 13 |
+
|
| 14 |
+
class FileList:
|
| 15 |
+
"""A list of files built by on exploring the filesystem and filtered by
|
| 16 |
+
applying various patterns to what we find there.
|
| 17 |
+
|
| 18 |
+
Instance attributes:
|
| 19 |
+
dir
|
| 20 |
+
directory from which files will be taken -- only used if
|
| 21 |
+
'allfiles' not supplied to constructor
|
| 22 |
+
files
|
| 23 |
+
list of filenames currently being built/filtered/manipulated
|
| 24 |
+
allfiles
|
| 25 |
+
complete list of files under consideration (ie. without any
|
| 26 |
+
filtering applied)
|
| 27 |
+
"""
|
| 28 |
+
|
| 29 |
+
def __init__(self, warn=None, debug_print=None):
|
| 30 |
+
# ignore argument to FileList, but keep them for backwards
|
| 31 |
+
# compatibility
|
| 32 |
+
self.allfiles = None
|
| 33 |
+
self.files = []
|
| 34 |
+
|
| 35 |
+
def set_allfiles(self, allfiles):
|
| 36 |
+
self.allfiles = allfiles
|
| 37 |
+
|
| 38 |
+
def findall(self, dir=os.curdir):
|
| 39 |
+
self.allfiles = findall(dir)
|
| 40 |
+
|
| 41 |
+
def debug_print(self, msg):
|
| 42 |
+
"""Print 'msg' to stdout if the global DEBUG (taken from the
|
| 43 |
+
DISTUTILS_DEBUG environment variable) flag is true.
|
| 44 |
+
"""
|
| 45 |
+
from distutils.debug import DEBUG
|
| 46 |
+
if DEBUG:
|
| 47 |
+
print(msg)
|
| 48 |
+
|
| 49 |
+
# -- List-like methods ---------------------------------------------
|
| 50 |
+
|
| 51 |
+
def append(self, item):
|
| 52 |
+
self.files.append(item)
|
| 53 |
+
|
| 54 |
+
def extend(self, items):
|
| 55 |
+
self.files.extend(items)
|
| 56 |
+
|
| 57 |
+
def sort(self):
|
| 58 |
+
# Not a strict lexical sort!
|
| 59 |
+
sortable_files = sorted(map(os.path.split, self.files))
|
| 60 |
+
self.files = []
|
| 61 |
+
for sort_tuple in sortable_files:
|
| 62 |
+
self.files.append(os.path.join(*sort_tuple))
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
# -- Other miscellaneous utility methods ---------------------------
|
| 66 |
+
|
| 67 |
+
def remove_duplicates(self):
|
| 68 |
+
# Assumes list has been sorted!
|
| 69 |
+
for i in range(len(self.files) - 1, 0, -1):
|
| 70 |
+
if self.files[i] == self.files[i - 1]:
|
| 71 |
+
del self.files[i]
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
# -- "File template" methods ---------------------------------------
|
| 75 |
+
|
| 76 |
+
def _parse_template_line(self, line):
|
| 77 |
+
words = line.split()
|
| 78 |
+
action = words[0]
|
| 79 |
+
|
| 80 |
+
patterns = dir = dir_pattern = None
|
| 81 |
+
|
| 82 |
+
if action in ('include', 'exclude',
|
| 83 |
+
'global-include', 'global-exclude'):
|
| 84 |
+
if len(words) < 2:
|
| 85 |
+
raise DistutilsTemplateError(
|
| 86 |
+
"'%s' expects <pattern1> <pattern2> ..." % action)
|
| 87 |
+
patterns = [convert_path(w) for w in words[1:]]
|
| 88 |
+
elif action in ('recursive-include', 'recursive-exclude'):
|
| 89 |
+
if len(words) < 3:
|
| 90 |
+
raise DistutilsTemplateError(
|
| 91 |
+
"'%s' expects <dir> <pattern1> <pattern2> ..." % action)
|
| 92 |
+
dir = convert_path(words[1])
|
| 93 |
+
patterns = [convert_path(w) for w in words[2:]]
|
| 94 |
+
elif action in ('graft', 'prune'):
|
| 95 |
+
if len(words) != 2:
|
| 96 |
+
raise DistutilsTemplateError(
|
| 97 |
+
"'%s' expects a single <dir_pattern>" % action)
|
| 98 |
+
dir_pattern = convert_path(words[1])
|
| 99 |
+
else:
|
| 100 |
+
raise DistutilsTemplateError("unknown action '%s'" % action)
|
| 101 |
+
|
| 102 |
+
return (action, patterns, dir, dir_pattern)
|
| 103 |
+
|
| 104 |
+
def process_template_line(self, line):
|
| 105 |
+
# Parse the line: split it up, make sure the right number of words
|
| 106 |
+
# is there, and return the relevant words. 'action' is always
|
| 107 |
+
# defined: it's the first word of the line. Which of the other
|
| 108 |
+
# three are defined depends on the action; it'll be either
|
| 109 |
+
# patterns, (dir and patterns), or (dir_pattern).
|
| 110 |
+
(action, patterns, dir, dir_pattern) = self._parse_template_line(line)
|
| 111 |
+
|
| 112 |
+
# OK, now we know that the action is valid and we have the
|
| 113 |
+
# right number of words on the line for that action -- so we
|
| 114 |
+
# can proceed with minimal error-checking.
|
| 115 |
+
if action == 'include':
|
| 116 |
+
self.debug_print("include " + ' '.join(patterns))
|
| 117 |
+
for pattern in patterns:
|
| 118 |
+
if not self.include_pattern(pattern, anchor=1):
|
| 119 |
+
log.warn("warning: no files found matching '%s'",
|
| 120 |
+
pattern)
|
| 121 |
+
|
| 122 |
+
elif action == 'exclude':
|
| 123 |
+
self.debug_print("exclude " + ' '.join(patterns))
|
| 124 |
+
for pattern in patterns:
|
| 125 |
+
if not self.exclude_pattern(pattern, anchor=1):
|
| 126 |
+
log.warn(("warning: no previously-included files "
|
| 127 |
+
"found matching '%s'"), pattern)
|
| 128 |
+
|
| 129 |
+
elif action == 'global-include':
|
| 130 |
+
self.debug_print("global-include " + ' '.join(patterns))
|
| 131 |
+
for pattern in patterns:
|
| 132 |
+
if not self.include_pattern(pattern, anchor=0):
|
| 133 |
+
log.warn(("warning: no files found matching '%s' "
|
| 134 |
+
"anywhere in distribution"), pattern)
|
| 135 |
+
|
| 136 |
+
elif action == 'global-exclude':
|
| 137 |
+
self.debug_print("global-exclude " + ' '.join(patterns))
|
| 138 |
+
for pattern in patterns:
|
| 139 |
+
if not self.exclude_pattern(pattern, anchor=0):
|
| 140 |
+
log.warn(("warning: no previously-included files matching "
|
| 141 |
+
"'%s' found anywhere in distribution"),
|
| 142 |
+
pattern)
|
| 143 |
+
|
| 144 |
+
elif action == 'recursive-include':
|
| 145 |
+
self.debug_print("recursive-include %s %s" %
|
| 146 |
+
(dir, ' '.join(patterns)))
|
| 147 |
+
for pattern in patterns:
|
| 148 |
+
if not self.include_pattern(pattern, prefix=dir):
|
| 149 |
+
log.warn(("warning: no files found matching '%s' "
|
| 150 |
+
"under directory '%s'"),
|
| 151 |
+
pattern, dir)
|
| 152 |
+
|
| 153 |
+
elif action == 'recursive-exclude':
|
| 154 |
+
self.debug_print("recursive-exclude %s %s" %
|
| 155 |
+
(dir, ' '.join(patterns)))
|
| 156 |
+
for pattern in patterns:
|
| 157 |
+
if not self.exclude_pattern(pattern, prefix=dir):
|
| 158 |
+
log.warn(("warning: no previously-included files matching "
|
| 159 |
+
"'%s' found under directory '%s'"),
|
| 160 |
+
pattern, dir)
|
| 161 |
+
|
| 162 |
+
elif action == 'graft':
|
| 163 |
+
self.debug_print("graft " + dir_pattern)
|
| 164 |
+
if not self.include_pattern(None, prefix=dir_pattern):
|
| 165 |
+
log.warn("warning: no directories found matching '%s'",
|
| 166 |
+
dir_pattern)
|
| 167 |
+
|
| 168 |
+
elif action == 'prune':
|
| 169 |
+
self.debug_print("prune " + dir_pattern)
|
| 170 |
+
if not self.exclude_pattern(None, prefix=dir_pattern):
|
| 171 |
+
log.warn(("no previously-included directories found "
|
| 172 |
+
"matching '%s'"), dir_pattern)
|
| 173 |
+
else:
|
| 174 |
+
raise DistutilsInternalError(
|
| 175 |
+
"this cannot happen: invalid action '%s'" % action)
|
| 176 |
+
|
| 177 |
+
|
| 178 |
+
# -- Filtering/selection methods -----------------------------------
|
| 179 |
+
|
| 180 |
+
def include_pattern(self, pattern, anchor=1, prefix=None, is_regex=0):
|
| 181 |
+
"""Select strings (presumably filenames) from 'self.files' that
|
| 182 |
+
match 'pattern', a Unix-style wildcard (glob) pattern. Patterns
|
| 183 |
+
are not quite the same as implemented by the 'fnmatch' module: '*'
|
| 184 |
+
and '?' match non-special characters, where "special" is platform-
|
| 185 |
+
dependent: slash on Unix; colon, slash, and backslash on
|
| 186 |
+
DOS/Windows; and colon on Mac OS.
|
| 187 |
+
|
| 188 |
+
If 'anchor' is true (the default), then the pattern match is more
|
| 189 |
+
stringent: "*.py" will match "foo.py" but not "foo/bar.py". If
|
| 190 |
+
'anchor' is false, both of these will match.
|
| 191 |
+
|
| 192 |
+
If 'prefix' is supplied, then only filenames starting with 'prefix'
|
| 193 |
+
(itself a pattern) and ending with 'pattern', with anything in between
|
| 194 |
+
them, will match. 'anchor' is ignored in this case.
|
| 195 |
+
|
| 196 |
+
If 'is_regex' is true, 'anchor' and 'prefix' are ignored, and
|
| 197 |
+
'pattern' is assumed to be either a string containing a regex or a
|
| 198 |
+
regex object -- no translation is done, the regex is just compiled
|
| 199 |
+
and used as-is.
|
| 200 |
+
|
| 201 |
+
Selected strings will be added to self.files.
|
| 202 |
+
|
| 203 |
+
Return True if files are found, False otherwise.
|
| 204 |
+
"""
|
| 205 |
+
# XXX docstring lying about what the special chars are?
|
| 206 |
+
files_found = False
|
| 207 |
+
pattern_re = translate_pattern(pattern, anchor, prefix, is_regex)
|
| 208 |
+
self.debug_print("include_pattern: applying regex r'%s'" %
|
| 209 |
+
pattern_re.pattern)
|
| 210 |
+
|
| 211 |
+
# delayed loading of allfiles list
|
| 212 |
+
if self.allfiles is None:
|
| 213 |
+
self.findall()
|
| 214 |
+
|
| 215 |
+
for name in self.allfiles:
|
| 216 |
+
if pattern_re.search(name):
|
| 217 |
+
self.debug_print(" adding " + name)
|
| 218 |
+
self.files.append(name)
|
| 219 |
+
files_found = True
|
| 220 |
+
return files_found
|
| 221 |
+
|
| 222 |
+
|
| 223 |
+
def exclude_pattern (self, pattern,
|
| 224 |
+
anchor=1, prefix=None, is_regex=0):
|
| 225 |
+
"""Remove strings (presumably filenames) from 'files' that match
|
| 226 |
+
'pattern'. Other parameters are the same as for
|
| 227 |
+
'include_pattern()', above.
|
| 228 |
+
The list 'self.files' is modified in place.
|
| 229 |
+
Return True if files are found, False otherwise.
|
| 230 |
+
"""
|
| 231 |
+
files_found = False
|
| 232 |
+
pattern_re = translate_pattern(pattern, anchor, prefix, is_regex)
|
| 233 |
+
self.debug_print("exclude_pattern: applying regex r'%s'" %
|
| 234 |
+
pattern_re.pattern)
|
| 235 |
+
for i in range(len(self.files)-1, -1, -1):
|
| 236 |
+
if pattern_re.search(self.files[i]):
|
| 237 |
+
self.debug_print(" removing " + self.files[i])
|
| 238 |
+
del self.files[i]
|
| 239 |
+
files_found = True
|
| 240 |
+
return files_found
|
| 241 |
+
|
| 242 |
+
|
| 243 |
+
# ----------------------------------------------------------------------
|
| 244 |
+
# Utility functions
|
| 245 |
+
|
| 246 |
+
def _find_all_simple(path):
|
| 247 |
+
"""
|
| 248 |
+
Find all files under 'path'
|
| 249 |
+
"""
|
| 250 |
+
results = (
|
| 251 |
+
os.path.join(base, file)
|
| 252 |
+
for base, dirs, files in os.walk(path, followlinks=True)
|
| 253 |
+
for file in files
|
| 254 |
+
)
|
| 255 |
+
return filter(os.path.isfile, results)
|
| 256 |
+
|
| 257 |
+
|
| 258 |
+
def findall(dir=os.curdir):
|
| 259 |
+
"""
|
| 260 |
+
Find all files under 'dir' and return the list of full filenames.
|
| 261 |
+
Unless dir is '.', return full filenames with dir prepended.
|
| 262 |
+
"""
|
| 263 |
+
files = _find_all_simple(dir)
|
| 264 |
+
if dir == os.curdir:
|
| 265 |
+
make_rel = functools.partial(os.path.relpath, start=dir)
|
| 266 |
+
files = map(make_rel, files)
|
| 267 |
+
return list(files)
|
| 268 |
+
|
| 269 |
+
|
| 270 |
+
def glob_to_re(pattern):
|
| 271 |
+
"""Translate a shell-like glob pattern to a regular expression; return
|
| 272 |
+
a string containing the regex. Differs from 'fnmatch.translate()' in
|
| 273 |
+
that '*' does not match "special characters" (which are
|
| 274 |
+
platform-specific).
|
| 275 |
+
"""
|
| 276 |
+
pattern_re = fnmatch.translate(pattern)
|
| 277 |
+
|
| 278 |
+
# '?' and '*' in the glob pattern become '.' and '.*' in the RE, which
|
| 279 |
+
# IMHO is wrong -- '?' and '*' aren't supposed to match slash in Unix,
|
| 280 |
+
# and by extension they shouldn't match such "special characters" under
|
| 281 |
+
# any OS. So change all non-escaped dots in the RE to match any
|
| 282 |
+
# character except the special characters (currently: just os.sep).
|
| 283 |
+
sep = os.sep
|
| 284 |
+
if os.sep == '\\':
|
| 285 |
+
# we're using a regex to manipulate a regex, so we need
|
| 286 |
+
# to escape the backslash twice
|
| 287 |
+
sep = r'\\\\'
|
| 288 |
+
escaped = r'\1[^%s]' % sep
|
| 289 |
+
pattern_re = re.sub(r'((?<!\\)(\\\\)*)\.', escaped, pattern_re)
|
| 290 |
+
return pattern_re
|
| 291 |
+
|
| 292 |
+
|
| 293 |
+
def translate_pattern(pattern, anchor=1, prefix=None, is_regex=0):
|
| 294 |
+
"""Translate a shell-like wildcard pattern to a compiled regular
|
| 295 |
+
expression. Return the compiled regex. If 'is_regex' true,
|
| 296 |
+
then 'pattern' is directly compiled to a regex (if it's a string)
|
| 297 |
+
or just returned as-is (assumes it's a regex object).
|
| 298 |
+
"""
|
| 299 |
+
if is_regex:
|
| 300 |
+
if isinstance(pattern, str):
|
| 301 |
+
return re.compile(pattern)
|
| 302 |
+
else:
|
| 303 |
+
return pattern
|
| 304 |
+
|
| 305 |
+
# ditch start and end characters
|
| 306 |
+
start, _, end = glob_to_re('_').partition('_')
|
| 307 |
+
|
| 308 |
+
if pattern:
|
| 309 |
+
pattern_re = glob_to_re(pattern)
|
| 310 |
+
assert pattern_re.startswith(start) and pattern_re.endswith(end)
|
| 311 |
+
else:
|
| 312 |
+
pattern_re = ''
|
| 313 |
+
|
| 314 |
+
if prefix is not None:
|
| 315 |
+
prefix_re = glob_to_re(prefix)
|
| 316 |
+
assert prefix_re.startswith(start) and prefix_re.endswith(end)
|
| 317 |
+
prefix_re = prefix_re[len(start): len(prefix_re) - len(end)]
|
| 318 |
+
sep = os.sep
|
| 319 |
+
if os.sep == '\\':
|
| 320 |
+
sep = r'\\'
|
| 321 |
+
pattern_re = pattern_re[len(start): len(pattern_re) - len(end)]
|
| 322 |
+
pattern_re = r'%s\A%s%s.*%s%s' % (start, prefix_re, sep, pattern_re, end)
|
| 323 |
+
else: # no prefix -- respect anchor flag
|
| 324 |
+
if anchor:
|
| 325 |
+
pattern_re = r'%s\A%s' % (start, pattern_re[len(start):])
|
| 326 |
+
|
| 327 |
+
return re.compile(pattern_re)
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/msvccompiler.py
ADDED
|
@@ -0,0 +1,643 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""distutils.msvccompiler
|
| 2 |
+
|
| 3 |
+
Contains MSVCCompiler, an implementation of the abstract CCompiler class
|
| 4 |
+
for the Microsoft Visual Studio.
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
# Written by Perry Stoll
|
| 8 |
+
# hacked by Robin Becker and Thomas Heller to do a better job of
|
| 9 |
+
# finding DevStudio (through the registry)
|
| 10 |
+
|
| 11 |
+
import sys, os
|
| 12 |
+
from distutils.errors import \
|
| 13 |
+
DistutilsExecError, DistutilsPlatformError, \
|
| 14 |
+
CompileError, LibError, LinkError
|
| 15 |
+
from distutils.ccompiler import \
|
| 16 |
+
CCompiler, gen_preprocess_options, gen_lib_options
|
| 17 |
+
from distutils import log
|
| 18 |
+
|
| 19 |
+
_can_read_reg = False
|
| 20 |
+
try:
|
| 21 |
+
import winreg
|
| 22 |
+
|
| 23 |
+
_can_read_reg = True
|
| 24 |
+
hkey_mod = winreg
|
| 25 |
+
|
| 26 |
+
RegOpenKeyEx = winreg.OpenKeyEx
|
| 27 |
+
RegEnumKey = winreg.EnumKey
|
| 28 |
+
RegEnumValue = winreg.EnumValue
|
| 29 |
+
RegError = winreg.error
|
| 30 |
+
|
| 31 |
+
except ImportError:
|
| 32 |
+
try:
|
| 33 |
+
import win32api
|
| 34 |
+
import win32con
|
| 35 |
+
_can_read_reg = True
|
| 36 |
+
hkey_mod = win32con
|
| 37 |
+
|
| 38 |
+
RegOpenKeyEx = win32api.RegOpenKeyEx
|
| 39 |
+
RegEnumKey = win32api.RegEnumKey
|
| 40 |
+
RegEnumValue = win32api.RegEnumValue
|
| 41 |
+
RegError = win32api.error
|
| 42 |
+
except ImportError:
|
| 43 |
+
log.info("Warning: Can't read registry to find the "
|
| 44 |
+
"necessary compiler setting\n"
|
| 45 |
+
"Make sure that Python modules winreg, "
|
| 46 |
+
"win32api or win32con are installed.")
|
| 47 |
+
pass
|
| 48 |
+
|
| 49 |
+
if _can_read_reg:
|
| 50 |
+
HKEYS = (hkey_mod.HKEY_USERS,
|
| 51 |
+
hkey_mod.HKEY_CURRENT_USER,
|
| 52 |
+
hkey_mod.HKEY_LOCAL_MACHINE,
|
| 53 |
+
hkey_mod.HKEY_CLASSES_ROOT)
|
| 54 |
+
|
| 55 |
+
def read_keys(base, key):
|
| 56 |
+
"""Return list of registry keys."""
|
| 57 |
+
try:
|
| 58 |
+
handle = RegOpenKeyEx(base, key)
|
| 59 |
+
except RegError:
|
| 60 |
+
return None
|
| 61 |
+
L = []
|
| 62 |
+
i = 0
|
| 63 |
+
while True:
|
| 64 |
+
try:
|
| 65 |
+
k = RegEnumKey(handle, i)
|
| 66 |
+
except RegError:
|
| 67 |
+
break
|
| 68 |
+
L.append(k)
|
| 69 |
+
i += 1
|
| 70 |
+
return L
|
| 71 |
+
|
| 72 |
+
def read_values(base, key):
|
| 73 |
+
"""Return dict of registry keys and values.
|
| 74 |
+
|
| 75 |
+
All names are converted to lowercase.
|
| 76 |
+
"""
|
| 77 |
+
try:
|
| 78 |
+
handle = RegOpenKeyEx(base, key)
|
| 79 |
+
except RegError:
|
| 80 |
+
return None
|
| 81 |
+
d = {}
|
| 82 |
+
i = 0
|
| 83 |
+
while True:
|
| 84 |
+
try:
|
| 85 |
+
name, value, type = RegEnumValue(handle, i)
|
| 86 |
+
except RegError:
|
| 87 |
+
break
|
| 88 |
+
name = name.lower()
|
| 89 |
+
d[convert_mbcs(name)] = convert_mbcs(value)
|
| 90 |
+
i += 1
|
| 91 |
+
return d
|
| 92 |
+
|
| 93 |
+
def convert_mbcs(s):
|
| 94 |
+
dec = getattr(s, "decode", None)
|
| 95 |
+
if dec is not None:
|
| 96 |
+
try:
|
| 97 |
+
s = dec("mbcs")
|
| 98 |
+
except UnicodeError:
|
| 99 |
+
pass
|
| 100 |
+
return s
|
| 101 |
+
|
| 102 |
+
class MacroExpander:
|
| 103 |
+
def __init__(self, version):
|
| 104 |
+
self.macros = {}
|
| 105 |
+
self.load_macros(version)
|
| 106 |
+
|
| 107 |
+
def set_macro(self, macro, path, key):
|
| 108 |
+
for base in HKEYS:
|
| 109 |
+
d = read_values(base, path)
|
| 110 |
+
if d:
|
| 111 |
+
self.macros["$(%s)" % macro] = d[key]
|
| 112 |
+
break
|
| 113 |
+
|
| 114 |
+
def load_macros(self, version):
|
| 115 |
+
vsbase = r"Software\Microsoft\VisualStudio\%0.1f" % version
|
| 116 |
+
self.set_macro("VCInstallDir", vsbase + r"\Setup\VC", "productdir")
|
| 117 |
+
self.set_macro("VSInstallDir", vsbase + r"\Setup\VS", "productdir")
|
| 118 |
+
net = r"Software\Microsoft\.NETFramework"
|
| 119 |
+
self.set_macro("FrameworkDir", net, "installroot")
|
| 120 |
+
try:
|
| 121 |
+
if version > 7.0:
|
| 122 |
+
self.set_macro("FrameworkSDKDir", net, "sdkinstallrootv1.1")
|
| 123 |
+
else:
|
| 124 |
+
self.set_macro("FrameworkSDKDir", net, "sdkinstallroot")
|
| 125 |
+
except KeyError as exc: #
|
| 126 |
+
raise DistutilsPlatformError(
|
| 127 |
+
"""Python was built with Visual Studio 2003;
|
| 128 |
+
extensions must be built with a compiler than can generate compatible binaries.
|
| 129 |
+
Visual Studio 2003 was not found on this system. If you have Cygwin installed,
|
| 130 |
+
you can try compiling with MingW32, by passing "-c mingw32" to setup.py.""")
|
| 131 |
+
|
| 132 |
+
p = r"Software\Microsoft\NET Framework Setup\Product"
|
| 133 |
+
for base in HKEYS:
|
| 134 |
+
try:
|
| 135 |
+
h = RegOpenKeyEx(base, p)
|
| 136 |
+
except RegError:
|
| 137 |
+
continue
|
| 138 |
+
key = RegEnumKey(h, 0)
|
| 139 |
+
d = read_values(base, r"%s\%s" % (p, key))
|
| 140 |
+
self.macros["$(FrameworkVersion)"] = d["version"]
|
| 141 |
+
|
| 142 |
+
def sub(self, s):
|
| 143 |
+
for k, v in self.macros.items():
|
| 144 |
+
s = s.replace(k, v)
|
| 145 |
+
return s
|
| 146 |
+
|
| 147 |
+
def get_build_version():
|
| 148 |
+
"""Return the version of MSVC that was used to build Python.
|
| 149 |
+
|
| 150 |
+
For Python 2.3 and up, the version number is included in
|
| 151 |
+
sys.version. For earlier versions, assume the compiler is MSVC 6.
|
| 152 |
+
"""
|
| 153 |
+
prefix = "MSC v."
|
| 154 |
+
i = sys.version.find(prefix)
|
| 155 |
+
if i == -1:
|
| 156 |
+
return 6
|
| 157 |
+
i = i + len(prefix)
|
| 158 |
+
s, rest = sys.version[i:].split(" ", 1)
|
| 159 |
+
majorVersion = int(s[:-2]) - 6
|
| 160 |
+
if majorVersion >= 13:
|
| 161 |
+
# v13 was skipped and should be v14
|
| 162 |
+
majorVersion += 1
|
| 163 |
+
minorVersion = int(s[2:3]) / 10.0
|
| 164 |
+
# I don't think paths are affected by minor version in version 6
|
| 165 |
+
if majorVersion == 6:
|
| 166 |
+
minorVersion = 0
|
| 167 |
+
if majorVersion >= 6:
|
| 168 |
+
return majorVersion + minorVersion
|
| 169 |
+
# else we don't know what version of the compiler this is
|
| 170 |
+
return None
|
| 171 |
+
|
| 172 |
+
def get_build_architecture():
|
| 173 |
+
"""Return the processor architecture.
|
| 174 |
+
|
| 175 |
+
Possible results are "Intel" or "AMD64".
|
| 176 |
+
"""
|
| 177 |
+
|
| 178 |
+
prefix = " bit ("
|
| 179 |
+
i = sys.version.find(prefix)
|
| 180 |
+
if i == -1:
|
| 181 |
+
return "Intel"
|
| 182 |
+
j = sys.version.find(")", i)
|
| 183 |
+
return sys.version[i+len(prefix):j]
|
| 184 |
+
|
| 185 |
+
def normalize_and_reduce_paths(paths):
|
| 186 |
+
"""Return a list of normalized paths with duplicates removed.
|
| 187 |
+
|
| 188 |
+
The current order of paths is maintained.
|
| 189 |
+
"""
|
| 190 |
+
# Paths are normalized so things like: /a and /a/ aren't both preserved.
|
| 191 |
+
reduced_paths = []
|
| 192 |
+
for p in paths:
|
| 193 |
+
np = os.path.normpath(p)
|
| 194 |
+
# XXX(nnorwitz): O(n**2), if reduced_paths gets long perhaps use a set.
|
| 195 |
+
if np not in reduced_paths:
|
| 196 |
+
reduced_paths.append(np)
|
| 197 |
+
return reduced_paths
|
| 198 |
+
|
| 199 |
+
|
| 200 |
+
class MSVCCompiler(CCompiler) :
|
| 201 |
+
"""Concrete class that implements an interface to Microsoft Visual C++,
|
| 202 |
+
as defined by the CCompiler abstract class."""
|
| 203 |
+
|
| 204 |
+
compiler_type = 'msvc'
|
| 205 |
+
|
| 206 |
+
# Just set this so CCompiler's constructor doesn't barf. We currently
|
| 207 |
+
# don't use the 'set_executables()' bureaucracy provided by CCompiler,
|
| 208 |
+
# as it really isn't necessary for this sort of single-compiler class.
|
| 209 |
+
# Would be nice to have a consistent interface with UnixCCompiler,
|
| 210 |
+
# though, so it's worth thinking about.
|
| 211 |
+
executables = {}
|
| 212 |
+
|
| 213 |
+
# Private class data (need to distinguish C from C++ source for compiler)
|
| 214 |
+
_c_extensions = ['.c']
|
| 215 |
+
_cpp_extensions = ['.cc', '.cpp', '.cxx']
|
| 216 |
+
_rc_extensions = ['.rc']
|
| 217 |
+
_mc_extensions = ['.mc']
|
| 218 |
+
|
| 219 |
+
# Needed for the filename generation methods provided by the
|
| 220 |
+
# base class, CCompiler.
|
| 221 |
+
src_extensions = (_c_extensions + _cpp_extensions +
|
| 222 |
+
_rc_extensions + _mc_extensions)
|
| 223 |
+
res_extension = '.res'
|
| 224 |
+
obj_extension = '.obj'
|
| 225 |
+
static_lib_extension = '.lib'
|
| 226 |
+
shared_lib_extension = '.dll'
|
| 227 |
+
static_lib_format = shared_lib_format = '%s%s'
|
| 228 |
+
exe_extension = '.exe'
|
| 229 |
+
|
| 230 |
+
def __init__(self, verbose=0, dry_run=0, force=0):
|
| 231 |
+
CCompiler.__init__ (self, verbose, dry_run, force)
|
| 232 |
+
self.__version = get_build_version()
|
| 233 |
+
self.__arch = get_build_architecture()
|
| 234 |
+
if self.__arch == "Intel":
|
| 235 |
+
# x86
|
| 236 |
+
if self.__version >= 7:
|
| 237 |
+
self.__root = r"Software\Microsoft\VisualStudio"
|
| 238 |
+
self.__macros = MacroExpander(self.__version)
|
| 239 |
+
else:
|
| 240 |
+
self.__root = r"Software\Microsoft\Devstudio"
|
| 241 |
+
self.__product = "Visual Studio version %s" % self.__version
|
| 242 |
+
else:
|
| 243 |
+
# Win64. Assume this was built with the platform SDK
|
| 244 |
+
self.__product = "Microsoft SDK compiler %s" % (self.__version + 6)
|
| 245 |
+
|
| 246 |
+
self.initialized = False
|
| 247 |
+
|
| 248 |
+
def initialize(self):
|
| 249 |
+
self.__paths = []
|
| 250 |
+
if "DISTUTILS_USE_SDK" in os.environ and "MSSdk" in os.environ and self.find_exe("cl.exe"):
|
| 251 |
+
# Assume that the SDK set up everything alright; don't try to be
|
| 252 |
+
# smarter
|
| 253 |
+
self.cc = "cl.exe"
|
| 254 |
+
self.linker = "link.exe"
|
| 255 |
+
self.lib = "lib.exe"
|
| 256 |
+
self.rc = "rc.exe"
|
| 257 |
+
self.mc = "mc.exe"
|
| 258 |
+
else:
|
| 259 |
+
self.__paths = self.get_msvc_paths("path")
|
| 260 |
+
|
| 261 |
+
if len(self.__paths) == 0:
|
| 262 |
+
raise DistutilsPlatformError("Python was built with %s, "
|
| 263 |
+
"and extensions need to be built with the same "
|
| 264 |
+
"version of the compiler, but it isn't installed."
|
| 265 |
+
% self.__product)
|
| 266 |
+
|
| 267 |
+
self.cc = self.find_exe("cl.exe")
|
| 268 |
+
self.linker = self.find_exe("link.exe")
|
| 269 |
+
self.lib = self.find_exe("lib.exe")
|
| 270 |
+
self.rc = self.find_exe("rc.exe") # resource compiler
|
| 271 |
+
self.mc = self.find_exe("mc.exe") # message compiler
|
| 272 |
+
self.set_path_env_var('lib')
|
| 273 |
+
self.set_path_env_var('include')
|
| 274 |
+
|
| 275 |
+
# extend the MSVC path with the current path
|
| 276 |
+
try:
|
| 277 |
+
for p in os.environ['path'].split(';'):
|
| 278 |
+
self.__paths.append(p)
|
| 279 |
+
except KeyError:
|
| 280 |
+
pass
|
| 281 |
+
self.__paths = normalize_and_reduce_paths(self.__paths)
|
| 282 |
+
os.environ['path'] = ";".join(self.__paths)
|
| 283 |
+
|
| 284 |
+
self.preprocess_options = None
|
| 285 |
+
if self.__arch == "Intel":
|
| 286 |
+
self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GX' ,
|
| 287 |
+
'/DNDEBUG']
|
| 288 |
+
self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GX',
|
| 289 |
+
'/Z7', '/D_DEBUG']
|
| 290 |
+
else:
|
| 291 |
+
# Win64
|
| 292 |
+
self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GS-' ,
|
| 293 |
+
'/DNDEBUG']
|
| 294 |
+
self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GS-',
|
| 295 |
+
'/Z7', '/D_DEBUG']
|
| 296 |
+
|
| 297 |
+
self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO']
|
| 298 |
+
if self.__version >= 7:
|
| 299 |
+
self.ldflags_shared_debug = [
|
| 300 |
+
'/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG'
|
| 301 |
+
]
|
| 302 |
+
else:
|
| 303 |
+
self.ldflags_shared_debug = [
|
| 304 |
+
'/DLL', '/nologo', '/INCREMENTAL:no', '/pdb:None', '/DEBUG'
|
| 305 |
+
]
|
| 306 |
+
self.ldflags_static = [ '/nologo']
|
| 307 |
+
|
| 308 |
+
self.initialized = True
|
| 309 |
+
|
| 310 |
+
# -- Worker methods ------------------------------------------------
|
| 311 |
+
|
| 312 |
+
def object_filenames(self,
|
| 313 |
+
source_filenames,
|
| 314 |
+
strip_dir=0,
|
| 315 |
+
output_dir=''):
|
| 316 |
+
# Copied from ccompiler.py, extended to return .res as 'object'-file
|
| 317 |
+
# for .rc input file
|
| 318 |
+
if output_dir is None: output_dir = ''
|
| 319 |
+
obj_names = []
|
| 320 |
+
for src_name in source_filenames:
|
| 321 |
+
(base, ext) = os.path.splitext (src_name)
|
| 322 |
+
base = os.path.splitdrive(base)[1] # Chop off the drive
|
| 323 |
+
base = base[os.path.isabs(base):] # If abs, chop off leading /
|
| 324 |
+
if ext not in self.src_extensions:
|
| 325 |
+
# Better to raise an exception instead of silently continuing
|
| 326 |
+
# and later complain about sources and targets having
|
| 327 |
+
# different lengths
|
| 328 |
+
raise CompileError ("Don't know how to compile %s" % src_name)
|
| 329 |
+
if strip_dir:
|
| 330 |
+
base = os.path.basename (base)
|
| 331 |
+
if ext in self._rc_extensions:
|
| 332 |
+
obj_names.append (os.path.join (output_dir,
|
| 333 |
+
base + self.res_extension))
|
| 334 |
+
elif ext in self._mc_extensions:
|
| 335 |
+
obj_names.append (os.path.join (output_dir,
|
| 336 |
+
base + self.res_extension))
|
| 337 |
+
else:
|
| 338 |
+
obj_names.append (os.path.join (output_dir,
|
| 339 |
+
base + self.obj_extension))
|
| 340 |
+
return obj_names
|
| 341 |
+
|
| 342 |
+
|
| 343 |
+
def compile(self, sources,
|
| 344 |
+
output_dir=None, macros=None, include_dirs=None, debug=0,
|
| 345 |
+
extra_preargs=None, extra_postargs=None, depends=None):
|
| 346 |
+
|
| 347 |
+
if not self.initialized:
|
| 348 |
+
self.initialize()
|
| 349 |
+
compile_info = self._setup_compile(output_dir, macros, include_dirs,
|
| 350 |
+
sources, depends, extra_postargs)
|
| 351 |
+
macros, objects, extra_postargs, pp_opts, build = compile_info
|
| 352 |
+
|
| 353 |
+
compile_opts = extra_preargs or []
|
| 354 |
+
compile_opts.append ('/c')
|
| 355 |
+
if debug:
|
| 356 |
+
compile_opts.extend(self.compile_options_debug)
|
| 357 |
+
else:
|
| 358 |
+
compile_opts.extend(self.compile_options)
|
| 359 |
+
|
| 360 |
+
for obj in objects:
|
| 361 |
+
try:
|
| 362 |
+
src, ext = build[obj]
|
| 363 |
+
except KeyError:
|
| 364 |
+
continue
|
| 365 |
+
if debug:
|
| 366 |
+
# pass the full pathname to MSVC in debug mode,
|
| 367 |
+
# this allows the debugger to find the source file
|
| 368 |
+
# without asking the user to browse for it
|
| 369 |
+
src = os.path.abspath(src)
|
| 370 |
+
|
| 371 |
+
if ext in self._c_extensions:
|
| 372 |
+
input_opt = "/Tc" + src
|
| 373 |
+
elif ext in self._cpp_extensions:
|
| 374 |
+
input_opt = "/Tp" + src
|
| 375 |
+
elif ext in self._rc_extensions:
|
| 376 |
+
# compile .RC to .RES file
|
| 377 |
+
input_opt = src
|
| 378 |
+
output_opt = "/fo" + obj
|
| 379 |
+
try:
|
| 380 |
+
self.spawn([self.rc] + pp_opts +
|
| 381 |
+
[output_opt] + [input_opt])
|
| 382 |
+
except DistutilsExecError as msg:
|
| 383 |
+
raise CompileError(msg)
|
| 384 |
+
continue
|
| 385 |
+
elif ext in self._mc_extensions:
|
| 386 |
+
# Compile .MC to .RC file to .RES file.
|
| 387 |
+
# * '-h dir' specifies the directory for the
|
| 388 |
+
# generated include file
|
| 389 |
+
# * '-r dir' specifies the target directory of the
|
| 390 |
+
# generated RC file and the binary message resource
|
| 391 |
+
# it includes
|
| 392 |
+
#
|
| 393 |
+
# For now (since there are no options to change this),
|
| 394 |
+
# we use the source-directory for the include file and
|
| 395 |
+
# the build directory for the RC file and message
|
| 396 |
+
# resources. This works at least for win32all.
|
| 397 |
+
h_dir = os.path.dirname(src)
|
| 398 |
+
rc_dir = os.path.dirname(obj)
|
| 399 |
+
try:
|
| 400 |
+
# first compile .MC to .RC and .H file
|
| 401 |
+
self.spawn([self.mc] +
|
| 402 |
+
['-h', h_dir, '-r', rc_dir] + [src])
|
| 403 |
+
base, _ = os.path.splitext (os.path.basename (src))
|
| 404 |
+
rc_file = os.path.join (rc_dir, base + '.rc')
|
| 405 |
+
# then compile .RC to .RES file
|
| 406 |
+
self.spawn([self.rc] +
|
| 407 |
+
["/fo" + obj] + [rc_file])
|
| 408 |
+
|
| 409 |
+
except DistutilsExecError as msg:
|
| 410 |
+
raise CompileError(msg)
|
| 411 |
+
continue
|
| 412 |
+
else:
|
| 413 |
+
# how to handle this file?
|
| 414 |
+
raise CompileError("Don't know how to compile %s to %s"
|
| 415 |
+
% (src, obj))
|
| 416 |
+
|
| 417 |
+
output_opt = "/Fo" + obj
|
| 418 |
+
try:
|
| 419 |
+
self.spawn([self.cc] + compile_opts + pp_opts +
|
| 420 |
+
[input_opt, output_opt] +
|
| 421 |
+
extra_postargs)
|
| 422 |
+
except DistutilsExecError as msg:
|
| 423 |
+
raise CompileError(msg)
|
| 424 |
+
|
| 425 |
+
return objects
|
| 426 |
+
|
| 427 |
+
|
| 428 |
+
def create_static_lib(self,
|
| 429 |
+
objects,
|
| 430 |
+
output_libname,
|
| 431 |
+
output_dir=None,
|
| 432 |
+
debug=0,
|
| 433 |
+
target_lang=None):
|
| 434 |
+
|
| 435 |
+
if not self.initialized:
|
| 436 |
+
self.initialize()
|
| 437 |
+
(objects, output_dir) = self._fix_object_args(objects, output_dir)
|
| 438 |
+
output_filename = self.library_filename(output_libname,
|
| 439 |
+
output_dir=output_dir)
|
| 440 |
+
|
| 441 |
+
if self._need_link(objects, output_filename):
|
| 442 |
+
lib_args = objects + ['/OUT:' + output_filename]
|
| 443 |
+
if debug:
|
| 444 |
+
pass # XXX what goes here?
|
| 445 |
+
try:
|
| 446 |
+
self.spawn([self.lib] + lib_args)
|
| 447 |
+
except DistutilsExecError as msg:
|
| 448 |
+
raise LibError(msg)
|
| 449 |
+
else:
|
| 450 |
+
log.debug("skipping %s (up-to-date)", output_filename)
|
| 451 |
+
|
| 452 |
+
|
| 453 |
+
def link(self,
|
| 454 |
+
target_desc,
|
| 455 |
+
objects,
|
| 456 |
+
output_filename,
|
| 457 |
+
output_dir=None,
|
| 458 |
+
libraries=None,
|
| 459 |
+
library_dirs=None,
|
| 460 |
+
runtime_library_dirs=None,
|
| 461 |
+
export_symbols=None,
|
| 462 |
+
debug=0,
|
| 463 |
+
extra_preargs=None,
|
| 464 |
+
extra_postargs=None,
|
| 465 |
+
build_temp=None,
|
| 466 |
+
target_lang=None):
|
| 467 |
+
|
| 468 |
+
if not self.initialized:
|
| 469 |
+
self.initialize()
|
| 470 |
+
(objects, output_dir) = self._fix_object_args(objects, output_dir)
|
| 471 |
+
fixed_args = self._fix_lib_args(libraries, library_dirs,
|
| 472 |
+
runtime_library_dirs)
|
| 473 |
+
(libraries, library_dirs, runtime_library_dirs) = fixed_args
|
| 474 |
+
|
| 475 |
+
if runtime_library_dirs:
|
| 476 |
+
self.warn ("I don't know what to do with 'runtime_library_dirs': "
|
| 477 |
+
+ str (runtime_library_dirs))
|
| 478 |
+
|
| 479 |
+
lib_opts = gen_lib_options(self,
|
| 480 |
+
library_dirs, runtime_library_dirs,
|
| 481 |
+
libraries)
|
| 482 |
+
if output_dir is not None:
|
| 483 |
+
output_filename = os.path.join(output_dir, output_filename)
|
| 484 |
+
|
| 485 |
+
if self._need_link(objects, output_filename):
|
| 486 |
+
if target_desc == CCompiler.EXECUTABLE:
|
| 487 |
+
if debug:
|
| 488 |
+
ldflags = self.ldflags_shared_debug[1:]
|
| 489 |
+
else:
|
| 490 |
+
ldflags = self.ldflags_shared[1:]
|
| 491 |
+
else:
|
| 492 |
+
if debug:
|
| 493 |
+
ldflags = self.ldflags_shared_debug
|
| 494 |
+
else:
|
| 495 |
+
ldflags = self.ldflags_shared
|
| 496 |
+
|
| 497 |
+
export_opts = []
|
| 498 |
+
for sym in (export_symbols or []):
|
| 499 |
+
export_opts.append("/EXPORT:" + sym)
|
| 500 |
+
|
| 501 |
+
ld_args = (ldflags + lib_opts + export_opts +
|
| 502 |
+
objects + ['/OUT:' + output_filename])
|
| 503 |
+
|
| 504 |
+
# The MSVC linker generates .lib and .exp files, which cannot be
|
| 505 |
+
# suppressed by any linker switches. The .lib files may even be
|
| 506 |
+
# needed! Make sure they are generated in the temporary build
|
| 507 |
+
# directory. Since they have different names for debug and release
|
| 508 |
+
# builds, they can go into the same directory.
|
| 509 |
+
if export_symbols is not None:
|
| 510 |
+
(dll_name, dll_ext) = os.path.splitext(
|
| 511 |
+
os.path.basename(output_filename))
|
| 512 |
+
implib_file = os.path.join(
|
| 513 |
+
os.path.dirname(objects[0]),
|
| 514 |
+
self.library_filename(dll_name))
|
| 515 |
+
ld_args.append ('/IMPLIB:' + implib_file)
|
| 516 |
+
|
| 517 |
+
if extra_preargs:
|
| 518 |
+
ld_args[:0] = extra_preargs
|
| 519 |
+
if extra_postargs:
|
| 520 |
+
ld_args.extend(extra_postargs)
|
| 521 |
+
|
| 522 |
+
self.mkpath(os.path.dirname(output_filename))
|
| 523 |
+
try:
|
| 524 |
+
self.spawn([self.linker] + ld_args)
|
| 525 |
+
except DistutilsExecError as msg:
|
| 526 |
+
raise LinkError(msg)
|
| 527 |
+
|
| 528 |
+
else:
|
| 529 |
+
log.debug("skipping %s (up-to-date)", output_filename)
|
| 530 |
+
|
| 531 |
+
|
| 532 |
+
# -- Miscellaneous methods -----------------------------------------
|
| 533 |
+
# These are all used by the 'gen_lib_options() function, in
|
| 534 |
+
# ccompiler.py.
|
| 535 |
+
|
| 536 |
+
def library_dir_option(self, dir):
|
| 537 |
+
return "/LIBPATH:" + dir
|
| 538 |
+
|
| 539 |
+
def runtime_library_dir_option(self, dir):
|
| 540 |
+
raise DistutilsPlatformError(
|
| 541 |
+
"don't know how to set runtime library search path for MSVC++")
|
| 542 |
+
|
| 543 |
+
def library_option(self, lib):
|
| 544 |
+
return self.library_filename(lib)
|
| 545 |
+
|
| 546 |
+
|
| 547 |
+
def find_library_file(self, dirs, lib, debug=0):
|
| 548 |
+
# Prefer a debugging library if found (and requested), but deal
|
| 549 |
+
# with it if we don't have one.
|
| 550 |
+
if debug:
|
| 551 |
+
try_names = [lib + "_d", lib]
|
| 552 |
+
else:
|
| 553 |
+
try_names = [lib]
|
| 554 |
+
for dir in dirs:
|
| 555 |
+
for name in try_names:
|
| 556 |
+
libfile = os.path.join(dir, self.library_filename (name))
|
| 557 |
+
if os.path.exists(libfile):
|
| 558 |
+
return libfile
|
| 559 |
+
else:
|
| 560 |
+
# Oops, didn't find it in *any* of 'dirs'
|
| 561 |
+
return None
|
| 562 |
+
|
| 563 |
+
# Helper methods for using the MSVC registry settings
|
| 564 |
+
|
| 565 |
+
def find_exe(self, exe):
|
| 566 |
+
"""Return path to an MSVC executable program.
|
| 567 |
+
|
| 568 |
+
Tries to find the program in several places: first, one of the
|
| 569 |
+
MSVC program search paths from the registry; next, the directories
|
| 570 |
+
in the PATH environment variable. If any of those work, return an
|
| 571 |
+
absolute path that is known to exist. If none of them work, just
|
| 572 |
+
return the original program name, 'exe'.
|
| 573 |
+
"""
|
| 574 |
+
for p in self.__paths:
|
| 575 |
+
fn = os.path.join(os.path.abspath(p), exe)
|
| 576 |
+
if os.path.isfile(fn):
|
| 577 |
+
return fn
|
| 578 |
+
|
| 579 |
+
# didn't find it; try existing path
|
| 580 |
+
for p in os.environ['Path'].split(';'):
|
| 581 |
+
fn = os.path.join(os.path.abspath(p),exe)
|
| 582 |
+
if os.path.isfile(fn):
|
| 583 |
+
return fn
|
| 584 |
+
|
| 585 |
+
return exe
|
| 586 |
+
|
| 587 |
+
def get_msvc_paths(self, path, platform='x86'):
|
| 588 |
+
"""Get a list of devstudio directories (include, lib or path).
|
| 589 |
+
|
| 590 |
+
Return a list of strings. The list will be empty if unable to
|
| 591 |
+
access the registry or appropriate registry keys not found.
|
| 592 |
+
"""
|
| 593 |
+
if not _can_read_reg:
|
| 594 |
+
return []
|
| 595 |
+
|
| 596 |
+
path = path + " dirs"
|
| 597 |
+
if self.__version >= 7:
|
| 598 |
+
key = (r"%s\%0.1f\VC\VC_OBJECTS_PLATFORM_INFO\Win32\Directories"
|
| 599 |
+
% (self.__root, self.__version))
|
| 600 |
+
else:
|
| 601 |
+
key = (r"%s\6.0\Build System\Components\Platforms"
|
| 602 |
+
r"\Win32 (%s)\Directories" % (self.__root, platform))
|
| 603 |
+
|
| 604 |
+
for base in HKEYS:
|
| 605 |
+
d = read_values(base, key)
|
| 606 |
+
if d:
|
| 607 |
+
if self.__version >= 7:
|
| 608 |
+
return self.__macros.sub(d[path]).split(";")
|
| 609 |
+
else:
|
| 610 |
+
return d[path].split(";")
|
| 611 |
+
# MSVC 6 seems to create the registry entries we need only when
|
| 612 |
+
# the GUI is run.
|
| 613 |
+
if self.__version == 6:
|
| 614 |
+
for base in HKEYS:
|
| 615 |
+
if read_values(base, r"%s\6.0" % self.__root) is not None:
|
| 616 |
+
self.warn("It seems you have Visual Studio 6 installed, "
|
| 617 |
+
"but the expected registry settings are not present.\n"
|
| 618 |
+
"You must at least run the Visual Studio GUI once "
|
| 619 |
+
"so that these entries are created.")
|
| 620 |
+
break
|
| 621 |
+
return []
|
| 622 |
+
|
| 623 |
+
def set_path_env_var(self, name):
|
| 624 |
+
"""Set environment variable 'name' to an MSVC path type value.
|
| 625 |
+
|
| 626 |
+
This is equivalent to a SET command prior to execution of spawned
|
| 627 |
+
commands.
|
| 628 |
+
"""
|
| 629 |
+
|
| 630 |
+
if name == "lib":
|
| 631 |
+
p = self.get_msvc_paths("library")
|
| 632 |
+
else:
|
| 633 |
+
p = self.get_msvc_paths(name)
|
| 634 |
+
if p:
|
| 635 |
+
os.environ[name] = ';'.join(p)
|
| 636 |
+
|
| 637 |
+
|
| 638 |
+
if get_build_version() >= 8.0:
|
| 639 |
+
log.debug("Importing new compiler from distutils.msvc9compiler")
|
| 640 |
+
OldMSVCCompiler = MSVCCompiler
|
| 641 |
+
from distutils.msvc9compiler import MSVCCompiler
|
| 642 |
+
# get_build_architecture not really relevant now we support cross-compile
|
| 643 |
+
from distutils.msvc9compiler import MacroExpander
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/spawn.py
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""distutils.spawn
|
| 2 |
+
|
| 3 |
+
Provides the 'spawn()' function, a front-end to various platform-
|
| 4 |
+
specific functions for launching another program in a sub-process.
|
| 5 |
+
Also provides the 'find_executable()' to search the path for a given
|
| 6 |
+
executable name.
|
| 7 |
+
"""
|
| 8 |
+
|
| 9 |
+
import sys
|
| 10 |
+
import os
|
| 11 |
+
|
| 12 |
+
from distutils.errors import DistutilsPlatformError, DistutilsExecError
|
| 13 |
+
from distutils.debug import DEBUG
|
| 14 |
+
from distutils import log
|
| 15 |
+
|
| 16 |
+
def spawn(cmd, search_path=1, verbose=0, dry_run=0):
|
| 17 |
+
"""Run another program, specified as a command list 'cmd', in a new process.
|
| 18 |
+
|
| 19 |
+
'cmd' is just the argument list for the new process, ie.
|
| 20 |
+
cmd[0] is the program to run and cmd[1:] are the rest of its arguments.
|
| 21 |
+
There is no way to run a program with a name different from that of its
|
| 22 |
+
executable.
|
| 23 |
+
|
| 24 |
+
If 'search_path' is true (the default), the system's executable
|
| 25 |
+
search path will be used to find the program; otherwise, cmd[0]
|
| 26 |
+
must be the exact path to the executable. If 'dry_run' is true,
|
| 27 |
+
the command will not actually be run.
|
| 28 |
+
|
| 29 |
+
Raise DistutilsExecError if running the program fails in any way; just
|
| 30 |
+
return on success.
|
| 31 |
+
"""
|
| 32 |
+
# cmd is documented as a list, but just in case some code passes a tuple
|
| 33 |
+
# in, protect our %-formatting code against horrible death
|
| 34 |
+
cmd = list(cmd)
|
| 35 |
+
if os.name == 'posix':
|
| 36 |
+
_spawn_posix(cmd, search_path, dry_run=dry_run)
|
| 37 |
+
elif os.name == 'nt':
|
| 38 |
+
_spawn_nt(cmd, search_path, dry_run=dry_run)
|
| 39 |
+
else:
|
| 40 |
+
raise DistutilsPlatformError(
|
| 41 |
+
"don't know how to spawn programs on platform '%s'" % os.name)
|
| 42 |
+
|
| 43 |
+
def _nt_quote_args(args):
|
| 44 |
+
"""Quote command-line arguments for DOS/Windows conventions.
|
| 45 |
+
|
| 46 |
+
Just wraps every argument which contains blanks in double quotes, and
|
| 47 |
+
returns a new argument list.
|
| 48 |
+
"""
|
| 49 |
+
# XXX this doesn't seem very robust to me -- but if the Windows guys
|
| 50 |
+
# say it'll work, I guess I'll have to accept it. (What if an arg
|
| 51 |
+
# contains quotes? What other magic characters, other than spaces,
|
| 52 |
+
# have to be escaped? Is there an escaping mechanism other than
|
| 53 |
+
# quoting?)
|
| 54 |
+
for i, arg in enumerate(args):
|
| 55 |
+
if ' ' in arg:
|
| 56 |
+
args[i] = '"%s"' % arg
|
| 57 |
+
return args
|
| 58 |
+
|
| 59 |
+
def _spawn_nt(cmd, search_path=1, verbose=0, dry_run=0):
|
| 60 |
+
executable = cmd[0]
|
| 61 |
+
cmd = _nt_quote_args(cmd)
|
| 62 |
+
if search_path:
|
| 63 |
+
# either we find one or it stays the same
|
| 64 |
+
executable = find_executable(executable) or executable
|
| 65 |
+
log.info(' '.join([executable] + cmd[1:]))
|
| 66 |
+
if not dry_run:
|
| 67 |
+
# spawn for NT requires a full path to the .exe
|
| 68 |
+
try:
|
| 69 |
+
rc = os.spawnv(os.P_WAIT, executable, cmd)
|
| 70 |
+
except OSError as exc:
|
| 71 |
+
# this seems to happen when the command isn't found
|
| 72 |
+
if not DEBUG:
|
| 73 |
+
cmd = executable
|
| 74 |
+
raise DistutilsExecError(
|
| 75 |
+
"command %r failed: %s" % (cmd, exc.args[-1]))
|
| 76 |
+
if rc != 0:
|
| 77 |
+
# and this reflects the command running but failing
|
| 78 |
+
if not DEBUG:
|
| 79 |
+
cmd = executable
|
| 80 |
+
raise DistutilsExecError(
|
| 81 |
+
"command %r failed with exit status %d" % (cmd, rc))
|
| 82 |
+
|
| 83 |
+
if sys.platform == 'darwin':
|
| 84 |
+
_cfg_target = None
|
| 85 |
+
_cfg_target_split = None
|
| 86 |
+
|
| 87 |
+
def _spawn_posix(cmd, search_path=1, verbose=0, dry_run=0):
|
| 88 |
+
log.info(' '.join(cmd))
|
| 89 |
+
if dry_run:
|
| 90 |
+
return
|
| 91 |
+
executable = cmd[0]
|
| 92 |
+
exec_fn = search_path and os.execvp or os.execv
|
| 93 |
+
env = None
|
| 94 |
+
if sys.platform == 'darwin':
|
| 95 |
+
global _cfg_target, _cfg_target_split
|
| 96 |
+
if _cfg_target is None:
|
| 97 |
+
from distutils import sysconfig
|
| 98 |
+
_cfg_target = sysconfig.get_config_var(
|
| 99 |
+
'MACOSX_DEPLOYMENT_TARGET') or ''
|
| 100 |
+
if _cfg_target:
|
| 101 |
+
_cfg_target_split = [int(x) for x in _cfg_target.split('.')]
|
| 102 |
+
if _cfg_target:
|
| 103 |
+
# ensure that the deployment target of build process is not less
|
| 104 |
+
# than that used when the interpreter was built. This ensures
|
| 105 |
+
# extension modules are built with correct compatibility values
|
| 106 |
+
cur_target = os.environ.get('MACOSX_DEPLOYMENT_TARGET', _cfg_target)
|
| 107 |
+
if _cfg_target_split > [int(x) for x in cur_target.split('.')]:
|
| 108 |
+
my_msg = ('$MACOSX_DEPLOYMENT_TARGET mismatch: '
|
| 109 |
+
'now "%s" but "%s" during configure'
|
| 110 |
+
% (cur_target, _cfg_target))
|
| 111 |
+
raise DistutilsPlatformError(my_msg)
|
| 112 |
+
env = dict(os.environ,
|
| 113 |
+
MACOSX_DEPLOYMENT_TARGET=cur_target)
|
| 114 |
+
exec_fn = search_path and os.execvpe or os.execve
|
| 115 |
+
pid = os.fork()
|
| 116 |
+
if pid == 0: # in the child
|
| 117 |
+
try:
|
| 118 |
+
if env is None:
|
| 119 |
+
exec_fn(executable, cmd)
|
| 120 |
+
else:
|
| 121 |
+
exec_fn(executable, cmd, env)
|
| 122 |
+
except OSError as e:
|
| 123 |
+
if not DEBUG:
|
| 124 |
+
cmd = executable
|
| 125 |
+
sys.stderr.write("unable to execute %r: %s\n"
|
| 126 |
+
% (cmd, e.strerror))
|
| 127 |
+
os._exit(1)
|
| 128 |
+
|
| 129 |
+
if not DEBUG:
|
| 130 |
+
cmd = executable
|
| 131 |
+
sys.stderr.write("unable to execute %r for unknown reasons" % cmd)
|
| 132 |
+
os._exit(1)
|
| 133 |
+
else: # in the parent
|
| 134 |
+
# Loop until the child either exits or is terminated by a signal
|
| 135 |
+
# (ie. keep waiting if it's merely stopped)
|
| 136 |
+
while True:
|
| 137 |
+
try:
|
| 138 |
+
pid, status = os.waitpid(pid, 0)
|
| 139 |
+
except OSError as exc:
|
| 140 |
+
if not DEBUG:
|
| 141 |
+
cmd = executable
|
| 142 |
+
raise DistutilsExecError(
|
| 143 |
+
"command %r failed: %s" % (cmd, exc.args[-1]))
|
| 144 |
+
if os.WIFSIGNALED(status):
|
| 145 |
+
if not DEBUG:
|
| 146 |
+
cmd = executable
|
| 147 |
+
raise DistutilsExecError(
|
| 148 |
+
"command %r terminated by signal %d"
|
| 149 |
+
% (cmd, os.WTERMSIG(status)))
|
| 150 |
+
elif os.WIFEXITED(status):
|
| 151 |
+
exit_status = os.WEXITSTATUS(status)
|
| 152 |
+
if exit_status == 0:
|
| 153 |
+
return # hey, it succeeded!
|
| 154 |
+
else:
|
| 155 |
+
if not DEBUG:
|
| 156 |
+
cmd = executable
|
| 157 |
+
raise DistutilsExecError(
|
| 158 |
+
"command %r failed with exit status %d"
|
| 159 |
+
% (cmd, exit_status))
|
| 160 |
+
elif os.WIFSTOPPED(status):
|
| 161 |
+
continue
|
| 162 |
+
else:
|
| 163 |
+
if not DEBUG:
|
| 164 |
+
cmd = executable
|
| 165 |
+
raise DistutilsExecError(
|
| 166 |
+
"unknown error executing %r: termination status %d"
|
| 167 |
+
% (cmd, status))
|
| 168 |
+
|
| 169 |
+
def find_executable(executable, path=None):
|
| 170 |
+
"""Tries to find 'executable' in the directories listed in 'path'.
|
| 171 |
+
|
| 172 |
+
A string listing directories separated by 'os.pathsep'; defaults to
|
| 173 |
+
os.environ['PATH']. Returns the complete filename or None if not found.
|
| 174 |
+
"""
|
| 175 |
+
_, ext = os.path.splitext(executable)
|
| 176 |
+
if (sys.platform == 'win32') and (ext != '.exe'):
|
| 177 |
+
executable = executable + '.exe'
|
| 178 |
+
|
| 179 |
+
if os.path.isfile(executable):
|
| 180 |
+
return executable
|
| 181 |
+
|
| 182 |
+
if path is None:
|
| 183 |
+
path = os.environ.get('PATH', None)
|
| 184 |
+
if path is None:
|
| 185 |
+
try:
|
| 186 |
+
path = os.confstr("CS_PATH")
|
| 187 |
+
except (AttributeError, ValueError):
|
| 188 |
+
# os.confstr() or CS_PATH is not available
|
| 189 |
+
path = os.defpath
|
| 190 |
+
# bpo-35755: Don't use os.defpath if the PATH environment variable is
|
| 191 |
+
# set to an empty string
|
| 192 |
+
|
| 193 |
+
# PATH='' doesn't match, whereas PATH=':' looks in the current directory
|
| 194 |
+
if not path:
|
| 195 |
+
return None
|
| 196 |
+
|
| 197 |
+
paths = path.split(os.pathsep)
|
| 198 |
+
for p in paths:
|
| 199 |
+
f = os.path.join(p, executable)
|
| 200 |
+
if os.path.isfile(f):
|
| 201 |
+
# the file exists, we have a shot at spawn working
|
| 202 |
+
return f
|
| 203 |
+
return None
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/unixccompiler.py
ADDED
|
@@ -0,0 +1,330 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""distutils.unixccompiler
|
| 2 |
+
|
| 3 |
+
Contains the UnixCCompiler class, a subclass of CCompiler that handles
|
| 4 |
+
the "typical" Unix-style command-line C compiler:
|
| 5 |
+
* macros defined with -Dname[=value]
|
| 6 |
+
* macros undefined with -Uname
|
| 7 |
+
* include search directories specified with -Idir
|
| 8 |
+
* libraries specified with -lllib
|
| 9 |
+
* library search directories specified with -Ldir
|
| 10 |
+
* compile handled by 'cc' (or similar) executable with -c option:
|
| 11 |
+
compiles .c to .o
|
| 12 |
+
* link static library handled by 'ar' command (possibly with 'ranlib')
|
| 13 |
+
* link shared library handled by 'cc -shared'
|
| 14 |
+
"""
|
| 15 |
+
|
| 16 |
+
import os, sys, re
|
| 17 |
+
|
| 18 |
+
from distutils import sysconfig
|
| 19 |
+
from distutils.dep_util import newer
|
| 20 |
+
from distutils.ccompiler import \
|
| 21 |
+
CCompiler, gen_preprocess_options, gen_lib_options
|
| 22 |
+
from distutils.errors import \
|
| 23 |
+
DistutilsExecError, CompileError, LibError, LinkError
|
| 24 |
+
from distutils import log
|
| 25 |
+
|
| 26 |
+
if sys.platform == 'darwin':
|
| 27 |
+
import _osx_support
|
| 28 |
+
|
| 29 |
+
# XXX Things not currently handled:
|
| 30 |
+
# * optimization/debug/warning flags; we just use whatever's in Python's
|
| 31 |
+
# Makefile and live with it. Is this adequate? If not, we might
|
| 32 |
+
# have to have a bunch of subclasses GNUCCompiler, SGICCompiler,
|
| 33 |
+
# SunCCompiler, and I suspect down that road lies madness.
|
| 34 |
+
# * even if we don't know a warning flag from an optimization flag,
|
| 35 |
+
# we need some way for outsiders to feed preprocessor/compiler/linker
|
| 36 |
+
# flags in to us -- eg. a sysadmin might want to mandate certain flags
|
| 37 |
+
# via a site config file, or a user might want to set something for
|
| 38 |
+
# compiling this module distribution only via the setup.py command
|
| 39 |
+
# line, whatever. As long as these options come from something on the
|
| 40 |
+
# current system, they can be as system-dependent as they like, and we
|
| 41 |
+
# should just happily stuff them into the preprocessor/compiler/linker
|
| 42 |
+
# options and carry on.
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
class UnixCCompiler(CCompiler):
|
| 46 |
+
|
| 47 |
+
compiler_type = 'unix'
|
| 48 |
+
|
| 49 |
+
# These are used by CCompiler in two places: the constructor sets
|
| 50 |
+
# instance attributes 'preprocessor', 'compiler', etc. from them, and
|
| 51 |
+
# 'set_executable()' allows any of these to be set. The defaults here
|
| 52 |
+
# are pretty generic; they will probably have to be set by an outsider
|
| 53 |
+
# (eg. using information discovered by the sysconfig about building
|
| 54 |
+
# Python extensions).
|
| 55 |
+
executables = {'preprocessor' : None,
|
| 56 |
+
'compiler' : ["cc"],
|
| 57 |
+
'compiler_so' : ["cc"],
|
| 58 |
+
'compiler_cxx' : ["cc"],
|
| 59 |
+
'linker_so' : ["cc", "-shared"],
|
| 60 |
+
'linker_exe' : ["cc"],
|
| 61 |
+
'archiver' : ["ar", "-cr"],
|
| 62 |
+
'ranlib' : None,
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
if sys.platform[:6] == "darwin":
|
| 66 |
+
executables['ranlib'] = ["ranlib"]
|
| 67 |
+
|
| 68 |
+
# Needed for the filename generation methods provided by the base
|
| 69 |
+
# class, CCompiler. NB. whoever instantiates/uses a particular
|
| 70 |
+
# UnixCCompiler instance should set 'shared_lib_ext' -- we set a
|
| 71 |
+
# reasonable common default here, but it's not necessarily used on all
|
| 72 |
+
# Unices!
|
| 73 |
+
|
| 74 |
+
src_extensions = [".c",".C",".cc",".cxx",".cpp",".m"]
|
| 75 |
+
obj_extension = ".o"
|
| 76 |
+
static_lib_extension = ".a"
|
| 77 |
+
shared_lib_extension = ".so"
|
| 78 |
+
dylib_lib_extension = ".dylib"
|
| 79 |
+
xcode_stub_lib_extension = ".tbd"
|
| 80 |
+
static_lib_format = shared_lib_format = dylib_lib_format = "lib%s%s"
|
| 81 |
+
xcode_stub_lib_format = dylib_lib_format
|
| 82 |
+
if sys.platform == "cygwin":
|
| 83 |
+
exe_extension = ".exe"
|
| 84 |
+
|
| 85 |
+
def preprocess(self, source, output_file=None, macros=None,
|
| 86 |
+
include_dirs=None, extra_preargs=None, extra_postargs=None):
|
| 87 |
+
fixed_args = self._fix_compile_args(None, macros, include_dirs)
|
| 88 |
+
ignore, macros, include_dirs = fixed_args
|
| 89 |
+
pp_opts = gen_preprocess_options(macros, include_dirs)
|
| 90 |
+
pp_args = self.preprocessor + pp_opts
|
| 91 |
+
if output_file:
|
| 92 |
+
pp_args.extend(['-o', output_file])
|
| 93 |
+
if extra_preargs:
|
| 94 |
+
pp_args[:0] = extra_preargs
|
| 95 |
+
if extra_postargs:
|
| 96 |
+
pp_args.extend(extra_postargs)
|
| 97 |
+
pp_args.append(source)
|
| 98 |
+
|
| 99 |
+
# We need to preprocess: either we're being forced to, or we're
|
| 100 |
+
# generating output to stdout, or there's a target output file and
|
| 101 |
+
# the source file is newer than the target (or the target doesn't
|
| 102 |
+
# exist).
|
| 103 |
+
if self.force or output_file is None or newer(source, output_file):
|
| 104 |
+
if output_file:
|
| 105 |
+
self.mkpath(os.path.dirname(output_file))
|
| 106 |
+
try:
|
| 107 |
+
self.spawn(pp_args)
|
| 108 |
+
except DistutilsExecError as msg:
|
| 109 |
+
raise CompileError(msg)
|
| 110 |
+
|
| 111 |
+
def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
|
| 112 |
+
compiler_so = self.compiler_so
|
| 113 |
+
if sys.platform == 'darwin':
|
| 114 |
+
compiler_so = _osx_support.compiler_fixup(compiler_so,
|
| 115 |
+
cc_args + extra_postargs)
|
| 116 |
+
try:
|
| 117 |
+
self.spawn(compiler_so + cc_args + [src, '-o', obj] +
|
| 118 |
+
extra_postargs)
|
| 119 |
+
except DistutilsExecError as msg:
|
| 120 |
+
raise CompileError(msg)
|
| 121 |
+
|
| 122 |
+
def create_static_lib(self, objects, output_libname,
|
| 123 |
+
output_dir=None, debug=0, target_lang=None):
|
| 124 |
+
objects, output_dir = self._fix_object_args(objects, output_dir)
|
| 125 |
+
|
| 126 |
+
output_filename = \
|
| 127 |
+
self.library_filename(output_libname, output_dir=output_dir)
|
| 128 |
+
|
| 129 |
+
if self._need_link(objects, output_filename):
|
| 130 |
+
self.mkpath(os.path.dirname(output_filename))
|
| 131 |
+
self.spawn(self.archiver +
|
| 132 |
+
[output_filename] +
|
| 133 |
+
objects + self.objects)
|
| 134 |
+
|
| 135 |
+
# Not many Unices required ranlib anymore -- SunOS 4.x is, I
|
| 136 |
+
# think the only major Unix that does. Maybe we need some
|
| 137 |
+
# platform intelligence here to skip ranlib if it's not
|
| 138 |
+
# needed -- or maybe Python's configure script took care of
|
| 139 |
+
# it for us, hence the check for leading colon.
|
| 140 |
+
if self.ranlib:
|
| 141 |
+
try:
|
| 142 |
+
self.spawn(self.ranlib + [output_filename])
|
| 143 |
+
except DistutilsExecError as msg:
|
| 144 |
+
raise LibError(msg)
|
| 145 |
+
else:
|
| 146 |
+
log.debug("skipping %s (up-to-date)", output_filename)
|
| 147 |
+
|
| 148 |
+
def link(self, target_desc, objects,
|
| 149 |
+
output_filename, output_dir=None, libraries=None,
|
| 150 |
+
library_dirs=None, runtime_library_dirs=None,
|
| 151 |
+
export_symbols=None, debug=0, extra_preargs=None,
|
| 152 |
+
extra_postargs=None, build_temp=None, target_lang=None):
|
| 153 |
+
objects, output_dir = self._fix_object_args(objects, output_dir)
|
| 154 |
+
fixed_args = self._fix_lib_args(libraries, library_dirs,
|
| 155 |
+
runtime_library_dirs)
|
| 156 |
+
libraries, library_dirs, runtime_library_dirs = fixed_args
|
| 157 |
+
|
| 158 |
+
lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs,
|
| 159 |
+
libraries)
|
| 160 |
+
if not isinstance(output_dir, (str, type(None))):
|
| 161 |
+
raise TypeError("'output_dir' must be a string or None")
|
| 162 |
+
if output_dir is not None:
|
| 163 |
+
output_filename = os.path.join(output_dir, output_filename)
|
| 164 |
+
|
| 165 |
+
if self._need_link(objects, output_filename):
|
| 166 |
+
ld_args = (objects + self.objects +
|
| 167 |
+
lib_opts + ['-o', output_filename])
|
| 168 |
+
if debug:
|
| 169 |
+
ld_args[:0] = ['-g']
|
| 170 |
+
if extra_preargs:
|
| 171 |
+
ld_args[:0] = extra_preargs
|
| 172 |
+
if extra_postargs:
|
| 173 |
+
ld_args.extend(extra_postargs)
|
| 174 |
+
self.mkpath(os.path.dirname(output_filename))
|
| 175 |
+
try:
|
| 176 |
+
if target_desc == CCompiler.EXECUTABLE:
|
| 177 |
+
linker = self.linker_exe[:]
|
| 178 |
+
else:
|
| 179 |
+
linker = self.linker_so[:]
|
| 180 |
+
if target_lang == "c++" and self.compiler_cxx:
|
| 181 |
+
# skip over environment variable settings if /usr/bin/env
|
| 182 |
+
# is used to set up the linker's environment.
|
| 183 |
+
# This is needed on OSX. Note: this assumes that the
|
| 184 |
+
# normal and C++ compiler have the same environment
|
| 185 |
+
# settings.
|
| 186 |
+
i = 0
|
| 187 |
+
if os.path.basename(linker[0]) == "env":
|
| 188 |
+
i = 1
|
| 189 |
+
while '=' in linker[i]:
|
| 190 |
+
i += 1
|
| 191 |
+
|
| 192 |
+
if os.path.basename(linker[i]) == 'ld_so_aix':
|
| 193 |
+
# AIX platforms prefix the compiler with the ld_so_aix
|
| 194 |
+
# script, so we need to adjust our linker index
|
| 195 |
+
offset = 1
|
| 196 |
+
else:
|
| 197 |
+
offset = 0
|
| 198 |
+
|
| 199 |
+
linker[i+offset] = self.compiler_cxx[i]
|
| 200 |
+
|
| 201 |
+
if sys.platform == 'darwin':
|
| 202 |
+
linker = _osx_support.compiler_fixup(linker, ld_args)
|
| 203 |
+
from distutils.util import get_host_platform
|
| 204 |
+
ld_args = ['-arch', get_host_platform().split("-")[-1]] + ld_args
|
| 205 |
+
|
| 206 |
+
self.spawn(linker + ld_args)
|
| 207 |
+
except DistutilsExecError as msg:
|
| 208 |
+
raise LinkError(msg)
|
| 209 |
+
else:
|
| 210 |
+
log.debug("skipping %s (up-to-date)", output_filename)
|
| 211 |
+
|
| 212 |
+
# -- Miscellaneous methods -----------------------------------------
|
| 213 |
+
# These are all used by the 'gen_lib_options() function, in
|
| 214 |
+
# ccompiler.py.
|
| 215 |
+
|
| 216 |
+
def library_dir_option(self, dir):
|
| 217 |
+
return "-L" + dir
|
| 218 |
+
|
| 219 |
+
def _is_gcc(self, compiler_name):
|
| 220 |
+
return "gcc" in compiler_name or "g++" in compiler_name
|
| 221 |
+
|
| 222 |
+
def runtime_library_dir_option(self, dir):
|
| 223 |
+
# XXX Hackish, at the very least. See Python bug #445902:
|
| 224 |
+
# http://sourceforge.net/tracker/index.php
|
| 225 |
+
# ?func=detail&aid=445902&group_id=5470&atid=105470
|
| 226 |
+
# Linkers on different platforms need different options to
|
| 227 |
+
# specify that directories need to be added to the list of
|
| 228 |
+
# directories searched for dependencies when a dynamic library
|
| 229 |
+
# is sought. GCC on GNU systems (Linux, FreeBSD, ...) has to
|
| 230 |
+
# be told to pass the -R option through to the linker, whereas
|
| 231 |
+
# other compilers and gcc on other systems just know this.
|
| 232 |
+
# Other compilers may need something slightly different. At
|
| 233 |
+
# this time, there's no way to determine this information from
|
| 234 |
+
# the configuration data stored in the Python installation, so
|
| 235 |
+
# we use this hack.
|
| 236 |
+
compiler = os.path.basename(sysconfig.get_config_var("CC").split()[0])
|
| 237 |
+
if sys.platform[:6] == "darwin":
|
| 238 |
+
# MacOSX's linker doesn't understand the -R flag at all
|
| 239 |
+
return "-L" + dir
|
| 240 |
+
elif sys.platform[:7] == "freebsd":
|
| 241 |
+
return "-Wl,-rpath=" + dir
|
| 242 |
+
elif sys.platform[:5] == "hp-ux":
|
| 243 |
+
if self._is_gcc(compiler):
|
| 244 |
+
return ["-Wl,+s", "-L" + dir]
|
| 245 |
+
return ["+s", "-L" + dir]
|
| 246 |
+
else:
|
| 247 |
+
if self._is_gcc(compiler):
|
| 248 |
+
# gcc on non-GNU systems does not need -Wl, but can
|
| 249 |
+
# use it anyway. Since distutils has always passed in
|
| 250 |
+
# -Wl whenever gcc was used in the past it is probably
|
| 251 |
+
# safest to keep doing so.
|
| 252 |
+
if sysconfig.get_config_var("GNULD") == "yes" or sys.platform == 'win32':
|
| 253 |
+
# GNU ld needs an extra option to get a RUNPATH
|
| 254 |
+
# instead of just an RPATH.
|
| 255 |
+
return "-Wl,-R" + dir
|
| 256 |
+
else:
|
| 257 |
+
return "-Wl,--disable-new-dtags,-R" + dir
|
| 258 |
+
else:
|
| 259 |
+
# No idea how --enable-new-dtags would be passed on to
|
| 260 |
+
# ld if this system was using GNU ld. Don't know if a
|
| 261 |
+
# system like this even exists.
|
| 262 |
+
return "-R" + dir
|
| 263 |
+
|
| 264 |
+
def library_option(self, lib):
|
| 265 |
+
return "-l" + lib
|
| 266 |
+
|
| 267 |
+
def find_library_file(self, dirs, lib, debug=0):
|
| 268 |
+
shared_f = self.library_filename(lib, lib_type='shared')
|
| 269 |
+
dylib_f = self.library_filename(lib, lib_type='dylib')
|
| 270 |
+
xcode_stub_f = self.library_filename(lib, lib_type='xcode_stub')
|
| 271 |
+
static_f = self.library_filename(lib, lib_type='static')
|
| 272 |
+
|
| 273 |
+
if sys.platform == 'darwin':
|
| 274 |
+
# On OSX users can specify an alternate SDK using
|
| 275 |
+
# '-isysroot', calculate the SDK root if it is specified
|
| 276 |
+
# (and use it further on)
|
| 277 |
+
#
|
| 278 |
+
# Note that, as of Xcode 7, Apple SDKs may contain textual stub
|
| 279 |
+
# libraries with .tbd extensions rather than the normal .dylib
|
| 280 |
+
# shared libraries installed in /. The Apple compiler tool
|
| 281 |
+
# chain handles this transparently but it can cause problems
|
| 282 |
+
# for programs that are being built with an SDK and searching
|
| 283 |
+
# for specific libraries. Callers of find_library_file need to
|
| 284 |
+
# keep in mind that the base filename of the returned SDK library
|
| 285 |
+
# file might have a different extension from that of the library
|
| 286 |
+
# file installed on the running system, for example:
|
| 287 |
+
# /Applications/Xcode.app/Contents/Developer/Platforms/
|
| 288 |
+
# MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/
|
| 289 |
+
# usr/lib/libedit.tbd
|
| 290 |
+
# vs
|
| 291 |
+
# /usr/lib/libedit.dylib
|
| 292 |
+
cflags = sysconfig.get_config_var('CFLAGS')
|
| 293 |
+
m = re.search(r'-isysroot\s*(\S+)', cflags)
|
| 294 |
+
if m is None:
|
| 295 |
+
sysroot = _osx_support._default_sysroot(sysconfig.get_config_var('CC'))
|
| 296 |
+
else:
|
| 297 |
+
sysroot = m.group(1)
|
| 298 |
+
|
| 299 |
+
|
| 300 |
+
|
| 301 |
+
for dir in dirs:
|
| 302 |
+
shared = os.path.join(dir, shared_f)
|
| 303 |
+
dylib = os.path.join(dir, dylib_f)
|
| 304 |
+
static = os.path.join(dir, static_f)
|
| 305 |
+
xcode_stub = os.path.join(dir, xcode_stub_f)
|
| 306 |
+
|
| 307 |
+
if sys.platform == 'darwin' and (
|
| 308 |
+
dir.startswith('/System/') or (
|
| 309 |
+
dir.startswith('/usr/') and not dir.startswith('/usr/local/'))):
|
| 310 |
+
|
| 311 |
+
shared = os.path.join(sysroot, dir[1:], shared_f)
|
| 312 |
+
dylib = os.path.join(sysroot, dir[1:], dylib_f)
|
| 313 |
+
static = os.path.join(sysroot, dir[1:], static_f)
|
| 314 |
+
xcode_stub = os.path.join(sysroot, dir[1:], xcode_stub_f)
|
| 315 |
+
|
| 316 |
+
# We're second-guessing the linker here, with not much hard
|
| 317 |
+
# data to go on: GCC seems to prefer the shared library, so I'm
|
| 318 |
+
# assuming that *all* Unix C compilers do. And of course I'm
|
| 319 |
+
# ignoring even GCC's "-static" option. So sue me.
|
| 320 |
+
if os.path.exists(dylib):
|
| 321 |
+
return dylib
|
| 322 |
+
elif os.path.exists(xcode_stub):
|
| 323 |
+
return xcode_stub
|
| 324 |
+
elif os.path.exists(shared):
|
| 325 |
+
return shared
|
| 326 |
+
elif os.path.exists(static):
|
| 327 |
+
return static
|
| 328 |
+
|
| 329 |
+
# Oops, didn't find it in *any* of 'dirs'
|
| 330 |
+
return None
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/util.py
ADDED
|
@@ -0,0 +1,558 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""distutils.util
|
| 2 |
+
|
| 3 |
+
Miscellaneous utility functions -- anything that doesn't fit into
|
| 4 |
+
one of the other *util.py modules.
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
import os
|
| 8 |
+
import re
|
| 9 |
+
import importlib.util
|
| 10 |
+
import string
|
| 11 |
+
import sys
|
| 12 |
+
from distutils.errors import DistutilsPlatformError
|
| 13 |
+
from distutils.dep_util import newer
|
| 14 |
+
from distutils.spawn import spawn
|
| 15 |
+
from distutils import log
|
| 16 |
+
from distutils.errors import DistutilsByteCompileError
|
| 17 |
+
|
| 18 |
+
def get_host_platform():
|
| 19 |
+
"""Return a string that identifies the current platform. This is used mainly to
|
| 20 |
+
distinguish platform-specific build directories and platform-specific built
|
| 21 |
+
distributions. Typically includes the OS name and version and the
|
| 22 |
+
architecture (as supplied by 'os.uname()'), although the exact information
|
| 23 |
+
included depends on the OS; eg. on Linux, the kernel version isn't
|
| 24 |
+
particularly important.
|
| 25 |
+
|
| 26 |
+
Examples of returned values:
|
| 27 |
+
linux-i586
|
| 28 |
+
linux-alpha (?)
|
| 29 |
+
solaris-2.6-sun4u
|
| 30 |
+
|
| 31 |
+
Windows will return one of:
|
| 32 |
+
win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
|
| 33 |
+
win32 (all others - specifically, sys.platform is returned)
|
| 34 |
+
|
| 35 |
+
For other non-POSIX platforms, currently just returns 'sys.platform'.
|
| 36 |
+
|
| 37 |
+
"""
|
| 38 |
+
if os.name == 'nt':
|
| 39 |
+
if 'amd64' in sys.version.lower():
|
| 40 |
+
return 'win-amd64'
|
| 41 |
+
if '(arm)' in sys.version.lower():
|
| 42 |
+
return 'win-arm32'
|
| 43 |
+
if '(arm64)' in sys.version.lower():
|
| 44 |
+
return 'win-arm64'
|
| 45 |
+
return sys.platform
|
| 46 |
+
|
| 47 |
+
# Set for cross builds explicitly
|
| 48 |
+
if "_PYTHON_HOST_PLATFORM" in os.environ:
|
| 49 |
+
return os.environ["_PYTHON_HOST_PLATFORM"]
|
| 50 |
+
|
| 51 |
+
if os.name != "posix" or not hasattr(os, 'uname'):
|
| 52 |
+
# XXX what about the architecture? NT is Intel or Alpha,
|
| 53 |
+
# Mac OS is M68k or PPC, etc.
|
| 54 |
+
return sys.platform
|
| 55 |
+
|
| 56 |
+
# Try to distinguish various flavours of Unix
|
| 57 |
+
|
| 58 |
+
(osname, host, release, version, machine) = os.uname()
|
| 59 |
+
|
| 60 |
+
# Convert the OS name to lowercase, remove '/' characters, and translate
|
| 61 |
+
# spaces (for "Power Macintosh")
|
| 62 |
+
osname = osname.lower().replace('/', '')
|
| 63 |
+
machine = machine.replace(' ', '_')
|
| 64 |
+
machine = machine.replace('/', '-')
|
| 65 |
+
|
| 66 |
+
if osname[:5] == "linux":
|
| 67 |
+
# At least on Linux/Intel, 'machine' is the processor --
|
| 68 |
+
# i386, etc.
|
| 69 |
+
# XXX what about Alpha, SPARC, etc?
|
| 70 |
+
return "%s-%s" % (osname, machine)
|
| 71 |
+
elif osname[:5] == "sunos":
|
| 72 |
+
if release[0] >= "5": # SunOS 5 == Solaris 2
|
| 73 |
+
osname = "solaris"
|
| 74 |
+
release = "%d.%s" % (int(release[0]) - 3, release[2:])
|
| 75 |
+
# We can't use "platform.architecture()[0]" because a
|
| 76 |
+
# bootstrap problem. We use a dict to get an error
|
| 77 |
+
# if some suspicious happens.
|
| 78 |
+
bitness = {2147483647:"32bit", 9223372036854775807:"64bit"}
|
| 79 |
+
machine += ".%s" % bitness[sys.maxsize]
|
| 80 |
+
# fall through to standard osname-release-machine representation
|
| 81 |
+
elif osname[:3] == "aix":
|
| 82 |
+
return "%s-%s.%s" % (osname, version, release)
|
| 83 |
+
elif osname[:6] == "cygwin":
|
| 84 |
+
osname = "cygwin"
|
| 85 |
+
rel_re = re.compile (r'[\d.]+', re.ASCII)
|
| 86 |
+
m = rel_re.match(release)
|
| 87 |
+
if m:
|
| 88 |
+
release = m.group()
|
| 89 |
+
elif osname[:6] == "darwin":
|
| 90 |
+
import _osx_support, distutils.sysconfig
|
| 91 |
+
osname, release, machine = _osx_support.get_platform_osx(
|
| 92 |
+
distutils.sysconfig.get_config_vars(),
|
| 93 |
+
osname, release, machine)
|
| 94 |
+
|
| 95 |
+
return "%s-%s-%s" % (osname, release, machine)
|
| 96 |
+
|
| 97 |
+
def get_platform():
|
| 98 |
+
if os.name == 'nt':
|
| 99 |
+
TARGET_TO_PLAT = {
|
| 100 |
+
'x86' : 'win32',
|
| 101 |
+
'x64' : 'win-amd64',
|
| 102 |
+
'arm' : 'win-arm32',
|
| 103 |
+
}
|
| 104 |
+
return TARGET_TO_PLAT.get(os.environ.get('VSCMD_ARG_TGT_ARCH')) or get_host_platform()
|
| 105 |
+
else:
|
| 106 |
+
return get_host_platform()
|
| 107 |
+
|
| 108 |
+
def convert_path (pathname):
|
| 109 |
+
"""Return 'pathname' as a name that will work on the native filesystem,
|
| 110 |
+
i.e. split it on '/' and put it back together again using the current
|
| 111 |
+
directory separator. Needed because filenames in the setup script are
|
| 112 |
+
always supplied in Unix style, and have to be converted to the local
|
| 113 |
+
convention before we can actually use them in the filesystem. Raises
|
| 114 |
+
ValueError on non-Unix-ish systems if 'pathname' either starts or
|
| 115 |
+
ends with a slash.
|
| 116 |
+
"""
|
| 117 |
+
if os.sep == '/':
|
| 118 |
+
return pathname
|
| 119 |
+
if not pathname:
|
| 120 |
+
return pathname
|
| 121 |
+
if pathname[0] == '/':
|
| 122 |
+
raise ValueError("path '%s' cannot be absolute" % pathname)
|
| 123 |
+
if pathname[-1] == '/':
|
| 124 |
+
raise ValueError("path '%s' cannot end with '/'" % pathname)
|
| 125 |
+
|
| 126 |
+
paths = pathname.split('/')
|
| 127 |
+
while '.' in paths:
|
| 128 |
+
paths.remove('.')
|
| 129 |
+
if not paths:
|
| 130 |
+
return os.curdir
|
| 131 |
+
return os.path.join(*paths)
|
| 132 |
+
|
| 133 |
+
# convert_path ()
|
| 134 |
+
|
| 135 |
+
|
| 136 |
+
def change_root (new_root, pathname):
|
| 137 |
+
"""Return 'pathname' with 'new_root' prepended. If 'pathname' is
|
| 138 |
+
relative, this is equivalent to "os.path.join(new_root,pathname)".
|
| 139 |
+
Otherwise, it requires making 'pathname' relative and then joining the
|
| 140 |
+
two, which is tricky on DOS/Windows and Mac OS.
|
| 141 |
+
"""
|
| 142 |
+
if os.name == 'posix':
|
| 143 |
+
if not os.path.isabs(pathname):
|
| 144 |
+
return os.path.join(new_root, pathname)
|
| 145 |
+
else:
|
| 146 |
+
return os.path.join(new_root, pathname[1:])
|
| 147 |
+
|
| 148 |
+
elif os.name == 'nt':
|
| 149 |
+
(drive, path) = os.path.splitdrive(pathname)
|
| 150 |
+
if path[0] == '\\':
|
| 151 |
+
path = path[1:]
|
| 152 |
+
return os.path.join(new_root, path)
|
| 153 |
+
|
| 154 |
+
else:
|
| 155 |
+
raise DistutilsPlatformError("nothing known about platform '%s'" % os.name)
|
| 156 |
+
|
| 157 |
+
|
| 158 |
+
_environ_checked = 0
|
| 159 |
+
def check_environ ():
|
| 160 |
+
"""Ensure that 'os.environ' has all the environment variables we
|
| 161 |
+
guarantee that users can use in config files, command-line options,
|
| 162 |
+
etc. Currently this includes:
|
| 163 |
+
HOME - user's home directory (Unix only)
|
| 164 |
+
PLAT - description of the current platform, including hardware
|
| 165 |
+
and OS (see 'get_platform()')
|
| 166 |
+
"""
|
| 167 |
+
global _environ_checked
|
| 168 |
+
if _environ_checked:
|
| 169 |
+
return
|
| 170 |
+
|
| 171 |
+
if os.name == 'posix' and 'HOME' not in os.environ:
|
| 172 |
+
try:
|
| 173 |
+
import pwd
|
| 174 |
+
os.environ['HOME'] = pwd.getpwuid(os.getuid())[5]
|
| 175 |
+
except (ImportError, KeyError):
|
| 176 |
+
# bpo-10496: if the current user identifier doesn't exist in the
|
| 177 |
+
# password database, do nothing
|
| 178 |
+
pass
|
| 179 |
+
|
| 180 |
+
if 'PLAT' not in os.environ:
|
| 181 |
+
os.environ['PLAT'] = get_platform()
|
| 182 |
+
|
| 183 |
+
_environ_checked = 1
|
| 184 |
+
|
| 185 |
+
|
| 186 |
+
def subst_vars (s, local_vars):
|
| 187 |
+
"""Perform shell/Perl-style variable substitution on 'string'. Every
|
| 188 |
+
occurrence of '$' followed by a name is considered a variable, and
|
| 189 |
+
variable is substituted by the value found in the 'local_vars'
|
| 190 |
+
dictionary, or in 'os.environ' if it's not in 'local_vars'.
|
| 191 |
+
'os.environ' is first checked/augmented to guarantee that it contains
|
| 192 |
+
certain values: see 'check_environ()'. Raise ValueError for any
|
| 193 |
+
variables not found in either 'local_vars' or 'os.environ'.
|
| 194 |
+
"""
|
| 195 |
+
check_environ()
|
| 196 |
+
def _subst (match, local_vars=local_vars):
|
| 197 |
+
var_name = match.group(1)
|
| 198 |
+
if var_name in local_vars:
|
| 199 |
+
return str(local_vars[var_name])
|
| 200 |
+
else:
|
| 201 |
+
return os.environ[var_name]
|
| 202 |
+
|
| 203 |
+
try:
|
| 204 |
+
return re.sub(r'\$([a-zA-Z_][a-zA-Z_0-9]*)', _subst, s)
|
| 205 |
+
except KeyError as var:
|
| 206 |
+
raise ValueError("invalid variable '$%s'" % var)
|
| 207 |
+
|
| 208 |
+
# subst_vars ()
|
| 209 |
+
|
| 210 |
+
|
| 211 |
+
def grok_environment_error (exc, prefix="error: "):
|
| 212 |
+
# Function kept for backward compatibility.
|
| 213 |
+
# Used to try clever things with EnvironmentErrors,
|
| 214 |
+
# but nowadays str(exception) produces good messages.
|
| 215 |
+
return prefix + str(exc)
|
| 216 |
+
|
| 217 |
+
|
| 218 |
+
# Needed by 'split_quoted()'
|
| 219 |
+
_wordchars_re = _squote_re = _dquote_re = None
|
| 220 |
+
def _init_regex():
|
| 221 |
+
global _wordchars_re, _squote_re, _dquote_re
|
| 222 |
+
_wordchars_re = re.compile(r'[^\\\'\"%s ]*' % string.whitespace)
|
| 223 |
+
_squote_re = re.compile(r"'(?:[^'\\]|\\.)*'")
|
| 224 |
+
_dquote_re = re.compile(r'"(?:[^"\\]|\\.)*"')
|
| 225 |
+
|
| 226 |
+
def split_quoted (s):
|
| 227 |
+
"""Split a string up according to Unix shell-like rules for quotes and
|
| 228 |
+
backslashes. In short: words are delimited by spaces, as long as those
|
| 229 |
+
spaces are not escaped by a backslash, or inside a quoted string.
|
| 230 |
+
Single and double quotes are equivalent, and the quote characters can
|
| 231 |
+
be backslash-escaped. The backslash is stripped from any two-character
|
| 232 |
+
escape sequence, leaving only the escaped character. The quote
|
| 233 |
+
characters are stripped from any quoted string. Returns a list of
|
| 234 |
+
words.
|
| 235 |
+
"""
|
| 236 |
+
|
| 237 |
+
# This is a nice algorithm for splitting up a single string, since it
|
| 238 |
+
# doesn't require character-by-character examination. It was a little
|
| 239 |
+
# bit of a brain-bender to get it working right, though...
|
| 240 |
+
if _wordchars_re is None: _init_regex()
|
| 241 |
+
|
| 242 |
+
s = s.strip()
|
| 243 |
+
words = []
|
| 244 |
+
pos = 0
|
| 245 |
+
|
| 246 |
+
while s:
|
| 247 |
+
m = _wordchars_re.match(s, pos)
|
| 248 |
+
end = m.end()
|
| 249 |
+
if end == len(s):
|
| 250 |
+
words.append(s[:end])
|
| 251 |
+
break
|
| 252 |
+
|
| 253 |
+
if s[end] in string.whitespace: # unescaped, unquoted whitespace: now
|
| 254 |
+
words.append(s[:end]) # we definitely have a word delimiter
|
| 255 |
+
s = s[end:].lstrip()
|
| 256 |
+
pos = 0
|
| 257 |
+
|
| 258 |
+
elif s[end] == '\\': # preserve whatever is being escaped;
|
| 259 |
+
# will become part of the current word
|
| 260 |
+
s = s[:end] + s[end+1:]
|
| 261 |
+
pos = end+1
|
| 262 |
+
|
| 263 |
+
else:
|
| 264 |
+
if s[end] == "'": # slurp singly-quoted string
|
| 265 |
+
m = _squote_re.match(s, end)
|
| 266 |
+
elif s[end] == '"': # slurp doubly-quoted string
|
| 267 |
+
m = _dquote_re.match(s, end)
|
| 268 |
+
else:
|
| 269 |
+
raise RuntimeError("this can't happen (bad char '%c')" % s[end])
|
| 270 |
+
|
| 271 |
+
if m is None:
|
| 272 |
+
raise ValueError("bad string (mismatched %s quotes?)" % s[end])
|
| 273 |
+
|
| 274 |
+
(beg, end) = m.span()
|
| 275 |
+
s = s[:beg] + s[beg+1:end-1] + s[end:]
|
| 276 |
+
pos = m.end() - 2
|
| 277 |
+
|
| 278 |
+
if pos >= len(s):
|
| 279 |
+
words.append(s)
|
| 280 |
+
break
|
| 281 |
+
|
| 282 |
+
return words
|
| 283 |
+
|
| 284 |
+
# split_quoted ()
|
| 285 |
+
|
| 286 |
+
|
| 287 |
+
def execute (func, args, msg=None, verbose=0, dry_run=0):
|
| 288 |
+
"""Perform some action that affects the outside world (eg. by
|
| 289 |
+
writing to the filesystem). Such actions are special because they
|
| 290 |
+
are disabled by the 'dry_run' flag. This method takes care of all
|
| 291 |
+
that bureaucracy for you; all you have to do is supply the
|
| 292 |
+
function to call and an argument tuple for it (to embody the
|
| 293 |
+
"external action" being performed), and an optional message to
|
| 294 |
+
print.
|
| 295 |
+
"""
|
| 296 |
+
if msg is None:
|
| 297 |
+
msg = "%s%r" % (func.__name__, args)
|
| 298 |
+
if msg[-2:] == ',)': # correct for singleton tuple
|
| 299 |
+
msg = msg[0:-2] + ')'
|
| 300 |
+
|
| 301 |
+
log.info(msg)
|
| 302 |
+
if not dry_run:
|
| 303 |
+
func(*args)
|
| 304 |
+
|
| 305 |
+
|
| 306 |
+
def strtobool (val):
|
| 307 |
+
"""Convert a string representation of truth to true (1) or false (0).
|
| 308 |
+
|
| 309 |
+
True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values
|
| 310 |
+
are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if
|
| 311 |
+
'val' is anything else.
|
| 312 |
+
"""
|
| 313 |
+
val = val.lower()
|
| 314 |
+
if val in ('y', 'yes', 't', 'true', 'on', '1'):
|
| 315 |
+
return 1
|
| 316 |
+
elif val in ('n', 'no', 'f', 'false', 'off', '0'):
|
| 317 |
+
return 0
|
| 318 |
+
else:
|
| 319 |
+
raise ValueError("invalid truth value %r" % (val,))
|
| 320 |
+
|
| 321 |
+
|
| 322 |
+
def byte_compile (py_files,
|
| 323 |
+
optimize=0, force=0,
|
| 324 |
+
prefix=None, base_dir=None,
|
| 325 |
+
verbose=1, dry_run=0,
|
| 326 |
+
direct=None):
|
| 327 |
+
"""Byte-compile a collection of Python source files to .pyc
|
| 328 |
+
files in a __pycache__ subdirectory. 'py_files' is a list
|
| 329 |
+
of files to compile; any files that don't end in ".py" are silently
|
| 330 |
+
skipped. 'optimize' must be one of the following:
|
| 331 |
+
0 - don't optimize
|
| 332 |
+
1 - normal optimization (like "python -O")
|
| 333 |
+
2 - extra optimization (like "python -OO")
|
| 334 |
+
If 'force' is true, all files are recompiled regardless of
|
| 335 |
+
timestamps.
|
| 336 |
+
|
| 337 |
+
The source filename encoded in each bytecode file defaults to the
|
| 338 |
+
filenames listed in 'py_files'; you can modify these with 'prefix' and
|
| 339 |
+
'basedir'. 'prefix' is a string that will be stripped off of each
|
| 340 |
+
source filename, and 'base_dir' is a directory name that will be
|
| 341 |
+
prepended (after 'prefix' is stripped). You can supply either or both
|
| 342 |
+
(or neither) of 'prefix' and 'base_dir', as you wish.
|
| 343 |
+
|
| 344 |
+
If 'dry_run' is true, doesn't actually do anything that would
|
| 345 |
+
affect the filesystem.
|
| 346 |
+
|
| 347 |
+
Byte-compilation is either done directly in this interpreter process
|
| 348 |
+
with the standard py_compile module, or indirectly by writing a
|
| 349 |
+
temporary script and executing it. Normally, you should let
|
| 350 |
+
'byte_compile()' figure out to use direct compilation or not (see
|
| 351 |
+
the source for details). The 'direct' flag is used by the script
|
| 352 |
+
generated in indirect mode; unless you know what you're doing, leave
|
| 353 |
+
it set to None.
|
| 354 |
+
"""
|
| 355 |
+
|
| 356 |
+
# Late import to fix a bootstrap issue: _posixsubprocess is built by
|
| 357 |
+
# setup.py, but setup.py uses distutils.
|
| 358 |
+
import subprocess
|
| 359 |
+
|
| 360 |
+
# nothing is done if sys.dont_write_bytecode is True
|
| 361 |
+
if sys.dont_write_bytecode:
|
| 362 |
+
raise DistutilsByteCompileError('byte-compiling is disabled.')
|
| 363 |
+
|
| 364 |
+
# First, if the caller didn't force us into direct or indirect mode,
|
| 365 |
+
# figure out which mode we should be in. We take a conservative
|
| 366 |
+
# approach: choose direct mode *only* if the current interpreter is
|
| 367 |
+
# in debug mode and optimize is 0. If we're not in debug mode (-O
|
| 368 |
+
# or -OO), we don't know which level of optimization this
|
| 369 |
+
# interpreter is running with, so we can't do direct
|
| 370 |
+
# byte-compilation and be certain that it's the right thing. Thus,
|
| 371 |
+
# always compile indirectly if the current interpreter is in either
|
| 372 |
+
# optimize mode, or if either optimization level was requested by
|
| 373 |
+
# the caller.
|
| 374 |
+
if direct is None:
|
| 375 |
+
direct = (__debug__ and optimize == 0)
|
| 376 |
+
|
| 377 |
+
# "Indirect" byte-compilation: write a temporary script and then
|
| 378 |
+
# run it with the appropriate flags.
|
| 379 |
+
if not direct:
|
| 380 |
+
try:
|
| 381 |
+
from tempfile import mkstemp
|
| 382 |
+
(script_fd, script_name) = mkstemp(".py")
|
| 383 |
+
except ImportError:
|
| 384 |
+
from tempfile import mktemp
|
| 385 |
+
(script_fd, script_name) = None, mktemp(".py")
|
| 386 |
+
log.info("writing byte-compilation script '%s'", script_name)
|
| 387 |
+
if not dry_run:
|
| 388 |
+
if script_fd is not None:
|
| 389 |
+
script = os.fdopen(script_fd, "w")
|
| 390 |
+
else:
|
| 391 |
+
script = open(script_name, "w")
|
| 392 |
+
|
| 393 |
+
with script:
|
| 394 |
+
script.write("""\
|
| 395 |
+
from distutils.util import byte_compile
|
| 396 |
+
files = [
|
| 397 |
+
""")
|
| 398 |
+
|
| 399 |
+
# XXX would be nice to write absolute filenames, just for
|
| 400 |
+
# safety's sake (script should be more robust in the face of
|
| 401 |
+
# chdir'ing before running it). But this requires abspath'ing
|
| 402 |
+
# 'prefix' as well, and that breaks the hack in build_lib's
|
| 403 |
+
# 'byte_compile()' method that carefully tacks on a trailing
|
| 404 |
+
# slash (os.sep really) to make sure the prefix here is "just
|
| 405 |
+
# right". This whole prefix business is rather delicate -- the
|
| 406 |
+
# problem is that it's really a directory, but I'm treating it
|
| 407 |
+
# as a dumb string, so trailing slashes and so forth matter.
|
| 408 |
+
|
| 409 |
+
#py_files = map(os.path.abspath, py_files)
|
| 410 |
+
#if prefix:
|
| 411 |
+
# prefix = os.path.abspath(prefix)
|
| 412 |
+
|
| 413 |
+
script.write(",\n".join(map(repr, py_files)) + "]\n")
|
| 414 |
+
script.write("""
|
| 415 |
+
byte_compile(files, optimize=%r, force=%r,
|
| 416 |
+
prefix=%r, base_dir=%r,
|
| 417 |
+
verbose=%r, dry_run=0,
|
| 418 |
+
direct=1)
|
| 419 |
+
""" % (optimize, force, prefix, base_dir, verbose))
|
| 420 |
+
|
| 421 |
+
cmd = [sys.executable]
|
| 422 |
+
cmd.extend(subprocess._optim_args_from_interpreter_flags())
|
| 423 |
+
cmd.append(script_name)
|
| 424 |
+
spawn(cmd, dry_run=dry_run)
|
| 425 |
+
execute(os.remove, (script_name,), "removing %s" % script_name,
|
| 426 |
+
dry_run=dry_run)
|
| 427 |
+
|
| 428 |
+
# "Direct" byte-compilation: use the py_compile module to compile
|
| 429 |
+
# right here, right now. Note that the script generated in indirect
|
| 430 |
+
# mode simply calls 'byte_compile()' in direct mode, a weird sort of
|
| 431 |
+
# cross-process recursion. Hey, it works!
|
| 432 |
+
else:
|
| 433 |
+
from py_compile import compile
|
| 434 |
+
|
| 435 |
+
for file in py_files:
|
| 436 |
+
if file[-3:] != ".py":
|
| 437 |
+
# This lets us be lazy and not filter filenames in
|
| 438 |
+
# the "install_lib" command.
|
| 439 |
+
continue
|
| 440 |
+
|
| 441 |
+
# Terminology from the py_compile module:
|
| 442 |
+
# cfile - byte-compiled file
|
| 443 |
+
# dfile - purported source filename (same as 'file' by default)
|
| 444 |
+
if optimize >= 0:
|
| 445 |
+
opt = '' if optimize == 0 else optimize
|
| 446 |
+
cfile = importlib.util.cache_from_source(
|
| 447 |
+
file, optimization=opt)
|
| 448 |
+
else:
|
| 449 |
+
cfile = importlib.util.cache_from_source(file)
|
| 450 |
+
dfile = file
|
| 451 |
+
if prefix:
|
| 452 |
+
if file[:len(prefix)] != prefix:
|
| 453 |
+
raise ValueError("invalid prefix: filename %r doesn't start with %r"
|
| 454 |
+
% (file, prefix))
|
| 455 |
+
dfile = dfile[len(prefix):]
|
| 456 |
+
if base_dir:
|
| 457 |
+
dfile = os.path.join(base_dir, dfile)
|
| 458 |
+
|
| 459 |
+
cfile_base = os.path.basename(cfile)
|
| 460 |
+
if direct:
|
| 461 |
+
if force or newer(file, cfile):
|
| 462 |
+
log.info("byte-compiling %s to %s", file, cfile_base)
|
| 463 |
+
if not dry_run:
|
| 464 |
+
compile(file, cfile, dfile)
|
| 465 |
+
else:
|
| 466 |
+
log.debug("skipping byte-compilation of %s to %s",
|
| 467 |
+
file, cfile_base)
|
| 468 |
+
|
| 469 |
+
# byte_compile ()
|
| 470 |
+
|
| 471 |
+
def rfc822_escape (header):
|
| 472 |
+
"""Return a version of the string escaped for inclusion in an
|
| 473 |
+
RFC-822 header, by ensuring there are 8 spaces space after each newline.
|
| 474 |
+
"""
|
| 475 |
+
lines = header.split('\n')
|
| 476 |
+
sep = '\n' + 8 * ' '
|
| 477 |
+
return sep.join(lines)
|
| 478 |
+
|
| 479 |
+
# 2to3 support
|
| 480 |
+
|
| 481 |
+
def run_2to3(files, fixer_names=None, options=None, explicit=None):
|
| 482 |
+
"""Invoke 2to3 on a list of Python files.
|
| 483 |
+
The files should all come from the build area, as the
|
| 484 |
+
modification is done in-place. To reduce the build time,
|
| 485 |
+
only files modified since the last invocation of this
|
| 486 |
+
function should be passed in the files argument."""
|
| 487 |
+
|
| 488 |
+
if not files:
|
| 489 |
+
return
|
| 490 |
+
|
| 491 |
+
# Make this class local, to delay import of 2to3
|
| 492 |
+
from lib2to3.refactor import RefactoringTool, get_fixers_from_package
|
| 493 |
+
class DistutilsRefactoringTool(RefactoringTool):
|
| 494 |
+
def log_error(self, msg, *args, **kw):
|
| 495 |
+
log.error(msg, *args)
|
| 496 |
+
|
| 497 |
+
def log_message(self, msg, *args):
|
| 498 |
+
log.info(msg, *args)
|
| 499 |
+
|
| 500 |
+
def log_debug(self, msg, *args):
|
| 501 |
+
log.debug(msg, *args)
|
| 502 |
+
|
| 503 |
+
if fixer_names is None:
|
| 504 |
+
fixer_names = get_fixers_from_package('lib2to3.fixes')
|
| 505 |
+
r = DistutilsRefactoringTool(fixer_names, options=options)
|
| 506 |
+
r.refactor(files, write=True)
|
| 507 |
+
|
| 508 |
+
def copydir_run_2to3(src, dest, template=None, fixer_names=None,
|
| 509 |
+
options=None, explicit=None):
|
| 510 |
+
"""Recursively copy a directory, only copying new and changed files,
|
| 511 |
+
running run_2to3 over all newly copied Python modules afterward.
|
| 512 |
+
|
| 513 |
+
If you give a template string, it's parsed like a MANIFEST.in.
|
| 514 |
+
"""
|
| 515 |
+
from distutils.dir_util import mkpath
|
| 516 |
+
from distutils.file_util import copy_file
|
| 517 |
+
from distutils.filelist import FileList
|
| 518 |
+
filelist = FileList()
|
| 519 |
+
curdir = os.getcwd()
|
| 520 |
+
os.chdir(src)
|
| 521 |
+
try:
|
| 522 |
+
filelist.findall()
|
| 523 |
+
finally:
|
| 524 |
+
os.chdir(curdir)
|
| 525 |
+
filelist.files[:] = filelist.allfiles
|
| 526 |
+
if template:
|
| 527 |
+
for line in template.splitlines():
|
| 528 |
+
line = line.strip()
|
| 529 |
+
if not line: continue
|
| 530 |
+
filelist.process_template_line(line)
|
| 531 |
+
copied = []
|
| 532 |
+
for filename in filelist.files:
|
| 533 |
+
outname = os.path.join(dest, filename)
|
| 534 |
+
mkpath(os.path.dirname(outname))
|
| 535 |
+
res = copy_file(os.path.join(src, filename), outname, update=1)
|
| 536 |
+
if res[1]: copied.append(outname)
|
| 537 |
+
run_2to3([fn for fn in copied if fn.lower().endswith('.py')],
|
| 538 |
+
fixer_names=fixer_names, options=options, explicit=explicit)
|
| 539 |
+
return copied
|
| 540 |
+
|
| 541 |
+
class Mixin2to3:
|
| 542 |
+
'''Mixin class for commands that run 2to3.
|
| 543 |
+
To configure 2to3, setup scripts may either change
|
| 544 |
+
the class variables, or inherit from individual commands
|
| 545 |
+
to override how 2to3 is invoked.'''
|
| 546 |
+
|
| 547 |
+
# provide list of fixers to run;
|
| 548 |
+
# defaults to all from lib2to3.fixers
|
| 549 |
+
fixer_names = None
|
| 550 |
+
|
| 551 |
+
# options dictionary
|
| 552 |
+
options = None
|
| 553 |
+
|
| 554 |
+
# list of fixers to invoke even though they are marked as explicit
|
| 555 |
+
explicit = None
|
| 556 |
+
|
| 557 |
+
def run_2to3(self, files):
|
| 558 |
+
return run_2to3(files, self.fixer_names, self.options, self.explicit)
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/version.py
ADDED
|
@@ -0,0 +1,343 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#
|
| 2 |
+
# distutils/version.py
|
| 3 |
+
#
|
| 4 |
+
# Implements multiple version numbering conventions for the
|
| 5 |
+
# Python Module Distribution Utilities.
|
| 6 |
+
#
|
| 7 |
+
# $Id$
|
| 8 |
+
#
|
| 9 |
+
|
| 10 |
+
"""Provides classes to represent module version numbers (one class for
|
| 11 |
+
each style of version numbering). There are currently two such classes
|
| 12 |
+
implemented: StrictVersion and LooseVersion.
|
| 13 |
+
|
| 14 |
+
Every version number class implements the following interface:
|
| 15 |
+
* the 'parse' method takes a string and parses it to some internal
|
| 16 |
+
representation; if the string is an invalid version number,
|
| 17 |
+
'parse' raises a ValueError exception
|
| 18 |
+
* the class constructor takes an optional string argument which,
|
| 19 |
+
if supplied, is passed to 'parse'
|
| 20 |
+
* __str__ reconstructs the string that was passed to 'parse' (or
|
| 21 |
+
an equivalent string -- ie. one that will generate an equivalent
|
| 22 |
+
version number instance)
|
| 23 |
+
* __repr__ generates Python code to recreate the version number instance
|
| 24 |
+
* _cmp compares the current instance with either another instance
|
| 25 |
+
of the same class or a string (which will be parsed to an instance
|
| 26 |
+
of the same class, thus must follow the same rules)
|
| 27 |
+
"""
|
| 28 |
+
|
| 29 |
+
import re
|
| 30 |
+
|
| 31 |
+
class Version:
|
| 32 |
+
"""Abstract base class for version numbering classes. Just provides
|
| 33 |
+
constructor (__init__) and reproducer (__repr__), because those
|
| 34 |
+
seem to be the same for all version numbering classes; and route
|
| 35 |
+
rich comparisons to _cmp.
|
| 36 |
+
"""
|
| 37 |
+
|
| 38 |
+
def __init__ (self, vstring=None):
|
| 39 |
+
if vstring:
|
| 40 |
+
self.parse(vstring)
|
| 41 |
+
|
| 42 |
+
def __repr__ (self):
|
| 43 |
+
return "%s ('%s')" % (self.__class__.__name__, str(self))
|
| 44 |
+
|
| 45 |
+
def __eq__(self, other):
|
| 46 |
+
c = self._cmp(other)
|
| 47 |
+
if c is NotImplemented:
|
| 48 |
+
return c
|
| 49 |
+
return c == 0
|
| 50 |
+
|
| 51 |
+
def __lt__(self, other):
|
| 52 |
+
c = self._cmp(other)
|
| 53 |
+
if c is NotImplemented:
|
| 54 |
+
return c
|
| 55 |
+
return c < 0
|
| 56 |
+
|
| 57 |
+
def __le__(self, other):
|
| 58 |
+
c = self._cmp(other)
|
| 59 |
+
if c is NotImplemented:
|
| 60 |
+
return c
|
| 61 |
+
return c <= 0
|
| 62 |
+
|
| 63 |
+
def __gt__(self, other):
|
| 64 |
+
c = self._cmp(other)
|
| 65 |
+
if c is NotImplemented:
|
| 66 |
+
return c
|
| 67 |
+
return c > 0
|
| 68 |
+
|
| 69 |
+
def __ge__(self, other):
|
| 70 |
+
c = self._cmp(other)
|
| 71 |
+
if c is NotImplemented:
|
| 72 |
+
return c
|
| 73 |
+
return c >= 0
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
# Interface for version-number classes -- must be implemented
|
| 77 |
+
# by the following classes (the concrete ones -- Version should
|
| 78 |
+
# be treated as an abstract class).
|
| 79 |
+
# __init__ (string) - create and take same action as 'parse'
|
| 80 |
+
# (string parameter is optional)
|
| 81 |
+
# parse (string) - convert a string representation to whatever
|
| 82 |
+
# internal representation is appropriate for
|
| 83 |
+
# this style of version numbering
|
| 84 |
+
# __str__ (self) - convert back to a string; should be very similar
|
| 85 |
+
# (if not identical to) the string supplied to parse
|
| 86 |
+
# __repr__ (self) - generate Python code to recreate
|
| 87 |
+
# the instance
|
| 88 |
+
# _cmp (self, other) - compare two version numbers ('other' may
|
| 89 |
+
# be an unparsed version string, or another
|
| 90 |
+
# instance of your version class)
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
class StrictVersion (Version):
|
| 94 |
+
|
| 95 |
+
"""Version numbering for anal retentives and software idealists.
|
| 96 |
+
Implements the standard interface for version number classes as
|
| 97 |
+
described above. A version number consists of two or three
|
| 98 |
+
dot-separated numeric components, with an optional "pre-release" tag
|
| 99 |
+
on the end. The pre-release tag consists of the letter 'a' or 'b'
|
| 100 |
+
followed by a number. If the numeric components of two version
|
| 101 |
+
numbers are equal, then one with a pre-release tag will always
|
| 102 |
+
be deemed earlier (lesser) than one without.
|
| 103 |
+
|
| 104 |
+
The following are valid version numbers (shown in the order that
|
| 105 |
+
would be obtained by sorting according to the supplied cmp function):
|
| 106 |
+
|
| 107 |
+
0.4 0.4.0 (these two are equivalent)
|
| 108 |
+
0.4.1
|
| 109 |
+
0.5a1
|
| 110 |
+
0.5b3
|
| 111 |
+
0.5
|
| 112 |
+
0.9.6
|
| 113 |
+
1.0
|
| 114 |
+
1.0.4a3
|
| 115 |
+
1.0.4b1
|
| 116 |
+
1.0.4
|
| 117 |
+
|
| 118 |
+
The following are examples of invalid version numbers:
|
| 119 |
+
|
| 120 |
+
1
|
| 121 |
+
2.7.2.2
|
| 122 |
+
1.3.a4
|
| 123 |
+
1.3pl1
|
| 124 |
+
1.3c4
|
| 125 |
+
|
| 126 |
+
The rationale for this version numbering system will be explained
|
| 127 |
+
in the distutils documentation.
|
| 128 |
+
"""
|
| 129 |
+
|
| 130 |
+
version_re = re.compile(r'^(\d+) \. (\d+) (\. (\d+))? ([ab](\d+))?$',
|
| 131 |
+
re.VERBOSE | re.ASCII)
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
def parse (self, vstring):
|
| 135 |
+
match = self.version_re.match(vstring)
|
| 136 |
+
if not match:
|
| 137 |
+
raise ValueError("invalid version number '%s'" % vstring)
|
| 138 |
+
|
| 139 |
+
(major, minor, patch, prerelease, prerelease_num) = \
|
| 140 |
+
match.group(1, 2, 4, 5, 6)
|
| 141 |
+
|
| 142 |
+
if patch:
|
| 143 |
+
self.version = tuple(map(int, [major, minor, patch]))
|
| 144 |
+
else:
|
| 145 |
+
self.version = tuple(map(int, [major, minor])) + (0,)
|
| 146 |
+
|
| 147 |
+
if prerelease:
|
| 148 |
+
self.prerelease = (prerelease[0], int(prerelease_num))
|
| 149 |
+
else:
|
| 150 |
+
self.prerelease = None
|
| 151 |
+
|
| 152 |
+
|
| 153 |
+
def __str__ (self):
|
| 154 |
+
|
| 155 |
+
if self.version[2] == 0:
|
| 156 |
+
vstring = '.'.join(map(str, self.version[0:2]))
|
| 157 |
+
else:
|
| 158 |
+
vstring = '.'.join(map(str, self.version))
|
| 159 |
+
|
| 160 |
+
if self.prerelease:
|
| 161 |
+
vstring = vstring + self.prerelease[0] + str(self.prerelease[1])
|
| 162 |
+
|
| 163 |
+
return vstring
|
| 164 |
+
|
| 165 |
+
|
| 166 |
+
def _cmp (self, other):
|
| 167 |
+
if isinstance(other, str):
|
| 168 |
+
other = StrictVersion(other)
|
| 169 |
+
|
| 170 |
+
if self.version != other.version:
|
| 171 |
+
# numeric versions don't match
|
| 172 |
+
# prerelease stuff doesn't matter
|
| 173 |
+
if self.version < other.version:
|
| 174 |
+
return -1
|
| 175 |
+
else:
|
| 176 |
+
return 1
|
| 177 |
+
|
| 178 |
+
# have to compare prerelease
|
| 179 |
+
# case 1: neither has prerelease; they're equal
|
| 180 |
+
# case 2: self has prerelease, other doesn't; other is greater
|
| 181 |
+
# case 3: self doesn't have prerelease, other does: self is greater
|
| 182 |
+
# case 4: both have prerelease: must compare them!
|
| 183 |
+
|
| 184 |
+
if (not self.prerelease and not other.prerelease):
|
| 185 |
+
return 0
|
| 186 |
+
elif (self.prerelease and not other.prerelease):
|
| 187 |
+
return -1
|
| 188 |
+
elif (not self.prerelease and other.prerelease):
|
| 189 |
+
return 1
|
| 190 |
+
elif (self.prerelease and other.prerelease):
|
| 191 |
+
if self.prerelease == other.prerelease:
|
| 192 |
+
return 0
|
| 193 |
+
elif self.prerelease < other.prerelease:
|
| 194 |
+
return -1
|
| 195 |
+
else:
|
| 196 |
+
return 1
|
| 197 |
+
else:
|
| 198 |
+
assert False, "never get here"
|
| 199 |
+
|
| 200 |
+
# end class StrictVersion
|
| 201 |
+
|
| 202 |
+
|
| 203 |
+
# The rules according to Greg Stein:
|
| 204 |
+
# 1) a version number has 1 or more numbers separated by a period or by
|
| 205 |
+
# sequences of letters. If only periods, then these are compared
|
| 206 |
+
# left-to-right to determine an ordering.
|
| 207 |
+
# 2) sequences of letters are part of the tuple for comparison and are
|
| 208 |
+
# compared lexicographically
|
| 209 |
+
# 3) recognize the numeric components may have leading zeroes
|
| 210 |
+
#
|
| 211 |
+
# The LooseVersion class below implements these rules: a version number
|
| 212 |
+
# string is split up into a tuple of integer and string components, and
|
| 213 |
+
# comparison is a simple tuple comparison. This means that version
|
| 214 |
+
# numbers behave in a predictable and obvious way, but a way that might
|
| 215 |
+
# not necessarily be how people *want* version numbers to behave. There
|
| 216 |
+
# wouldn't be a problem if people could stick to purely numeric version
|
| 217 |
+
# numbers: just split on period and compare the numbers as tuples.
|
| 218 |
+
# However, people insist on putting letters into their version numbers;
|
| 219 |
+
# the most common purpose seems to be:
|
| 220 |
+
# - indicating a "pre-release" version
|
| 221 |
+
# ('alpha', 'beta', 'a', 'b', 'pre', 'p')
|
| 222 |
+
# - indicating a post-release patch ('p', 'pl', 'patch')
|
| 223 |
+
# but of course this can't cover all version number schemes, and there's
|
| 224 |
+
# no way to know what a programmer means without asking him.
|
| 225 |
+
#
|
| 226 |
+
# The problem is what to do with letters (and other non-numeric
|
| 227 |
+
# characters) in a version number. The current implementation does the
|
| 228 |
+
# obvious and predictable thing: keep them as strings and compare
|
| 229 |
+
# lexically within a tuple comparison. This has the desired effect if
|
| 230 |
+
# an appended letter sequence implies something "post-release":
|
| 231 |
+
# eg. "0.99" < "0.99pl14" < "1.0", and "5.001" < "5.001m" < "5.002".
|
| 232 |
+
#
|
| 233 |
+
# However, if letters in a version number imply a pre-release version,
|
| 234 |
+
# the "obvious" thing isn't correct. Eg. you would expect that
|
| 235 |
+
# "1.5.1" < "1.5.2a2" < "1.5.2", but under the tuple/lexical comparison
|
| 236 |
+
# implemented here, this just isn't so.
|
| 237 |
+
#
|
| 238 |
+
# Two possible solutions come to mind. The first is to tie the
|
| 239 |
+
# comparison algorithm to a particular set of semantic rules, as has
|
| 240 |
+
# been done in the StrictVersion class above. This works great as long
|
| 241 |
+
# as everyone can go along with bondage and discipline. Hopefully a
|
| 242 |
+
# (large) subset of Python module programmers will agree that the
|
| 243 |
+
# particular flavour of bondage and discipline provided by StrictVersion
|
| 244 |
+
# provides enough benefit to be worth using, and will submit their
|
| 245 |
+
# version numbering scheme to its domination. The free-thinking
|
| 246 |
+
# anarchists in the lot will never give in, though, and something needs
|
| 247 |
+
# to be done to accommodate them.
|
| 248 |
+
#
|
| 249 |
+
# Perhaps a "moderately strict" version class could be implemented that
|
| 250 |
+
# lets almost anything slide (syntactically), and makes some heuristic
|
| 251 |
+
# assumptions about non-digits in version number strings. This could
|
| 252 |
+
# sink into special-case-hell, though; if I was as talented and
|
| 253 |
+
# idiosyncratic as Larry Wall, I'd go ahead and implement a class that
|
| 254 |
+
# somehow knows that "1.2.1" < "1.2.2a2" < "1.2.2" < "1.2.2pl3", and is
|
| 255 |
+
# just as happy dealing with things like "2g6" and "1.13++". I don't
|
| 256 |
+
# think I'm smart enough to do it right though.
|
| 257 |
+
#
|
| 258 |
+
# In any case, I've coded the test suite for this module (see
|
| 259 |
+
# ../test/test_version.py) specifically to fail on things like comparing
|
| 260 |
+
# "1.2a2" and "1.2". That's not because the *code* is doing anything
|
| 261 |
+
# wrong, it's because the simple, obvious design doesn't match my
|
| 262 |
+
# complicated, hairy expectations for real-world version numbers. It
|
| 263 |
+
# would be a snap to fix the test suite to say, "Yep, LooseVersion does
|
| 264 |
+
# the Right Thing" (ie. the code matches the conception). But I'd rather
|
| 265 |
+
# have a conception that matches common notions about version numbers.
|
| 266 |
+
|
| 267 |
+
class LooseVersion (Version):
|
| 268 |
+
|
| 269 |
+
"""Version numbering for anarchists and software realists.
|
| 270 |
+
Implements the standard interface for version number classes as
|
| 271 |
+
described above. A version number consists of a series of numbers,
|
| 272 |
+
separated by either periods or strings of letters. When comparing
|
| 273 |
+
version numbers, the numeric components will be compared
|
| 274 |
+
numerically, and the alphabetic components lexically. The following
|
| 275 |
+
are all valid version numbers, in no particular order:
|
| 276 |
+
|
| 277 |
+
1.5.1
|
| 278 |
+
1.5.2b2
|
| 279 |
+
161
|
| 280 |
+
3.10a
|
| 281 |
+
8.02
|
| 282 |
+
3.4j
|
| 283 |
+
1996.07.12
|
| 284 |
+
3.2.pl0
|
| 285 |
+
3.1.1.6
|
| 286 |
+
2g6
|
| 287 |
+
11g
|
| 288 |
+
0.960923
|
| 289 |
+
2.2beta29
|
| 290 |
+
1.13++
|
| 291 |
+
5.5.kw
|
| 292 |
+
2.0b1pl0
|
| 293 |
+
|
| 294 |
+
In fact, there is no such thing as an invalid version number under
|
| 295 |
+
this scheme; the rules for comparison are simple and predictable,
|
| 296 |
+
but may not always give the results you want (for some definition
|
| 297 |
+
of "want").
|
| 298 |
+
"""
|
| 299 |
+
|
| 300 |
+
component_re = re.compile(r'(\d+ | [a-z]+ | \.)', re.VERBOSE)
|
| 301 |
+
|
| 302 |
+
def __init__ (self, vstring=None):
|
| 303 |
+
if vstring:
|
| 304 |
+
self.parse(vstring)
|
| 305 |
+
|
| 306 |
+
|
| 307 |
+
def parse (self, vstring):
|
| 308 |
+
# I've given up on thinking I can reconstruct the version string
|
| 309 |
+
# from the parsed tuple -- so I just store the string here for
|
| 310 |
+
# use by __str__
|
| 311 |
+
self.vstring = vstring
|
| 312 |
+
components = [x for x in self.component_re.split(vstring)
|
| 313 |
+
if x and x != '.']
|
| 314 |
+
for i, obj in enumerate(components):
|
| 315 |
+
try:
|
| 316 |
+
components[i] = int(obj)
|
| 317 |
+
except ValueError:
|
| 318 |
+
pass
|
| 319 |
+
|
| 320 |
+
self.version = components
|
| 321 |
+
|
| 322 |
+
|
| 323 |
+
def __str__ (self):
|
| 324 |
+
return self.vstring
|
| 325 |
+
|
| 326 |
+
|
| 327 |
+
def __repr__ (self):
|
| 328 |
+
return "LooseVersion ('%s')" % str(self)
|
| 329 |
+
|
| 330 |
+
|
| 331 |
+
def _cmp (self, other):
|
| 332 |
+
if isinstance(other, str):
|
| 333 |
+
other = LooseVersion(other)
|
| 334 |
+
|
| 335 |
+
if self.version == other.version:
|
| 336 |
+
return 0
|
| 337 |
+
if self.version < other.version:
|
| 338 |
+
return -1
|
| 339 |
+
if self.version > other.version:
|
| 340 |
+
return 1
|
| 341 |
+
|
| 342 |
+
|
| 343 |
+
# end class LooseVersion
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/distutils/versionpredicate.py
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Module for parsing and testing package version predicate strings.
|
| 2 |
+
"""
|
| 3 |
+
import re
|
| 4 |
+
import distutils.version
|
| 5 |
+
import operator
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
re_validPackage = re.compile(r"(?i)^\s*([a-z_]\w*(?:\.[a-z_]\w*)*)(.*)",
|
| 9 |
+
re.ASCII)
|
| 10 |
+
# (package) (rest)
|
| 11 |
+
|
| 12 |
+
re_paren = re.compile(r"^\s*\((.*)\)\s*$") # (list) inside of parentheses
|
| 13 |
+
re_splitComparison = re.compile(r"^\s*(<=|>=|<|>|!=|==)\s*([^\s,]+)\s*$")
|
| 14 |
+
# (comp) (version)
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
def splitUp(pred):
|
| 18 |
+
"""Parse a single version comparison.
|
| 19 |
+
|
| 20 |
+
Return (comparison string, StrictVersion)
|
| 21 |
+
"""
|
| 22 |
+
res = re_splitComparison.match(pred)
|
| 23 |
+
if not res:
|
| 24 |
+
raise ValueError("bad package restriction syntax: %r" % pred)
|
| 25 |
+
comp, verStr = res.groups()
|
| 26 |
+
return (comp, distutils.version.StrictVersion(verStr))
|
| 27 |
+
|
| 28 |
+
compmap = {"<": operator.lt, "<=": operator.le, "==": operator.eq,
|
| 29 |
+
">": operator.gt, ">=": operator.ge, "!=": operator.ne}
|
| 30 |
+
|
| 31 |
+
class VersionPredicate:
|
| 32 |
+
"""Parse and test package version predicates.
|
| 33 |
+
|
| 34 |
+
>>> v = VersionPredicate('pyepat.abc (>1.0, <3333.3a1, !=1555.1b3)')
|
| 35 |
+
|
| 36 |
+
The `name` attribute provides the full dotted name that is given::
|
| 37 |
+
|
| 38 |
+
>>> v.name
|
| 39 |
+
'pyepat.abc'
|
| 40 |
+
|
| 41 |
+
The str() of a `VersionPredicate` provides a normalized
|
| 42 |
+
human-readable version of the expression::
|
| 43 |
+
|
| 44 |
+
>>> print(v)
|
| 45 |
+
pyepat.abc (> 1.0, < 3333.3a1, != 1555.1b3)
|
| 46 |
+
|
| 47 |
+
The `satisfied_by()` method can be used to determine with a given
|
| 48 |
+
version number is included in the set described by the version
|
| 49 |
+
restrictions::
|
| 50 |
+
|
| 51 |
+
>>> v.satisfied_by('1.1')
|
| 52 |
+
True
|
| 53 |
+
>>> v.satisfied_by('1.4')
|
| 54 |
+
True
|
| 55 |
+
>>> v.satisfied_by('1.0')
|
| 56 |
+
False
|
| 57 |
+
>>> v.satisfied_by('4444.4')
|
| 58 |
+
False
|
| 59 |
+
>>> v.satisfied_by('1555.1b3')
|
| 60 |
+
False
|
| 61 |
+
|
| 62 |
+
`VersionPredicate` is flexible in accepting extra whitespace::
|
| 63 |
+
|
| 64 |
+
>>> v = VersionPredicate(' pat( == 0.1 ) ')
|
| 65 |
+
>>> v.name
|
| 66 |
+
'pat'
|
| 67 |
+
>>> v.satisfied_by('0.1')
|
| 68 |
+
True
|
| 69 |
+
>>> v.satisfied_by('0.2')
|
| 70 |
+
False
|
| 71 |
+
|
| 72 |
+
If any version numbers passed in do not conform to the
|
| 73 |
+
restrictions of `StrictVersion`, a `ValueError` is raised::
|
| 74 |
+
|
| 75 |
+
>>> v = VersionPredicate('p1.p2.p3.p4(>=1.0, <=1.3a1, !=1.2zb3)')
|
| 76 |
+
Traceback (most recent call last):
|
| 77 |
+
...
|
| 78 |
+
ValueError: invalid version number '1.2zb3'
|
| 79 |
+
|
| 80 |
+
It the module or package name given does not conform to what's
|
| 81 |
+
allowed as a legal module or package name, `ValueError` is
|
| 82 |
+
raised::
|
| 83 |
+
|
| 84 |
+
>>> v = VersionPredicate('foo-bar')
|
| 85 |
+
Traceback (most recent call last):
|
| 86 |
+
...
|
| 87 |
+
ValueError: expected parenthesized list: '-bar'
|
| 88 |
+
|
| 89 |
+
>>> v = VersionPredicate('foo bar (12.21)')
|
| 90 |
+
Traceback (most recent call last):
|
| 91 |
+
...
|
| 92 |
+
ValueError: expected parenthesized list: 'bar (12.21)'
|
| 93 |
+
|
| 94 |
+
"""
|
| 95 |
+
|
| 96 |
+
def __init__(self, versionPredicateStr):
|
| 97 |
+
"""Parse a version predicate string.
|
| 98 |
+
"""
|
| 99 |
+
# Fields:
|
| 100 |
+
# name: package name
|
| 101 |
+
# pred: list of (comparison string, StrictVersion)
|
| 102 |
+
|
| 103 |
+
versionPredicateStr = versionPredicateStr.strip()
|
| 104 |
+
if not versionPredicateStr:
|
| 105 |
+
raise ValueError("empty package restriction")
|
| 106 |
+
match = re_validPackage.match(versionPredicateStr)
|
| 107 |
+
if not match:
|
| 108 |
+
raise ValueError("bad package name in %r" % versionPredicateStr)
|
| 109 |
+
self.name, paren = match.groups()
|
| 110 |
+
paren = paren.strip()
|
| 111 |
+
if paren:
|
| 112 |
+
match = re_paren.match(paren)
|
| 113 |
+
if not match:
|
| 114 |
+
raise ValueError("expected parenthesized list: %r" % paren)
|
| 115 |
+
str = match.groups()[0]
|
| 116 |
+
self.pred = [splitUp(aPred) for aPred in str.split(",")]
|
| 117 |
+
if not self.pred:
|
| 118 |
+
raise ValueError("empty parenthesized list in %r"
|
| 119 |
+
% versionPredicateStr)
|
| 120 |
+
else:
|
| 121 |
+
self.pred = []
|
| 122 |
+
|
| 123 |
+
def __str__(self):
|
| 124 |
+
if self.pred:
|
| 125 |
+
seq = [cond + " " + str(ver) for cond, ver in self.pred]
|
| 126 |
+
return self.name + " (" + ", ".join(seq) + ")"
|
| 127 |
+
else:
|
| 128 |
+
return self.name
|
| 129 |
+
|
| 130 |
+
def satisfied_by(self, version):
|
| 131 |
+
"""True if version is compatible with all the predicates in self.
|
| 132 |
+
The parameter version must be acceptable to the StrictVersion
|
| 133 |
+
constructor. It may be either a string or StrictVersion.
|
| 134 |
+
"""
|
| 135 |
+
for cond, ver in self.pred:
|
| 136 |
+
if not compmap[cond](version, ver):
|
| 137 |
+
return False
|
| 138 |
+
return True
|
| 139 |
+
|
| 140 |
+
|
| 141 |
+
_provision_rx = None
|
| 142 |
+
|
| 143 |
+
def split_provision(value):
|
| 144 |
+
"""Return the name and optional version number of a provision.
|
| 145 |
+
|
| 146 |
+
The version number, if given, will be returned as a `StrictVersion`
|
| 147 |
+
instance, otherwise it will be `None`.
|
| 148 |
+
|
| 149 |
+
>>> split_provision('mypkg')
|
| 150 |
+
('mypkg', None)
|
| 151 |
+
>>> split_provision(' mypkg( 1.2 ) ')
|
| 152 |
+
('mypkg', StrictVersion ('1.2'))
|
| 153 |
+
"""
|
| 154 |
+
global _provision_rx
|
| 155 |
+
if _provision_rx is None:
|
| 156 |
+
_provision_rx = re.compile(
|
| 157 |
+
r"([a-zA-Z_]\w*(?:\.[a-zA-Z_]\w*)*)(?:\s*\(\s*([^)\s]+)\s*\))?$",
|
| 158 |
+
re.ASCII)
|
| 159 |
+
value = value.strip()
|
| 160 |
+
m = _provision_rx.match(value)
|
| 161 |
+
if not m:
|
| 162 |
+
raise ValueError("illegal provides specification: %r" % value)
|
| 163 |
+
ver = m.group(2) or None
|
| 164 |
+
if ver:
|
| 165 |
+
ver = distutils.version.StrictVersion(ver)
|
| 166 |
+
return m.group(1), ver
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/encodings/__pycache__/iso8859_13.cpython-38.pyc
ADDED
|
Binary file (2.42 kB). View file
|
|
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/encodings/__pycache__/iso8859_9.cpython-38.pyc
ADDED
|
Binary file (2.42 kB). View file
|
|
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/encodings/__pycache__/mbcs.cpython-38.pyc
ADDED
|
Binary file (1.71 kB). View file
|
|
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/encodings/__pycache__/ptcp154.cpython-38.pyc
ADDED
|
Binary file (2.54 kB). View file
|
|
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/http/__pycache__/__init__.cpython-38.pyc
ADDED
|
Binary file (6.06 kB). View file
|
|
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/http/__pycache__/client.cpython-38.pyc
ADDED
|
Binary file (34.9 kB). View file
|
|
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/http/__pycache__/cookiejar.cpython-38.pyc
ADDED
|
Binary file (53.6 kB). View file
|
|
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/http/__pycache__/cookies.cpython-38.pyc
ADDED
|
Binary file (15.3 kB). View file
|
|
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/http/__pycache__/server.cpython-38.pyc
ADDED
|
Binary file (34.9 kB). View file
|
|
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/CREDITS.txt
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Guido van Rossum, as well as being the creator of the Python language, is the
|
| 2 |
+
original creator of IDLE. Other contributors prior to Version 0.8 include
|
| 3 |
+
Mark Hammond, Jeremy Hylton, Tim Peters, and Moshe Zadka.
|
| 4 |
+
|
| 5 |
+
IDLE's recent development was carried out in the SF IDLEfork project. The
|
| 6 |
+
objective was to develop a version of IDLE which had an execution environment
|
| 7 |
+
which could be initialized prior to each run of user code.
|
| 8 |
+
|
| 9 |
+
The IDLEfork project was initiated by David Scherer, with some help from Peter
|
| 10 |
+
Schneider-Kamp and Nicholas Riley. David wrote the first version of the RPC
|
| 11 |
+
code and designed a fast turn-around environment for VPython. Guido developed
|
| 12 |
+
the RPC code and Remote Debugger currently integrated in IDLE. Bruce Sherwood
|
| 13 |
+
contributed considerable time testing and suggesting improvements.
|
| 14 |
+
|
| 15 |
+
Besides David and Guido, the main developers who were active on IDLEfork
|
| 16 |
+
are Stephen M. Gava, who implemented the configuration GUI, the new
|
| 17 |
+
configuration system, and the About dialog, and Kurt B. Kaiser, who completed
|
| 18 |
+
the integration of the RPC and remote debugger, implemented the threaded
|
| 19 |
+
subprocess, and made a number of usability enhancements.
|
| 20 |
+
|
| 21 |
+
Other contributors include Raymond Hettinger, Tony Lownds (Mac integration),
|
| 22 |
+
Neal Norwitz (code check and clean-up), Ronald Oussoren (Mac integration),
|
| 23 |
+
Noam Raphael (Code Context, Call Tips, many other patches), and Chui Tey (RPC
|
| 24 |
+
integration, debugger integration and persistent breakpoints).
|
| 25 |
+
|
| 26 |
+
Scott David Daniels, Tal Einat, Hernan Foffani, Christos Georgiou,
|
| 27 |
+
Jim Jewett, Martin v. Löwis, Jason Orendorff, Guilherme Polo, Josh Robb,
|
| 28 |
+
Nigel Rowe, Bruce Sherwood, Jeff Shute, and Weeble have submitted useful
|
| 29 |
+
patches. Thanks, guys!
|
| 30 |
+
|
| 31 |
+
For additional details refer to NEWS.txt and Changelog.
|
| 32 |
+
|
| 33 |
+
Please contact the IDLE maintainer (kbk@shore.net) to have yourself included
|
| 34 |
+
here if you are one of those we missed!
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/NEWS.txt
ADDED
|
@@ -0,0 +1,1256 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
What's New in IDLE 3.8.9
|
| 2 |
+
Released on 2021-05-03?
|
| 3 |
+
=========================
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
bpo-43283: Document why printing to IDLE's Shell is often slower than
|
| 7 |
+
printing to a system terminal and that it can be made faster by
|
| 8 |
+
pre-formatting a single string before printing.
|
| 9 |
+
|
| 10 |
+
What's New in IDLE 3.8.8
|
| 11 |
+
Released on 2021-02-19
|
| 12 |
+
======================================
|
| 13 |
+
|
| 14 |
+
bpo-23544: Disable Debug=>Stack Viewer when user code is running or
|
| 15 |
+
Debugger is active, to prevent hang or crash. Patch by Zackery Spytz.
|
| 16 |
+
|
| 17 |
+
bpo-43008: Make IDLE invoke :func:`sys.excepthook` in normal,
|
| 18 |
+
2-process mode. Patch by Ken Hilton.
|
| 19 |
+
|
| 20 |
+
bpo-33065: Fix problem debugging user classes with __repr__ method.
|
| 21 |
+
|
| 22 |
+
bpo-32631: Finish zzdummy example extension module: make menu entries
|
| 23 |
+
work; add docstrings and tests with 100% coverage.
|
| 24 |
+
|
| 25 |
+
bpo-42508: Keep IDLE running on macOS. Remove obsolete workaround
|
| 26 |
+
that prevented running files with shortcuts when using new universal2
|
| 27 |
+
installers built on macOS 11.
|
| 28 |
+
|
| 29 |
+
What's New in IDLE 3.8.7
|
| 30 |
+
Released on 2020-12-27
|
| 31 |
+
======================================
|
| 32 |
+
|
| 33 |
+
bpo-42426: Fix reporting offset of the RE error in searchengine.
|
| 34 |
+
|
| 35 |
+
bpo-42416: Get docstrings for IDLE calltips more often
|
| 36 |
+
by using inspect.getdoc.
|
| 37 |
+
|
| 38 |
+
bpo-33987: Mostly finish using ttk widgets, mainly for editor,
|
| 39 |
+
settings, and searches. Some patches by Mark Roseman.
|
| 40 |
+
|
| 41 |
+
bpo-41775: Make 'IDLE Shell' the shell title.
|
| 42 |
+
|
| 43 |
+
bpo-35764: Rewrite the Calltips doc section.
|
| 44 |
+
|
| 45 |
+
bpo-40181: In calltips, stop reminding that '/' marks the end of
|
| 46 |
+
positional-only arguments.
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
What's New in IDLE 3.8.6
|
| 50 |
+
Released on 2020-09-??
|
| 51 |
+
======================================
|
| 52 |
+
|
| 53 |
+
bpo-41468: Improve IDLE run crash error message (which users should
|
| 54 |
+
never see).
|
| 55 |
+
|
| 56 |
+
bpo-41373: Save files loaded with no line ending, as when blank, or
|
| 57 |
+
different line endings, by setting its line ending to the system
|
| 58 |
+
default. Fix regression in 3.8.4 and 3.9.0b4.
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
What's New in IDLE 3.8.5
|
| 62 |
+
Released on 2020-07-20
|
| 63 |
+
======================================
|
| 64 |
+
|
| 65 |
+
bpo-41300: Save files with non-ascii chars. Fix regression in
|
| 66 |
+
3.9.0b4 and 3.8.4.
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
What's New in IDLE 3.8.4
|
| 70 |
+
Released on 2020-06-30
|
| 71 |
+
======================================
|
| 72 |
+
|
| 73 |
+
bpo-37765: Add keywords to module name completion list. Rewrite
|
| 74 |
+
Completions section of IDLE doc.
|
| 75 |
+
|
| 76 |
+
bpo-41152: The encoding of ``stdin``, ``stdout`` and ``stderr`` in IDLE
|
| 77 |
+
is now always UTF-8.
|
| 78 |
+
|
| 79 |
+
bpo-41144: Make Open Module open a special module such as os.path.
|
| 80 |
+
|
| 81 |
+
bpo-40723: Make test_idle pass when run after import.
|
| 82 |
+
Patch by Florian Dahlitz.
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
What's New in IDLE 3.8.3
|
| 86 |
+
Released on 2020-05-13
|
| 87 |
+
======================================
|
| 88 |
+
|
| 89 |
+
bpo-38689: IDLE will no longer freeze when inspect.signature fails
|
| 90 |
+
when fetching a calltip.
|
| 91 |
+
|
| 92 |
+
bpo-27115: For 'Go to Line', use a Query entry box subclass with
|
| 93 |
+
IDLE standard behavior and improved error checking.
|
| 94 |
+
|
| 95 |
+
bpo-39885: When a context menu is invoked by right-clicking outside
|
| 96 |
+
of a selection, clear the selection and move the cursor. Cut and
|
| 97 |
+
Copy require that the click be within the selection.
|
| 98 |
+
|
| 99 |
+
bpo-39852: Edit "Go to line" now clears any selection, preventing
|
| 100 |
+
accidental deletion. It also updates Ln and Col on the status bar.
|
| 101 |
+
|
| 102 |
+
bpo-39781: Selecting code context lines no longer causes a jump.
|
| 103 |
+
|
| 104 |
+
bpo-39663: Add tests for pyparse find_good_parse_start().
|
| 105 |
+
|
| 106 |
+
|
| 107 |
+
What's New in IDLE 3.8.2
|
| 108 |
+
Released on 2020-02-17
|
| 109 |
+
======================================
|
| 110 |
+
|
| 111 |
+
bpo-39600: Remove duplicate font names from configuration list.
|
| 112 |
+
|
| 113 |
+
bpo-38792: Close a shell calltip if a :exc:`KeyboardInterrupt`
|
| 114 |
+
or shell restart occurs. Patch by Zackery Spytz.
|
| 115 |
+
|
| 116 |
+
bpo-30780: Add remaining configdialog tests for buttons and
|
| 117 |
+
highlights and keys tabs.
|
| 118 |
+
|
| 119 |
+
bpo-39388: Settings dialog Cancel button cancels pending changes.
|
| 120 |
+
|
| 121 |
+
bpo-39050: Settings dialog Help button again displays help text.
|
| 122 |
+
|
| 123 |
+
bpo-32989: Add tests for editor newline_and_indent_event method.
|
| 124 |
+
Remove unneeded arguments and dead code from pyparse
|
| 125 |
+
find_good_parse_start method.
|
| 126 |
+
|
| 127 |
+
|
| 128 |
+
What's New in IDLE 3.8.1
|
| 129 |
+
Released on 2019-12-18
|
| 130 |
+
======================================
|
| 131 |
+
|
| 132 |
+
bpo-38943: Fix autocomplete windows not always appearing on some
|
| 133 |
+
systems. Patch by Johnny Najera.
|
| 134 |
+
|
| 135 |
+
bpo-38944: Escape key now closes IDLE completion windows. Patch by
|
| 136 |
+
Johnny Najera.
|
| 137 |
+
|
| 138 |
+
bpo-38862: 'Strip Trailing Whitespace' on the Format menu removes extra
|
| 139 |
+
newlines at the end of non-shell files.
|
| 140 |
+
|
| 141 |
+
bpo-38636: Fix IDLE Format menu tab toggle and file indent width. These
|
| 142 |
+
functions (default shortcuts Alt-T and Alt-U) were mistakenly disabled
|
| 143 |
+
in 3.7.5 and 3.8.0.
|
| 144 |
+
|
| 145 |
+
bpo-4630: Add an option to toggle IDLE's cursor blink for shell,
|
| 146 |
+
editor, and output windows. See Settings, General, Window Preferences,
|
| 147 |
+
Cursor Blink. Patch by Zackery Spytz.
|
| 148 |
+
|
| 149 |
+
bpo-26353: Stop adding newline when saving an IDLE shell window.
|
| 150 |
+
|
| 151 |
+
bpo-38598: Do not try to compile IDLE shell or output windows.
|
| 152 |
+
|
| 153 |
+
|
| 154 |
+
What's New in IDLE 3.8.0 (since 3.7.0)
|
| 155 |
+
Released on 2019-10-14
|
| 156 |
+
======================================
|
| 157 |
+
|
| 158 |
+
bpo-36698: IDLE no longer fails when writing non-encodable characters
|
| 159 |
+
to stderr. It now escapes them with a backslash, like the regular
|
| 160 |
+
Python interpreter. Add an errors field to the standard streams.
|
| 161 |
+
|
| 162 |
+
bpo-13153: Improve tkinter's handing of non-BMP (astral) unicode
|
| 163 |
+
characters, such as 'rocket \U0001f680'. Whether a proper glyph or
|
| 164 |
+
replacement char is displayed depends on the OS and font. For IDLE,
|
| 165 |
+
astral chars in code interfere with editing.
|
| 166 |
+
|
| 167 |
+
bpo-35379: When exiting IDLE, catch any AttributeError. One happens
|
| 168 |
+
when EditorWindow.close is called twice. Printing a traceback, when
|
| 169 |
+
IDLE is run from a terminal, is useless and annoying.
|
| 170 |
+
|
| 171 |
+
bpo-38183: To avoid test issues, test_idle ignores the user config
|
| 172 |
+
directory. It no longer tries to create or access .idlerc or any files
|
| 173 |
+
within. Users must run IDLE to discover problems with saving settings.
|
| 174 |
+
|
| 175 |
+
bpo-38077: IDLE no longer adds 'argv' to the user namespace when
|
| 176 |
+
initializing it. This bug only affected 3.7.4 and 3.8.0b2 to 3.8.0b4.
|
| 177 |
+
|
| 178 |
+
bpo-38401: Shell restart lines now fill the window width, always start
|
| 179 |
+
with '=', and avoid wrapping unnecessarily. The line will still wrap
|
| 180 |
+
if the included file name is long relative to the width.
|
| 181 |
+
|
| 182 |
+
bpo-37092: Add mousewheel scrolling for IDLE module, path, and stack
|
| 183 |
+
browsers. Patch by George Zhang.
|
| 184 |
+
|
| 185 |
+
bpo-35771: To avoid occasional spurious test_idle failures on slower
|
| 186 |
+
machines, increase the ``hover_delay`` in test_tooltip.
|
| 187 |
+
|
| 188 |
+
bpo-37824: Properly handle user input warnings in IDLE shell.
|
| 189 |
+
Cease turning SyntaxWarnings into SyntaxErrors.
|
| 190 |
+
|
| 191 |
+
bpo-37929: IDLE Settings dialog now closes properly when there is no
|
| 192 |
+
shell window.
|
| 193 |
+
|
| 194 |
+
bpo-37849: Fix completions list appearing too high or low when shown
|
| 195 |
+
above the current line.
|
| 196 |
+
|
| 197 |
+
bpo-36419: Refactor autocompete and improve testing.
|
| 198 |
+
|
| 199 |
+
bpo-37748: Reorder the Run menu. Put the most common choice,
|
| 200 |
+
Run Module, at the top.
|
| 201 |
+
|
| 202 |
+
bpo-37692: Improve highlight config sample with example shell
|
| 203 |
+
interaction and better labels for shell elements.
|
| 204 |
+
|
| 205 |
+
bpo-37628: Settings dialog no longer expands with font size.
|
| 206 |
+
The font and highlight sample boxes gain scrollbars instead.
|
| 207 |
+
|
| 208 |
+
bpo-17535: Add optional line numbers for IDLE editor windows.
|
| 209 |
+
|
| 210 |
+
bpo-37627: Initialize the Customize Run dialog with the command line
|
| 211 |
+
arguments most recently entered before. The user can optionally edit
|
| 212 |
+
before submitting them.
|
| 213 |
+
|
| 214 |
+
bpo-33610: Code context always shows the correct context when toggled on.
|
| 215 |
+
|
| 216 |
+
bpo-36390: Gather Format menu functions into format.py. Combine
|
| 217 |
+
paragraph.py, rstrip.py, and format methods from editor.py.
|
| 218 |
+
|
| 219 |
+
bpo-37530: Optimize code context to reduce unneeded background activity.
|
| 220 |
+
Font and highlight changes now occur along with text changes instead
|
| 221 |
+
of after a random delay.
|
| 222 |
+
|
| 223 |
+
bpo-27452: Cleanup config.py by inlining RemoveFile and simplifying
|
| 224 |
+
the handling of __file__ in CreateConfigHandlers/
|
| 225 |
+
|
| 226 |
+
bpo-26806: To compensate for stack frames added by IDLE and avoid
|
| 227 |
+
possible problems with low recursion limits, add 30 to limits in the
|
| 228 |
+
user code execution process. Subtract 30 when reporting recursion
|
| 229 |
+
limits to make this addition mostly transparent.
|
| 230 |
+
|
| 231 |
+
bpo-37325: Fix tab focus traversal order for help source and custom
|
| 232 |
+
run dialogs.
|
| 233 |
+
|
| 234 |
+
bpo-37321: Both subprocess connection error messages now refer to
|
| 235 |
+
the 'Startup failure' section of the IDLE doc.
|
| 236 |
+
|
| 237 |
+
bpo-37177: Properly attach search dialogs to their main window so
|
| 238 |
+
that they behave like other dialogs and do not get hidden behind
|
| 239 |
+
their main window.
|
| 240 |
+
|
| 241 |
+
bpo-37039: Adjust "Zoom Height" to individual screens by momentarily
|
| 242 |
+
maximizing the window on first use with a particular screen. Changing
|
| 243 |
+
screen settings may invalidate the saved height. While a window is
|
| 244 |
+
maximized, "Zoom Height" has no effect.
|
| 245 |
+
|
| 246 |
+
bpo-35763: Make calltip reminder about '/' meaning positional-only less
|
| 247 |
+
obtrusive by only adding it when there is room on the first line.
|
| 248 |
+
|
| 249 |
+
bpo-5680: Add 'Run Customized' to the Run menu to run a module with
|
| 250 |
+
customized settings. Any command line arguments entered are added
|
| 251 |
+
to sys.argv. One can suppress the normal Shell main module restart.
|
| 252 |
+
|
| 253 |
+
bpo-35610: Replace now redundant editor.context_use_ps1 with
|
| 254 |
+
.prompt_last_line. This finishes change started in bpo-31858.
|
| 255 |
+
|
| 256 |
+
bpo-32411: Stop sorting dict created with desired line order.
|
| 257 |
+
|
| 258 |
+
bpo-37038: Make idlelib.run runnable; add test clause.
|
| 259 |
+
|
| 260 |
+
bpo-36958: Print any argument other than None or int passed to
|
| 261 |
+
SystemExit or sys.exit().
|
| 262 |
+
|
| 263 |
+
bpo-36807: When saving a file, call file.flush() and os.fsync()
|
| 264 |
+
so bits are flushed to e.g. a USB drive.
|
| 265 |
+
|
| 266 |
+
bpo-36429: Fix starting IDLE with pyshell.
|
| 267 |
+
Add idlelib.pyshell alias at top; remove pyshell alias at bottom.
|
| 268 |
+
Remove obsolete __name__=='__main__' command.
|
| 269 |
+
|
| 270 |
+
bpo-30348: Increase test coverage of idlelib.autocomplete by 30%.
|
| 271 |
+
Patch by Louie Lu.
|
| 272 |
+
|
| 273 |
+
bpo-23205: Add tests and refactor grep's findfiles.
|
| 274 |
+
|
| 275 |
+
bpo-36405: Use dict unpacking in idlelib.
|
| 276 |
+
|
| 277 |
+
bpo-36396: Remove fgBg param of idlelib.config.GetHighlight().
|
| 278 |
+
This param was only used twice and changed the return type.
|
| 279 |
+
|
| 280 |
+
bpo-23216: IDLE: Add docstrings to search modules.
|
| 281 |
+
|
| 282 |
+
bpo-36176: Fix IDLE autocomplete & calltip popup colors.
|
| 283 |
+
Prevent conflicts with Linux dark themes
|
| 284 |
+
(and slightly darken calltip background).
|
| 285 |
+
|
| 286 |
+
bpo-36152: Remove colorizer.ColorDelegator.close_when_done and the
|
| 287 |
+
corresponding argument of .close(). In IDLE, both have always been
|
| 288 |
+
None or False since 2007.
|
| 289 |
+
|
| 290 |
+
bpo-36096: Make colorizer state variables instance-only.
|
| 291 |
+
|
| 292 |
+
bpo-32129: Avoid blurry IDLE application icon on macOS with Tk 8.6.
|
| 293 |
+
Patch by Kevin Walzer.
|
| 294 |
+
|
| 295 |
+
bpo-24310: Document settings dialog font tab sample.
|
| 296 |
+
|
| 297 |
+
bpo-35689: Add docstrings and tests for colorizer.
|
| 298 |
+
|
| 299 |
+
bpo-35833: Revise IDLE doc for control codes sent to Shell.
|
| 300 |
+
Add a code example block.
|
| 301 |
+
|
| 302 |
+
bpo-35770: IDLE macosx deletes Options => Configure IDLE.
|
| 303 |
+
It previously deleted Window => Zoom Height by mistake.
|
| 304 |
+
(Zoom Height is now on the Options menu). On Mac, the settings
|
| 305 |
+
dialog is accessed via Preferences on the IDLE menu.
|
| 306 |
+
|
| 307 |
+
bpo-35769: Change new file name from 'Untitled' to 'untitled'.
|
| 308 |
+
|
| 309 |
+
bpo-35660: Fix imports in window module.
|
| 310 |
+
|
| 311 |
+
bpo-35641: Properly format calltip for function without docstring.
|
| 312 |
+
|
| 313 |
+
bpo-33987: Use ttk Frame for ttk widgets.
|
| 314 |
+
|
| 315 |
+
bpo-34055: Fix erroneous 'smart' indents and newlines in IDLE Shell.
|
| 316 |
+
|
| 317 |
+
bpo-28097: Add Previous/Next History entries to Shell menu.
|
| 318 |
+
|
| 319 |
+
bpo-35591: Find Selection now works when selection not found.
|
| 320 |
+
|
| 321 |
+
bpo-35598: Update config_key: use PEP 8 names and ttk widgets,
|
| 322 |
+
make some objects global, and add tests.
|
| 323 |
+
|
| 324 |
+
bpo-35196: Speed up squeezer line counting.
|
| 325 |
+
|
| 326 |
+
bpo-35208: Squeezer now counts wrapped lines before newlines.
|
| 327 |
+
|
| 328 |
+
bpo-35555: Gray out Code Context menu entry when it's not applicable.
|
| 329 |
+
|
| 330 |
+
bpo-22703: Improve the Code Context and Zoom Height menu labels.
|
| 331 |
+
The Code Context menu label now toggles between Show/Hide Code Context.
|
| 332 |
+
The Zoom Height menu now toggles between Zoom/Restore Height.
|
| 333 |
+
Zoom Height has moved from the Window menu to the Options menu.
|
| 334 |
+
|
| 335 |
+
bpo-35521: Document the editor code context feature.
|
| 336 |
+
Add some internal references within the IDLE doc.
|
| 337 |
+
|
| 338 |
+
bpo-34864: When starting IDLE on MacOS, warn if the system setting
|
| 339 |
+
"Prefer tabs when opening documents" is "Always". As previous
|
| 340 |
+
documented for this issue, running IDLE with this setting causes
|
| 341 |
+
problems. If the setting is changed while IDLE is running,
|
| 342 |
+
there will be no warning until IDLE is restarted.
|
| 343 |
+
|
| 344 |
+
bpo-35213: Where appropriate, use 'macOS' in idlelib.
|
| 345 |
+
|
| 346 |
+
bpo-34864: Document two IDLE on MacOS issues. The System Preferences
|
| 347 |
+
Dock "prefer tabs always" setting disables some IDLE features.
|
| 348 |
+
Menus are a bit different than as described for Windows and Linux.
|
| 349 |
+
|
| 350 |
+
bpo-35202: Remove unused imports in idlelib.
|
| 351 |
+
|
| 352 |
+
bpo-33000: Document that IDLE's shell has no line limit.
|
| 353 |
+
A program that runs indefinitely can overfill memory.
|
| 354 |
+
|
| 355 |
+
bpo-23220: Explain how IDLE's Shell displays output.
|
| 356 |
+
Add new subsection "User output in Shell".
|
| 357 |
+
|
| 358 |
+
bpo-35099: Improve the doc about IDLE running user code.
|
| 359 |
+
"IDLE -- console differences" is renamed "Running user code".
|
| 360 |
+
It mostly covers the implications of using custom sys.stdxxx objects.
|
| 361 |
+
|
| 362 |
+
bpo-35097: Add IDLE doc subsection explaining editor windows.
|
| 363 |
+
Topics include opening, title and status bars, .py* extension, and running.
|
| 364 |
+
|
| 365 |
+
Issue 35093: Document the IDLE document viewer in the IDLE doc.
|
| 366 |
+
Add a paragraph in "Help and preferences", "Help sources" subsection.
|
| 367 |
+
|
| 368 |
+
bpo-1529353: Explain Shell text squeezing in the IDLE doc.
|
| 369 |
+
|
| 370 |
+
bpo-35088: Update idlelib.help.copy_string docstring.
|
| 371 |
+
We now use git and backporting instead of hg and forward merging.
|
| 372 |
+
|
| 373 |
+
bpo-35087: Update idlelib help files for the current doc build.
|
| 374 |
+
The main change is the elimination of chapter-section numbers.
|
| 375 |
+
|
| 376 |
+
bpo-1529353: Output over N lines (50 by default) is squeezed down to a button.
|
| 377 |
+
N can be changed in the PyShell section of the General page of the
|
| 378 |
+
Settings dialog. Fewer, but possibly extra long, lines can be squeezed by
|
| 379 |
+
right clicking on the output. Squeezed output can be expanded in place
|
| 380 |
+
by double-clicking the button or into the clipboard or a separate window
|
| 381 |
+
by right-clicking the button.
|
| 382 |
+
|
| 383 |
+
bpo-34548: Use configured color theme for read-only text views.
|
| 384 |
+
|
| 385 |
+
bpo-33839: Refactor ToolTip and CallTip classes; add documentation
|
| 386 |
+
and tests.
|
| 387 |
+
|
| 388 |
+
bpo-34047: Fix mouse wheel scrolling direction on macOS.
|
| 389 |
+
|
| 390 |
+
bpo-34275: Make calltips always visible on Mac.
|
| 391 |
+
Patch by Kevin Walzer.
|
| 392 |
+
|
| 393 |
+
bpo-34120: Fix freezing after closing some dialogs on Mac.
|
| 394 |
+
This is one of multiple regressions from using newer tcl/tk.
|
| 395 |
+
|
| 396 |
+
bpo-33975: Avoid small type when running htests.
|
| 397 |
+
Since part of the purpose of human-viewed tests is to determine that
|
| 398 |
+
widgets look right, it is important that they look the same for
|
| 399 |
+
testing as when running IDLE.
|
| 400 |
+
|
| 401 |
+
bpo-33905: Add test for idlelib.stackview.StackBrowser.
|
| 402 |
+
|
| 403 |
+
bpo-33924: Change mainmenu.menudefs key 'windows' to 'window'.
|
| 404 |
+
Every other menudef key is the lowercase version of the
|
| 405 |
+
corresponding main menu entry (in this case, 'Window').
|
| 406 |
+
|
| 407 |
+
bpo-33906: Rename idlelib.windows as window
|
| 408 |
+
Match Window on the main menu and remove last plural module name.
|
| 409 |
+
Change imports, test, and attribute references to match new name.
|
| 410 |
+
|
| 411 |
+
bpo-33917: Fix and document idlelib/idle_test/template.py.
|
| 412 |
+
The revised file compiles, runs, and tests OK. idle_test/README.txt
|
| 413 |
+
explains how to use it to create new IDLE test files.
|
| 414 |
+
|
| 415 |
+
bpo-33904: In rstrip module, rename class RstripExtension as Rstrip.
|
| 416 |
+
|
| 417 |
+
bpo-33907: For consistency and clarity, rename calltip objects.
|
| 418 |
+
Module calltips and its class CallTips are now calltip and Calltip.
|
| 419 |
+
In module calltip_w, class CallTip is now CalltipWindow.
|
| 420 |
+
|
| 421 |
+
bpo-33855: Minimally test all IDLE modules.
|
| 422 |
+
Standardize the test file format. Add missing test files that import
|
| 423 |
+
the tested module and perform at least one test. Check and record the
|
| 424 |
+
coverage of each test.
|
| 425 |
+
|
| 426 |
+
bpo-33856: Add 'help' to Shell's initial welcome message.
|
| 427 |
+
|
| 428 |
+
|
| 429 |
+
What's New in IDLE 3.7.0 (since 3.6.0)
|
| 430 |
+
Released on 2018-06-27
|
| 431 |
+
======================================
|
| 432 |
+
|
| 433 |
+
bpo-33656: On Windows, add API call saying that tk scales for DPI.
|
| 434 |
+
On Windows 8.1+ or 10, with DPI compatibility properties of the Python
|
| 435 |
+
binary unchanged, and a monitor resolution greater than 96 DPI, this
|
| 436 |
+
should make text and lines sharper and some colors brighter.
|
| 437 |
+
On other systems, it should have no effect. If you have a custom theme,
|
| 438 |
+
you may want to adjust a color or two. If perchance it make text worse
|
| 439 |
+
on your monitor, you can disable the ctypes.OleDLL call near the top of
|
| 440 |
+
pyshell.py and report the problem on python-list or idle-dev@python.org.
|
| 441 |
+
|
| 442 |
+
bpo-33768: Clicking on a context line moves that line to the top
|
| 443 |
+
of the editor window.
|
| 444 |
+
|
| 445 |
+
bpo-33763: Replace the code context label widget with a text widget.
|
| 446 |
+
|
| 447 |
+
bpo-33664: Scroll IDLE editor text by lines.
|
| 448 |
+
(Previously, the mouse wheel and scrollbar slider moved text by a fixed
|
| 449 |
+
number of pixels, resulting in partial lines at the top of the editor
|
| 450 |
+
box.) This change also applies to the shell and grep output windows,
|
| 451 |
+
but currently not to read-only text views.
|
| 452 |
+
|
| 453 |
+
bpo-33679: Enable theme-specific color configuration for Code Context.
|
| 454 |
+
(Previously, there was one code context foreground and background font
|
| 455 |
+
color setting, default or custom, on the extensions tab, that applied
|
| 456 |
+
to all themes.) For built-in themes, the foreground is the same as
|
| 457 |
+
normal text and the background is a contrasting gray. Context colors for
|
| 458 |
+
custom themes are set on the Hightlights tab along with other colors.
|
| 459 |
+
When one starts IDLE from a console and loads a custom theme without
|
| 460 |
+
definitions for 'context', one will see a warning message on the
|
| 461 |
+
console.
|
| 462 |
+
|
| 463 |
+
bpo-33642: Display up to maxlines non-blank lines for Code Context.
|
| 464 |
+
If there is no current context, show a single blank line. (Previously,
|
| 465 |
+
the Code Contex had numlines lines, usually with some blank.) The use
|
| 466 |
+
of a new option, 'maxlines' (default 15), avoids possible interference
|
| 467 |
+
with user settings of the old option, 'numlines' (default 3).
|
| 468 |
+
|
| 469 |
+
bpo-33628: Cleanup codecontext.py and its test.
|
| 470 |
+
|
| 471 |
+
bpo-32831: Add docstrings and tests for codecontext.py.
|
| 472 |
+
Coverage is 100%. Patch by Cheryl Sabella.
|
| 473 |
+
|
| 474 |
+
bpo-33564: Code context now recognizes async as a block opener.
|
| 475 |
+
|
| 476 |
+
bpo-21474: Update word/identifier definition from ascii to unicode.
|
| 477 |
+
In text and entry boxes, this affects selection by double-click,
|
| 478 |
+
movement left/right by control-left/right, and deletion left/right
|
| 479 |
+
by control-BACKSPACE/DEL.
|
| 480 |
+
|
| 481 |
+
bpo-33204: Consistently color invalid string prefixes.
|
| 482 |
+
A 'u' string prefix cannot be paired with either 'r' or 'f'.
|
| 483 |
+
IDLE now consistently colors as much of the prefix, starting at the
|
| 484 |
+
right, as is valid. Revise and extend colorizer test.
|
| 485 |
+
|
| 486 |
+
bpo-32984: Set __file__ while running a startup file.
|
| 487 |
+
Like Python, IDLE optionally runs 1 startup file in the Shell window
|
| 488 |
+
before presenting the first interactive input prompt. For IDLE,
|
| 489 |
+
option -s runs a file named in environmental variable IDLESTARTUP or
|
| 490 |
+
PYTHONSTARTUP; -r file runs file. Python sets __file__ to the startup
|
| 491 |
+
file name before running the file and unsets it before the first
|
| 492 |
+
prompt. IDLE now does the same when run normally, without the -n
|
| 493 |
+
option.
|
| 494 |
+
|
| 495 |
+
bpo-32940: Replace StringTranslatePseudoMapping with faster code.
|
| 496 |
+
|
| 497 |
+
bpo-32916: Change 'str' to 'code' in idlelib.pyparse and users.
|
| 498 |
+
|
| 499 |
+
bpo-32905: Remove unused code in pyparse module.
|
| 500 |
+
|
| 501 |
+
bpo-32874: IDLE - add pyparse tests with 97% coverage.
|
| 502 |
+
|
| 503 |
+
bpo-32837: IDLE - require encoding argument for textview.view_file.
|
| 504 |
+
Using the system and place-dependent default encoding for open()
|
| 505 |
+
is a bad idea for IDLE's system and location-independent files.
|
| 506 |
+
|
| 507 |
+
bpo-32826: Add "encoding=utf-8" to open() in IDLE's test_help_about.
|
| 508 |
+
GUI test test_file_buttons() only looks at initial ascii-only lines,
|
| 509 |
+
but failed on systems where open() defaults to 'ascii' because
|
| 510 |
+
readline() internally reads and decodes far enough ahead to encounter
|
| 511 |
+
a non-ascii character in CREDITS.txt.
|
| 512 |
+
|
| 513 |
+
bpo-32765: Update configdialog General tab create page docstring.
|
| 514 |
+
Add new widgets to the widget list.
|
| 515 |
+
|
| 516 |
+
bpo-32207: Improve tk event exception tracebacks in IDLE.
|
| 517 |
+
When tk event handling is driven by IDLE's run loop, a confusing
|
| 518 |
+
and distracting queue.EMPTY traceback context is no longer added
|
| 519 |
+
to tk event exception tracebacks. The traceback is now the same
|
| 520 |
+
as when event handling is driven by user code. Patch based on
|
| 521 |
+
a suggestion by Serhiy Storchaka.
|
| 522 |
+
|
| 523 |
+
bpo-32164: Delete unused file idlelib/tabbedpages.py.
|
| 524 |
+
Use of TabbedPageSet in configdialog was replaced by ttk.Notebook.
|
| 525 |
+
|
| 526 |
+
bpo-32100: Fix old and new bugs in pathbrowser; improve tests.
|
| 527 |
+
Patch mostly by Cheryl Sabella.
|
| 528 |
+
|
| 529 |
+
bpo-31860: The font sample in the settings dialog is now editable.
|
| 530 |
+
Edits persist while IDLE remains open.
|
| 531 |
+
Patch by Serhiy Storchake and Terry Jan Reedy.
|
| 532 |
+
|
| 533 |
+
bpo-31858: Restrict shell prompt manipulation to the shell.
|
| 534 |
+
Editor and output windows only see an empty last prompt line. This
|
| 535 |
+
simplifies the code and fixes a minor bug when newline is inserted.
|
| 536 |
+
Sys.ps1, if present, is read on Shell start-up, but is not set or changed.
|
| 537 |
+
Patch by Terry Jan Reedy.
|
| 538 |
+
|
| 539 |
+
bpo-28603: Fix a TypeError that caused a shell restart when printing
|
| 540 |
+
a traceback that includes an exception that is unhashable.
|
| 541 |
+
Patch by Zane Bitter.
|
| 542 |
+
|
| 543 |
+
bpo-13802: Use non-Latin characters in the Font settings sample.
|
| 544 |
+
Even if one selects a font that defines a limited subset of the unicode
|
| 545 |
+
Basic Multilingual Plane, tcl/tk will use other fonts that define a
|
| 546 |
+
character. The expanded example give users of non-Latin characters
|
| 547 |
+
a better idea of what they might see in the shell and editors.
|
| 548 |
+
|
| 549 |
+
To make room for the expanded sample, frames on the Font tab are
|
| 550 |
+
re-arranged. The Font/Tabs help explains a bit about the additions.
|
| 551 |
+
Patch by Terry Jan Reedy
|
| 552 |
+
|
| 553 |
+
bpo-31460: Simplify the API of IDLE's Module Browser.
|
| 554 |
+
Passing a widget instead of an flist with a root widget opens the
|
| 555 |
+
option of creating a browser frame that is only part of a window.
|
| 556 |
+
Passing a full file name instead of pieces assumed to come from a
|
| 557 |
+
.py file opens the possibility of browsing python files that do not
|
| 558 |
+
end in .py.
|
| 559 |
+
|
| 560 |
+
bpo-31649: Make _htest and _utest parameters keyword-only.
|
| 561 |
+
These are used to adjust code for human and unit tests.
|
| 562 |
+
|
| 563 |
+
bpo-31459: Rename module browser from Class Browser to Module Browser.
|
| 564 |
+
The original module-level class and method browser became a module
|
| 565 |
+
browser, with the addition of module-level functions, years ago.
|
| 566 |
+
Nested classes and functions were added yesterday. For back-
|
| 567 |
+
compatibility, the virtual event <<open-class-browser>>, which
|
| 568 |
+
appears on the Keys tab of the Settings dialog, is not changed.
|
| 569 |
+
Patch by Cheryl Sabella.
|
| 570 |
+
|
| 571 |
+
bpo-1612262: Module browser now shows nested classes and functions.
|
| 572 |
+
Original patches for code and tests by Guilherme Polo and
|
| 573 |
+
Cheryl Sabella, respectively. Revisions by Terry Jan Reedy.
|
| 574 |
+
|
| 575 |
+
bpo-31500: Tk's default fonts now are scaled on HiDPI displays.
|
| 576 |
+
This affects all dialogs. Patch by Serhiy Storchaka.
|
| 577 |
+
|
| 578 |
+
bpo-31493: Fix code context update and font update timers.
|
| 579 |
+
Canceling timers prevents a warning message when test_idle completes.
|
| 580 |
+
|
| 581 |
+
bpo-31488: Update non-key options in former extension classes.
|
| 582 |
+
When applying configdialog changes, call .reload for each feature class.
|
| 583 |
+
Change ParenMatch so updated options affect existing instances attached
|
| 584 |
+
to existing editor windows.
|
| 585 |
+
|
| 586 |
+
bpo-31477: Improve rstrip entry in IDLE doc.
|
| 587 |
+
Strip Trailing Whitespace strips more than blank spaces.
|
| 588 |
+
Multiline string literals are not skipped.
|
| 589 |
+
|
| 590 |
+
bpo-31480: fix tests to pass with zzdummy extension disabled. (#3590)
|
| 591 |
+
To see the example in action, enable it on options extensions tab.
|
| 592 |
+
|
| 593 |
+
bpo-31421: Document how IDLE runs tkinter programs.
|
| 594 |
+
IDLE calls tcl/tk update in the background in order to make live
|
| 595 |
+
interaction and experimentation with tkinter applications much easier.
|
| 596 |
+
|
| 597 |
+
bpo-31414: Fix tk entry box tests by deleting first.
|
| 598 |
+
Adding to an int entry is not the same as deleting and inserting
|
| 599 |
+
because int('') will fail. Patch by Terry Jan Reedy.
|
| 600 |
+
|
| 601 |
+
bpo-27099: Convert IDLE's built-in 'extensions' to regular features.
|
| 602 |
+
About 10 IDLE features were implemented as supposedly optional
|
| 603 |
+
extensions. Their different behavior could be confusing or worse for
|
| 604 |
+
users and not good for maintenance. Hence the conversion.
|
| 605 |
+
The main difference for users is that user configurable key bindings
|
| 606 |
+
for builtin features are now handled uniformly. Now, editing a binding
|
| 607 |
+
in a keyset only affects its value in the keyset. All bindings are
|
| 608 |
+
defined together in the system-specific default keysets in config-
|
| 609 |
+
extensions.def. All custom keysets are saved as a whole in config-
|
| 610 |
+
extension.cfg. All take effect as soon as one clicks Apply or Ok.
|
| 611 |
+
The affected events are '<<force-open-completions>>',
|
| 612 |
+
'<<expand-word>>', '<<force-open-calltip>>', '<<flash-paren>>',
|
| 613 |
+
'<<format-paragraph>>', '<<run-module>>', '<<check-module>>', and
|
| 614 |
+
'<<zoom-height>>'. Any (global) customizations made before 3.6.3 will
|
| 615 |
+
not affect their keyset-specific customization after 3.6.3. and vice
|
| 616 |
+
versa.
|
| 617 |
+
Initial patch by Charles Wohlganger, revised by Terry Jan Reedy.
|
| 618 |
+
|
| 619 |
+
bpo-31051: Rearrange condigdialog General tab.
|
| 620 |
+
Sort non-Help options into Window (Shell+Editor) and Editor (only).
|
| 621 |
+
Leave room for the addition of new options.
|
| 622 |
+
Patch by Terry Jan Reedy.
|
| 623 |
+
|
| 624 |
+
bpo-30617: Add docstrings and tests for outwin subclass of editor.
|
| 625 |
+
Move some data and functions from the class to module level.
|
| 626 |
+
Patch by Cheryl Sabella.
|
| 627 |
+
|
| 628 |
+
bpo-31287: Do not modify tkinter.messagebox in test_configdialog.
|
| 629 |
+
Instead, mask it with an instance mock that can be deleted.
|
| 630 |
+
Patch by Terry Jan Reedy.
|
| 631 |
+
|
| 632 |
+
bpo-30781: Use ttk widgets in ConfigDialog pages.
|
| 633 |
+
These should especially look better on MacOSX.
|
| 634 |
+
Patches by Terry Jan Reedy and Cheryl Sabella.
|
| 635 |
+
|
| 636 |
+
bpo-31206: Factor HighPage(Frame) class from ConfigDialog.
|
| 637 |
+
Patch by Cheryl Sabella.
|
| 638 |
+
|
| 639 |
+
bp0-31001: Add tests for configdialog highlight tab.
|
| 640 |
+
Patch by Cheryl Sabella.
|
| 641 |
+
|
| 642 |
+
bpo-31205: Factor KeysPage(Frame) class from ConfigDialog.
|
| 643 |
+
The slightly modified tests continue to pass.
|
| 644 |
+
Patch by Cheryl Sabella.
|
| 645 |
+
|
| 646 |
+
bpo-31002: Add tests for configdialog keys tab.
|
| 647 |
+
Patch by Cheryl Sabella.
|
| 648 |
+
|
| 649 |
+
bpo-19903: Change calltipes to use inspect.signature.
|
| 650 |
+
Idlelib.calltips.get_argspec now uses inspect.signature instead of
|
| 651 |
+
inspect.getfullargspec, like help() does. This improves the signature
|
| 652 |
+
in the call tip in a few different cases, including builtins converted
|
| 653 |
+
to provide a signature. A message is added if the object is not
|
| 654 |
+
callable, has an invalid signature, or if it has positional-only
|
| 655 |
+
parameters. Patch by Louie Lu.
|
| 656 |
+
|
| 657 |
+
bop-31083: Add an outline of a TabPage class in configdialog.
|
| 658 |
+
Add template as comment. Update existing classes to match outline.
|
| 659 |
+
Initial patch by Cheryl Sabella.
|
| 660 |
+
|
| 661 |
+
bpo-31050: Factor GenPage(Frame) class from ConfigDialog.
|
| 662 |
+
The slightly modified tests for the General tab continue to pass.
|
| 663 |
+
Patch by Cheryl Sabella.
|
| 664 |
+
|
| 665 |
+
bpo-31004: Factor FontPage(Frame) class from ConfigDialog.
|
| 666 |
+
The slightly modified tests continue to pass. The General test
|
| 667 |
+
broken by the switch to ttk.Notebook is fixed.
|
| 668 |
+
Patch mostly by Cheryl Sabella.
|
| 669 |
+
|
| 670 |
+
bpo-30781: IDLE - Use ttk Notebook in ConfigDialog.
|
| 671 |
+
This improves navigation by tabbing.
|
| 672 |
+
Patch by Terry Jan Reedy.
|
| 673 |
+
|
| 674 |
+
bpo-31060: IDLE - Finish rearranging methods of ConfigDialog.
|
| 675 |
+
Grouping methods pertaining to each tab and the buttons will aid
|
| 676 |
+
writing tests and improving the tabs and will enable splitting the
|
| 677 |
+
groups into classes.
|
| 678 |
+
Patch by Terry Jan Reedy.
|
| 679 |
+
|
| 680 |
+
bpo-30853: IDLE -- Factor a VarTrace class out of ConfigDialog.
|
| 681 |
+
Instance tracers manages pairs consisting of a tk variable and a
|
| 682 |
+
callback function. When tracing is turned on, setting the variable
|
| 683 |
+
calls the function. Test coverage for the new class is 100%.
|
| 684 |
+
Patch by Terry Jan Reedy.
|
| 685 |
+
|
| 686 |
+
bpo-31003: IDLE: Add more tests for General tab.
|
| 687 |
+
Patch by Terry Jan Reedy.
|
| 688 |
+
|
| 689 |
+
bpo-30993: IDLE - Improve configdialog font page and tests.
|
| 690 |
+
*In configdialog: Document causal pathways in create_font_tab
|
| 691 |
+
docstring. Simplify some attribute names. Move set_samples calls to
|
| 692 |
+
var_changed_font (idea from Cheryl Sabella). Move related functions to
|
| 693 |
+
positions after the create widgets function.
|
| 694 |
+
* In test_configdialog: Fix test_font_set so not order dependent. Fix
|
| 695 |
+
renamed test_indent_scale so it tests the widget. Adjust tests for
|
| 696 |
+
movement of set_samples call. Add tests for load functions. Put all
|
| 697 |
+
font tests in one class and tab indent tests in another. Except for
|
| 698 |
+
two lines, these tests completely cover the related functions.
|
| 699 |
+
Patch by Terry Jan Reedy.
|
| 700 |
+
|
| 701 |
+
bpo-30981: IDLE -- Add more configdialog font page tests.
|
| 702 |
+
|
| 703 |
+
bpo-28523: IDLE: replace 'colour' with 'color' in configdialog.
|
| 704 |
+
|
| 705 |
+
bpo-30917: Add tests for idlelib.config.IdleConf.
|
| 706 |
+
Increase coverage from 46% to 96%.
|
| 707 |
+
Patch by Louie Lu.
|
| 708 |
+
|
| 709 |
+
bpo-30913: Document ConfigDialog tk Vars, methods, and widgets in docstrings
|
| 710 |
+
This will facilitate improving the dialog and splitting up the class.
|
| 711 |
+
Original patch by Cheryl Sabella.
|
| 712 |
+
|
| 713 |
+
bpo-30899: Add tests for ConfigParser subclasses in config.
|
| 714 |
+
Coverage is 100% for those classes and ConfigChanges.
|
| 715 |
+
Patch by Louie Lu.
|
| 716 |
+
|
| 717 |
+
bpo-30881: Add docstrings to browser.py.
|
| 718 |
+
Patch by Cheryl Sabella.
|
| 719 |
+
|
| 720 |
+
bpo-30851: Remove unused tk variables in configdialog.
|
| 721 |
+
One is a duplicate, one is set but cannot be altered by users.
|
| 722 |
+
Patch by Cheryl Sabella.
|
| 723 |
+
|
| 724 |
+
bpo-30870: Select font option with Up and Down keys, as well as with mouse.
|
| 725 |
+
Added test increases configdialog coverage to 60%
|
| 726 |
+
Patches mostly by Louie Lu.
|
| 727 |
+
|
| 728 |
+
bpo-8231: Call config.IdleConf.GetUserCfgDir only once per process.
|
| 729 |
+
|
| 730 |
+
bpo-30779: Factor ConfigChanges class from configdialog, put in config; test.
|
| 731 |
+
* In config, put dump test code in a function; run it and unittest in
|
| 732 |
+
'if __name__ == '__main__'.
|
| 733 |
+
* Add class config.ConfigChanges based on changes_class_v4.py on bpo issue.
|
| 734 |
+
* Add class test_config.ChangesTest, partly using configdialog_tests_v1.py.
|
| 735 |
+
* Revise configdialog to use ConfigChanges; see tracker msg297804.
|
| 736 |
+
* Revise test_configdialog to match configdialog changes.
|
| 737 |
+
* Remove configdialog functions unused or moved to ConfigChanges.
|
| 738 |
+
Cheryl Sabella contributed parts of the patch.
|
| 739 |
+
|
| 740 |
+
bpo-30777: Configdialog - add docstrings and improve comments.
|
| 741 |
+
Patch by Cheryl Sabella.
|
| 742 |
+
|
| 743 |
+
bpo-30495: Improve textview with docstrings, PEP8 names, and more tests.
|
| 744 |
+
Split TextViewer class into ViewWindow, ViewFrame, and TextFrame classes
|
| 745 |
+
so that instances of the latter two can be placed with other widgets
|
| 746 |
+
within a multiframe window.
|
| 747 |
+
Patches by Cheryl Sabella and Terry Jan Reedy.
|
| 748 |
+
|
| 749 |
+
bpo-30723: Make several improvements to parenmatch.
|
| 750 |
+
* Add 'parens' style to highlight both opener and closer.
|
| 751 |
+
* Make 'default' style, which is not default, a synonym for 'opener'.
|
| 752 |
+
* Make time-delay work the same with all styles.
|
| 753 |
+
* Add help for config dialog extensions tab, including parenmatch.
|
| 754 |
+
* Add new tests.
|
| 755 |
+
Original patch by Charles Wohlganger. Revisions by Terry Jan Reedy
|
| 756 |
+
|
| 757 |
+
bpo-30674: Grep -- Add docstrings. Patch by Cheryl Sabella.
|
| 758 |
+
|
| 759 |
+
bpo-21519: IDLE's basic custom key entry dialog now detects
|
| 760 |
+
duplicates properly. Original patch by Saimadhav Heblikar.
|
| 761 |
+
|
| 762 |
+
bpo-29910: IDLE no longer deletes a character after commenting out a
|
| 763 |
+
region by a key shortcut. Add "return 'break'" for this and other
|
| 764 |
+
potential conflicts between IDLE and default key bindings.
|
| 765 |
+
Patch by Serhiy Storchaka.
|
| 766 |
+
|
| 767 |
+
bpo-30728: Modernize idlelib.configdialog:
|
| 768 |
+
* replace import * with specific imports;
|
| 769 |
+
* lowercase method and attribute lines.
|
| 770 |
+
Patch by Cheryl Sabella.
|
| 771 |
+
|
| 772 |
+
bpo-6739: Verify user-entered key sequences by trying to bind them
|
| 773 |
+
with to a tk widget. Add tests for all 3 validation functions.
|
| 774 |
+
Original patch by G Polo. Tests added by Cheryl Sabella.
|
| 775 |
+
Code revised and more tests added by Terry Jan Reedy
|
| 776 |
+
|
| 777 |
+
bpo-24813: Add icon to help_about and make other changes.
|
| 778 |
+
|
| 779 |
+
bpo-15786: Fix several problems with IDLE's autocompletion box.
|
| 780 |
+
The following should now work: clicking on selection box items;
|
| 781 |
+
using the scrollbar; selecting an item by hitting Return.
|
| 782 |
+
Hangs on MacOSX should no longer happen. Patch by Louie Lu.
|
| 783 |
+
|
| 784 |
+
bpo-25514: Add doc subsubsection about IDLE failure to start.
|
| 785 |
+
Popup no-connection message directs users to this section.
|
| 786 |
+
|
| 787 |
+
bpo-30642: Fix reference leaks in IDLE tests.
|
| 788 |
+
Patches by Louie Lu and Terry Jan Reedy.
|
| 789 |
+
|
| 790 |
+
bpo-30495: Add docstrings for textview.py and use PEP8 names.
|
| 791 |
+
Patches by Cheryl Sabella and Terry Jan Reedy.
|
| 792 |
+
|
| 793 |
+
bpo-30290: Help-about: use pep8 names and add tests.
|
| 794 |
+
Increase coverage to 100%.
|
| 795 |
+
Patches by Louie Lu, Cheryl Sabella, and Terry Jan Reedy.
|
| 796 |
+
|
| 797 |
+
bpo-30303: Add _utest option to textview; add new tests.
|
| 798 |
+
Increase coverage to 100%.
|
| 799 |
+
Patches by Louie Lu and Terry Jan Reedy.
|
| 800 |
+
|
| 801 |
+
Issue #29071: IDLE colors f-string prefixes but not invalid ur prefixes.
|
| 802 |
+
|
| 803 |
+
Issue #28572: Add 10% to coverage of IDLE's test_configdialog.
|
| 804 |
+
Update and augment description of the configuration system.
|
| 805 |
+
|
| 806 |
+
|
| 807 |
+
What's New in IDLE 3.6.0 (since 3.5.0)
|
| 808 |
+
Released on 2016-12-23
|
| 809 |
+
======================================
|
| 810 |
+
|
| 811 |
+
- Issue #15308: Add 'interrupt execution' (^C) to Shell menu.
|
| 812 |
+
Patch by Roger Serwy, updated by Bayard Randel.
|
| 813 |
+
|
| 814 |
+
- Issue #27922: Stop IDLE tests from 'flashing' gui widgets on the screen.
|
| 815 |
+
|
| 816 |
+
- Issue #27891: Consistently group and sort imports within idlelib modules.
|
| 817 |
+
|
| 818 |
+
- Issue #17642: add larger font sizes for classroom projection.
|
| 819 |
+
|
| 820 |
+
- Add version to title of IDLE help window.
|
| 821 |
+
|
| 822 |
+
- Issue #25564: In section on IDLE -- console differences, mention that
|
| 823 |
+
using exec means that __builtins__ is defined for each statement.
|
| 824 |
+
|
| 825 |
+
- Issue #27821: Fix 3.6.0a3 regression that prevented custom key sets
|
| 826 |
+
from being selected when no custom theme was defined.
|
| 827 |
+
|
| 828 |
+
- Issue #27714: text_textview and test_autocomplete now pass when re-run
|
| 829 |
+
in the same process. This occurs when test_idle fails when run with the
|
| 830 |
+
-w option but without -jn. Fix warning from test_config.
|
| 831 |
+
|
| 832 |
+
- Issue #27621: Put query response validation error messages in the query
|
| 833 |
+
box itself instead of in a separate messagebox. Redo tests to match.
|
| 834 |
+
Add Mac OSX refinements. Original patch by Mark Roseman.
|
| 835 |
+
|
| 836 |
+
- Issue #27620: Escape key now closes Query box as cancelled.
|
| 837 |
+
|
| 838 |
+
- Issue #27609: IDLE: tab after initial whitespace should tab, not
|
| 839 |
+
autocomplete. This fixes problem with writing docstrings at least
|
| 840 |
+
twice indented.
|
| 841 |
+
|
| 842 |
+
- Issue #27609: Explicitly return None when there are also non-None
|
| 843 |
+
returns. In a few cases, reverse a condition and eliminate a return.
|
| 844 |
+
|
| 845 |
+
- Issue #25507: IDLE no longer runs buggy code because of its tkinter imports.
|
| 846 |
+
Users must include the same imports required to run directly in Python.
|
| 847 |
+
|
| 848 |
+
- Issue #27173: Add 'IDLE Modern Unix' to the built-in key sets.
|
| 849 |
+
Make the default key set depend on the platform.
|
| 850 |
+
Add tests for the changes to the config module.
|
| 851 |
+
|
| 852 |
+
- Issue #27452: add line counter and crc to IDLE configHandler test dump.
|
| 853 |
+
|
| 854 |
+
- Issue #27477: IDLE search dialogs now use ttk widgets.
|
| 855 |
+
|
| 856 |
+
- Issue #27173: Add 'IDLE Modern Unix' to the built-in key sets.
|
| 857 |
+
Make the default key set depend on the platform.
|
| 858 |
+
Add tests for the changes to the config module.
|
| 859 |
+
|
| 860 |
+
- Issue #27452: make command line "idle-test> python test_help.py" work.
|
| 861 |
+
__file__ is relative when python is started in the file's directory.
|
| 862 |
+
|
| 863 |
+
- Issue #27452: add line counter and crc to IDLE configHandler test dump.
|
| 864 |
+
|
| 865 |
+
- Issue #27380: IDLE: add query.py with base Query dialog and ttk widgets.
|
| 866 |
+
Module had subclasses SectionName, ModuleName, and HelpSource, which are
|
| 867 |
+
used to get information from users by configdialog and file =>Load Module.
|
| 868 |
+
Each subclass has itw own validity checks. Using ModuleName allows users
|
| 869 |
+
to edit bad module names instead of starting over.
|
| 870 |
+
Add tests and delete the two files combined into the new one.
|
| 871 |
+
|
| 872 |
+
- Issue #27372: Test_idle no longer changes the locale.
|
| 873 |
+
|
| 874 |
+
- Issue #27365: Allow non-ascii chars in IDLE NEWS.txt, for contributor names.
|
| 875 |
+
|
| 876 |
+
- Issue #27245: IDLE: Cleanly delete custom themes and key bindings.
|
| 877 |
+
Previously, when IDLE was started from a console or by import, a cascade
|
| 878 |
+
of warnings was emitted. Patch by Serhiy Storchaka.
|
| 879 |
+
|
| 880 |
+
- Issue #24137: Run IDLE, test_idle, and htest with tkinter default root disabled.
|
| 881 |
+
Fix code and tests that fail with this restriction.
|
| 882 |
+
Fix htests to not create a second and redundant root and mainloop.
|
| 883 |
+
|
| 884 |
+
- Issue #27310: Fix IDLE.app failure to launch on OS X due to vestigial import.
|
| 885 |
+
|
| 886 |
+
- Issue #5124: Paste with text selected now replaces the selection on X11.
|
| 887 |
+
This matches how paste works on Windows, Mac, most modern Linux apps,
|
| 888 |
+
and ttk widgets. Original patch by Serhiy Storchaka.
|
| 889 |
+
|
| 890 |
+
- Issue #24750: Switch all scrollbars in IDLE to ttk versions.
|
| 891 |
+
Where needed, minimal tests are added to cover changes.
|
| 892 |
+
|
| 893 |
+
- Issue #24759: IDLE requires tk 8.5 and availability ttk widgets.
|
| 894 |
+
Delete now unneeded tk version tests and code for older versions.
|
| 895 |
+
Add test for IDLE syntax colorizer.
|
| 896 |
+
|
| 897 |
+
- Issue #27239: idlelib.macosx.isXyzTk functions initialize as needed.
|
| 898 |
+
|
| 899 |
+
- Issue #27262: move Aqua unbinding code, which enable context menus, to macosx.
|
| 900 |
+
|
| 901 |
+
- Issue #24759: Make clear in idlelib.idle_test.__init__ that the directory
|
| 902 |
+
is a private implementation of test.test_idle and tool for maintainers.
|
| 903 |
+
|
| 904 |
+
- Issue #27196: Stop 'ThemeChanged' warnings when running IDLE tests.
|
| 905 |
+
These persisted after other warnings were suppressed in #20567.
|
| 906 |
+
Apply Serhiy Storchaka's update_idletasks solution to four test files.
|
| 907 |
+
Record this additional advice in idle_test/README.txt
|
| 908 |
+
|
| 909 |
+
- Issue #20567: Revise idle_test/README.txt with advice about avoiding
|
| 910 |
+
tk warning messages from tests. Apply advice to several IDLE tests.
|
| 911 |
+
|
| 912 |
+
- Issue # 24225: Update idlelib/README.txt with new file names
|
| 913 |
+
and event handlers.
|
| 914 |
+
|
| 915 |
+
- Issue #27156: Remove obsolete code not used by IDLE. Replacements:
|
| 916 |
+
1. help.txt, replaced by help.html, is out-of-date and should not be used.
|
| 917 |
+
Its dedicated viewer has be replaced by the html viewer in help.py.
|
| 918 |
+
2. 'import idlever; I = idlever.IDLE_VERSION' is the same as
|
| 919 |
+
'import sys; I = version[:version.index(' ')]'
|
| 920 |
+
3. After 'ob = stackviewer.VariablesTreeItem(*args)',
|
| 921 |
+
'ob.keys()' == 'list(ob.object.keys).
|
| 922 |
+
4. In macosc, runningAsOSXAPP == isAquaTk; idCarbonAquaTk == isCarbonTk
|
| 923 |
+
|
| 924 |
+
- Issue #27117: Make colorizer htest and turtledemo work with dark themes.
|
| 925 |
+
Move code for configuring text widget colors to a new function.
|
| 926 |
+
|
| 927 |
+
- Issue #24225: Rename many idlelib/*.py and idle_test/test_*.py files.
|
| 928 |
+
Edit files to replace old names with new names when the old name
|
| 929 |
+
referred to the module rather than the class it contained.
|
| 930 |
+
See the issue and IDLE section in What's New in 3.6 for more.
|
| 931 |
+
|
| 932 |
+
- Issue #26673: When tk reports font size as 0, change to size 10.
|
| 933 |
+
Such fonts on Linux prevented the configuration dialog from opening.
|
| 934 |
+
|
| 935 |
+
- Issue #21939: Add test for IDLE's percolator.
|
| 936 |
+
Original patch by Saimadhav Heblikar.
|
| 937 |
+
|
| 938 |
+
- Issue #21676: Add test for IDLE's replace dialog.
|
| 939 |
+
Original patch by Saimadhav Heblikar.
|
| 940 |
+
|
| 941 |
+
- Issue #18410: Add test for IDLE's search dialog.
|
| 942 |
+
Original patch by Westley Martínez.
|
| 943 |
+
|
| 944 |
+
- Issue #21703: Add test for undo delegator. Patch mostly by
|
| 945 |
+
Saimadhav Heblikar .
|
| 946 |
+
|
| 947 |
+
- Issue #27044: Add ConfigDialog.remove_var_callbacks to stop memory leaks.
|
| 948 |
+
|
| 949 |
+
- Issue #23977: Add more asserts to test_delegator.
|
| 950 |
+
|
| 951 |
+
- Issue #20640: Add tests for idlelib.configHelpSourceEdit.
|
| 952 |
+
Patch by Saimadhav Heblikar.
|
| 953 |
+
|
| 954 |
+
- In the 'IDLE-console differences' section of the IDLE doc, clarify
|
| 955 |
+
how running with IDLE affects sys.modules and the standard streams.
|
| 956 |
+
|
| 957 |
+
- Issue #25507: fix incorrect change in IOBinding that prevented printing.
|
| 958 |
+
Augment IOBinding htest to include all major IOBinding functions.
|
| 959 |
+
|
| 960 |
+
- Issue #25905: Revert unwanted conversion of ' to ’ RIGHT SINGLE QUOTATION
|
| 961 |
+
MARK in README.txt and open this and NEWS.txt with 'ascii'.
|
| 962 |
+
Re-encode CREDITS.txt to utf-8 and open it with 'utf-8'.
|
| 963 |
+
|
| 964 |
+
- Issue 15348: Stop the debugger engine (normally in a user process)
|
| 965 |
+
before closing the debugger window (running in the IDLE process).
|
| 966 |
+
This prevents the RuntimeErrors that were being caught and ignored.
|
| 967 |
+
|
| 968 |
+
- Issue #24455: Prevent IDLE from hanging when a) closing the shell while the
|
| 969 |
+
debugger is active (15347); b) closing the debugger with the [X] button
|
| 970 |
+
(15348); and c) activating the debugger when already active (24455).
|
| 971 |
+
The patch by Mark Roseman does this by making two changes.
|
| 972 |
+
1. Suspend and resume the gui.interaction method with the tcl vwait
|
| 973 |
+
mechanism intended for this purpose (instead of root.mainloop & .quit).
|
| 974 |
+
2. In gui.run, allow any existing interaction to terminate first.
|
| 975 |
+
|
| 976 |
+
- Change 'The program' to 'Your program' in an IDLE 'kill program?' message
|
| 977 |
+
to make it clearer that the program referred to is the currently running
|
| 978 |
+
user program, not IDLE itself.
|
| 979 |
+
|
| 980 |
+
- Issue #24750: Improve the appearance of the IDLE editor window status bar.
|
| 981 |
+
Patch by Mark Roseman.
|
| 982 |
+
|
| 983 |
+
- Issue #25313: Change the handling of new built-in text color themes to better
|
| 984 |
+
address the compatibility problem introduced by the addition of IDLE Dark.
|
| 985 |
+
Consistently use the revised idleConf.CurrentTheme everywhere in idlelib.
|
| 986 |
+
|
| 987 |
+
- Issue #24782: Extension configuration is now a tab in the IDLE Preferences
|
| 988 |
+
dialog rather than a separate dialog. The former tabs are now a sorted
|
| 989 |
+
list. Patch by Mark Roseman.
|
| 990 |
+
|
| 991 |
+
- Issue #22726: Re-activate the config dialog help button with some content
|
| 992 |
+
about the other buttons and the new IDLE Dark theme.
|
| 993 |
+
|
| 994 |
+
- Issue #24820: IDLE now has an 'IDLE Dark' built-in text color theme.
|
| 995 |
+
It is more or less IDLE Classic inverted, with a cobalt blue background.
|
| 996 |
+
Strings, comments, keywords, ... are still green, red, orange, ... .
|
| 997 |
+
To use it with IDLEs released before November 2015, hit the
|
| 998 |
+
'Save as New Custom Theme' button and enter a new name,
|
| 999 |
+
such as 'Custom Dark'. The custom theme will work with any IDLE
|
| 1000 |
+
release, and can be modified.
|
| 1001 |
+
|
| 1002 |
+
- Issue #25224: README.txt is now an idlelib index for IDLE developers and
|
| 1003 |
+
curious users. The previous user content is now in the IDLE doc chapter.
|
| 1004 |
+
'IDLE' now means 'Integrated Development and Learning Environment'.
|
| 1005 |
+
|
| 1006 |
+
- Issue #24820: Users can now set breakpoint colors in
|
| 1007 |
+
Settings -> Custom Highlighting. Original patch by Mark Roseman.
|
| 1008 |
+
|
| 1009 |
+
- Issue #24972: Inactive selection background now matches active selection
|
| 1010 |
+
background, as configured by users, on all systems. Found items are now
|
| 1011 |
+
always highlighted on Windows. Initial patch by Mark Roseman.
|
| 1012 |
+
|
| 1013 |
+
- Issue #24570: Idle: make calltip and completion boxes appear on Macs
|
| 1014 |
+
affected by a tk regression. Initial patch by Mark Roseman.
|
| 1015 |
+
|
| 1016 |
+
- Issue #24988: Idle ScrolledList context menus (used in debugger)
|
| 1017 |
+
now work on Mac Aqua. Patch by Mark Roseman.
|
| 1018 |
+
|
| 1019 |
+
- Issue #24801: Make right-click for context menu work on Mac Aqua.
|
| 1020 |
+
Patch by Mark Roseman.
|
| 1021 |
+
|
| 1022 |
+
- Issue #25173: Associate tkinter messageboxes with a specific widget.
|
| 1023 |
+
For Mac OSX, make them a 'sheet'. Patch by Mark Roseman.
|
| 1024 |
+
|
| 1025 |
+
- Issue #25198: Enhance the initial html viewer now used for Idle Help.
|
| 1026 |
+
* Properly indent fixed-pitch text (patch by Mark Roseman).
|
| 1027 |
+
* Give code snippet a very Sphinx-like light blueish-gray background.
|
| 1028 |
+
* Re-use initial width and height set by users for shell and editor.
|
| 1029 |
+
* When the Table of Contents (TOC) menu is used, put the section header
|
| 1030 |
+
at the top of the screen.
|
| 1031 |
+
|
| 1032 |
+
- Issue #25225: Condense and rewrite Idle doc section on text colors.
|
| 1033 |
+
|
| 1034 |
+
- Issue #21995: Explain some differences between IDLE and console Python.
|
| 1035 |
+
|
| 1036 |
+
- Issue #22820: Explain need for *print* when running file from Idle editor.
|
| 1037 |
+
|
| 1038 |
+
- Issue #25224: Doc: augment Idle feature list and no-subprocess section.
|
| 1039 |
+
|
| 1040 |
+
- Issue #25219: Update doc for Idle command line options.
|
| 1041 |
+
Some were missing and notes were not correct.
|
| 1042 |
+
|
| 1043 |
+
- Issue #24861: Most of idlelib is private and subject to change.
|
| 1044 |
+
Use idleib.idle.* to start Idle. See idlelib.__init__.__doc__.
|
| 1045 |
+
|
| 1046 |
+
- Issue #25199: Idle: add synchronization comments for future maintainers.
|
| 1047 |
+
|
| 1048 |
+
- Issue #16893: Replace help.txt with help.html for Idle doc display.
|
| 1049 |
+
The new idlelib/help.html is rstripped Doc/build/html/library/idle.html.
|
| 1050 |
+
It looks better than help.txt and will better document Idle as released.
|
| 1051 |
+
The tkinter html viewer that works for this file was written by Mark Roseman.
|
| 1052 |
+
The now unused EditorWindow.HelpDialog class and helt.txt file are deprecated.
|
| 1053 |
+
|
| 1054 |
+
- Issue #24199: Deprecate unused idlelib.idlever with possible removal in 3.6.
|
| 1055 |
+
|
| 1056 |
+
- Issue #24790: Remove extraneous code (which also create 2 & 3 conflicts).
|
| 1057 |
+
|
| 1058 |
+
|
| 1059 |
+
What's New in IDLE 3.5.0?
|
| 1060 |
+
=========================
|
| 1061 |
+
*Release date: 2015-09-13*
|
| 1062 |
+
|
| 1063 |
+
- Issue #23672: Allow Idle to edit and run files with astral chars in name.
|
| 1064 |
+
Patch by Mohd Sanad Zaki Rizvi.
|
| 1065 |
+
|
| 1066 |
+
- Issue 24745: Idle editor default font. Switch from Courier to
|
| 1067 |
+
platform-sensitive TkFixedFont. This should not affect current customized
|
| 1068 |
+
font selections. If there is a problem, edit $HOME/.idlerc/config-main.cfg
|
| 1069 |
+
and remove 'fontxxx' entries from [Editor Window]. Patch by Mark Roseman.
|
| 1070 |
+
|
| 1071 |
+
- Issue #21192: Idle editor. When a file is run, put its name in the restart bar.
|
| 1072 |
+
Do not print false prompts. Original patch by Adnan Umer.
|
| 1073 |
+
|
| 1074 |
+
- Issue #13884: Idle menus. Remove tearoff lines. Patch by Roger Serwy.
|
| 1075 |
+
|
| 1076 |
+
- Issue #23184: remove unused names and imports in idlelib.
|
| 1077 |
+
Initial patch by Al Sweigart.
|
| 1078 |
+
|
| 1079 |
+
- Issue #20577: Configuration of the max line length for the FormatParagraph
|
| 1080 |
+
extension has been moved from the General tab of the Idle preferences dialog
|
| 1081 |
+
to the FormatParagraph tab of the Config Extensions dialog.
|
| 1082 |
+
Patch by Tal Einat.
|
| 1083 |
+
|
| 1084 |
+
- Issue #16893: Update Idle doc chapter to match current Idle and add new
|
| 1085 |
+
information.
|
| 1086 |
+
|
| 1087 |
+
- Issue #3068: Add Idle extension configuration dialog to Options menu.
|
| 1088 |
+
Changes are written to HOME/.idlerc/config-extensions.cfg.
|
| 1089 |
+
Original patch by Tal Einat.
|
| 1090 |
+
|
| 1091 |
+
- Issue #16233: A module browser (File : Class Browser, Alt+C) requires an
|
| 1092 |
+
editor window with a filename. When Class Browser is requested otherwise,
|
| 1093 |
+
from a shell, output window, or 'Untitled' editor, Idle no longer displays
|
| 1094 |
+
an error box. It now pops up an Open Module box (Alt+M). If a valid name
|
| 1095 |
+
is entered and a module is opened, a corresponding browser is also opened.
|
| 1096 |
+
|
| 1097 |
+
- Issue #4832: Save As to type Python files automatically adds .py to the
|
| 1098 |
+
name you enter (even if your system does not display it). Some systems
|
| 1099 |
+
automatically add .txt when type is Text files.
|
| 1100 |
+
|
| 1101 |
+
- Issue #21986: Code objects are not normally pickled by the pickle module.
|
| 1102 |
+
To match this, they are no longer pickled when running under Idle.
|
| 1103 |
+
|
| 1104 |
+
- Issue #23180: Rename IDLE "Windows" menu item to "Window".
|
| 1105 |
+
Patch by Al Sweigart.
|
| 1106 |
+
|
| 1107 |
+
- Issue #17390: Adjust Editor window title; remove 'Python',
|
| 1108 |
+
move version to end.
|
| 1109 |
+
|
| 1110 |
+
- Issue #14105: Idle debugger breakpoints no longer disappear
|
| 1111 |
+
when inserting or deleting lines.
|
| 1112 |
+
|
| 1113 |
+
- Issue #17172: Turtledemo can now be run from Idle.
|
| 1114 |
+
Currently, the entry is on the Help menu, but it may move to Run.
|
| 1115 |
+
Patch by Ramchandra Apt and Lita Cho.
|
| 1116 |
+
|
| 1117 |
+
- Issue #21765: Add support for non-ascii identifiers to HyperParser.
|
| 1118 |
+
|
| 1119 |
+
- Issue #21940: Add unittest for WidgetRedirector. Initial patch by Saimadhav
|
| 1120 |
+
Heblikar.
|
| 1121 |
+
|
| 1122 |
+
- Issue #18592: Add unittest for SearchDialogBase. Patch by Phil Webster.
|
| 1123 |
+
|
| 1124 |
+
- Issue #21694: Add unittest for ParenMatch. Patch by Saimadhav Heblikar.
|
| 1125 |
+
|
| 1126 |
+
- Issue #21686: add unittest for HyperParser. Original patch by Saimadhav
|
| 1127 |
+
Heblikar.
|
| 1128 |
+
|
| 1129 |
+
- Issue #12387: Add missing upper(lower)case versions of default Windows key
|
| 1130 |
+
bindings for Idle so Caps Lock does not disable them. Patch by Roger Serwy.
|
| 1131 |
+
|
| 1132 |
+
- Issue #21695: Closing a Find-in-files output window while the search is
|
| 1133 |
+
still in progress no longer closes Idle.
|
| 1134 |
+
|
| 1135 |
+
- Issue #18910: Add unittest for textView. Patch by Phil Webster.
|
| 1136 |
+
|
| 1137 |
+
- Issue #18292: Add unittest for AutoExpand. Patch by Saihadhav Heblikar.
|
| 1138 |
+
|
| 1139 |
+
- Issue #18409: Add unittest for AutoComplete. Patch by Phil Webster.
|
| 1140 |
+
|
| 1141 |
+
- Issue #21477: htest.py - Improve framework, complete set of tests.
|
| 1142 |
+
Patches by Saimadhav Heblikar
|
| 1143 |
+
|
| 1144 |
+
- Issue #18104: Add idlelib/idle_test/htest.py with a few sample tests to begin
|
| 1145 |
+
consolidating and improving human-validated tests of Idle. Change other files
|
| 1146 |
+
as needed to work with htest. Running the module as __main__ runs all tests.
|
| 1147 |
+
|
| 1148 |
+
- Issue #21139: Change default paragraph width to 72, the PEP 8 recommendation.
|
| 1149 |
+
|
| 1150 |
+
- Issue #21284: Paragraph reformat test passes after user changes reformat width.
|
| 1151 |
+
|
| 1152 |
+
- Issue #17654: Ensure IDLE menus are customized properly on OS X for
|
| 1153 |
+
non-framework builds and for all variants of Tk.
|
| 1154 |
+
|
| 1155 |
+
|
| 1156 |
+
What's New in IDLE 3.4.0?
|
| 1157 |
+
=========================
|
| 1158 |
+
*Release date: 2014-03-16*
|
| 1159 |
+
|
| 1160 |
+
- Issue #17390: Display Python version on Idle title bar.
|
| 1161 |
+
Initial patch by Edmond Burnett.
|
| 1162 |
+
|
| 1163 |
+
- Issue #5066: Update IDLE docs. Patch by Todd Rovito.
|
| 1164 |
+
|
| 1165 |
+
- Issue #17625: Close the replace dialog after it is used.
|
| 1166 |
+
|
| 1167 |
+
- Issue #16226: Fix IDLE Path Browser crash.
|
| 1168 |
+
(Patch by Roger Serwy)
|
| 1169 |
+
|
| 1170 |
+
- Issue #15853: Prevent IDLE crash on OS X when opening Preferences menu
|
| 1171 |
+
with certain versions of Tk 8.5. Initial patch by Kevin Walzer.
|
| 1172 |
+
|
| 1173 |
+
|
| 1174 |
+
What's New in IDLE 3.3.0?
|
| 1175 |
+
=========================
|
| 1176 |
+
*Release date: 2012-09-29*
|
| 1177 |
+
|
| 1178 |
+
- Issue #17625: Close the replace dialog after it is used.
|
| 1179 |
+
|
| 1180 |
+
- Issue #7163: Propagate return value of sys.stdout.write.
|
| 1181 |
+
|
| 1182 |
+
- Issue #15318: Prevent writing to sys.stdin.
|
| 1183 |
+
|
| 1184 |
+
- Issue #4832: Modify IDLE to save files with .py extension by
|
| 1185 |
+
default on Windows and OS X (Tk 8.5) as it already does with X11 Tk.
|
| 1186 |
+
|
| 1187 |
+
- Issue #13532, #15319: Check that arguments to sys.stdout.write are strings.
|
| 1188 |
+
|
| 1189 |
+
- Issue # 12510: Attempt to get certain tool tips no longer crashes IDLE.
|
| 1190 |
+
Erroneous tool tips have been corrected. Default added for callables.
|
| 1191 |
+
|
| 1192 |
+
- Issue #10365: File open dialog now works instead of crashing even when
|
| 1193 |
+
parent window is closed while dialog is open.
|
| 1194 |
+
|
| 1195 |
+
- Issue 14876: use user-selected font for highlight configuration.
|
| 1196 |
+
|
| 1197 |
+
- Issue #14937: Perform auto-completion of filenames in strings even for
|
| 1198 |
+
non-ASCII filenames. Likewise for identifiers.
|
| 1199 |
+
|
| 1200 |
+
- Issue #8515: Set __file__ when run file in IDLE.
|
| 1201 |
+
Initial patch by Bruce Frederiksen.
|
| 1202 |
+
|
| 1203 |
+
- IDLE can be launched as `python -m idlelib`
|
| 1204 |
+
|
| 1205 |
+
- Issue #14409: IDLE now properly executes commands in the Shell window
|
| 1206 |
+
when it cannot read the normal config files on startup and
|
| 1207 |
+
has to use the built-in default key bindings.
|
| 1208 |
+
There was previously a bug in one of the defaults.
|
| 1209 |
+
|
| 1210 |
+
- Issue #3573: IDLE hangs when passing invalid command line args
|
| 1211 |
+
(directory(ies) instead of file(s)).
|
| 1212 |
+
|
| 1213 |
+
- Issue #14018: Update checks for unstable system Tcl/Tk versions on OS X
|
| 1214 |
+
to include versions shipped with OS X 10.7 and 10.8 in addition to 10.6.
|
| 1215 |
+
|
| 1216 |
+
|
| 1217 |
+
What's New in IDLE 3.2.1?
|
| 1218 |
+
=========================
|
| 1219 |
+
*Release date: 15-May-11*
|
| 1220 |
+
|
| 1221 |
+
- Issue #6378: Further adjust idle.bat to start associated Python
|
| 1222 |
+
|
| 1223 |
+
- Issue #11896: Save on Close failed despite selecting "Yes" in dialog.
|
| 1224 |
+
|
| 1225 |
+
- Issue #1028: Ctrl-space binding to show completions was causing IDLE to exit.
|
| 1226 |
+
Tk < 8.5 was sending invalid Unicode null; replaced with valid null.
|
| 1227 |
+
|
| 1228 |
+
- Issue #4676: <Home> toggle failing on Tk 8.5, causing IDLE exits and strange selection
|
| 1229 |
+
behavior. Improve selection extension behaviour.
|
| 1230 |
+
|
| 1231 |
+
- Issue #3851: <Home> toggle non-functional when NumLock set on Windows.
|
| 1232 |
+
|
| 1233 |
+
|
| 1234 |
+
What's New in IDLE 3.1b1?
|
| 1235 |
+
=========================
|
| 1236 |
+
*Release date: 06-May-09*
|
| 1237 |
+
|
| 1238 |
+
- Issue #5707: Use of 'filter' in keybindingDialog.py was causing custom key assignment to
|
| 1239 |
+
fail. Patch by Amaury Forgeot d'Arc.
|
| 1240 |
+
|
| 1241 |
+
- Issue #4815: Offer conversion to UTF-8 if source files have
|
| 1242 |
+
no encoding declaration and are not encoded in UTF-8.
|
| 1243 |
+
|
| 1244 |
+
- Issue #4008: Fix problems with non-ASCII source files.
|
| 1245 |
+
|
| 1246 |
+
- Issue #4323: Always encode source as UTF-8 without asking
|
| 1247 |
+
the user (unless a different encoding is declared); remove
|
| 1248 |
+
user configuration of source encoding; all according to
|
| 1249 |
+
PEP 3120.
|
| 1250 |
+
|
| 1251 |
+
- Issue #2665: On Windows, an IDLE installation upgraded from an old version
|
| 1252 |
+
would not start if a custom theme was defined.
|
| 1253 |
+
|
| 1254 |
+
------------------------------------------------------------------------
|
| 1255 |
+
Refer to NEWS2x.txt and HISTORY.txt for information on earlier releases.
|
| 1256 |
+
------------------------------------------------------------------------
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/idlelib/README.txt
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
README.txt: an index to idlelib files and the IDLE menu.
|
| 2 |
+
|
| 3 |
+
IDLE is Python's Integrated Development and Learning
|
| 4 |
+
Environment. The user documentation is part of the Library Reference and
|
| 5 |
+
is available in IDLE by selecting Help => IDLE Help. This README documents
|
| 6 |
+
idlelib for IDLE developers and curious users.
|
| 7 |
+
|
| 8 |
+
IDLELIB FILES lists files alphabetically by category,
|
| 9 |
+
with a short description of each.
|
| 10 |
+
|
| 11 |
+
IDLE MENU show the menu tree, annotated with the module
|
| 12 |
+
or module object that implements the corresponding function.
|
| 13 |
+
|
| 14 |
+
This file is descriptive, not prescriptive, and may have errors
|
| 15 |
+
and omissions and lag behind changes in idlelib.
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
IDLELIB FILES
|
| 19 |
+
Implementation files not in IDLE MENU are marked (nim).
|
| 20 |
+
Deprecated files and objects are listed separately as the end.
|
| 21 |
+
|
| 22 |
+
Startup
|
| 23 |
+
-------
|
| 24 |
+
__init__.py # import, does nothing
|
| 25 |
+
__main__.py # -m, starts IDLE
|
| 26 |
+
idle.bat
|
| 27 |
+
idle.py
|
| 28 |
+
idle.pyw
|
| 29 |
+
|
| 30 |
+
Implementation
|
| 31 |
+
--------------
|
| 32 |
+
autocomplete.py # Complete attribute names or filenames.
|
| 33 |
+
autocomplete_w.py # Display completions.
|
| 34 |
+
autoexpand.py # Expand word with previous word in file.
|
| 35 |
+
browser.py # Create module browser window.
|
| 36 |
+
calltip_w.py # Display calltip.
|
| 37 |
+
calltips.py # Create calltip text.
|
| 38 |
+
codecontext.py # Show compound statement headers otherwise not visible.
|
| 39 |
+
colorizer.py # Colorize text (nim)
|
| 40 |
+
config.py # Load, fetch, and save configuration (nim).
|
| 41 |
+
configdialog.py # Display user configuration dialogs.
|
| 42 |
+
config_help.py # Specify help source in configdialog.
|
| 43 |
+
config_key.py # Change keybindings.
|
| 44 |
+
dynoption.py # Define mutable OptionMenu widget (nim).
|
| 45 |
+
debugobj.py # Define class used in stackviewer.
|
| 46 |
+
debugobj_r.py # Communicate objects between processes with rpc (nim).
|
| 47 |
+
debugger.py # Debug code run from shell or editor; show window.
|
| 48 |
+
debugger_r.py # Debug code run in remote process.
|
| 49 |
+
delegator.py # Define base class for delegators (nim).
|
| 50 |
+
editor.py # Define most of editor and utility functions.
|
| 51 |
+
filelist.py # Open files and manage list of open windows (nim).
|
| 52 |
+
grep.py # Find all occurrences of pattern in multiple files.
|
| 53 |
+
help.py # Display IDLE's html doc.
|
| 54 |
+
help_about.py # Display About IDLE dialog.
|
| 55 |
+
history.py # Get previous or next user input in shell (nim)
|
| 56 |
+
hyperparser.py # Parse code around a given index.
|
| 57 |
+
iomenu.py # Open, read, and write files
|
| 58 |
+
macosx.py # Help IDLE run on Macs (nim).
|
| 59 |
+
mainmenu.py # Define most of IDLE menu.
|
| 60 |
+
multicall.py # Wrap tk widget to allow multiple calls per event (nim).
|
| 61 |
+
outwin.py # Create window for grep output.
|
| 62 |
+
paragraph.py # Re-wrap multiline strings and comments.
|
| 63 |
+
parenmatch.py # Match fenceposts: (), [], and {}.
|
| 64 |
+
pathbrowser.py # Create path browser window.
|
| 65 |
+
percolator.py # Manage delegator stack (nim).
|
| 66 |
+
pyparse.py # Give information on code indentation
|
| 67 |
+
pyshell.py # Start IDLE, manage shell, complete editor window
|
| 68 |
+
query.py # Query user for information
|
| 69 |
+
redirector.py # Intercept widget subcommands (for percolator) (nim).
|
| 70 |
+
replace.py # Search and replace pattern in text.
|
| 71 |
+
rpc.py # Communicate between idle and user processes (nim).
|
| 72 |
+
rstrip.py # Strip trailing whitespace.
|
| 73 |
+
run.py # Manage user code execution subprocess.
|
| 74 |
+
runscript.py # Check and run user code.
|
| 75 |
+
scrolledlist.py # Define scrolledlist widget for IDLE (nim).
|
| 76 |
+
search.py # Search for pattern in text.
|
| 77 |
+
searchbase.py # Define base for search, replace, and grep dialogs.
|
| 78 |
+
searchengine.py # Define engine for all 3 search dialogs.
|
| 79 |
+
stackviewer.py # View stack after exception.
|
| 80 |
+
statusbar.py # Define status bar for windows (nim).
|
| 81 |
+
tabbedpages.py # Define tabbed pages widget (nim).
|
| 82 |
+
textview.py # Define read-only text widget (nim).
|
| 83 |
+
tree.py # Define tree widget, used in browsers (nim).
|
| 84 |
+
undo.py # Manage undo stack.
|
| 85 |
+
windows.py # Manage window list and define listed top level.
|
| 86 |
+
zoomheight.py # Zoom window to full height of screen.
|
| 87 |
+
|
| 88 |
+
Configuration
|
| 89 |
+
-------------
|
| 90 |
+
config-extensions.def # Defaults for extensions
|
| 91 |
+
config-highlight.def # Defaults for colorizing
|
| 92 |
+
config-keys.def # Defaults for key bindings
|
| 93 |
+
config-main.def # Defaults for font and general tabs
|
| 94 |
+
|
| 95 |
+
Text
|
| 96 |
+
----
|
| 97 |
+
CREDITS.txt # not maintained, displayed by About IDLE
|
| 98 |
+
HISTORY.txt # NEWS up to July 2001
|
| 99 |
+
NEWS.txt # commits, displayed by About IDLE
|
| 100 |
+
README.txt # this file, displayed by About IDLE
|
| 101 |
+
TODO.txt # needs review
|
| 102 |
+
extend.txt # about writing extensions
|
| 103 |
+
help.html # copy of idle.html in docs, displayed by IDLE Help
|
| 104 |
+
|
| 105 |
+
Subdirectories
|
| 106 |
+
--------------
|
| 107 |
+
Icons # small image files
|
| 108 |
+
idle_test # files for human test and automated unit tests
|
| 109 |
+
|
| 110 |
+
Unused and Deprecated files and objects (nim)
|
| 111 |
+
---------------------------------------------
|
| 112 |
+
tooltip.py # unused
|
| 113 |
+
|
| 114 |
+
|
| 115 |
+
|
| 116 |
+
IDLE MENUS
|
| 117 |
+
Top level items and most submenu items are defined in mainmenu.
|
| 118 |
+
Extensions add submenu items when active. The names given are
|
| 119 |
+
found, quoted, in one of these modules, paired with a '<<pseudoevent>>'.
|
| 120 |
+
Each pseudoevent is bound to an event handler. Some event handlers
|
| 121 |
+
call another function that does the actual work. The annotations below
|
| 122 |
+
are intended to at least give the module where the actual work is done.
|
| 123 |
+
'eEW' = editor.EditorWindow
|
| 124 |
+
|
| 125 |
+
File
|
| 126 |
+
New File # eEW.new_callback
|
| 127 |
+
Open... # iomenu.open
|
| 128 |
+
Open Module # eEw.open_module
|
| 129 |
+
Recent Files
|
| 130 |
+
Class Browser # eEW.open_class_browser, browser.ClassBrowser
|
| 131 |
+
Path Browser # eEW.open_path_browser, pathbrowser
|
| 132 |
+
---
|
| 133 |
+
Save # iomenu.save
|
| 134 |
+
Save As... # iomenu.save_as
|
| 135 |
+
Save Copy As... # iomenu.save_a_copy
|
| 136 |
+
---
|
| 137 |
+
Print Window # iomenu.print_window
|
| 138 |
+
---
|
| 139 |
+
Close # eEW.close_event
|
| 140 |
+
Exit # flist.close_all_callback (bound in eEW)
|
| 141 |
+
|
| 142 |
+
Edit
|
| 143 |
+
Undo # undodelegator
|
| 144 |
+
Redo # undodelegator
|
| 145 |
+
--- # eEW.right_menu_event
|
| 146 |
+
Cut # eEW.cut
|
| 147 |
+
Copy # eEW.copy
|
| 148 |
+
Paste # eEW.past
|
| 149 |
+
Select All # eEW.select_all (+ see eEW.remove_selection)
|
| 150 |
+
--- # Next 5 items use searchengine; dialogs use searchbase
|
| 151 |
+
Find # eEW.find_event, search.SearchDialog.find
|
| 152 |
+
Find Again # eEW.find_again_event, sSD.find_again
|
| 153 |
+
Find Selection # eEW.find_selection_event, sSD.find_selection
|
| 154 |
+
Find in Files... # eEW.find_in_files_event, grep
|
| 155 |
+
Replace... # eEW.replace_event, replace.ReplaceDialog.replace
|
| 156 |
+
Go to Line # eEW.goto_line_event
|
| 157 |
+
Show Completions # autocomplete extension and autocompleteWidow (&HP)
|
| 158 |
+
Expand Word # autoexpand extension
|
| 159 |
+
Show call tip # Calltips extension and CalltipWindow (& Hyperparser)
|
| 160 |
+
Show surrounding parens # parenmatch (& Hyperparser)
|
| 161 |
+
|
| 162 |
+
Shell # pyshell
|
| 163 |
+
View Last Restart # pyshell.PyShell.view_restart_mark
|
| 164 |
+
Restart Shell # pyshell.PyShell.restart_shell
|
| 165 |
+
Interrupt Execution # pyshell.PyShell.cancel_callback
|
| 166 |
+
|
| 167 |
+
Debug (Shell only)
|
| 168 |
+
Go to File/Line
|
| 169 |
+
debugger # debugger, debugger_r, PyShell.toggle_debugger
|
| 170 |
+
Stack Viewer # stackviewer, PyShell.open_stack_viewer
|
| 171 |
+
Auto-open Stack Viewer # stackviewer
|
| 172 |
+
|
| 173 |
+
Format (Editor only)
|
| 174 |
+
Indent Region # eEW.indent_region_event
|
| 175 |
+
Dedent Region # eEW.dedent_region_event
|
| 176 |
+
Comment Out Reg. # eEW.comment_region_event
|
| 177 |
+
Uncomment Region # eEW.uncomment_region_event
|
| 178 |
+
Tabify Region # eEW.tabify_region_event
|
| 179 |
+
Untabify Region # eEW.untabify_region_event
|
| 180 |
+
Toggle Tabs # eEW.toggle_tabs_event
|
| 181 |
+
New Indent Width # eEW.change_indentwidth_event
|
| 182 |
+
Format Paragraph # paragraph extension
|
| 183 |
+
---
|
| 184 |
+
Strip tailing whitespace # rstrip extension
|
| 185 |
+
|
| 186 |
+
Run (Editor only)
|
| 187 |
+
Python Shell # pyshell
|
| 188 |
+
---
|
| 189 |
+
Check Module # runscript
|
| 190 |
+
Run Module # runscript
|
| 191 |
+
|
| 192 |
+
Options
|
| 193 |
+
Configure IDLE # eEW.config_dialog, configdialog
|
| 194 |
+
(tabs in the dialog)
|
| 195 |
+
Font tab # config-main.def
|
| 196 |
+
Highlight tab # query, config-highlight.def
|
| 197 |
+
Keys tab # query, config_key, config_keys.def
|
| 198 |
+
General tab # config_help, config-main.def
|
| 199 |
+
Extensions tab # config-extensions.def, corresponding .py
|
| 200 |
+
---
|
| 201 |
+
Code Context (ed)# codecontext extension
|
| 202 |
+
|
| 203 |
+
Window
|
| 204 |
+
Zoomheight # zoomheight extension
|
| 205 |
+
---
|
| 206 |
+
<open windows> # windows
|
| 207 |
+
|
| 208 |
+
Help
|
| 209 |
+
About IDLE # eEW.about_dialog, help_about.AboutDialog
|
| 210 |
+
---
|
| 211 |
+
IDLE Help # eEW.help_dialog, helpshow_idlehelp
|
| 212 |
+
Python Doc # eEW.python_docs
|
| 213 |
+
Turtle Demo # eEW.open_turtle_demo
|
| 214 |
+
---
|
| 215 |
+
<other help sources>
|
| 216 |
+
|
| 217 |
+
<Context Menu> (right click)
|
| 218 |
+
Defined in editor, PyShelpyshellut
|
| 219 |
+
Cut
|
| 220 |
+
Copy
|
| 221 |
+
Paste
|
| 222 |
+
---
|
| 223 |
+
Go to file/line (shell and output only)
|
| 224 |
+
Set Breakpoint (editor only)
|
| 225 |
+
Clear Breakpoint (editor only)
|
| 226 |
+
Defined in debugger
|
| 227 |
+
Go to source line
|
| 228 |
+
Show stack frame
|
| 229 |
+
|
| 230 |
+
<No menu>
|
| 231 |
+
Center Insert # eEW.center_insert_event
|
| 232 |
+
|
| 233 |
+
|
| 234 |
+
CODE STYLE -- Generally PEP 8.
|
| 235 |
+
|
| 236 |
+
import
|
| 237 |
+
------
|
| 238 |
+
Put import at the top, unless there is a good reason otherwise.
|
| 239 |
+
PEP 8 says to group stdlib, 3rd-party dependencies, and package imports.
|
| 240 |
+
For idlelib, the groups are general stdlib, tkinter, and idlelib.
|
| 241 |
+
Sort modules within each group, except that tkinter.ttk follows tkinter.
|
| 242 |
+
Sort 'from idlelib import mod1' and 'from idlelib.mod2 import object'
|
| 243 |
+
together by module, ignoring within module objects.
|
| 244 |
+
Put 'import __main__' after other idlelib imports.
|
| 245 |
+
|
| 246 |
+
Imports only needed for testing are put not at the top but in an
|
| 247 |
+
htest function def or "if __name__ == '__main__'" clause.
|
| 248 |
+
|
| 249 |
+
Within module imports like "from idlelib.mod import class" may cause
|
| 250 |
+
circular imports to deadlock. Even without this, circular imports may
|
| 251 |
+
require at least one of the imports to be delayed until a function call.
|