##// END OF EJS Templates
support negative indexing
Matthias Bussonnier -
Show More
@@ -432,12 +432,14 b' class EscapedCommand(TokenTransformBase):'
432
432
433 _help_end_re = re.compile(
433 _help_end_re = re.compile(
434 r"""(%{0,2}
434 r"""(%{0,2}
435 (?!\d)[\w*]+ # Variable name
435 (?!\d)[\w*]+ # Variable name
436 (\.(?!\d)[\w*]+|\[[0-9]+\])* # .etc.etc or [0], we only support literal integers.
436 (\.(?!\d)[\w*]+|\[-?[0-9]+\])* # .etc.etc or [0], we only support literal integers.
437 )
437 )
438 (\?\??)$ # ? or ??
438 (\?\??)$ # ? or ??
439 """,
439 """,
440 re.VERBOSE)
440 re.VERBOSE,
441 )
442
441
443
442 class HelpEnd(TokenTransformBase):
444 class HelpEnd(TokenTransformBase):
443 """Transformer for help syntax: obj? and obj??"""
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 # Utilities
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 @undoc
161 @undoc
151 def softspace(file, newvalue):
162 def softspace(file, newvalue):
152 """Copied from code.py, to remove the dependency"""
163 """Copied from code.py, to remove the dependency"""
@@ -1548,7 +1559,7 b' class InteractiveShell(SingletonConfigurable):'
1548 break
1559 break
1549 parts.append(var)
1560 parts.append(var)
1550 for ind in indices:
1561 for ind in indices:
1551 if ind[-1] != "]" and not ind[:-1].isnumeric():
1562 if ind[-1] != "]" and not is_integer_string(ind[:-1]):
1552 parts_ok = False
1563 parts_ok = False
1553 break
1564 break
1554 parts.append(ind[:-1])
1565 parts.append(ind[:-1])
@@ -1602,7 +1613,7 b' class InteractiveShell(SingletonConfigurable):'
1602 if idx == len(oname_rest) - 1:
1613 if idx == len(oname_rest) - 1:
1603 obj = self._getattr_property(obj, part)
1614 obj = self._getattr_property(obj, part)
1604 else:
1615 else:
1605 if part.isnumeric():
1616 if is_integer_string(part):
1606 obj = obj[int(part)]
1617 obj = obj[int(part)]
1607 else:
1618 else:
1608 obj = getattr(obj, part)
1619 obj = getattr(obj, part)
@@ -1669,7 +1680,7 b' class InteractiveShell(SingletonConfigurable):'
1669 #
1680 #
1670 # The universal alternative is to traverse the mro manually
1681 # The universal alternative is to traverse the mro manually
1671 # searching for attrname in class dicts.
1682 # searching for attrname in class dicts.
1672 if attrname.isnumeric():
1683 if is_integer_string(attrname):
1673 return obj[int(attrname)]
1684 return obj[int(attrname)]
1674 else:
1685 else:
1675 attr = getattr(type(obj), attrname)
1686 attr = getattr(type(obj), attrname)
@@ -395,6 +395,19 b' def test_qmark_getindex():'
395 ip.run_cell("container[0]?")
395 ip.run_cell("container[0]?")
396 assert "container" not in ip.user_ns.keys()
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 def test_pinfo_nonascii():
412 def test_pinfo_nonascii():
400 # See gh-1177
413 # See gh-1177
General Comments 0
You need to be logged in to leave comments. Login now