Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make "resolve_annotations" more lenient, allowing for missing modules #2366

Merged
merged 2 commits into from Feb 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions changes/2363-samuelcolvin.md
@@ -0,0 +1 @@
Make `resolve_annotations` more lenient, allowing for missing modules
12 changes: 9 additions & 3 deletions pydantic/typing.py
Expand Up @@ -289,10 +289,16 @@ def resolve_annotations(raw_annotations: Dict[str, Type[Any]], module_name: Opti

Resolve string or ForwardRef annotations into type objects if possible.
"""
base_globals: Optional[Dict[str, Any]] = None
if module_name:
base_globals: Optional[Dict[str, Any]] = sys.modules[module_name].__dict__
else:
base_globals = None
try:
module = sys.modules[module_name]
except KeyError:
# happens occasionally, see https://github.com/samuelcolvin/pydantic/issues/2363
pass
else:
base_globals = module.__dict__

annotations = {}
for name, value in raw_annotations.items():
if isinstance(value, str):
Expand Down
20 changes: 20 additions & 0 deletions tests/test_edge_cases.py
@@ -1,3 +1,4 @@
import importlib.util
import sys
from collections.abc import Hashable
from decimal import Decimal
Expand Down Expand Up @@ -1773,3 +1774,22 @@ def get_double_a(self) -> float:
assert model.a == 10.2
assert model.b == 10
return model.get_double_a() == 20.2


def test_resolve_annotations_module_missing(tmp_path):
# see https://github.com/samuelcolvin/pydantic/issues/2363
file_path = tmp_path / 'module_to_load.py'
# language=Python
file_path.write_text(
"""
from pydantic import BaseModel
class User(BaseModel):
id: int
name = 'Jane Doe'
"""
)

spec = importlib.util.spec_from_file_location('my_test_module', file_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
assert module.User(id=12).dict() == {'id': 12, 'name': 'Jane Doe'}