Ephemerals#

New in version 2.71.0.

Ephemeral packages (or simply ‘ephemerals’) are requests for packages that do not exist. Ephemeral package names always begin with a dot (.). Like all package requests, ephemerals can be requested as part of packages’ requires or variants lists, or directly by the user (via rez-env for eg).

Example:

]$ rez-env .foo-1
You are now in a rez-configured environment.

resolved by ajohns@turtle, on Tue Dec 22 08:17:00 2020, using Rez v2.70.0

requested packages:
.foo-1             (ephemeral)
~platform==linux   (implicit)
~arch==x86_64      (implicit)
~os==Ubuntu-16.04  (implicit)

resolved packages:
.foo-1    (ephemeral)

Ephemerals will act like real packages during a resolve (ie, their request ranges will intersect, and conflicts can occur) but they never actually correlate to a real package, nor do they perform any configuration on the runtime (not directly in any case).

Example showing range intersection:

]$ rez-env .foo-1 '.foo-1.5+'

You are now in a rez-configured environment.

resolved by ajohns@turtle, on Tue Dec 22 08:21:04 2020, using Rez v2.70.0

requested packages:
.foo-1             (ephemeral)
.foo-1.5+          (ephemeral)
~platform==linux   (implicit)
~arch==x86_64      (implicit)
~os==Ubuntu-16.04  (implicit)

resolved packages:
.foo-1.5+<1_    (ephemeral)

Example of conflicting request:

]$ rez-env .foo-1 .foo-2
The context failed to resolve:
The following package conflicts occurred: (.foo-1 <--!--> .foo-2)

Environment Variables#

Ephemerals do not affect the runtime in the way that packages can (via their commands() section), however some environment variables are set:

The following example illustrates:

]$ rez-env python .foo-1 .bah-2
...
]$ echo $REZ_EPH_FOO_REQUEST
1
]$ echo $REZ_USED_EPH_RESOLVE
.foo-1 .bah-2

Introspection#

In order for a package to inspect the ephemerals that are present in a runtime, there is an ephemerals object provided, similar to the resolve object. You would typically use the intersects() function to inspect it, like so:

# in package.py
def commands()
   if intersects(ephemerals.get_range('enable_tracking', '0'), '1'):
      env.TRACKING_ENABLED = 1

In this example, the given package would set the TRACKING_ENABLED environment variable if an ephemeral such as .enable_tracking-1 (or .enable_tracking-1.2+ etc) is present in the resolve. Note that the leading . is implied and not included when querying the ephemerals object.

Warning

Since ephemerals is a dict-like object, so it has a get function which will return a full request string if key exists. Hence, the default value should also be a full request string, not just a version range string like 0 in ephemerals.get_range(). Or intersects() may not work as expect.

Ephemeral Use Cases#

Why would you want to request packages that don’t exist? There are two main use cases.

Passing Information to Packages#

Ephemerals can be used as a kind of ‘package option’, or a way to pass information to packages in a resolve. For example, consider the following package definition:

name = 'bah'

def commands():
   if intersects(ephemerals.get_range('bah.cli', '1'), '1'):
      env.PATH.append('{root}/bin')

This package will disable its command line tools if an ephemeral like .bah.cli-0 is present in the runtime.

Note

Ephemerals are standard package requests and so can have any range, such as 1.2.3, 2.5+ and so on. However, they’re often used as boolean package options, as in the example above. In this case, it is recommended to use the conventional ranges 1 and 0 to designate true and false.

Since ephemerals can be pretty much anything, you might also decide to use them as a global package option. Here’s another take on our example, but in this case we introduce a .cli ephemeral that acts as a global whitelist:

name = 'bah'

def commands():
   if intersects(ephemerals.get_range('cli', ''), 'bah'):
      env.PATH.append('{root}/bin')

Here, all packages’ cli will be enabled if .cli is not specified, but if it is specified then it acts as a whitelist:

# turn on cli for foo and bah only
]$ rez-env foo-1 bah==2.3.1 eek-2.4 '.cli-foo|bah'

Abstract Package Representation#

Sometimes it makes sense for a package to require some form of abstract object or capability, rather than an actual package. For example, perhaps your package (or one of its variants) requires a GPU to be present on the host machine. To support this, you might have something setup that includes a .gpu-1 ephemeral in the implicits list on all GPU-enabled hosts. Then, your package could look like this:

name = 'pixxelator'

variants = [
   ['.gpu-0'],  # renders via CPU
   ['.gpu-1']  # renders via GPU
]

Warning

Be aware that on hosts that do not have a gpu implicit, either variant could be selected. You would want to either guarantee that every host has the gpu implicit set to 0 or 1, or that the user always explicitly specifies .gpu-0 or .gpu-1 in their request.