Format: text/x-python
⬇ Download File (6.4 KB)
   1  # -*- coding: utf-8 -*-
   2  """Tests for completerlib.
   3  
   4  """
   5  
   6  #-----------------------------------------------------------------------------
   7  # Imports
   8  #-----------------------------------------------------------------------------
   9  
  10  import os
  11  import shutil
  12  import sys
  13  import tempfile
  14  import unittest
  15  from os.path import join
  16  
  17  from tempfile import TemporaryDirectory
  18  
  19  from IPython.core.completerlib import magic_run_completer, module_completion, try_import
  20  from IPython.testing.decorators import onlyif_unicode_paths
  21  
  22  
  23  class MockEvent(object):
  24      def __init__(self, line):
  25          self.line = line
  26  
  27  #-----------------------------------------------------------------------------
  28  # Test functions begin
  29  #-----------------------------------------------------------------------------
  30  class Test_magic_run_completer(unittest.TestCase):
  31      files = [u"aao.py", u"a.py", u"b.py", u"aao.txt"]
  32      dirs = [u"adir/", "bdir/"]
  33  
  34      def setUp(self):
  35          self.BASETESTDIR = tempfile.mkdtemp()
  36          for fil in self.files:
  37              with open(join(self.BASETESTDIR, fil), "w", encoding="utf-8") as sfile:
  38                  sfile.write("pass\n")
  39          for d in self.dirs:
  40              os.mkdir(join(self.BASETESTDIR, d))
  41  
  42          self.oldpath = os.getcwd()
  43          os.chdir(self.BASETESTDIR)
  44  
  45      def tearDown(self):
  46          os.chdir(self.oldpath)
  47          shutil.rmtree(self.BASETESTDIR)
  48  
  49      def test_1(self):
  50          """Test magic_run_completer, should match two alternatives
  51          """
  52          event = MockEvent(u"%run a")
  53          mockself = None
  54          match = set(magic_run_completer(mockself, event))
  55          self.assertEqual(match, {u"a.py", u"aao.py", u"adir/"})
  56  
  57      def test_2(self):
  58          """Test magic_run_completer, should match one alternative
  59          """
  60          event = MockEvent(u"%run aa")
  61          mockself = None
  62          match = set(magic_run_completer(mockself, event))
  63          self.assertEqual(match, {u"aao.py"})
  64  
  65      def test_3(self):
  66          """Test magic_run_completer with unterminated " """
  67          event = MockEvent(u'%run "a')
  68          mockself = None
  69          match = set(magic_run_completer(mockself, event))
  70          self.assertEqual(match, {u"a.py", u"aao.py", u"adir/"})
  71  
  72      def test_completion_more_args(self):
  73          event = MockEvent(u'%run a.py ')
  74          match = set(magic_run_completer(None, event))
  75          self.assertEqual(match, set(self.files + self.dirs))
  76  
  77      def test_completion_in_dir(self):
  78          # Github issue #3459
  79          event = MockEvent(u'%run a.py {}'.format(join(self.BASETESTDIR, 'a')))
  80          print(repr(event.line))
  81          match = set(magic_run_completer(None, event))
  82          # We specifically use replace here rather than normpath, because
  83          # at one point there were duplicates 'adir' and 'adir/', and normpath
  84          # would hide the failure for that.
  85          self.assertEqual(match, {join(self.BASETESTDIR, f).replace('\\','/')
  86                              for f in (u'a.py', u'aao.py', u'aao.txt', u'adir/')})
  87  
  88  class Test_magic_run_completer_nonascii(unittest.TestCase):
  89      @onlyif_unicode_paths
  90      def setUp(self):
  91          self.BASETESTDIR = tempfile.mkdtemp()
  92          for fil in [u"aaø.py", u"a.py", u"b.py"]:
  93              with open(join(self.BASETESTDIR, fil), "w", encoding="utf-8") as sfile:
  94                  sfile.write("pass\n")
  95          self.oldpath = os.getcwd()
  96          os.chdir(self.BASETESTDIR)
  97  
  98      def tearDown(self):
  99          os.chdir(self.oldpath)
 100          shutil.rmtree(self.BASETESTDIR)
 101  
 102      @onlyif_unicode_paths
 103      def test_1(self):
 104          """Test magic_run_completer, should match two alternatives
 105          """
 106          event = MockEvent(u"%run a")
 107          mockself = None
 108          match = set(magic_run_completer(mockself, event))
 109          self.assertEqual(match, {u"a.py", u"aaø.py"})
 110  
 111      @onlyif_unicode_paths
 112      def test_2(self):
 113          """Test magic_run_completer, should match one alternative
 114          """
 115          event = MockEvent(u"%run aa")
 116          mockself = None
 117          match = set(magic_run_completer(mockself, event))
 118          self.assertEqual(match, {u"aaø.py"})
 119  
 120      @onlyif_unicode_paths
 121      def test_3(self):
 122          """Test magic_run_completer with unterminated " """
 123          event = MockEvent(u'%run "a')
 124          mockself = None
 125          match = set(magic_run_completer(mockself, event))
 126          self.assertEqual(match, {u"a.py", u"aaø.py"})
 127  
 128  # module_completer:
 129  
 130  def test_import_invalid_module():
 131      """Testing of issue https://github.com/ipython/ipython/issues/1107"""
 132      invalid_module_names = {'foo-bar', 'foo:bar', '10foo'}
 133      valid_module_names = {'foobar'}
 134      with TemporaryDirectory() as tmpdir:
 135          sys.path.insert( 0, tmpdir )
 136          for name in invalid_module_names | valid_module_names:
 137              filename = os.path.join(tmpdir, name + ".py")
 138              open(filename, "w", encoding="utf-8").close()
 139  
 140          s = set( module_completion('import foo') )
 141          intersection = s.intersection(invalid_module_names)
 142          assert intersection == set()
 143  
 144          assert valid_module_names.issubset(s), valid_module_names.intersection(s)
 145  
 146  
 147  def test_bad_module_all():
 148      """Test module with invalid __all__
 149  
 150      https://github.com/ipython/ipython/issues/9678
 151      """
 152      testsdir = os.path.dirname(__file__)
 153      sys.path.insert(0, testsdir)
 154      try:
 155          results = module_completion("from bad_all import ")
 156          assert "puppies" in results
 157          for r in results:
 158              assert isinstance(r, str)
 159  
 160          # bad_all doesn't contain submodules, but this completion
 161          # should finish without raising an exception:
 162          results = module_completion("import bad_all.")
 163          assert results == []
 164      finally:
 165          sys.path.remove(testsdir)
 166  
 167  
 168  def test_module_without_init():
 169      """
 170      Test module without __init__.py.
 171      
 172      https://github.com/ipython/ipython/issues/11226
 173      """
 174      fake_module_name = "foo"
 175      with TemporaryDirectory() as tmpdir:
 176          sys.path.insert(0, tmpdir)
 177          try:
 178              os.makedirs(os.path.join(tmpdir, fake_module_name))
 179              s = try_import(mod=fake_module_name)
 180              assert s == [], f"for module {fake_module_name}"
 181          finally:
 182              sys.path.remove(tmpdir)
 183  
 184  
 185  def test_valid_exported_submodules():
 186      """
 187      Test checking exported (__all__) objects are submodules
 188      """
 189      results = module_completion("import os.pa")
 190      # ensure we get a valid submodule:
 191      assert "os.path" in results
 192      # ensure we don't get objects that aren't submodules:
 193      assert "os.pathconf" not in results
 194