(root)/
Python-3.12.0/
Lib/
test/
test_zipimport_support.py
       1  # This test module covers support in various parts of the standard library
       2  # for working with modules located inside zipfiles
       3  # The tests are centralised in this fashion to make it easy to drop them
       4  # if a platform doesn't support zipimport
       5  import test.support
       6  import os
       7  import os.path
       8  import sys
       9  import textwrap
      10  import zipfile
      11  import zipimport
      12  import doctest
      13  import inspect
      14  import linecache
      15  import unittest
      16  from test.support import os_helper
      17  from test.support.script_helper import (spawn_python, kill_python, assert_python_ok,
      18                                          make_script, make_zip_script)
      19  
      20  verbose = test.support.verbose
      21  
      22  # Library modules covered by this test set
      23  #  pdb (Issue 4201)
      24  #  inspect (Issue 4223)
      25  #  doctest (Issue 4197)
      26  
      27  # Other test modules with zipimport related tests
      28  #  test_zipimport (of course!)
      29  #  test_cmd_line_script (covers the zipimport support in runpy)
      30  
      31  # Retrieve some helpers from other test cases
      32  from test import (test_doctest, sample_doctest, sample_doctest_no_doctests,
      33                    sample_doctest_no_docstrings)
      34  
      35  
      36  def _run_object_doctest(obj, module):
      37      finder = doctest.DocTestFinder(verbose=verbose, recurse=False)
      38      runner = doctest.DocTestRunner(verbose=verbose)
      39      # Use the object's fully qualified name if it has one
      40      # Otherwise, use the module's name
      41      try:
      42          name = "%s.%s" % (obj.__module__, obj.__qualname__)
      43      except AttributeError:
      44          name = module.__name__
      45      for example in finder.find(obj, name, module):
      46          runner.run(example)
      47      f, t = runner.failures, runner.tries
      48      if f:
      49          raise test.support.TestFailed("%d of %d doctests failed" % (f, t))
      50      if verbose:
      51          print ('doctest (%s) ... %d tests with zero failures' % (module.__name__, t))
      52      return f, t
      53  
      54  
      55  
      56  class ESC[4;38;5;81mZipSupportTests(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      57      # This used to use the ImportHooksBaseTestCase to restore
      58      # the state of the import related information
      59      # in the sys module after each test. However, that restores
      60      # *too much* information and breaks for the invocation
      61      # of test_doctest. So we do our own thing and leave
      62      # sys.modules alone.
      63      # We also clear the linecache and zipimport cache
      64      # just to avoid any bogus errors due to name reuse in the tests
      65      def setUp(self):
      66          linecache.clearcache()
      67          zipimport._zip_directory_cache.clear()
      68          self.path = sys.path[:]
      69          self.meta_path = sys.meta_path[:]
      70          self.path_hooks = sys.path_hooks[:]
      71          sys.path_importer_cache.clear()
      72  
      73      def tearDown(self):
      74          sys.path[:] = self.path
      75          sys.meta_path[:] = self.meta_path
      76          sys.path_hooks[:] = self.path_hooks
      77          sys.path_importer_cache.clear()
      78  
      79      def test_inspect_getsource_issue4223(self):
      80          test_src = "def foo(): pass\n"
      81          with os_helper.temp_dir() as d:
      82              init_name = make_script(d, '__init__', test_src)
      83              name_in_zip = os.path.join('zip_pkg',
      84                                         os.path.basename(init_name))
      85              zip_name, run_name = make_zip_script(d, 'test_zip',
      86                                                  init_name, name_in_zip)
      87              os.remove(init_name)
      88              sys.path.insert(0, zip_name)
      89              import zip_pkg
      90              try:
      91                  self.assertEqual(inspect.getsource(zip_pkg.foo), test_src)
      92              finally:
      93                  del sys.modules["zip_pkg"]
      94  
      95      def test_doctest_issue4197(self):
      96          # To avoid having to keep two copies of the doctest module's
      97          # unit tests in sync, this test works by taking the source of
      98          # test_doctest itself, rewriting it a bit to cope with a new
      99          # location, and then throwing it in a zip file to make sure
     100          # everything still works correctly
     101          test_src = inspect.getsource(test_doctest)
     102          test_src = test_src.replace(
     103                           "from test import test_doctest",
     104                           "import test_zipped_doctest as test_doctest")
     105          test_src = test_src.replace("test.test_doctest",
     106                                      "test_zipped_doctest")
     107          test_src = test_src.replace("test.sample_doctest",
     108                                      "sample_zipped_doctest")
     109          # The sample doctest files rewritten to include in the zipped version.
     110          sample_sources = {}
     111          for mod in [sample_doctest, sample_doctest_no_doctests,
     112                      sample_doctest_no_docstrings]:
     113              src = inspect.getsource(mod)
     114              src = src.replace("test.test_doctest", "test_zipped_doctest")
     115              # Rewrite the module name so that, for example,
     116              # "test.sample_doctest" becomes "sample_zipped_doctest".
     117              mod_name = mod.__name__.split(".")[-1]
     118              mod_name = mod_name.replace("sample_", "sample_zipped_")
     119              sample_sources[mod_name] = src
     120  
     121          with os_helper.temp_dir() as d:
     122              script_name = make_script(d, 'test_zipped_doctest',
     123                                              test_src)
     124              zip_name, run_name = make_zip_script(d, 'test_zip',
     125                                                  script_name)
     126              with zipfile.ZipFile(zip_name, 'a') as z:
     127                  for mod_name, src in sample_sources.items():
     128                      z.writestr(mod_name + ".py", src)
     129              if verbose:
     130                  with zipfile.ZipFile(zip_name, 'r') as zip_file:
     131                      print ('Contents of %r:' % zip_name)
     132                      zip_file.printdir()
     133              os.remove(script_name)
     134              sys.path.insert(0, zip_name)
     135              import test_zipped_doctest
     136              try:
     137                  # Some of the doc tests depend on the colocated text files
     138                  # which aren't available to the zipped version (the doctest
     139                  # module currently requires real filenames for non-embedded
     140                  # tests). So we're forced to be selective about which tests
     141                  # to run.
     142                  # doctest could really use some APIs which take a text
     143                  # string or a file object instead of a filename...
     144                  known_good_tests = [
     145                      test_zipped_doctest.SampleClass,
     146                      test_zipped_doctest.SampleClass.NestedClass,
     147                      test_zipped_doctest.SampleClass.NestedClass.__init__,
     148                      test_zipped_doctest.SampleClass.__init__,
     149                      test_zipped_doctest.SampleClass.a_classmethod,
     150                      test_zipped_doctest.SampleClass.a_property,
     151                      test_zipped_doctest.SampleClass.a_staticmethod,
     152                      test_zipped_doctest.SampleClass.double,
     153                      test_zipped_doctest.SampleClass.get,
     154                      test_zipped_doctest.SampleNewStyleClass,
     155                      test_zipped_doctest.SampleNewStyleClass.__init__,
     156                      test_zipped_doctest.SampleNewStyleClass.double,
     157                      test_zipped_doctest.SampleNewStyleClass.get,
     158                      test_zipped_doctest.sample_func,
     159                      test_zipped_doctest.test_DocTest,
     160                      test_zipped_doctest.test_DocTestParser,
     161                      test_zipped_doctest.test_DocTestRunner.basics,
     162                      test_zipped_doctest.test_DocTestRunner.exceptions,
     163                      test_zipped_doctest.test_DocTestRunner.option_directives,
     164                      test_zipped_doctest.test_DocTestRunner.optionflags,
     165                      test_zipped_doctest.test_DocTestRunner.verbose_flag,
     166                      test_zipped_doctest.test_Example,
     167                      test_zipped_doctest.test_debug,
     168                      test_zipped_doctest.test_testsource,
     169                      test_zipped_doctest.test_trailing_space_in_test,
     170                      test_zipped_doctest.test_DocTestSuite,
     171                      test_zipped_doctest.test_DocTestFinder,
     172                  ]
     173                  # These tests are the ones which need access
     174                  # to the data files, so we don't run them
     175                  fail_due_to_missing_data_files = [
     176                      test_zipped_doctest.test_DocFileSuite,
     177                      test_zipped_doctest.test_testfile,
     178                      test_zipped_doctest.test_unittest_reportflags,
     179                  ]
     180  
     181                  for obj in known_good_tests:
     182                      _run_object_doctest(obj, test_zipped_doctest)
     183              finally:
     184                  del sys.modules["test_zipped_doctest"]
     185  
     186      def test_doctest_main_issue4197(self):
     187          test_src = textwrap.dedent("""\
     188                      class Test:
     189                          ">>> 'line 2'"
     190                          pass
     191  
     192                      import doctest
     193                      doctest.testmod()
     194                      """)
     195          pattern = 'File "%s", line 2, in %s'
     196          with os_helper.temp_dir() as d:
     197              script_name = make_script(d, 'script', test_src)
     198              rc, out, err = assert_python_ok(script_name)
     199              expected = pattern % (script_name, "__main__.Test")
     200              if verbose:
     201                  print ("Expected line", expected)
     202                  print ("Got stdout:")
     203                  print (ascii(out))
     204              self.assertIn(expected.encode('utf-8'), out)
     205              zip_name, run_name = make_zip_script(d, "test_zip",
     206                                                  script_name, '__main__.py')
     207              rc, out, err = assert_python_ok(zip_name)
     208              expected = pattern % (run_name, "__main__.Test")
     209              if verbose:
     210                  print ("Expected line", expected)
     211                  print ("Got stdout:")
     212                  print (ascii(out))
     213              self.assertIn(expected.encode('utf-8'), out)
     214  
     215      def test_pdb_issue4201(self):
     216          test_src = textwrap.dedent("""\
     217                      def f():
     218                          pass
     219  
     220                      import pdb
     221                      pdb.Pdb(nosigint=True).runcall(f)
     222                      """)
     223          with os_helper.temp_dir() as d:
     224              script_name = make_script(d, 'script', test_src)
     225              p = spawn_python(script_name)
     226              p.stdin.write(b'l\n')
     227              data = kill_python(p)
     228              # bdb/pdb applies normcase to its filename before displaying
     229              self.assertIn(os.path.normcase(script_name.encode('utf-8')), data)
     230              zip_name, run_name = make_zip_script(d, "test_zip",
     231                                                  script_name, '__main__.py')
     232              p = spawn_python(zip_name)
     233              p.stdin.write(b'l\n')
     234              data = kill_python(p)
     235              # bdb/pdb applies normcase to its filename before displaying
     236              self.assertIn(os.path.normcase(run_name.encode('utf-8')), data)
     237  
     238  
     239  def tearDownModule():
     240      test.support.reap_children()
     241  
     242  if __name__ == '__main__':
     243      unittest.main()