AcademySoftwareFoundation / AcademySoftwareFoundation/rez

[Bug] Unable to catch RexUndefinedVariableError

Open
#635 1 comment 0 reactions 0 assignees View on GitHub
bug
Dominant language
Python
Stars
1.1k
Forks
369
Avg merge
12d 3h
Merged PRs (30d)
5

Description

When a package is referencing a non-existent variable, the associated exception is discarded, and replaced with a generic `SourceCodeExecError`, which means it can't be handled, without parsing the resulting text for clues. This applies to *any* exception happening in a `package.py`.

**package.py**

```python
name = "my_package"

def commands():
env.PYTHONPATH.append("{env.MISSING_VARIABLE}")
```

**Problem**

```python
from rez.resolved_context import ResolvedContext
ctx = ResolvedContext (["my_package"])
ctx.get_environ()
# Traceback (most recent call last):
# ...
# RexUndefinedVariableError: Referenced undefined environment variable: MISSING_VARIABLE
```

Full Traceback

```bash
Traceback (most recent call last):
File "", line 1, in
File "c:\virtualenv\rez\lib\site-packages\rez\resolved_context.py", line 873, in _check
return fn(self, *nargs, **kwargs)
File "c:\virtualenv\rez\lib\site-packages\rez\resolved_context.py", line 934, in get_environ
self._execute(executor)
File "c:\virtualenv\rez\lib\site-packages\rez\utils\memcached.py", line 253, in wrapper
return func(*nargs, **kwargs)
File "c:\virtualenv\rez\lib\site-packages\rez\resolved_context.py", line 1678, in _execute
executor.execute_code(commands, isolate=True)
File "c:\virtualenv\rez\lib\site-packages\rez\rex.py", line 1211, in execute_code
_apply()
File "c:\virtualenv\rez\lib\site-packages\rez\rex.py", line 1198, in _apply
exec_namespace=self.globals)
File "c:\virtualenv\rez\lib\site-packages\rez\rex.py", line 1179, in compile_code
reraise(e, RexError)
File "c:\virtualenv\rez\lib\site-packages\rez\utils\__init__.py", line 20, in reraise
six.reraise(new_exc_cls, exc, traceback)
File "c:\virtualenv\rez\lib\site-packages\rez\rex.py", line 1173, in compile_code
code.exec_(globals_=exec_namespace)
File "c:\virtualenv\rez\lib\site-packages\rez\utils\sourcecode.py", line 220, in exec_
short_msg=str(e))
rez.exceptions.RexError: Failed to execute :
Traceback (most recent call last):
File "c:\virtualenv\rez\lib\site-packages\rez\utils\sourcecode.py", line 215, in exec_
exec(pyc, globals_)
File "", line 11, in
File "c:\virtualenv\rez\lib\site-packages\rez\rex.py", line 262, in expandvars
value = str(self._format(value))
File "c:\virtualenv\rez\lib\site-packages\rez\rex.py", line 225, in _format
return EscapedString.promote(value).formatted(self.formatter)
File "c:\virtualenv\rez\lib\site-packages\rez\rex.py", line 778, in formatted
value = func(value)
File "c:\virtualenv\rez\lib\site-packages\rez\rex.py", line 1251, in expand
return self.formatter.format(str(value))
File "c:\virtualenv\rez\lib\site-packages\rez\rex.py", line 902, in format
return Formatter.format(self, format_string_, *args, **kwargs)
File "c:\Python27\Lib\string.py", line 559, in format
return self.vformat(format_string, args, kwargs)
File "c:\Python27\Lib\string.py", line 563, in vformat
result = self._vformat(format_string, args, kwargs, used_args, 2)
File "c:\Python27\Lib\string.py", line 596, in _vformat
result.append(self.format_field(obj, format_spec))
File "c:\virtualenv\rez\lib\site-packages\rez\rex.py", line 912, in format_field
return format(value, format_spec)
File "c:\virtualenv\rez\lib\site-packages\rez\rex.py", line 1015, in __str__
return self.value()
File "c:\virtualenv\rez\lib\site-packages\rez\rex.py", line 1007, in value
return self.get()
File "c:\virtualenv\rez\lib\site-packages\rez\rex.py", line 1004, in get
return self._environ_map.manager.getenv(self.name)
File "c:\virtualenv\rez\lib\site-packages\rez\rex.py", line 272, in getenv
"Referenced undefined environment variable: %s" % expanded_key)
RexUndefinedVariableError: Referenced undefined environment variable: MISSING_VARIABLE
```

Even though the exception type is `rez.exceptions.RexError`. Note the dual tracebacks, one printed by another.

What I'd like to be able to do is:

```python
try:
ctx.get_environ()
except rez.exceptions.RexUndefinedVariableError:
# Handle it
```

**Source**

The problem is coming from here:

https://github.com/nerdvegas/rez/blob/3c194ba105330b509f9434881abe38b0c23636ad/src/rez/utils/sourcecode.py#L214-L220

### Proposal

There's config option called [catch_rex_errors](https://github.com/nerdvegas/rez/wiki/Configuring-Rez#catch_rex_errors) that I was expecting to work for this usecase, but it appears to only relate to certain rex-related errors.

Would it make sense to implement this here as well?

Contributor guide

Open the contributing guide

Research direction

Start with src/rez/utils/sourcecode.py around lines 214–220 and trace how package.py exceptions flow through rex.py and ResolvedContext.get_environ(). Reproduce the MISSING_VARIABLE example and compare the behavior with the catch_rex_errors configuration. Done means RexUndefinedVariableError remains catchable instead of being replaced by a generic RexError.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.