stepup.core.extapi¶
Utilities for developers building StepUp extension packages.
These functions are not intended for use in plan.py files.
stepup.core.extapi.subs_env_vars()
¶
A context manager for substituting environment variables and tracking the used variables.
The context manager yields a function, subs, which takes a path or string with variables and
returns the substituted form.
All used variables are recorded and sent to the director with amend(env=...).
For example:
This function may be used in other API functions to substitute environment variables in all relevant paths.
Source code in stepup/core/extapi.py
stepup.core.extapi.run_subprocess(cmd, *, workdir='.', stdin=None, shell=False, check=True, text=None)
¶
Run a subprocess and record it for archival purposes.
This is the convenience wrapper for the case where an extension step wraps an executable.
The invocation and its return code are recorded via record_subprocess.
Parameters:
-
cmd(str) –The command line, as a single shell-quoted string. When
shell=False(the default),cmdis split withshlex.splitand executed directly (no shell), so shell features (pipes, redirections, …) are not available. Whenshell=True,cmdis passed as-is to the system shell, which enables shell features. As an exception, leadingVAR=valueassignments are extracted and applied to the subprocess environment, even whenshell=False. In either case, the caller is then responsible for proper quoting. -
workdir(StrPath, default:'.') –The working directory of the subprocess as a path or string, relative to the step’s own working directory. It is passed to
subprocess.runascwd. -
stdin(str | bytes | None, default:None) –Standard input fed to the subprocess, or
None. Astris passed tosubprocess.runas-is and impliestext=True.bytesare passed as-is as well and implytext=False. Inconsistent combinations (e.g.stdinisbytesbuttext=True) raise aValueError. The value is forwarded torecord_subprocess, which storesbytesas a short summary (byte length and a truncated SHA-256) rather than raw binary. -
shell(bool, default:False) –When
True, executecmdvia the system shell (subprocess.run(..., shell=True)). Enables shell features such as pipes, redirections, and glob expansion. The flag is also recorded for display purposes. -
check(bool, default:True) –When
True, asubprocess.CalledProcessErroris raised on a non-zero exit code. The invocation is recorded before this check, so a failing subprocess is still archived. In case of such a failure, the subprocess’s standard output and error are printed to the caller’s standard output and error stream. -
text(bool | None, default:None) –The default is to follow the type of
stdinto run in text or binary mode. If nostdinis provided, the default is text mode.
Returns:
-
completed–The
subprocess.CompletedProcessreturned bysubprocess.run.
Raises:
-
CalledProcessError–When
checkisTrueand the subprocess exits with a non-zero return code.
Source code in stepup/core/extapi.py
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 | |
stepup.core.extapi.record_subprocess(cmd, returncode, *, workdir='.', env_overrides=None, shell=False, stdin=None)
¶
Record a subprocess invocation (already run by the caller) for archival purposes.
This is the low-level escape hatch for wrappers that run the subprocess themselves
(e.g. for streaming output, Popen-style pipe interaction, shell features, or
conditional invocations).
Most wrappers should use run_subprocess instead.
The recorded metadata is meant to be informative for archival and debugging, not authoritative. Outside a running step (e.g. under the dummy RPC client used in tests or driver code), this function is a no-op.
Parameters:
-
cmd(str) –The command line, as a single shell-quoted string. The caller is responsible for quoting: build it from parts with
shlex.join(parts)when arguments may contain spaces or special characters. The string is stored and displayed verbatim. -
returncode(int) –The exit code of the subprocess.
-
workdir(StrPath, default:'.') –The working directory of the subprocess as a path or string, relative to the step’s own working directory. It is translated to be relative to
STEPUP_ROOTfor storage. -
env_overrides(dict[str, str] | None, default:None) –The environment overlay that the caller applied on top of the inherited environment (only the variables it explicitly set), or
None. Only this overlay is stored, not the full resolved environment. -
shell(bool, default:False) –Whether
cmdwas executed via a shell (i.e.subprocess.run(..., shell=True)). This is stored and used when formatting the invocation for display. -
stdin(str | bytes | None, default:None) –The standard input that was fed to the subprocess, or
None. Astris stored verbatim.bytes(e.g. a pickle blob) are not stored raw; they are recorded as a short summary (byte length and a truncated SHA-256), since the archival record isTEXTand informative rather than authoritative.
Source code in stepup/core/extapi.py
stepup.core.extapi.filter_dependencies(paths)
¶
Select path retained by the ${STEPUP_PATH_FILTER}.
Parameters:
-
paths(Collection[StrPath]) –A collection of paths or strings to filter. Relative paths are assumed to be relative to the current working directory.
Returns:
-
filtered_paths–A collection of paths relative to
${STEPUP_ROOT}that were retained by the filter.
Source code in stepup/core/extapi.py
stepup.core.extapi.get_local_import_paths(script_path=None)
¶
Get all local files from sys.modules.
Files are only included if they match the ${STEPUP_PATH_FILTER} environment variable.
Non-existing files will be ignored, as they can only be the result of a dynamically created
module, as in issue https://github.com/reproducible-reporting/stepup-core/issues/21
There is no risk of missing files that still need to be created,
as all imports have already been successfully resolved already at this point.