bleeding-rez icon indicating copy to clipboard operation
bleeding-rez copied to clipboard

Opt-in environment inheritance

Open mottosso opened this issue 5 years ago • 1 comments

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"]

mottosso avatar Jul 19 '19 07:07 mottosso

Having a look at this, and there are a few areas of interest.

  1. There is a notion of a "syspath", which is the PATH of an environment getting special treatment
  2. 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.

mottosso avatar Jul 19 '19 15:07 mottosso