Skip to content

Commit f36a778

Browse files
committed
Add more tests, allow to pass dotted path
1 parent 3c6b120 commit f36a778

File tree

2 files changed

+32
-9
lines changed

2 files changed

+32
-9
lines changed

IPython/core/guarded_eval.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ def _get_external(module_name: str, access_path: Sequence[str]):
134134
for attr in access_path:
135135
member_type = getattr(member_type, attr)
136136
return member_type
137-
except KeyError:
137+
except (KeyError, AttributeError):
138138
# handle modules in namespace packages
139139
module_path = ".".join([module_name, *access_path])
140140
if module_path in sys.modules:
@@ -215,7 +215,7 @@ class SelectivePolicy(EvaluationPolicy):
215215
allowed_getitem_external: set[tuple[str, ...]] = field(default_factory=set)
216216

217217
allowed_getattr: set[MayHaveGetattr] = field(default_factory=set)
218-
allowed_getattr_external: set[tuple[str, ...]] = field(default_factory=set)
218+
allowed_getattr_external: set[tuple[str, ...] | str] = field(default_factory=set)
219219

220220
allowed_operations: set = field(default_factory=set)
221221
allowed_operations_external: set[tuple[str, ...]] = field(default_factory=set)
@@ -225,18 +225,23 @@ class SelectivePolicy(EvaluationPolicy):
225225
)
226226

227227
def can_get_attr(self, value, attr):
228+
allowed_getattr_external: set[tuple[str, ...]] = {
229+
path if isinstance(path, tuple) else tuple(path.split("."))
230+
for path in self.allowed_getattr_external
231+
}
232+
228233
has_original_attribute = _has_original_dunder(
229234
value,
230235
allowed_types=self.allowed_getattr,
231236
allowed_methods=self._getattribute_methods,
232-
allowed_external=self.allowed_getattr_external,
237+
allowed_external=allowed_getattr_external,
233238
method_name="__getattribute__",
234239
)
235240
has_original_attr = _has_original_dunder(
236241
value,
237242
allowed_types=self.allowed_getattr,
238243
allowed_methods=self._getattr_methods,
239-
allowed_external=self.allowed_getattr_external,
244+
allowed_external=allowed_getattr_external,
240245
method_name="__getattr__",
241246
)
242247

@@ -268,7 +273,7 @@ def can_get_attr(self, value, attr):
268273
return True # pragma: no cover
269274

270275
# Properties in subclasses of allowed types may be ok if not changed
271-
for module_name, *access_path in self.allowed_getattr_external:
276+
for module_name, *access_path in allowed_getattr_external:
272277
try:
273278
external_class = _get_external(module_name, access_path)
274279
external_class_attr_val = getattr(external_class, attr)

tests/test_completer.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1426,15 +1426,33 @@ def __getattr__(self, attr):
14261426
ip.user_ns["unsafe_list_factory"] = unsafe_lib.ListFactory()
14271427
complete = ip.Completer.complete
14281428
with (
1429-
evaluation_policy(
1430-
"limited", allowed_getattr_external={("my", "safe", "lib")}
1431-
),
1429+
evaluation_policy("limited", allowed_getattr_external={"my.safe.lib"}),
14321430
jedi_status(False),
14331431
):
14341432
_, matches = complete(line_buffer="safe_list_factory.example.")
14351433
self.assertIn(".append", matches)
14361434
# this also checks against https://github.com/ipython/ipython/issues/14916
1437-
# because removing "un" would caus this test to incorrectly pass
1435+
# because removing "un" would cause this test to incorrectly pass
1436+
_, matches = complete(line_buffer="unsafe_list_factory.example.")
1437+
self.assertNotIn(".append", matches)
1438+
1439+
sys.modules["my"] = types.ModuleType("my")
1440+
1441+
with (
1442+
evaluation_policy("limited", allowed_getattr_external={"my"}),
1443+
jedi_status(False),
1444+
):
1445+
_, matches = complete(line_buffer="safe_list_factory.example.")
1446+
self.assertIn(".append", matches)
1447+
_, matches = complete(line_buffer="unsafe_list_factory.example.")
1448+
self.assertIn(".append", matches)
1449+
1450+
with (
1451+
evaluation_policy("limited"),
1452+
jedi_status(False),
1453+
):
1454+
_, matches = complete(line_buffer="safe_list_factory.example.")
1455+
self.assertNotIn(".append", matches)
14381456
_, matches = complete(line_buffer="unsafe_list_factory.example.")
14391457
self.assertNotIn(".append", matches)
14401458

0 commit comments

Comments
 (0)