AcademySoftwareFoundation / AcademySoftwareFoundation/rez
[Bug] Unable to catch RexUndefinedVariableError
- 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
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