-
-
Notifications
You must be signed in to change notification settings - Fork 30.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bpo-18576: Add test.support.script_helper documentation #1252
Closed
Closed
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -677,3 +677,182 @@ The :mod:`test.support` module defines the following classes: | |
|
||
Class used to record warnings for unit tests. See documentation of | ||
:func:`check_warnings` above for more details. | ||
|
||
|
||
:mod:`test.support.script_helper` --- Helper utilities for script execution tests | ||
--------------------------------------------------------------------------------- | ||
|
||
.. module:: test.support.script_helper | ||
:synopsis: Support for script creation and execution tests | ||
|
||
The :mod:`test.support.script_helper` module defines common utilities used | ||
across various script execution or command line interface tests, such as creating | ||
scripts in temporary directories or running python subprocesses based on given | ||
arguments. | ||
|
||
|
||
This module defines the following functions: | ||
|
||
.. function:: assert_python_ok(*args, **env_vars) | ||
.. function:: assert_python_failure(*args, **env_vars) | ||
|
||
Runs the interpreter with *args* and optional environment | ||
variables *env_vars*, asserting that the run succeeds (exit status is zero) | ||
or fails (exit status is non-zero) | ||
|
||
If the exit status is non-zero (for :func:`assert_python_ok`), or the exit | ||
status is zero (for :func:`assert_python_failure`), the function raises an | ||
:exc:`AssertionError`, which includes the *stdout* and *stderr* from the | ||
interpreter. Otherwise, the function returns an (*exit status*, *stdout*, | ||
*stderr*) tuple. | ||
|
||
Trailing whitespace will be stripped for stderr. | ||
|
||
You can change the way the interpreter is started using these keywords: | ||
|
||
* *__cleanenv*: If the *__cleanenv* keyword is set, *env_vars* is used as a | ||
fresh environment, otherwise it is added to the environment of the current | ||
process. | ||
* *__isolated*: Python is started in isolated mode (command line option | ||
``-I``), except if the *__isolated* keyword is present and set to False. | ||
|
||
|
||
.. function:: spawn_python(*args, **kw) | ||
|
||
Spawns a Python subprocess with the given arguments and returns the | ||
resulting :class:`subprocess.Popen` instance. | ||
|
||
The ``-E`` option is always passed to the subprocess, both ``stdin`` and | ||
``stdout`` are configured as binary pipes and ``stderr`` is merged with | ||
``stdout``. | ||
|
||
The *kw* arguments are passed through to subprocess.Popen. | ||
|
||
|
||
.. function:: kill_python(p) | ||
|
||
Runs the given Popen process until completion and returns stdout. Note that | ||
this won't send a signal (e.g. *SIGTERM*, *SIGKILL*) to the given process, but | ||
it does close the input pipe. | ||
|
||
This will also include stderr output if the process was started with | ||
:func:`spawn_python`. | ||
|
||
|
||
.. function:: make_script(script_dir, script_basename, \ | ||
source, omit_suffix=False) | ||
|
||
Creates a new Python script/module in the given directory. | ||
|
||
This function invalidates the import system caches, allowing the created | ||
file to be immediately imported. | ||
|
||
By default, *script_dir* and *script_basename* are combined with | ||
:data:`os.extsep` and the normal ``py`` extension to create the full | ||
path to the file. If *omit_suffix* is true, the base name is used | ||
directly as the name of the created file with no extension. | ||
|
||
The *source* argument is a Unicode string which will be written to the file | ||
as UTF-8. | ||
|
||
|
||
.. function:: make_zip_script(zip_dir, zip_basename, \ | ||
script_name, name_in_zip=None) | ||
|
||
Creates a new zip archive in the given directory, containing the specified | ||
Python script/module. | ||
|
||
This function invalidates the import system caches, allowing the created | ||
file to be immediately imported. | ||
|
||
By default, the script is placed at the base of the zip archive using | ||
just the same filename as the script itself. This can be changed by | ||
specifying the *name_in_zip* parameter to choose a particular name. | ||
|
||
There is also a special case for when *script_name* refers to a file | ||
in a ``__pycache__`` directory. In that case, the helper will create a | ||
new compiled bytecode file from the original source file using the | ||
legacy naming scheme and place that in the zip archive instead. | ||
|
||
|
||
.. function:: make_pkg(pkg_dir, init_source='') | ||
|
||
Creates a simple self-contained Python package, optionally with a | ||
non-empty init file. | ||
|
||
This function invalidates the import system caches, allowing the created | ||
directory to be immediately imported. | ||
|
||
Equivalent to:: | ||
|
||
os.mkdir(pkg_dir) | ||
make_script(pkg_dir, "__init__", init_source) | ||
|
||
|
||
.. function:: make_zip_pkg(zip_dir, zip_basename, \ | ||
pkg_name, script_basename, source, \ | ||
depth=1, compiled=False) | ||
|
||
Create a self-contained Python package inside a new zip archive in the | ||
given directory. | ||
|
||
This function invalidates the import system caches, allowing the contents | ||
of the created archive to be immediately imported. | ||
|
||
For example, this call:: | ||
|
||
make_zip_pkg('.', 'example', 'mypkg', 'submodule', '', depth=2) | ||
|
||
would create an archive in the current directory called ``example.zip`` | ||
with the layout:: | ||
|
||
mypkg/ | ||
__init__.py | ||
mypkg/ | ||
__init__.py | ||
submodule.py | ||
|
||
The init modules in the packages inside the archive are always empty, | ||
while *source* is written to the submodule named by *script_basename*. | ||
|
||
The *depth* argument controls how deeply nested the package is. | ||
|
||
If *compiled* is true, then the files added to the archive will be | ||
suitably-named compiled bytecode files rather than the original source | ||
files. | ||
|
||
|
||
.. function:: interpreter_requires_environment() | ||
|
||
Returns ``True`` if our :data:`sys.executable` interpreter requires | ||
environment variables in order to be able to run at all. | ||
|
||
This is designed to be used with :func:`unittest.skipIf` to annotate tests | ||
that need to use an ``assert_python_*()`` function to launch an isolated | ||
mode (-I) or no environment mode (-E) sub-interpreter process. | ||
|
||
A normal build & test does not run into this situation but it can happen | ||
when trying to run the standard library test suite from an interpreter that | ||
doesn't have an obvious home with Python's current home finding logic. | ||
|
||
Setting ``PYTHONHOME`` is one way to get most of the test suite to run in that | ||
situation. ``PYTHONPATH`` or ``PYTHONUSERSITE`` are the other common | ||
environment variables that might impact whether or not the interpreter | ||
can start. | ||
|
||
|
||
.. function:: run_python_until_end(*args, **env_vars) | ||
|
||
Starts a python interpreter process with *args* and environment variables | ||
*env_vars*. Pipes are created for stdout, stdin and stderr. | ||
|
||
Waits until the process completes and returns the runcode, stdout and | ||
stderr as a `_PythonRunResult`. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It returns a tuple containing the |
||
|
||
You can change the way the interpreter is started using these keywords: | ||
|
||
* *__cleanenv*: If the *__cleanenv* keyword is set, *env_vars* is used as a | ||
fresh environment, otherwise it is added to the environment of the current | ||
process. | ||
* *__isolated*: Python is started in isolated mode (command line option | ||
``-I``), except if the *__isolated* keyword is present and set to False. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these both return a
_PythonRunResult
namedtuple as obtained fromrun_python_until_end