Format: text/x-python
⬇ Download File (3.8 KB)
   1  """Tests for tokenutil"""
   2  # Copyright (c) IPython Development Team.
   3  # Distributed under the terms of the Modified BSD License.
   4  
   5  import pytest
   6  
   7  from IPython.utils.tokenutil import token_at_cursor, line_at_cursor
   8  
   9  def expect_token(expected, cell, cursor_pos):
  10      token = token_at_cursor(cell, cursor_pos)
  11      offset = 0
  12      for line in cell.splitlines():
  13          if offset + len(line) >= cursor_pos:
  14              break
  15          else:
  16              offset += len(line)+1
  17      column = cursor_pos - offset
  18      line_with_cursor = "%s|%s" % (line[:column], line[column:])
  19      assert token == expected, "Expected %r, got %r in: %r (pos %i)" % (
  20          expected,
  21          token,
  22          line_with_cursor,
  23          cursor_pos,
  24      )
  25  
  26  
  27  def test_simple():
  28      cell = "foo"
  29      for i in range(len(cell)):
  30          expect_token("foo", cell, i)
  31  
  32  def test_function():
  33      cell = "foo(a=5, b='10')"
  34      expected = 'foo'
  35      # up to `foo(|a=`
  36      for i in range(cell.find('a=') + 1):
  37          expect_token("foo", cell, i)
  38      # find foo after `=`
  39      for i in [cell.find('=') + 1, cell.rfind('=') + 1]:
  40          expect_token("foo", cell, i)
  41      # in between `5,|` and `|b=`
  42      for i in range(cell.find(','), cell.find('b=')):
  43          expect_token("foo", cell, i)
  44  
  45  def test_multiline():
  46      cell = '\n'.join([
  47          'a = 5',
  48          'b = hello("string", there)'
  49      ])
  50      expected = 'hello'
  51      start = cell.index(expected) + 1
  52      for i in range(start, start + len(expected)):
  53          expect_token(expected, cell, i)
  54      expected = 'hello'
  55      start = cell.index(expected) + 1
  56      for i in range(start, start + len(expected)):
  57          expect_token(expected, cell, i)
  58  
  59  def test_multiline_token():
  60      cell = '\n'.join([
  61          '"""\n\nxxxxxxxxxx\n\n"""',
  62          '5, """',
  63          'docstring',
  64          'multiline token',
  65          '""", [',
  66          '2, 3, "complicated"]',
  67          'b = hello("string", there)'
  68      ])
  69      expected = 'hello'
  70      start = cell.index(expected) + 1
  71      for i in range(start, start + len(expected)):
  72          expect_token(expected, cell, i)
  73      expected = 'hello'
  74      start = cell.index(expected) + 1
  75      for i in range(start, start + len(expected)):
  76          expect_token(expected, cell, i)
  77  
  78  def test_nested_call():
  79      cell = "foo(bar(a=5), b=10)"
  80      expected = 'foo'
  81      start = cell.index('bar') + 1
  82      for i in range(start, start + 3):
  83          expect_token(expected, cell, i)
  84      expected = 'bar'
  85      start = cell.index('a=')
  86      for i in range(start, start + 3):
  87          expect_token(expected, cell, i)
  88      expected = 'foo'
  89      start = cell.index(')') + 1
  90      for i in range(start, len(cell)-1):
  91          expect_token(expected, cell, i)
  92  
  93  def test_attrs():
  94      cell = "a = obj.attr.subattr"
  95      expected = 'obj'
  96      idx = cell.find('obj') + 1
  97      for i in range(idx, idx + 3):
  98          expect_token(expected, cell, i)
  99      idx = cell.find('.attr') + 2
 100      expected = 'obj.attr'
 101      for i in range(idx, idx + 4):
 102          expect_token(expected, cell, i)
 103      idx = cell.find('.subattr') + 2
 104      expected = 'obj.attr.subattr'
 105      for i in range(idx, len(cell)):
 106          expect_token(expected, cell, i)
 107  
 108  def test_line_at_cursor():
 109      cell = ""
 110      (line, offset) = line_at_cursor(cell, cursor_pos=11)
 111      assert line == ""
 112      assert offset == 0
 113  
 114      # The position after a newline should be the start of the following line.
 115      cell = "One\nTwo\n"
 116      (line, offset) = line_at_cursor(cell, cursor_pos=4)
 117      assert line == "Two\n"
 118      assert offset == 4
 119  
 120      # The end of a cell should be on the last line
 121      cell = "pri\npri"
 122      (line, offset) = line_at_cursor(cell, cursor_pos=7)
 123      assert line == "pri"
 124      assert offset == 4
 125  
 126  
 127  @pytest.mark.parametrize(
 128      "c, token",
 129      zip(
 130          list(range(16, 22)) + list(range(22, 28)),
 131          ["int"] * (22 - 16) + ["map"] * (28 - 22),
 132      ),
 133  )
 134  def test_multiline_statement(c, token):
 135      cell = """a = (1,
 136      3)
 137  
 138  int()
 139  map()
 140  """
 141      expect_token(token, cell, c)
 142