If in the code below we used the import version of the function of create_model_from_dict_hide we get the below namespace error in typing. If however we use a local definition of the function the PyDantic Models are available in both the local and global namespace at line 539 of typing.py
How can we make the models available in the namespace with imported functions
Example code. Copy create_model_from_dict_hide to a file called pydantic_utils to recreate the error
from typing import (
Any,
Dict,
Type,
cast,
)
import warnings
from pydantic import BaseConfig, ConfigError, BaseModel
from pydantic.utils import is_valid_field
from pydantic.main import inherit_config
from pydantic_utils import create_model_from_dict
import family
def create_model_from_dict_hide(
__model_name: str,
*,
__config__: Type[BaseConfig] = None,
__base__: Type["Model"] = None,
__module__: str = __name__,
__validators__: Dict[str, classmethod] = None,
**field_definitions: Any,
) -> Type["Model"]:
"""
Dynamically create a model.
:param __model_name: name of the created model
:param __config__: config class to use for the new model
:param __base__: base class for the new model to inherit from
:param __module__: module of the created model
:param __validators__: a dict of method names and @validator class methods
:param field_definitions: fields of the model (or extra fields if a base is supplied)
in the format `<name>=(<type>, <default default>)` or `<name>=<default value>, e.g.
`foobar=(str, ...)` or `foobar=123`, or, for complex use-cases, in the format
`<name>=<FieldInfo>`, e.g. `foo=Field(default_factory=datetime.utcnow, alias='bar')`
"""
if __base__ is not None:
if __config__ is not None:
raise ConfigError("to avoid confusion __config__ and __base__ cannot be used together")
else:
__base__ = cast(Type["Model"], BaseModel)
fields = {}
annotations = {}
for f_name, f_def in field_definitions.items():
if not is_valid_field(f_name):
warnings.warn(f'fields may not start with an underscore, ignoring "{f_name}"', RuntimeWarning)
if "dict" in f_def:
f_def = f_def.replace("(", "[").replace(")", "]")
annotations[f_name] = f_def
fields[f_name] = None
namespace: "DictStrAny" = {"__annotations__": annotations, "__module__": __module__}
if __validators__:
namespace.update(__validators__)
namespace.update(fields)
if __config__:
namespace["Config"] = inherit_config(__config__, BaseConfig)
return type(__model_name, (__base__,), namespace)
# comment out this line to create the error
create_model_from_dict = create_model_from_dict_hide
Parent = create_model_from_dict("Parent", __config__=BaseConfig, **family.parent)
Child = create_model_from_dict("Child", __config__=BaseConfig, **family.child)
GrandChild = create_model_from_dict("GrandChild", __config__=BaseConfig, **family.grand_child)
GrandChild.update_forward_refs()
Parent.update_forward_refs()
Child.update_forward_refs()
g1 = GrandChild(name='donald jr jr', age=1)
g2 = GrandChild(name='donald jr jr', age=2)
x1 = Child(name='donald jr', age=1, grand_child=g1)
x2 = Child(name='eric', age=1, grand_child=g2)
y = Parent(name='donald', child=x1)
File "/Users/henry/payaable/fastapp/backend/temp.py", line 74, in <module>
Parent.update_forward_refs()
File "pydantic/main.py", line 832, in pydantic.main.BaseModel.update_forward_refs
File "pydantic/typing.py", line 382, in pydantic.typing.update_field_forward_refs
File "pydantic/typing.py", line 70, in pydantic.typing.evaluate_forwardref
'Coroutine',
File "/usr/local/Cellar/python@3.9/3.9.4/Frameworks/Python.framework/Versions/3.9/lib/python3.9/typing.py", line 539, in _evaluate
eval(self.__forward_code__, globalns, localns),
File "<string>", line 1, in <module>
NameError: name 'Child' is not defined