Skip to content

Commit 3b6afc4

Browse files
committed
Add allow_fail keyword to ModuleType
1 parent ac4c1c7 commit 3b6afc4

File tree

2 files changed

+20
-3
lines changed

2 files changed

+20
-3
lines changed

plum/type.py

+10-3
Original file line numberDiff line numberDiff line change
@@ -87,28 +87,35 @@ class ModuleType(ResolvableType):
8787
Args:
8888
module (str): Module that the type lives in.
8989
name (str): Name of the type that is promised.
90+
allow_fail (bool, optional): If the type is does not exist in `module`,
91+
do not raise an `AttributeError`.
9092
"""
9193

92-
def __init__(self, module, name):
94+
def __init__(self, module, name, allow_fail=False):
9395
if module in {"__builtin__", "__builtins__"}:
9496
module = "builtins"
9597
ResolvableType.__init__(self, f"ModuleType[{module}.{name}]")
9698
self._name = name
9799
self._module = module
100+
self._allow_fail = allow_fail
98101

99-
def __new__(cls, module, name):
102+
def __new__(cls, module, name, allow_fail=False):
100103
return ResolvableType.__new__(cls, f"ModuleType[{module}.{name}]")
101104

102105
def retrieve(self):
103106
"""Attempt to retrieve the type from the reference module.
104107
105108
Returns:
106-
:class:`ModuleType`: `self`.
109+
bool: Whether the retrieval succeeded.
107110
"""
108111
if self._type is None:
109112
if self._module in sys.modules:
110113
type = sys.modules[self._module]
111114
for name in self._name.split("."):
115+
# If `type` does not contain `name` and `self._allow_fail` is
116+
# set, then silently fail.
117+
if not hasattr(type, name) and self._allow_fail:
118+
return False
112119
type = getattr(type, name)
113120
self.deliver(type)
114121
return self._type is not None

tests/test_type.py

+10
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,16 @@ def test_moduletype(module, name, type):
7171
assert not t.retrieve()
7272

7373

74+
def test_moduletype_allow_fail():
75+
t_not_allowed = ModuleType("__builtin__", "nonexisting")
76+
t_allowed = ModuleType("__builtin__", "nonexisting", allow_fail=True)
77+
78+
with pytest.raises(AttributeError):
79+
t_not_allowed.retrieve()
80+
81+
assert not t_allowed.retrieve()
82+
83+
7484
def test_is_hint():
7585
assert not _is_hint(int)
7686
assert _is_hint(typing.Union[int, float])

0 commit comments

Comments
 (0)