Show More
@@ -432,12 +432,14 b' class EscapedCommand(TokenTransformBase):' | |||
|
432 | 432 | |
|
433 | 433 | _help_end_re = re.compile( |
|
434 | 434 | r"""(%{0,2} |
|
435 |
|
|
|
436 |
|
|
|
437 | ) | |
|
438 |
|
|
|
439 | """, | |
|
440 | re.VERBOSE) | |
|
435 | (?!\d)[\w*]+ # Variable name | |
|
436 | (\.(?!\d)[\w*]+|\[-?[0-9]+\])* # .etc.etc or [0], we only support literal integers. | |
|
437 | ) | |
|
438 | (\?\??)$ # ? or ?? | |
|
439 | """, | |
|
440 | re.VERBOSE, | |
|
441 | ) | |
|
442 | ||
|
441 | 443 | |
|
442 | 444 | class HelpEnd(TokenTransformBase): |
|
443 | 445 | """Transformer for help syntax: obj? and obj??""" |
@@ -147,6 +147,17 b" dedent_re = re.compile(r'^\\s+raise|^\\s+return|^\\s+pass')" | |||
|
147 | 147 | # Utilities |
|
148 | 148 | #----------------------------------------------------------------------------- |
|
149 | 149 | |
|
150 | def is_integer_string(s:str): | |
|
151 | """ | |
|
152 | Variant of "str.isnumeric()" that allow negative values and other ints. | |
|
153 | """ | |
|
154 | try: | |
|
155 | int(s) | |
|
156 | return True | |
|
157 | except ValueError: | |
|
158 | return False | |
|
159 | raise ValueError('Unexpected error') | |
|
160 | ||
|
150 | 161 | @undoc |
|
151 | 162 | def softspace(file, newvalue): |
|
152 | 163 | """Copied from code.py, to remove the dependency""" |
@@ -1548,7 +1559,7 b' class InteractiveShell(SingletonConfigurable):' | |||
|
1548 | 1559 | break |
|
1549 | 1560 | parts.append(var) |
|
1550 | 1561 | for ind in indices: |
|
1551 |
if ind[-1] != "]" and not ind[:-1] |
|
|
1562 | if ind[-1] != "]" and not is_integer_string(ind[:-1]): | |
|
1552 | 1563 | parts_ok = False |
|
1553 | 1564 | break |
|
1554 | 1565 | parts.append(ind[:-1]) |
@@ -1602,7 +1613,7 b' class InteractiveShell(SingletonConfigurable):' | |||
|
1602 | 1613 | if idx == len(oname_rest) - 1: |
|
1603 | 1614 | obj = self._getattr_property(obj, part) |
|
1604 | 1615 | else: |
|
1605 |
if part |
|
|
1616 | if is_integer_string(part): | |
|
1606 | 1617 | obj = obj[int(part)] |
|
1607 | 1618 | else: |
|
1608 | 1619 | obj = getattr(obj, part) |
@@ -1669,7 +1680,7 b' class InteractiveShell(SingletonConfigurable):' | |||
|
1669 | 1680 | # |
|
1670 | 1681 | # The universal alternative is to traverse the mro manually |
|
1671 | 1682 | # searching for attrname in class dicts. |
|
1672 |
if attrname |
|
|
1683 | if is_integer_string(attrname): | |
|
1673 | 1684 | return obj[int(attrname)] |
|
1674 | 1685 | else: |
|
1675 | 1686 | attr = getattr(type(obj), attrname) |
@@ -395,6 +395,19 b' def test_qmark_getindex():' | |||
|
395 | 395 | ip.run_cell("container[0]?") |
|
396 | 396 | assert "container" not in ip.user_ns.keys() |
|
397 | 397 | |
|
398 | def test_qmark_getindex_negatif(): | |
|
399 | def dummy(): | |
|
400 | """ | |
|
401 | MARKER 3 | |
|
402 | """ | |
|
403 | ||
|
404 | container = [dummy] | |
|
405 | with cleanup_user_ns(container=container): | |
|
406 | with AssertPrints("MARKER 3"): | |
|
407 | ip.run_cell("container[-1]?") | |
|
408 | assert "container" not in ip.user_ns.keys() | |
|
409 | ||
|
410 | ||
|
398 | 411 | |
|
399 | 412 | def test_pinfo_nonascii(): |
|
400 | 413 | # See gh-1177 |
General Comments 0
You need to be logged in to leave comments.
Login now