bleeding-rez
bleeding-rez copied to clipboard
Opt-in environment inheritance
Goal
Reduce the risk of "Works on My Machine (tm)".
Related
- #36
Motivation
Rez currently inherits all variables from the parent environment with one exception; when a variable is written to using package.py:commands():env[]
.
def commands():
# First time it's referenced? I'm clearing it.
env["PATH"].append("value")
That means that there is no way to know whether a variable is inherited or overwritten by a package.
rez env my_package
echo $PATH
path1:path2:path3 # From parent or package?
What's worse, if a package does not reference a path used by the command-line, like PATH
, then every package gains access to the same executables as the parent process, which is unlikely to be expected.
rez env my_package
python
>>> print("System or package Python?")
The same applies to all variables, such as PYTHON_HOME
, PYTHONPATH
and LD_LIBRARY_PATH
etc.
Examples
- If
PYTHONDONOTWRITEBYTECODE
is set on an artist machine, byte code isn't written which can cause libraries that depend on it to misbehave. - If
PYTHONHOME
is set, no version of Python other than the one its pointing to is able to launch. - If
LD_LIBRARY_PATH
is set, libraries will successfully build on the authors machine, but not anywhere else.
Implementation
Like #36, strip an environment from everything, but enable packages to reference the parent environment internally, so as to "promote" variables from parent to child.
def commands():
import os
env["MY_VARIABLE"] = os.environ["MY_VARIABLE"]
Having a look at this, and there are a few areas of interest.
- There is a notion of a "syspath", which is the
PATH
of an environment getting special treatment - There is a notion of "Rez tools" which is the executables provided via
pip install bleeding-rez
Because PATH
is the only variable getting special treatment, there are a number of assertions throughout the code involving these two notions.
rez env --quiet
Per default, any context is created with a tailing call to rez context
, which prints some interesting information to screen following a resolve. When --quiet
is passed, this command is suppressed. However, because the command depends on rez
being present on PATH, there is an extra check being performed, which isn't whether rez
is on PATH, but whether the global configuration member rez_tools_visibility
is set to anything but "never"
. As a result, when tools are in fact hidden, but Rez is included as a Package, the --quiet
flag is always passed.
This is supposed to suppress a subsequent call to rez context
, so as to output related information to a context. However this command relies on rez
being present on PATH, which is secretly added by the rez_tools_visibility
config. In an isolated environment, there can be no "tools" available, unless they are coming from another package, such as Rez itself.