22import sys
33import typing
44import warnings
5- from collections .abc import Hashable
6- from typing import Union , get_args , get_origin
5+ from collections .abc import Callable , Hashable
6+ from typing import Optional , Union , get_args , get_origin
77
88from typing_extensions import Self , TypeGuard
99
@@ -91,17 +91,34 @@ class ModuleType(ResolvableType):
9191 name (str): Name of the type that is promised.
9292 allow_fail (bool, optional): If the type is does not exist in `module`,
9393 do not raise an `AttributeError`.
94+ condition (Callable[[], bool], optional): A callable that can check a condition,
95+ like a package version. This callable will be run whenever `module` has been
96+ imported. Only if the callable returns `True`, `name` will be imported
97+ from `module`.
9498 """
9599
96- def __init__ (self , module : str , name : str , allow_fail : bool = False ) -> None :
100+ def __init__ (
101+ self ,
102+ module : str ,
103+ name : str ,
104+ allow_fail : bool = False ,
105+ condition : Optional [Callable [[], bool ]] = None ,
106+ ) -> None :
97107 if module in {"__builtin__" , "__builtins__" }:
98108 module = "builtins"
99109 ResolvableType .__init__ (self , f"ModuleType[{ module } .{ name } ]" )
100110 self ._name = name
101111 self ._module = module
102112 self ._allow_fail = allow_fail
103-
104- def __new__ (cls , module : str , name : str , allow_fail : bool = False ) -> Self :
113+ self ._condition = condition
114+
115+ def __new__ (
116+ cls ,
117+ module : str ,
118+ name : str ,
119+ allow_fail : bool = False ,
120+ condition : Optional [Callable [[], bool ]] = None ,
121+ ) -> Self :
105122 return ResolvableType .__new__ (cls , f"ModuleType[{ module } .{ name } ]" )
106123
107124 def retrieve (self ) -> bool :
@@ -111,6 +128,10 @@ def retrieve(self) -> bool:
111128 bool: Whether the retrieval succeeded.
112129 """
113130 if self ._type is None and self ._module in sys .modules :
131+ # If a condition is given, check the condition before attempting to import.
132+ if self ._condition is not None and not self ._condition ():
133+ return False
134+
114135 type = sys .modules [self ._module ]
115136 for name in self ._name .split ("." ):
116137 # If `type` does not contain `name` and `self._allow_fail` is
0 commit comments