Return the global and local namespaces to be used when evaluating annotations for the provided function. The global namespace will be the `__dict__` attribute of the module the function was defined in. The local namespace will contain the `__type_params__` introduced by PEP 695. Args:
(obj: Callable[..., Any], parent_namespace: MappingNamespace | None = None)
| 104 | |
| 105 | |
| 106 | def ns_for_function(obj: Callable[..., Any], parent_namespace: MappingNamespace | None = None) -> NamespacesTuple: |
| 107 | """Return the global and local namespaces to be used when evaluating annotations for the provided function. |
| 108 | |
| 109 | The global namespace will be the `__dict__` attribute of the module the function was defined in. |
| 110 | The local namespace will contain the `__type_params__` introduced by PEP 695. |
| 111 | |
| 112 | Args: |
| 113 | obj: The object to use when building namespaces. |
| 114 | parent_namespace: Optional namespace to be added with the lowest priority in the local namespace. |
| 115 | If the passed function is a method, the `parent_namespace` will be the namespace of the class |
| 116 | the method is defined in. Thus, we also fetch type `__type_params__` from there (i.e. the |
| 117 | class-scoped type variables). |
| 118 | """ |
| 119 | locals_list: list[MappingNamespace] = [] |
| 120 | if parent_namespace is not None: |
| 121 | locals_list.append(parent_namespace) |
| 122 | |
| 123 | # Get the `__type_params__` attribute introduced by PEP 695. |
| 124 | # Note that the `typing._eval_type` function expects type params to be |
| 125 | # passed as a separate argument. However, internally, `_eval_type` calls |
| 126 | # `ForwardRef._evaluate` which will merge type params with the localns, |
| 127 | # essentially mimicking what we do here. |
| 128 | type_params: tuple[_TypeVarLike, ...] = getattr(obj, '__type_params__', ()) |
| 129 | if parent_namespace is not None: |
| 130 | # We also fetch type params from the parent namespace. If present, it probably |
| 131 | # means the function was defined in a class. This is to support the following: |
| 132 | # https://github.com/python/cpython/issues/124089. |
| 133 | type_params += parent_namespace.get('__type_params__', ()) |
| 134 | |
| 135 | locals_list.append({t.__name__: t for t in type_params}) |
| 136 | |
| 137 | # What about short-circuiting to `obj.__globals__`? |
| 138 | globalns = get_module_ns_of(obj) |
| 139 | |
| 140 | return NamespacesTuple(globalns, LazyLocalNamespace(*locals_list)) |
| 141 | |
| 142 | |
| 143 | class NsResolver: |
no test coverage detected