(
expression: str,
module_name: str,
*,
locals_: Optional[Mapping[str, Any]] = None,
in_class: Optional[Type[Any]] = None,
)
| 238 | |
| 239 | |
| 240 | def eval_expression( |
| 241 | expression: str, |
| 242 | module_name: str, |
| 243 | *, |
| 244 | locals_: Optional[Mapping[str, Any]] = None, |
| 245 | in_class: Optional[Type[Any]] = None, |
| 246 | ) -> Any: |
| 247 | try: |
| 248 | base_globals: Dict[str, Any] = sys.modules[module_name].__dict__ |
| 249 | except KeyError as ke: |
| 250 | raise NameError( |
| 251 | f"Module {module_name} isn't present in sys.modules; can't " |
| 252 | f"evaluate expression {expression}" |
| 253 | ) from ke |
| 254 | |
| 255 | try: |
| 256 | if in_class is not None: |
| 257 | cls_namespace = dict(in_class.__dict__) |
| 258 | cls_namespace.setdefault(in_class.__name__, in_class) |
| 259 | |
| 260 | # see #10899. We want the locals/globals to take precedence |
| 261 | # over the class namespace in this context, even though this |
| 262 | # is not the usual way variables would resolve. |
| 263 | cls_namespace.update(base_globals) |
| 264 | |
| 265 | annotation = eval(expression, cls_namespace, locals_) |
| 266 | else: |
| 267 | annotation = eval(expression, base_globals, locals_) |
| 268 | except Exception as err: |
| 269 | raise NameError( |
| 270 | f"Could not de-stringify annotation {expression!r}" |
| 271 | ) from err |
| 272 | else: |
| 273 | return annotation |
| 274 | |
| 275 | |
| 276 | def eval_name_only( |
no test coverage detected