diff --git a/IPython/core/guarded_eval.py b/IPython/core/guarded_eval.py index 3c95213734a..1eca14db11d 100644 --- a/IPython/core/guarded_eval.py +++ b/IPython/core/guarded_eval.py @@ -637,6 +637,7 @@ def _list_methods(cls, source=None): dict_keys: Type[collections.abc.KeysView] = type({}.keys()) method_descriptor: Any = type(list.copy) +module = type(builtins) NUMERICS = {int, float, complex} @@ -686,6 +687,7 @@ def _list_methods(cls, source=None): *NUMERICS, dict_keys, method_descriptor, + module, } diff --git a/IPython/core/tests/test_guarded_eval.py b/IPython/core/tests/test_guarded_eval.py index 905cf3ab8e3..6fb321abe12 100644 --- a/IPython/core/tests/test_guarded_eval.py +++ b/IPython/core/tests/test_guarded_eval.py @@ -568,3 +568,15 @@ class B(NamedTuple): pass assert A.__getitem__ == B.__getitem__ + + +@dec.skip_without("numpy") +def test_module_access(): + import numpy + + context = limited(numpy=numpy) + assert guarded_eval("numpy.linalg.norm", context) == numpy.linalg.norm + + context = minimal(numpy=numpy) + with pytest.raises(GuardRejection): + guarded_eval("np.linalg.norm", context)