Pipcl documentation¶
[This is all auto-generated from pipcl doc-comments using sphinx.ext.autodoc, sphinx.ext.autosummary and autodocsumm. ]
pipcl¶
Python packaging operations, including PEP-517 support, for use by a
setup.py script.
Overview:
The intention is to take care of as many packaging details as possible so that setup.py contains only project-specific information, while also giving as much flexibility as possible.
For example we provide a function
pipcl.build_extension()that can be used to build a SWIG extension, but we also give access to the located compiler/linker so that asetup.pyscript can take over the details itself.
- Doctests:
Doctest strings are provided in some comments.
Test in the usual way with:
python -m doctest pipcl.py
Test specific functions/classes with:
python pipcl.py --doctest run_if ...
If no functions or classes are specified, this tests everything.
- Graal:
For Graal we require that PIPCL_GRAAL_PYTHON is set to non-graal Python (we build for non-graal except with Graal Python’s include paths and library directory).
Classes:
|
A context manager to add a temporary prefix to log output. |
|
Detects new/modified/updated files matching a glob pattern. |
|
Represents a Python package. |
Compile/link flags for the current python, for example the include path needed to get |
Functions:
|
|
|
Returns basic compiler command and PythonFlags. |
|
Returns basic linker command. |
|
Builds a Python extension module using SWIG. |
|
Returns generic compiler and linker commands. |
|
Returns CPU wordsize in bits. |
Returns value of PyLIMITED_API to build for current Python. |
|
|
Returns true of we are running on MacOS. |
|
Ensures directory <path> exists. |
|
Ensures <path> is an empty directory. |
|
Ensures parent directory of <path> exists. |
|
Returns size of <filename> or <default> if error (e.g. doesn't exist). |
|
Looks for |
|
Returns string containing contents of file <path>. |
|
Removes file or directory, without raising exception if it doesn't exist. |
|
Removes all items in directory |
|
|
|
Writes <data> to file <path>. |
|
Writes <data> to <path>, ensuring that <path> is created with appropriate permissions. |
|
If we are on Linux and |
|
Converts ISO-8601 text to Unix time. |
|
Creates/updates local checkout <local> of remote repository and returns absolute path of <local>. |
|
Returns |
|
Returns author date (as a Unix time) of HEAD. |
|
Returns committer date (as a Unix time) of HEAD. |
|
Returns python code that defines variables that contain information about a git checkout, typically the checkout that is being used to build a package. :param path: Path of git checkout. :param check: If true we raise if we fail to get git info (e.g. <path> is not a Git checkout), otherwise the returned text sets all variables to None. :param name_branch: Name of variable containing git branch, or false to omit. :param name_comment: Name of variable containing git comment, or false to omit. :param name_diff: Name of variable containing output of git diff, or false to omit. :param name_diff_n: Name of variable containing length of output of git diff. :param name_sha: Name of variable containing git sha, or false to omit. :param prefix: Prefix of each variable name. |
|
Returns list of paths for all files known to git within a |
|
Returns install directory used by |
|
Returns generic compiler and linker commands. |
|
Returns true of we are running on Linux. |
|
Writes <text> to log. |
|
|
|
|
|
|
|
Sets log prefix pattern. |
|
Copies log output to <path>. |
|
Adds path(s) for Brew <package>'s binaries to env['PATH']. |
|
If running on MacOS and environment variables ARCHFLAGS is set (indicating we are cross-building, e.g. for arm64), returns |
|
If running on MacOS, patches |
|
|
|
Returns true of we are running on OpenBSD. |
|
Returns true of we are running on Pyodide. |
Like platform.python_version_tuple() except converts items to integers if possible. |
|
|
A safe alternative to |
|
Runs a command using |
|
Runs a command only if the output file is not up to date. |
Shows contents of |
|
Show useful information about the system plus argv and environ. |
|
|
Returns string converted to int, with configurable behaviour if the string is not convertible. |
|
Returns <swig> or a new swig binary. |
|
Builds required tools for building swig (not Windows). |
Returns include paths and library directory for Python. |
|
|
Returns command that will enter venv, different on Windows vs Unix. |
|
Sets verbose level if |
|
If PIPCL_CHANGE_VERSIONS is set and contains a match for <name>, we return the override version. |
|
Returns a tuple containing each item from <version> converted to an int. |
|
Returns true of we are running on Wasm. |
|
Returns true of we are running on Windows. |
|
Alternative to |
- class pipcl.LogPrefix(prefix)¶
A context manager to add a temporary prefix to log output.
- class pipcl.NewFiles(glob_pattern, recursive=None)¶
Detects new/modified/updated files matching a glob pattern. Useful for detecting wheels created by pip or cubuildwheel etc.
Sets things up to look for new files matching <glob_pattern>. <recursive> is passed to
glob.glob(), so for example set to true if using**.Methods:
get()Returns list of new matches of <glob_pattern> - paths of files that were not present previously, or have different mtimes or have different contents.
get_n(n)Returns new files matching <glob_pattern>, asserting that there are exactly <n>.
get_one()Returns new match of <glob_pattern>, asserting that there is exactly one.
- get()¶
Returns list of new matches of <glob_pattern> - paths of files that were not present previously, or have different mtimes or have different contents.
- get_n(n)¶
Returns new files matching <glob_pattern>, asserting that there are exactly <n>.
- get_one()¶
Returns new match of <glob_pattern>, asserting that there is exactly one.
- class pipcl.Package(
- name,
- version,
- *,
- author=None,
- author_email=None,
- classifier=None,
- description=None,
- description_content_type=None,
- download_url=None,
- home_page=None,
- keywords=None,
- license=None,
- maintainer=None,
- maintainer_email=None,
- platform=None,
- project_url=None,
- provides_extra=None,
- requires_dist=None,
- requires_external=None,
- requires_python=None,
- summary=None,
- supported_platform=None,
- entry_points=None,
- fn_build=None,
- fn_clean=None,
- fn_sdist=None,
- pure=False,
- py_limited_api=None,
- tag_python=None,
- tag_abi=None,
- tag_platform=None,
- root=None,
- wheel_compression=8,
- wheel_compresslevel=None,
Represents a Python package.
The constructor takes a definition of a Python package similar to that passed to
distutils.core.setup()orsetuptools.setup()(name, version, summary etc) plus callbacks for building, getting a list of sdist filenames, and cleaning.Methods are provided that can be used to implement a Python package’s
setup.pysupporting PEP-517.Basic command line handling is also supported for use with a legacy (pre-PEP-517) pip, as implemented by legacy distutils/setuptools and described in: https://pip.pypa.io/en/stable/reference/build-system/setup-py/
The file pyproject.toml must exist; this is checked if/when
fn_build()is called.Here is a
doctestexample of using pipcl to create a SWIG extension module called ‘foo’, with a console-script command line tool calledcli. Requiresswig.Create an empty test directory:
>>> import os >>> import shutil >>> shutil.rmtree('pipcl_test', ignore_errors=1) >>> os.mkdir('pipcl_test')
Create a
setup.pywhich usespipclto define an extension module.>>> import textwrap >>> with open('pipcl_test/setup.py', 'w') as f: ... _ = f.write(textwrap.dedent(""" ... import sys ... import pipcl ... ... def build(): ... so_leaf = pipcl.build_extension( ... name = 'foo', ... path_i = 'foo.i', ... outdir = 'build', ... source_extra = 'wibble.c', ... ) ... return [ ... ('build/foo.py', 'foo/__init__.py'), ... ('cli.py', 'foo/__main__.py'), ... (f'build/{so_leaf}', f'foo/'), ... (b'Hello world', 'foo/hw.txt'), ... ] ... ... def sdist(): ... return [ ... 'foo.i', ... 'bar.i', ... 'wibble.c', ... 'setup.py', ... 'pipcl.py', ... 'pyproject.toml', ... 'wdev.py', ... 'README', ... ] ... ... p = pipcl.Package( ... name = 'foo', ... version = '1.2.3', ... description = 'README', ... fn_build = build, ... fn_sdist = sdist, ... entry_points = ( ... { 'console_scripts': [ ... 'foo_cli = foo.__main__:main', ... ], ... }), ... ) ... ... build_wheel = p.build_wheel ... build_sdist = p.build_sdist ... ... # Handle old-style setup.py command-line usage: ... if __name__ == '__main__': ... p.handle_argv(sys.argv) ... """))
Create the files required by the above
setup.py- pyproject.toml, the SWIG.iinput file, the README file, and copies ofpipcl.pyandwdev.py.>>> with open('pipcl_test/pyproject.toml', 'w') as f: ... _ = f.write(textwrap.dedent(""" ... [build-system] ... requires = [] ... ... # See pep-517. ... # ... build-backend = "setup" ... backend-path = ["."] ... """))
>>> with open('pipcl_test/foo.i', 'w') as f: ... _ = f.write(textwrap.dedent(""" ... %include bar.i ... %{ ... #include <stdio.h> ... #include <string.h> ... int bar(const char* text) ... { ... printf("bar(): text: %s\\n", text); ... int len = (int) strlen(text); ... printf("bar(): len=%i\\n", len); ... fflush(stdout); ... return len; ... } ... %} ... int bar(const char* text); ... """))
>>> with open('pipcl_test/bar.i', 'w') as f: ... _ = f.write( '\n')
>>> with open('pipcl_test/wibble.c', 'w') as f: ... _ = f.write( '\n')
>>> with open('pipcl_test/README', 'w') as f: ... _ = f.write(textwrap.dedent(""" ... This is Foo. ... """))
>>> with open('pipcl_test/cli.py', 'w') as f: ... _ = f.write(textwrap.dedent(""" ... def main(): ... print('pipcl_test:main().') ... if __name__ == '__main__': ... main() ... """))
>>> root = os.path.dirname(__file__) >>> _ = shutil.copy2(f'{root}/pipcl.py', 'pipcl_test/pipcl.py') >>> _ = shutil.copy2(f'{root}/wdev.py', 'pipcl_test/wdev.py')
Use
setup.py’s command-line interface to build and install the extension module into rootpipcl_test/install.>>> _ = subprocess.run( ... f'cd pipcl_test && {sys.executable} setup.py --root install install', ... shell=1, check=1)
The actual install directory depends on
sysconfig.get_path('platlib'):>>> if windows(): ... install_dir = 'pipcl_test/install' ... else: ... install_dir = f'pipcl_test/install/{sysconfig.get_path("platlib").lstrip(os.sep)}' >>> assert os.path.isfile( f'{install_dir}/foo/__init__.py')
Create a test script which asserts that Python function call
foo.bar(s)returns the length ofs, and run it withPYTHONPATHset to the install directory:>>> with open('pipcl_test/test.py', 'w') as f: ... _ = f.write(textwrap.dedent(""" ... import sys ... import foo ... text = 'hello' ... print(f'test.py: calling foo.bar() with text={text!r}') ... sys.stdout.flush() ... l = foo.bar(text) ... print(f'test.py: foo.bar() returned: {l}') ... assert l == len(text) ... """)) >>> r = subprocess.run( ... f'{sys.executable} pipcl_test/test.py', ... shell=1, check=1, text=1, ... stdout=subprocess.PIPE, stderr=subprocess.STDOUT, ... env=os.environ | dict(PYTHONPATH=install_dir), ... ) >>> print(r.stdout) test.py: calling foo.bar() with text='hello' bar(): text: hello bar(): len=5 test.py: foo.bar() returned: 5
Check that building sdist and wheel succeeds. For now we don’t attempt to check that the sdist and wheel actually work.
>>> _ = subprocess.run( ... f'cd pipcl_test && {sys.executable} setup.py sdist', ... shell=1, check=1)
>>> _ = subprocess.run( ... f'cd pipcl_test && {sys.executable} setup.py bdist_wheel', ... shell=1, check=1)
Check that rebuild does nothing.
>>> t0 = os.path.getmtime('pipcl_test/build/foo.py') >>> _ = subprocess.run( ... f'cd pipcl_test && {sys.executable} setup.py bdist_wheel', ... shell=1, check=1) >>> t = os.path.getmtime('pipcl_test/build/foo.py') >>> assert t == t0
Check that touching bar.i forces rebuild.
>>> os.utime('pipcl_test/bar.i') >>> _ = subprocess.run( ... f'cd pipcl_test && {sys.executable} setup.py bdist_wheel', ... shell=1, check=1) >>> t = os.path.getmtime('pipcl_test/build/foo.py') >>> assert t > t0
Check that touching foo.i.cpp does not run swig, but does recompile/link.
>>> so_suffix = 'pyd' if windows() else 'so' >>> t0 = time.time() >>> os.utime('pipcl_test/build/foo.i.cpp') >>> _ = subprocess.run( ... f'cd pipcl_test && {sys.executable} setup.py bdist_wheel', ... shell=1, check=1) >>> assert os.path.getmtime('pipcl_test/build/foo.py') <= t0 >>> so = glob.glob(f'pipcl_test/build/*.{so_suffix}') >>> assert len(so) == 1, f'{so_suffix=} {so=} {os.path.abspath(".")=}' >>> so = so[0] >>> assert os.path.getmtime(so) > t0
Check that touching wibbble.c does not run swig, but does recompile/link.
>>> t0 = time.time() >>> os.utime('pipcl_test/wibble.c') >>> _ = subprocess.run( ... f'cd pipcl_test && {sys.executable} setup.py bdist_wheel', ... shell=1, check=1) >>> assert os.path.getmtime('pipcl_test/build/foo.py') <= t0 >>> so = glob.glob(f'pipcl_test/build/*.{so_suffix}') >>> assert len(so) == 1 >>> so = so[0] >>> assert os.path.getmtime(so) > t0
Check
entry_pointscauses creation of commandfoo_cliwhen we install from our wheel using pip. [As of 2024-02-24 using pipcl’s CLI interface directly withsetup.py installdoes not support entry points.]>>> print('Creating venv.', file=sys.stderr) >>> _ = subprocess.run( ... f'cd pipcl_test && {sys.executable} -m venv pylocal', ... shell=1, check=1)
>>> print('Installing from wheel into venv using pip.', file=sys.stderr) >>> whl = glob.glob(f'pipcl_test/dist/*.whl')[0] >>> _ = subprocess.run(f'{venv_enter_cmd("pipcl_test/pylocal")} && pip install {whl}', ... shell=1, check=1)
>>> print('Running foo_cli.', file=sys.stderr) >>> _ = subprocess.run( ... f'{venv_enter_cmd("pipcl_test/pylocal")} && foo_cli', ... shell=1, check=1)
Check that wheel contents’ unix permissions are readable by all.
>>> wheel_path = glob.glob('pipcl_test/dist/*.whl')[0] >>> with zipfile.ZipFile(wheel_path) as z: ... for zi in z.infolist(): ... external_attr_lo = zi.external_attr & 15 ... external_attr_hi = zi.external_attr >> 16 ... assert external_attr_lo + (external_attr_hi << 16) == zi.external_attr ... assert external_attr_hi & 0o444 == 0o444, ( ... f'info.external_attr not readable by all:' ... f' {zi.external_attr=:#x}' ... f' {external_attr_hi=:#o}' ... f' {external_attr_lo=:#o}' ... f' {zi.filename=}' ... )
Wheels and sdists
- Wheels:
We generate wheels according to: https://packaging.python.org/specifications/binary-distribution-format/
{name}-{version}.dist-info/RECORDuses sha256 hashes.Other
RECORD*files such asRECORD.jwsorRECORD.p7sare not generated.{name}-{version}.dist-info/WHEELhas:Wheel-Version: 1.0Root-Is-Purelib: false
No support for signed wheels.
- Sdists:
We generate sdist’s according to: https://packaging.python.org/specifications/source-distribution-format/
The initial args before
entry_pointsdefine the package metadata and closely follow the definitions in: https://packaging.python.org/specifications/core-metadata/- Parameters:
name – Used for metadata
Name. A string, the name of the Python package.version –
Used for metadata
Version. A string, the version of the Python package. Also see PEP-440Version Identification and Dependency Specification.- Special handling of PIPCL_CHANGE_VERSIONS:
If environment variable PIPCL_CHANGE_VERSIONS is set, it is used to override
version. PIPCL_CHANGE_VERSIONS should contain one or more lines matching:<package-name-regex> <new-version>
If any line’s <package-name-regex> matches <name>, then <version> is changed to the line’s <new-version>.
For example if foo/ contains a package called foo that uses pipcl, then this:
$ export PIPCL_CHANGE_VERSIONS=’ > ^foo$ 1.2.3.4 > ^bar$ 3.4.5 ‘ $ pip wheel foo/ … $
Will create a foo wheel with version 1.2.3.4, regardless of what version is specified in foo/setup.py.
Any dependency of package foo on package bar, will be changed to
bar==3.4.5.
Note that if <package-name-regex> is not in the form
^...$, it may match extra unintended package names.
author – Used for metadata
Author. Author name.author_email – Used for metadata
Author-email. Author email.classifier –
Used for metadata
Classifier. A string or list of strings. Also see:description – Used for metadata
Description. A string. If contains newlines, a detailed description of the package. Otherwise the path of a file containing the detailed description of the package.description_content_type – Used for metadata
Description-Content-Type. A string describing markup ofdescriptionarg. For exampletext/markdown; variant=GFM. If not specified we try to infer a value from <description> file suffix.download_url – Used for metadata
Download-URL. Where this version can be downloaded from. Deprecated since metadata-1.2 - use project_url.home_page – Used for metadata
Home-page. URL of home page. Deprecated since metadata-1.2 - use project_url.keywords – Used for metadata
Keywords. A string containing comma-separated keywords.license – Used for metadata
License. A string containing the license text. Written into metadata fileCOPYING. Is also written into metadata itself if not multi-line.maintainer – Used for metadata
Maintainer. Maintainer.maintainer_email – Used for metadata
Maintainer-email. Maintainer email.platform – Used for metadata
Platform. A string or list of strings.project_url – Used for metadata
Project-URL. A string or list of strings, each of the form:{name}, {url}. Well-known names include: homepage, source, documentation, issues; for more details, see: https://packaging.python.org/en/latest/specifications/well-known-project-urls/#well-known-project-urlsprovides_extra – Used for metadata
Provides-Extra. A string or list of strings.requires_dist –
Used for metadata
Requires-Dist. A string or list of strings, Python packages required at runtime. None items are ignored.If environment variable PIPCL_CHANGE_VERSIONS is set, version numbers for matching items in <requires_dist> will be overridden - see description of <version> for details. (This will overwrite matching requirements to be in the simple form
<name>==; any other elements will be lost.)requires_external – Used for metadata
Requires-External. A string or list of strings.requires_python – Used for metadata
Requires-Python. A string or list of strings.summary – Used for metadata
Summary. A string, short description of the package.supported_platform – Used for metadata
Supported-Platform. A string or list of strings.entry_points –
A string specifying *.dist-info/entry_points.txt, for example:
[console_scripts] foo_cli = foo.__main__:main
See: https://packaging.python.org/en/latest/specifications/entry-points/
Alternatively one can specify a dict similar to that supported by setuptools (see https://setuptools.pypa.io/en/latest/userguide/entry_point.html):
{ 'console_scripts': [ 'foo_cli = foo.__main__:main', ], }
fn_build –
A function taking no args, or a single
config_settingsdict arg (as described in PEP-517). This should build all required files and return a list of items; each item should be a tuple(from_, to_), or a single stringpathwhich is treated as the tuple(path, path).from_can be a string or abytes. If a string it should be the path to a file; a relative path is treated as relative toroot. If abytesit is the contents of the file to be added.to_identifies what the file should be called within a wheel or when installing. Ifto_is empty or/we set it to the leaf offrom_(from_must not be abytes) - i.e. we place the file in the root directory of the wheel; otherwise ifto_ends with/the leaf offrom_is appended to it (andfrom_must not be abytes).Initial
$dist-info/in_tois replaced by{name}-{version}.dist-info/; this is useful for license files etc.Initial
$data/in_tois replaced by{name}-{version}.data/. We do not enforce particular subdirectories, instead it is up tofn_build()to specify specific subdirectories such aspurelib,headers,scripts,dataetc.If we are building a wheel (e.g.
python setup.py bdist_wheel, or PEP-517 pip callsself.build_wheel()), we add filefrom_to the wheel archive with nameto_.If we are installing (e.g.
installcommand in the argv passed toself.handle_argv()), then we copyfrom_to{sitepackages}/{to_}, wheresitepackagesis the installation directory, the default beingsysconfig.get_path('platlib')e.g.myvenv/lib/python3.9/site-packages/.When calling this function, we assert that the file pyproject.toml exists in the current directory. (We do this here rather than in pipcl.Package’s constructor, as otherwise importing setup.py from non-package-related code could fail.)
fn_clean –
A function taking a single arg
all_that cleans generated files.all_is true iff--allis in argv.For safety and convenience, can also returns a list of files/directory paths to be deleted. Relative paths are interpreted as relative to
root. All paths are asserted to be withinroot.fn_sdist –
A function taking no args, or a single
config_settingsdict arg (as described in PEP517), that returns a list of items to be copied into the sdist. The list should be in the same format as returned byfn_build.It can be convenient to use
pipcl.git_items().The specification for sdists requires that the list contains
pyproject.toml; we enforce this with a Python assert.pure – If true we mark wheels as pure python - for example default wheel tag will be
py3-none-any.py_limited_api – If true we build extension modules that use the Python Limited API. We use the version of
sys.executableto definePy_LIMITED_APIwhen compiling extensions, and use ABI tagabi3in the wheel name if argumenttag_abiis None.tag_python – First element of wheel tag defined in PEP-425. If None we use
cp{version}.tag_abi – Second element of wheel tag defined in PEP-425. If None we use
none.tag_platform – Third element of wheel tag defined in PEP-425. Default is
os.environ('AUDITWHEEL_PLAT')if set, otherwise derived fromsysconfig.get_platform()(wassetuptools.distutils.util.get_platform(), before thatdistutils.util.get_platform()as specified in the PEP), e.g.openbsd_7_0_amd64.root – Root of package, defaults to current directory.
wheel_compression – Used as
zipfile.ZipFile()’scompressionparameter when creating wheels.
Occurrences of
Nonein lists are ignored.Methods:
build_sdist(sdist_directory, formats[, ...])A PEP-517
build_sdist()function.build_wheel(wheel_directory[, ...])A PEP-517
build_wheel()function.handle_argv(argv)Attempt to handle old-style (pre PEP-517) command line passed by old releases of pip to a
setup.pyscript, and manual running ofsetup.py.install([record_path, root])Called by
handle_argv()to handleinstallcommand..tag_abi()ABI tag.
Find platform tag used in wheel filename.
Get two-digit python version, e.g. 'cp3.8' for python-3.8.6.
wheel_name_match(wheel)Returns true if
wheelmatches our wheel.Returns <tag_python>-<tag_abi>-<tag_platform>.
- build_sdist(
- sdist_directory,
- formats,
- config_settings=None,
A PEP-517
build_sdist()function.Also called by
handle_argv()to handle thesdistcommand.Returns leafname of generated archive within
sdist_directory.
- build_wheel(
- wheel_directory,
- config_settings=None,
- metadata_directory=None,
A PEP-517
build_wheel()function.Also called by
handle_argv()to handle thebdist_wheelcommand.Returns leafname of generated wheel within
wheel_directory.
- handle_argv(argv)¶
Attempt to handle old-style (pre PEP-517) command line passed by old releases of pip to a
setup.pyscript, and manual running ofsetup.py.This is partial support at best.
- install(
- record_path=None,
- root=None,
Called by
handle_argv()to handleinstallcommand..
- tag_abi()¶
ABI tag.
- tag_platform()¶
Find platform tag used in wheel filename.
- tag_python()¶
Get two-digit python version, e.g. ‘cp3.8’ for python-3.8.6.
- wheel_name()¶
- wheel_name_match(wheel)¶
Returns true if
wheelmatches our wheel. We basically require the name to be the same, except that we accept platform tags that contain extra items (see pep-0600/), for example we return true with:self: foo-cp38-none-manylinux2014_x86_64.whl wheel: foo-cp38-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- wheel_tag_string()¶
Returns <tag_python>-<tag_abi>-<tag_platform>.
- class pipcl.PythonFlags¶
Compile/link flags for the current python, for example the include path needed to get
Python.h.The ‘PIPCL_PYTHON_CONFIG’ environment variable allows to override the location of the python-config executable.
- Members:
- .includes:
String containing compiler flags for include paths.
- .ldflags:
String containing linker flags for library paths.
- pipcl.any_cpp(source_paths)¶
- pipcl.base_compiler(
- vs=None,
- pythonflags=None,
- cpp=False,
- use_env=True,
Returns basic compiler command and PythonFlags.
- Parameters:
vs – Windows only. A
wdev.WindowsVSinstance or None to use defaultwdev.WindowsVSinstance.pythonflags – A
pipcl.PythonFlagsinstance or None to use defaultpipcl.PythonFlagsinstance.cpp – If true we return C++ compiler command instead of C. On Windows this has no effect - we always return
cl.exe.use_env – If true we return ‘$CC’ or ‘$CXX’ if the corresponding environmental variable is set (without evaluating with
os.getenv()oros.environ).
- Returns
(cc, pythonflags): - cc:
C or C++ command. On Windows this is of the form
{vs.vcvars}&&{vs.cl}; otherwise it is typicallyccorc++.- pythonflags:
The
pythonflagsarg or a newpipcl.PythonFlagsinstance.
- pipcl.base_linker(
- vs=None,
- pythonflags=None,
- cpp=False,
- use_env=True,
Returns basic linker command.
- Parameters:
vs – Windows only. A
wdev.WindowsVSinstance or None to use defaultwdev.WindowsVSinstance.pythonflags – A
pipcl.PythonFlagsinstance or None to use defaultpipcl.PythonFlagsinstance.cpp – If true we return C++ linker command instead of C. On Windows this has no effect - we always return
link.exe.use_env – If true we use
os.environ['LD']if set.
- Returns
(linker, pythonflags): - linker:
Linker command. On Windows this is of the form
{vs.vcvars}&&{vs.link}; otherwise it is typicallyccorc++.- pythonflags:
The
pythonflagsarg or a newpipcl.PythonFlagsinstance.
- pipcl.build_extension(
- name,
- path_i,
- outdir,
- *,
- builddir=None,
- includes=None,
- defines=None,
- libpaths=None,
- libs=None,
- optimise=True,
- debug=False,
- compiler_extra='',
- compiler_extra_cpp='',
- linker_extra='',
- swig=None,
- cpp=True,
- source_extra=None,
- prerequisites_swig=None,
- prerequisites_compile=None,
- prerequisites_link=None,
- infer_swig_includes=True,
- py_limited_api=False,
- nogil=False,
Builds a Python extension module using SWIG. Works on Windows, Linux, MacOS and OpenBSD.
On Unix, sets rpath when linking shared libraries.
- Parameters:
name – Name of generated extension module.
path_i – Path of input SWIG
.ifile. Internally we use swig to generate a corresponding.cor.cppfile.outdir –
Output directory for generated files:
{outdir}/{name}.py{outdir}/_{name}.so# Unix{outdir}/_{name}.*.pyd# Windows
We return the leafname of the
.soor.pydfile.builddir – Where to put intermediate files, for example the .cpp file generated by swig and
.ddependency files. Default isoutdir.includes – A string, or a sequence of extra include directories to be prefixed with
-I.defines – A string, or a sequence of extra preprocessor defines to be prefixed with
-D.libpaths – A string, or a sequence of library paths to be prefixed with
/LIBPATH:on Windows or-Lon Unix.libs – A string, or a sequence of library names. Each item is prefixed with
-lon non-Windows.optimise – Whether to use compiler optimisations and define NDEBUG.
debug – Whether to build with debug symbols.
compiler_extra – Extra compiler flags. Can be None.
compiler_extra_cpp – Extra c++ compiler flags. Can be None.
linker_extra – Extra linker flags. Can be None.
swig – Swig command; if false we use ‘swig’.
cpp – If true we tell SWIG to generate C++ code instead of C.
source_extra – Extra source files to build into the shared library,
prerequisites_swig
prerequisites_compile
prerequisites_link –
[These are mainly for use on Windows. On other systems we automatically generate dynamic dependencies using swig/compile/link commands’
-MDand-MFargs.]Sequences of extra input files/directories that should force running of swig, compile or link commands if they are newer than any existing generated SWIG
.ifile, compiled object file or shared library file.If present, the first occurrence of
TrueorFalseforces re-run or no re-run. Any occurrence of None is ignored. If an item is a directory path we look for newest file within the directory tree.If not a sequence, we convert into a single-item list.
prerequisites_swig
We use swig’s -MD and -MF args to generate dynamic dependencies automatically, so this is not usually required.
prerequisites_compile prerequisites_link
On non-Windows we use cc’s -MF and -MF args to generate dynamic dependencies so this is not usually required.
infer_swig_includes – If true, we extract
-Iand-Iargs fromcompile_extra(also/Ion windows) and use them with swig so that it can see the same header files as C/C++. This is useful when using enviromment variables such asCCandCXXto setcompile_extra.py_limited_api –
If true we build for current Python’s limited API / stable ABI.
Note that we will assert false if this extension is added to a pipcl.Package that has a different <py_limited_api>, because on Windows importing a non-py_limited_api extension inside a py_limited=True package fails.
nogil – If true we use swig’s
-nogilflag which marks the extension as being thread safe.
Returns the leafname of the generated library file within
outdir, e.g._{name}.soon Unix or_{name}.cp311-win_amd64.pydon Windows.
- pipcl.compiler_command(
- *,
- includes=None,
- defines=None,
- optimise=True,
- debug=False,
- compiler_extra='',
- compiler_extra_cpp='',
- cpp=None,
- python=False,
- py_limited_api=False,
- rpath=False,
- source_paths=None,
- path_o=None,
Returns generic compiler and linker commands. Used by
build_extension().- Parameters:
includes – A string, or a sequence of extra include directories to be prefixed with
-I.defines – A string, or a sequence of extra preprocessor defines to be prefixed with
-D.optimise – Whether to use compiler optimisations and define NDEBUG.
debug – Whether to build with debug symbols.
compiler_extra – Extra compiler flags. Can be None.
compiler_extra – Extra c++ compiler flags. Can be None.
cpp – If true we tell SWIG to generate C++ code instead of C. If None we use suffix of items in <source_paths>.
python –
If true: * We include flags for using Python headers and libraries. * We predefine Py_GIL_DISABLED if
sysconfig.get_config_var(‘Py_GIL_DISABLED’)==1 (i.e. free-thread build).
py_limited_api –
If true we build for current Python’s limited API / stable ABI.
Note that we will assert false if this extension is added to a pipcl.Package that has a different <py_limited_api>, because on Windows importing a non-py_limited_api extension inside a py_limited=True package fails.
- pipcl.cpu_bits()¶
Returns CPU wordsize in bits.
- pipcl.current_py_limited_api()¶
Returns value of PyLIMITED_API to build for current Python.
- pipcl.darwin()¶
Returns true of we are running on MacOS.
- pipcl.fs_ensure_dir(path)¶
Ensures directory <path> exists.
- pipcl.fs_ensure_empty_dir(path)¶
Ensures <path> is an empty directory.
- pipcl.fs_ensure_parent_dir(path)¶
Ensures parent directory of <path> exists.
- pipcl.fs_filesize(filename, default=0)¶
Returns size of <filename> or <default> if error (e.g. doesn’t exist).
- pipcl.fs_find_in_paths(
- name,
- paths=None,
- verbose=False,
Looks for
namein paths and returns complete path.pathsis list/tuple oros.pathsep-separated string; ifNonewe use$PATH. Ifnamecontains/, we returnnameitself if it is a file or None, regardless of <paths>.
- pipcl.fs_read(path, binary=False)¶
Returns string containing contents of file <path>. Returns bytes if <binary> is true.
- pipcl.fs_remove(path)¶
Removes file or directory, without raising exception if it doesn’t exist.
We assert-fail if the path still exists when we return, in case of permission problems etc.
- pipcl.fs_remove_dir_contents(path)¶
Removes all items in directory
path; does not removepathitself.
- pipcl.fs_write(path, data, binary=False)¶
Writes <data> to file <path>.
- pipcl.fs_write_key(path, data)¶
Writes <data> to <path>, ensuring that <path> is created with appropriate permissions.
- pipcl.get_soname(path)¶
If we are on Linux and
pathis softlink and points to a shared library for whichobjdump -pcontains ‘SONAME’, return the pointee. Otherwise returnpath. Useful if Linux shared libraries have been created with-Wl,-soname,..., where we need to embed the versioned library.
- pipcl.get_time_iso_8601(text)¶
Converts ISO-8601 text to Unix time.
- pipcl.git_get(
- local,
- *,
- remote=None,
- branch=None,
- tag=None,
- sha=None,
- text=None,
- depth=1,
- env_extra=None,
- update=True,
- submodules=True,
- devel=1,
- key=None,
- keyfile=None,
- clone_extra=None,
Creates/updates local checkout <local> of remote repository and returns absolute path of <local>.
If <text> is set but does not start with ‘git:’, it is assumed to be an up to date local checkout, and we return absolute path of <text> without doing any git operations.
- Parameters:
local – Local directory. Created and/or updated using
git cloneandgit fetchetc.remote – Remote git repostitory, for example ‘https://github.com/ArtifexSoftware/mupdf.git’. Can be overridden by <text>.
branch – Branch to use; can be overridden by <text>.
tag – Tag to use; can be overridden by <text>.
sha – Use this sha; must be the full length sha, e.g.
5ea4449c3edba8840d5c27e15095536cbfc7c1ftext –
- If None or empty:
Ignored.
- If starts with ‘git:’:
The remaining text should be a command-line style string containing some or all of these args:
-b|–branch <branch> -t|-tag <tag> –depth <depth> <remote>
These overrides <branch>, <tag>, <remote> and <depth>.
- Otherwise:
<text> is assumed to be a local directory, and we simply return it as an absolute path without doing any git operations.
For example these all clone/update/branch master of https://foo.bar/qwerty.git to local checkout ‘foo-local’:
git_get(‘foo-local’, remote=’https://foo.bar/qwerty.git’, branch=’master’) git_get(‘foo-local’, text=’git:–branch master https://foo.bar/qwerty.git’) git_get(‘foo-local’, text=’git:–branch master’, remote=’https://foo.bar/qwerty.git’) git_get(‘foo-local’, text=’git:’, branch=’master’, remote=’https://foo.bar/qwerty.git’)
depth – Depth of local checkout when cloning and fetching, or None.
env_extra – Dict of extra name=value environment variables to use whenever we run git.
update – If false we do not update existing repository. Might be useful if testing without network access.
submodules – If true, we clone with
--recursive --shallow-submodulesand rungit submodule update --init --recursivebefore returning.key – Ssh key to use.
keyfile – Ssh key file to use. Only used if <key> is None.
clone_extra – If true, is added to any
git clonecommand. For exampleclone_extra='--config core.autocrlf=input'to avoid converting text files to Windows line endings.
- pipcl.git_info(directory)¶
Returns
(sha, comment, diff, branch), all items are str or None if not available. <comment> is the first line of the commit message.- directory:
Root of git checkout.
- pipcl.git_info_author_date(directory)¶
Returns author date (as a Unix time) of HEAD.
- pipcl.git_info_committer_date(directory)¶
Returns committer date (as a Unix time) of HEAD.
- pipcl.git_info_py(
- path,
- *,
- check=True,
- name_branch='branch',
- name_comment='comment',
- name_diff='diff',
- name_diff_n='diff_n',
- name_sha='sha',
- prefix='git_',
Returns python code that defines variables that contain information about a git checkout, typically the checkout that is being used to build a package. :param path: Path of git checkout. :param check: If true we raise if we fail to get git info (e.g. <path> is not a
Git checkout), otherwise the returned text sets all variables to None.
- Parameters:
name_branch – Name of variable containing git branch, or false to omit.
name_comment – Name of variable containing git comment, or false to omit.
name_diff – Name of variable containing output of git diff, or false to omit.
name_diff_n – Name of variable containing length of output of git diff.
name_sha – Name of variable containing git sha, or false to omit.
prefix – Prefix of each variable name.
- Example output:
git_branch = ‘main’ comment = ‘Add wibble’ git_diff = ‘’ git_diff_n = 0 git_sha = ‘aa00d79773e1e3c4176b59ac76bfef89830bd289’
- pipcl.git_items(directory, submodules=False)¶
Returns list of paths for all files known to git within a
directory.- Parameters:
directory – Must be somewhere within a git checkout.
submodules – If true we also include git submodules.
- Returns:
A list of paths for all files known to git within
directory. Each path is relative todirectory.directorymust be somewhere within a git checkout.
We run a
git ls-filescommand internally.This function can be useful for the
fn_sdist()callback.
- pipcl.install_dir(root=None)¶
Returns install directory used by
install().This will be
sysconfig.get_path('platlib'), modified byrootif not None.
- pipcl.linker_command(
- *,
- libpaths=None,
- libs=None,
- optimise=True,
- debug=False,
- linker_extra='',
- cpp=True,
- python=False,
- py_limited_api=False,
- rpath=False,
- path_os=None,
- path_out=None,
Returns generic compiler and linker commands. Used by
build_extension().- Parameters:
libpaths – A string, or a sequence of library paths to be prefixed with
/LIBPATH:on Windows or-Lon Unix.libs – A string, or a sequence of library names. Each item is prefixed with
-lon non-Windows.optimise – Whether to use compiler optimisations and define NDEBUG.
debug – Whether to build with debug symbols.
linker_extra – Extra linker flags. Can be None.
cpp –
.
python – If true we include flags for using Python headers and libraries.
py_limited_api –
If true we build for current Python’s limited API / stable ABI.
Note that we will assert false if this extension is added to a pipcl.Package that has a different <py_limited_api>, because on Windows importing a non-py_limited_api extension inside a py_limited=True package fails.
rpath – If true we include an rpath arg to linker command, and patch up libraries on MacOS.
- pipcl.linux()¶
Returns true of we are running on Linux.
- pipcl.log(text='', caller=1)¶
Writes <text> to log. Caller identifies the frame to use if file:line is included in prefix; default 1 identifies the caller.
- pipcl.log0(text='', caller=1)¶
- pipcl.log1(text='', caller=1)¶
- pipcl.log2(text='', caller=1)¶
- pipcl.log_prefix(pattern)¶
Sets log prefix pattern.
- pipcl.log_tee(path, path_simple=None)¶
Copies log output to <path>. If path_simple is specified, on exit we make a convenience symlink from <path_simple> to <path>.
- pipcl.macos_add_brew_path(
- package,
- env=None,
- gnubin=True,
Adds path(s) for Brew <package>’s binaries to env[‘PATH’].
We assert-fail if the relevant directory does no exist.
- Parameters:
package – Name of package. We get <package_root> of installed package by running
brew --prefix.env – The environment dict to modify. If None we use os.environ. If PATH is not in <env>, we first copy os.environ[‘PATH’] into <env>.
gnubin – If true, we also add path to gnu binaries if it exists, <package_root>/libexe/gnubin.
- pipcl.macos_add_cross_flags(command)¶
If running on MacOS and environment variables ARCHFLAGS is set (indicating we are cross-building, e.g. for arm64), returns
commandwith extra flags appended. Otherwise returns unchangedcommand.
- pipcl.macos_patch(library, *sublibraries)¶
If running on MacOS, patches
libraryso that all references to items insublibrariesare changed to@rpath/{leafname}. Does nothing on other platforms.- library:
Path of shared library.
- sublibraries:
List of paths of shared libraries; these have typically been specified with
-lwhenlibrarywas created.
- pipcl.macos_patch2(path_so, libpaths, libs)¶
- pipcl.openbsd()¶
Returns true of we are running on OpenBSD.
- pipcl.pyodide()¶
Returns true of we are running on Pyodide.
- pipcl.python_version_tuple()¶
Like platform.python_version_tuple() except converts items to integers if possible.
- pipcl.relpath(path, start=None, allow_up=True)¶
A safe alternative to
os.path.relpath(), avoiding an exception on Windows if the drive needs to change - in this case we useos.path.abspath().- Parameters:
path – Path to be processed.
start – Start directory or current directory if None.
allow_up – If false we return absolute path is <path> is not within <start>.
- pipcl.run(
- command,
- *,
- capture=False,
- check=1,
- verbose=1,
- env=None,
- env_extra=None,
- timeout=None,
- caller=1,
- prefix=None,
- encoding=None,
- errors='backslashreplace',
- ticker=0,
- out=None,
- tee=None,
- log=None,
Runs a command using
subprocess.run().- Parameters:
command –
A string command to run or list of string args to run.
- If a string:
Multiple lines in
commandare treated as a single command.If a line starts with
#it is discarded.If a line contains ` #`, the trailing text is discarded.
When running the command on Windows, newlines are replaced by spaces; otherwise each line is terminated by a backslash character.
capture – If true, we include the command’s output in our return value.
check – If true we raise an exception on error; otherwise we include the command’s returncode in our return value.
verbose – If true we show the command.
env – None or dict to use instead of <os.environ>.
env_extra – None or dict to add to <os.environ> or <env>.
timeout – If not None, timeout in seconds; passed directly to
subprocess.run(). Note that on MacOSsubprocess.run()seems to leave processes running if timeout expires.prefix –
String prefix for each line of output.
If true: * We run command with stdout=subprocess.PIPE and
stderr=subprocess.STDOUT, repetaedly reading the command’s output and writing it with <prefix>.
We do not support <timeout>, which must be None.
encoding
errors – Encoding of child process output.
ticker – If non-zero, we show a rotating bar when waiting for child process output, with <ticker> seconds between each rotation.
out – Where to write output. Single item or list/tuple of items. Each item can be a callable or an object with .write() and .flush() members. Special value ‘log’ writes to
pipcl.log().tee – Name of file to also write to. We refuse to overwrite existing file.
log – If true we write to
pipcl.log(). This is the default.
- On Windows:
<ticker> is not supported and ignored. <prefix> and <timeout> both being true is not supported, and will raise an exception. These restrictions are because the Python module
selectorsdoes not handle pipes.
- Returns:
false false returncode false true (returncode, output) true false None or raise exception true true output or raise exception
- pipcl.run_if(
- command,
- out,
- *prerequisites,
- caller=1,
Runs a command only if the output file is not up to date.
- Parameters:
command – The command to run. We write this and a hash of argv[0] into a file <out>.cmd so that we know to run a command if the command itself has changed.
out – Path of the output file.
prerequisites – List of prerequisite paths or true/false/None items. If an item is None it is ignored, otherwise if an item is not a string we immediately return it cast to a bool. We recurse into directories, effectively using the newest file in the directory.
- Returns:
True if we ran the command, otherwise None.
If the output file does not exist, the command is run:
>>> del _log_f[:] >>> _log_f.append(sys.stdout) >>> log_prefix('%f(): ') >>> out = 'tests/run_if_test_out' >>> fs_remove(out) >>> fs_remove( f'{out}.cmd') >>> run_if( f'touch {out}', out, caller=0) run_if(): Running command because: File does not exist: 'tests/run_if_test_out' run_if(): Running: touch tests/run_if_test_out True
If we repeat, the output file will be up to date so the command is not run:
>>> run_if( f'touch {out}', out, caller=0) run_if(): Not running command because up to date: 'tests/run_if_test_out'
If we change the command, the command is run:
>>> run_if( f'touch {out};', out, caller=0) run_if(): Running command because: Command has changed: run_if(): @@ -1,2 +1,2 @@ run_if(): touch run_if(): -tests/run_if_test_out run_if(): +tests/run_if_test_out; run_if(): Running: touch tests/run_if_test_out; True
If we add a prerequisite that is newer than the output, the command is run:
>>> time.sleep(1) >>> prerequisite = 'tests/run_if_test_prerequisite' >>> run( f'touch {prerequisite}', caller=0) run(): Running: touch tests/run_if_test_prerequisite >>> run_if( f'touch {out}', out, prerequisite, caller=0) run_if(): Running command because: Command has changed: run_if(): @@ -1,2 +1,2 @@ run_if(): touch run_if(): -tests/run_if_test_out; run_if(): +tests/run_if_test_out run_if(): Running: touch tests/run_if_test_out True
If we repeat, the output will be newer than the prerequisite, so the command is not run:
>>> run_if( f'touch {out}', out, prerequisite, caller=0) run_if(): Not running command because up to date: 'tests/run_if_test_out'
Also see OS-specific doctest examples for
_run_if_test_scripting_windows()and_run_if_test_scripting_unix().
- pipcl.show_sysconfig()¶
Shows contents of
sysconfig.get_paths()andsysconfig.get_config_vars()dicts.
- pipcl.show_system()¶
Show useful information about the system plus argv and environ.
Omits os.environ if $PIPCL_SHOW_ENV is ‘0’.
- pipcl.str_to_int(s, replace=<class 'str'>)¶
Returns string converted to int, with configurable behaviour if the string is not convertible.
- Parameters:
s – The input string.
replace –
- Governs what we do if int(s) fails:
- None:
Raise.
- str:
Return the string <s>.
- Otherwise:
Return <replace> itself.
- pipcl.swig_get(
- swig,
- quick,
- swig_local='pipcl-swig-git',
Returns <swig> or a new swig binary.
If <swig> is true and starts with ‘git:’ (not Windows), the remaining text is passed to
git_get()and we clone/update/build swig, and return the built binary. We default to the main swig repository, branch master, so for example ‘git:’ will return the latest swig from branch master.Otherwise we simply return <swig>.
- Parameters:
swig –
If starts with ‘git:’, passed as <text> arg to
git_get(), and we return the absolute path of the build binary. (Not windows.)If starts with ‘pip:’ we do:
pip install swigand return ‘swig’. E.g. ‘pip:==4.3.1’.Otherwise we simply return <swig>.
quick – If true, we do not update/build local checkout if the binary is already present.
swig_local – path to use for checkout.
- pipcl.swig_prepare_build(swig_env_extra)¶
Builds required tools for building swig (not Windows).
Adds to swig_env_extra[‘PATH’].
- pipcl.sysconfig_python_flags()¶
Returns include paths and library directory for Python.
Uses sysconfig.*(), overridden by environment variables PIPCL_SYSCONFIG_PATH_include, PIPCL_SYSCONFIG_PATH_platinclude and PIPCL_SYSCONFIG_CONFIG_VAR_LIBDIR if set.
- pipcl.venv_enter_cmd(venv_name)¶
Returns command that will enter venv, different on Windows vs Unix.
- pipcl.verbose(level=None)¶
Sets verbose level if
levelis not None. Returns verbose level.
- pipcl.version_override(name)¶
If PIPCL_CHANGE_VERSIONS is set and contains a match for <name>, we return the override version.
Otherwise we return None.
This should be called by a setup.py’s get_requires_for_build_wheel() for each item it returns.
- pipcl.version_to_tuple(
- version,
- replace=<class 'str'>,
Returns a tuple containing each item from <version> converted to an int.
If an item does not convert to an int, behaviour depends on <replace>. :param version: A string containing items separated by ‘.’ :param replace:
- Governs what we do if conversion of item to int fails:
- None:
Raise.
- str:
Use the string value.
- Otherwise:
Use <replace> itself.
.-separated string as tuple, with each item converted to an int, or kept as a string if the conversion failed (or to <replace> if notstr.>>> version_to_tuple('1.2.3') (1, 2, 3) >>> version_to_tuple('1.2.3.alpha') (1, 2, 3, 'alpha') >>> version_to_tuple('1.2.3.alpha', replace=0) (1, 2, 3, 0)
- pipcl.wasm()¶
Returns true of we are running on Wasm.
- pipcl.windows()¶
Returns true of we are running on Windows.
- pipcl.zipfile_writestr(
- zf,
- name,
- contents,
- unix_permissions=384,
Alternative to
zipfile.ZipFile.writestr(), which allows control over permissions. Our default 0o600 matcheszipfile.ZipFile.writestr().
pipcl.wdev¶
Finds locations of Windows command-line development tools.
Classes:
|
For Windows only. |
|
Windows only. |
|
Windows only. |
Functions:
|
Returns list of WindowsVS instances. |
- class pipcl.wdev.WindowsCpu(name=None)¶
For Windows only. Paths and names that depend on cpu.
- Members:
- .bits
32 or 64.
- .name
One of: arm32 arm64 x32 x64.
- .windows_subdir
Empty string,
x64/,arm64etc.- .windows_name
x86,`x64`,arm64etc.- .windows_config
x64,Win32,arm64etc, e.g. for use in/Build Release|x64.- .windows_suffix
64or empty string.
ARM members are not fixed yet.
- class pipcl.wdev.WindowsPython(
- cpu=None,
- version=None,
- verbose=True,
Windows only. Information about installed Python with specific word size and version. Defaults to the currently-running Python.
Members:
- .path:
Path of python binary.
- .version:
{major}.{minor}, e.g.3.9or3.11. Same asversionpassed to__init__()if not None, otherwise the inferred version.- .include:
Python include path.
- .cpu:
A
WindowsCpuinstance, same ascpupassed to__init__()if not None, otherwise the inferred cpu.
We parse the output from
py -0pto find all available python installations.- Parameters:
cpu – A WindowsCpu instance. If None, we use whatever we are running on.
version – Two-digit Python version as a string such as
3.8. If None we use current Python’s version.verbose – If true we show diagnostics.
Methods:
description_ml([indent])- description_ml(indent='')¶
- class pipcl.wdev.WindowsVS(
- *,
- year=None,
- grade=None,
- version=None,
- cpu=None,
- directory=None,
- verbose=False,
Windows only. Finds locations of Visual Studio command-line tools. Assumes VS2019-style paths.
Members and example values:
.year: 2019 .grade: Community .version: 14.28.29910 .directory: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community .vcvars: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat .cl: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29910\bin\Hostx64\x64\cl.exe .link: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29910\bin\Hostx64\x64\link.exe .csc: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\Roslyn\csc.exe .msbuild: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe .devenv: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\devenv.com .tools: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\devenv.com .toolvs: [142, 143]
.cscis C# compiler; will be None if not found.- Parameters:
year – None or, for example,
2019. If None we use environment variable WDEV_VS_YEAR if set.grade –
None or, for example, one of:
CommunityProfessionalEnterprise
If None we use environment variable WDEV_VS_GRADE if set.
version – None or, for example:
14.28.29910. If None we use environment variable WDEV_VS_VERSION if set.cpu – None or a
WindowsCpuinstance.directory – Ignore year, grade, version and cpu and use this directory directly.
verbose –
.
Methods:
description_ml([indent])Return multiline description of
self.- description_ml(indent='')¶
Return multiline description of
self.
- pipcl.wdev.windows_vs_multiple(
- year=None,
- grade=None,
- verbose=0,
Returns list of WindowsVS instances.