Skip to content

Commit

Permalink
-added more executor control - ubind, reset_globals
Browse files Browse the repository at this point in the history
  • Loading branch information
ajohns committed Dec 16, 2019
1 parent c369436 commit d031039
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 17 deletions.
5 changes: 3 additions & 2 deletions src/rez/build_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,8 +274,9 @@ def add_standard_build_actions(cls, executor, context, variant, build_type,
pre_build_commands = getattr(variant, "pre_build_commands")

if pre_build_commands:
executor.bind("this", variant)
executor.execute_code(pre_build_commands, isolate=True)
with executor.reset_globals():
executor.bind("this", variant)
executor.execute_code(pre_build_commands)


# Copyright 2013-2016 Allan Johns.
Expand Down
7 changes: 7 additions & 0 deletions src/rez/resolved_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -1678,6 +1678,13 @@ def _execute(self, executor):

raise PackageCommandError(msg)

# clear bindings from last variant. Note that we could've used
# executor.reset_globals to do this, however manually clearing the last
# bindings avoid lots of dict copies and updates.
#
for name in ("this", "version", "root", "base"):
executor.unbind(name)

header_comment(executor, "post system setup")

# append suite paths based on suite visibility setting
Expand Down
58 changes: 43 additions & 15 deletions src/rez/rex.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
import re
import inspect
import traceback
from contextlib import contextmanager
from string import Formatter

from rez.system import system
from rez.config import config
from rez.exceptions import RexError, RexUndefinedVariableError, RezSystemError
Expand Down Expand Up @@ -1191,9 +1193,47 @@ def __getattr__(self, attr):
else getattr(super(RexExecutor, self), attr)

def bind(self, name, obj):
"""Binds an object to the execution context."""
"""Binds an object to the execution context.
Args:
name (str) Variable name to bind to.
obj (object): Object to bind.
"""
self.globals[name] = obj

def unbind(self, name):
"""Unbind an object from the execution context.
Has no effect if the binding does not exist.
Args:
name (str) Variable name to bind to.
"""
self.globals.pop(name, None)

@contextmanager
def reset_globals(self):
"""Remove changes to globals dict post-context.
Any bindings (self.bind) will only be visible during this context.
"""

# we want to execute the code using self.globals - if for no other
# reason that self.formatter is pointing at self.globals, so if we
# passed in a copy, we would also need to make self.formatter "look" at
# the same copy - but we don't want to "pollute" our namespace, because
# the same executor may be used to run multiple packages. Therefore,
# we save a copy of self.globals before execution, and restore it after
#
saved_globals = dict(self.globals)

try:
yield

finally:
self.globals.clear()
self.globals.update(saved_globals)

def append_system_paths(self):
"""Append system paths to $PATH."""
from rez.shells import Shell, create_shell
Expand Down Expand Up @@ -1272,28 +1312,16 @@ def execute_code(self, code, filename=None, isolate=False):
code (str or SourceCode): Rex code to execute.
filename (str): Filename to report if there are syntax errors.
isolate (bool): If True, do not affect `self.globals` by executing
this code.
this code. DEPRECATED - use `self.reset_globals` instead.
"""
def _apply():
self.compile_code(code=code,
filename=filename,
exec_namespace=self.globals)

# we want to execute the code using self.globals - if for no other
# reason that self.formatter is pointing at self.globals, so if we
# passed in a copy, we would also need to make self.formatter "look" at
# the same copy - but we don't want to "pollute" our namespace, because
# the same executor may be used to run multiple packages. Therefore,
# we save a copy of self.globals before execution, and restore it after
#
if isolate:
saved_globals = dict(self.globals)

try:
with self.reset_globals():
_apply()
finally:
self.globals.clear()
self.globals.update(saved_globals)
else:
_apply()

Expand Down

0 comments on commit d031039

Please sign in to comment.