Show More
@@ -429,9 +429,11 b' class EscapedCommand(TokenTransformBase):' | |||||
429 |
|
429 | |||
430 | return lines_before + [new_line] + lines_after |
|
430 | return lines_before + [new_line] + lines_after | |
431 |
|
431 | |||
432 | _help_end_re = re.compile(r"""(%{0,2} |
|
432 | ||
|
433 | _help_end_re = re.compile( | |||
|
434 | r"""(%{0,2} | |||
433 | (?!\d)[\w*]+ # Variable name |
|
435 | (?!\d)[\w*]+ # Variable name | |
434 | (\.(?!\d)[\w*]+)* # .etc.etc |
|
436 | (\.(?!\d)[\w*]+|\[[0-9]+\])* # .etc.etc or [0], we only support literal integers. | |
435 |
|
|
437 | ) | |
436 | (\?\??)$ # ? or ?? |
|
438 | (\?\??)$ # ? or ?? | |
437 | """, |
|
439 | """, | |
@@ -464,10 +466,11 b' class HelpEnd(TokenTransformBase):' | |||||
464 | def transform(self, lines): |
|
466 | def transform(self, lines): | |
465 | """Transform a help command found by the ``find()`` classmethod. |
|
467 | """Transform a help command found by the ``find()`` classmethod. | |
466 | """ |
|
468 | """ | |
467 | piece = ''.join(lines[self.start_line:self.q_line+1]) |
|
469 | ||
468 | indent, content = piece[:self.start_col], piece[self.start_col:] |
|
470 | piece = "".join(lines[self.start_line : self.q_line + 1]) | |
469 | lines_before = lines[:self.start_line] |
|
471 | indent, content = piece[: self.start_col], piece[self.start_col :] | |
470 |
lines_ |
|
472 | lines_before = lines[: self.start_line] | |
|
473 | lines_after = lines[self.q_line + 1 :] | |||
471 |
|
474 | |||
472 | m = _help_end_re.search(content) |
|
475 | m = _help_end_re.search(content) | |
473 | if not m: |
|
476 | if not m: | |
@@ -543,8 +546,13 b' def has_sunken_brackets(tokens: List[tokenize.TokenInfo]):' | |||||
543 |
|
546 | |||
544 | def show_linewise_tokens(s: str): |
|
547 | def show_linewise_tokens(s: str): | |
545 | """For investigation and debugging""" |
|
548 | """For investigation and debugging""" | |
546 | if not s.endswith('\n'): |
|
549 | warnings.warn( | |
547 | s += '\n' |
|
550 | "show_linewise_tokens is deprecated since IPython 8.6", | |
|
551 | DeprecationWarning, | |||
|
552 | stacklevel=2, | |||
|
553 | ) | |||
|
554 | if not s.endswith("\n"): | |||
|
555 | s += "\n" | |||
548 | lines = s.splitlines(keepends=True) |
|
556 | lines = s.splitlines(keepends=True) | |
549 | for line in make_tokens_by_line(lines): |
|
557 | for line in make_tokens_by_line(lines): | |
550 | print("Line -------") |
|
558 | print("Line -------") |
@@ -213,14 +213,17 b' class ExecutionInfo(object):' | |||||
213 | raw_cell = ( |
|
213 | raw_cell = ( | |
214 | (self.raw_cell[:50] + "..") if len(self.raw_cell) > 50 else self.raw_cell |
|
214 | (self.raw_cell[:50] + "..") if len(self.raw_cell) > 50 else self.raw_cell | |
215 | ) |
|
215 | ) | |
216 | return '<%s object at %x, raw_cell="%s" store_history=%s silent=%s shell_futures=%s cell_id=%s>' % ( |
|
216 | return ( | |
217 | name, |
|
217 | '<%s object at %x, raw_cell="%s" store_history=%s silent=%s shell_futures=%s cell_id=%s>' | |
218 |
|
|
218 | % ( | |
219 |
|
|
219 | name, | |
220 |
self |
|
220 | id(self), | |
221 |
|
|
221 | raw_cell, | |
222 |
self.s |
|
222 | self.store_history, | |
223 |
self. |
|
223 | self.silent, | |
|
224 | self.shell_futures, | |||
|
225 | self.cell_id, | |||
|
226 | ) | |||
224 | ) |
|
227 | ) | |
225 |
|
228 | |||
226 |
|
229 | |||
@@ -1537,10 +1540,33 b' class InteractiveShell(SingletonConfigurable):' | |||||
1537 | Has special code to detect magic functions. |
|
1540 | Has special code to detect magic functions. | |
1538 | """ |
|
1541 | """ | |
1539 | oname = oname.strip() |
|
1542 | oname = oname.strip() | |
1540 | if not oname.startswith(ESC_MAGIC) and \ |
|
1543 | raw_parts = oname.split(".") | |
1541 | not oname.startswith(ESC_MAGIC2) and \ |
|
1544 | parts = [] | |
1542 | not all(a.isidentifier() for a in oname.split(".")): |
|
1545 | parts_ok = True | |
1543 | return {'found': False} |
|
1546 | for p in raw_parts: | |
|
1547 | if p.endswith("]"): | |||
|
1548 | var, *indices = p.split("[") | |||
|
1549 | if not var.isidentifier(): | |||
|
1550 | parts_ok = False | |||
|
1551 | break | |||
|
1552 | parts.append(var) | |||
|
1553 | for ind in indices: | |||
|
1554 | if ind[-1] != "]" and not ind[:-1].isnumeric(): | |||
|
1555 | parts_ok = False | |||
|
1556 | break | |||
|
1557 | parts.append(ind[:-1]) | |||
|
1558 | continue | |||
|
1559 | ||||
|
1560 | if not p.isidentifier(): | |||
|
1561 | parts_ok = False | |||
|
1562 | parts.append(p) | |||
|
1563 | ||||
|
1564 | if ( | |||
|
1565 | not oname.startswith(ESC_MAGIC) | |||
|
1566 | and not oname.startswith(ESC_MAGIC2) | |||
|
1567 | and not parts_ok | |||
|
1568 | ): | |||
|
1569 | return {"found": False} | |||
1544 |
|
1570 | |||
1545 | if namespaces is None: |
|
1571 | if namespaces is None: | |
1546 | # Namespaces to search in: |
|
1572 | # Namespaces to search in: | |
@@ -1562,7 +1588,7 b' class InteractiveShell(SingletonConfigurable):' | |||||
1562 | # Look for the given name by splitting it in parts. If the head is |
|
1588 | # Look for the given name by splitting it in parts. If the head is | |
1563 | # found, then we look for all the remaining parts as members, and only |
|
1589 | # found, then we look for all the remaining parts as members, and only | |
1564 | # declare success if we can find them all. |
|
1590 | # declare success if we can find them all. | |
1565 |
oname_parts = |
|
1591 | oname_parts = parts | |
1566 | oname_head, oname_rest = oname_parts[0],oname_parts[1:] |
|
1592 | oname_head, oname_rest = oname_parts[0],oname_parts[1:] | |
1567 | for nsname,ns in namespaces: |
|
1593 | for nsname,ns in namespaces: | |
1568 | try: |
|
1594 | try: | |
@@ -1579,7 +1605,10 b' class InteractiveShell(SingletonConfigurable):' | |||||
1579 | if idx == len(oname_rest) - 1: |
|
1605 | if idx == len(oname_rest) - 1: | |
1580 | obj = self._getattr_property(obj, part) |
|
1606 | obj = self._getattr_property(obj, part) | |
1581 | else: |
|
1607 | else: | |
1582 |
|
|
1608 | if part.isnumeric(): | |
|
1609 | obj = obj[int(part)] | |||
|
1610 | else: | |||
|
1611 | obj = getattr(obj, part) | |||
1583 | except: |
|
1612 | except: | |
1584 | # Blanket except b/c some badly implemented objects |
|
1613 | # Blanket except b/c some badly implemented objects | |
1585 | # allow __getattr__ to raise exceptions other than |
|
1614 | # allow __getattr__ to raise exceptions other than | |
@@ -1643,7 +1672,10 b' class InteractiveShell(SingletonConfigurable):' | |||||
1643 | # |
|
1672 | # | |
1644 | # The universal alternative is to traverse the mro manually |
|
1673 | # The universal alternative is to traverse the mro manually | |
1645 | # searching for attrname in class dicts. |
|
1674 | # searching for attrname in class dicts. | |
1646 | attr = getattr(type(obj), attrname) |
|
1675 | if attrname.isnumeric(): | |
|
1676 | return obj[int(attrname)] | |||
|
1677 | else: | |||
|
1678 | attr = getattr(type(obj), attrname) | |||
1647 | except AttributeError: |
|
1679 | except AttributeError: | |
1648 | pass |
|
1680 | pass | |
1649 | else: |
|
1681 | else: |
@@ -5,6 +5,7 b'' | |||||
5 | # Distributed under the terms of the Modified BSD License. |
|
5 | # Distributed under the terms of the Modified BSD License. | |
6 |
|
6 | |||
7 |
|
7 | |||
|
8 | from contextlib import contextmanager | |||
8 | from inspect import signature, Signature, Parameter |
|
9 | from inspect import signature, Signature, Parameter | |
9 | import inspect |
|
10 | import inspect | |
10 | import os |
|
11 | import os | |
@@ -43,7 +44,7 b' class SourceModuleMainTest:' | |||||
43 | # defined, if any code is inserted above, the following line will need to be |
|
44 | # defined, if any code is inserted above, the following line will need to be | |
44 | # updated. Do NOT insert any whitespace between the next line and the function |
|
45 | # updated. Do NOT insert any whitespace between the next line and the function | |
45 | # definition below. |
|
46 | # definition below. | |
46 |
THIS_LINE_NUMBER = 4 |
|
47 | THIS_LINE_NUMBER = 47 # Put here the actual number of this line | |
47 |
|
48 | |||
48 |
|
49 | |||
49 | def test_find_source_lines(): |
|
50 | def test_find_source_lines(): | |
@@ -345,6 +346,56 b' def test_pdef():' | |||||
345 | inspector.pdef(foo, 'foo') |
|
346 | inspector.pdef(foo, 'foo') | |
346 |
|
347 | |||
347 |
|
348 | |||
|
349 | @contextmanager | |||
|
350 | def cleanup_user_ns(**kwargs): | |||
|
351 | """ | |||
|
352 | On exit delete all the keys that were not in user_ns before entering. | |||
|
353 | ||||
|
354 | It does not restore old values ! | |||
|
355 | ||||
|
356 | Parameters | |||
|
357 | ---------- | |||
|
358 | ||||
|
359 | **kwargs | |||
|
360 | used to update ip.user_ns | |||
|
361 | ||||
|
362 | """ | |||
|
363 | try: | |||
|
364 | known = set(ip.user_ns.keys()) | |||
|
365 | ip.user_ns.update(kwargs) | |||
|
366 | yield | |||
|
367 | finally: | |||
|
368 | added = set(ip.user_ns.keys()) - known | |||
|
369 | for k in added: | |||
|
370 | del ip.user_ns[k] | |||
|
371 | ||||
|
372 | ||||
|
373 | def test_pinfo_getindex(): | |||
|
374 | def dummy(): | |||
|
375 | """ | |||
|
376 | MARKER | |||
|
377 | """ | |||
|
378 | ||||
|
379 | container = [dummy] | |||
|
380 | with cleanup_user_ns(container=container): | |||
|
381 | with AssertPrints("MARKER"): | |||
|
382 | ip._inspect("pinfo", "container[0]", detail_level=0) | |||
|
383 | assert "container" not in ip.user_ns.keys() | |||
|
384 | ||||
|
385 | ||||
|
386 | def test_qmark_getindex(): | |||
|
387 | def dummy(): | |||
|
388 | """ | |||
|
389 | MARKER 2 | |||
|
390 | """ | |||
|
391 | ||||
|
392 | container = [dummy] | |||
|
393 | with cleanup_user_ns(container=container): | |||
|
394 | with AssertPrints("MARKER 2"): | |||
|
395 | ip.run_cell("container[0]?") | |||
|
396 | assert "container" not in ip.user_ns.keys() | |||
|
397 | ||||
|
398 | ||||
348 | def test_pinfo_nonascii(): |
|
399 | def test_pinfo_nonascii(): | |
349 | # See gh-1177 |
|
400 | # See gh-1177 | |
350 | from . import nonascii2 |
|
401 | from . import nonascii2 |
@@ -782,7 +782,7 b' def _init_checker_class() -> Type["IPDoctestOutputChecker"]:' | |||||
782 | precision = 0 if fraction is None else len(fraction) |
|
782 | precision = 0 if fraction is None else len(fraction) | |
783 | if exponent is not None: |
|
783 | if exponent is not None: | |
784 | precision -= int(exponent) |
|
784 | precision -= int(exponent) | |
785 |
if float(w.group()) == approx(float(g.group()), abs=10 |
|
785 | if float(w.group()) == approx(float(g.group()), abs=10**-precision): | |
786 | # They're close enough. Replace the text we actually |
|
786 | # They're close enough. Replace the text we actually | |
787 | # got with the text we want, so that it will match when we |
|
787 | # got with the text we want, so that it will match when we | |
788 | # check the string literally. |
|
788 | # check the string literally. |
General Comments 0
You need to be logged in to leave comments.
Login now