(root)/
Python-3.11.7/
Lib/
test/
test_importlib/
fixtures.py
       1  import os
       2  import sys
       3  import copy
       4  import shutil
       5  import pathlib
       6  import tempfile
       7  import textwrap
       8  import functools
       9  import contextlib
      10  
      11  from test.support.os_helper import FS_NONASCII
      12  from test.support import requires_zlib
      13  from typing import Dict, Union
      14  
      15  try:
      16      from importlib import resources  # type: ignore
      17  
      18      getattr(resources, 'files')
      19      getattr(resources, 'as_file')
      20  except (ImportError, AttributeError):
      21      import importlib_resources as resources  # type: ignore
      22  
      23  
      24  @contextlib.contextmanager
      25  def tempdir():
      26      tmpdir = tempfile.mkdtemp()
      27      try:
      28          yield pathlib.Path(tmpdir)
      29      finally:
      30          shutil.rmtree(tmpdir)
      31  
      32  
      33  @contextlib.contextmanager
      34  def save_cwd():
      35      orig = os.getcwd()
      36      try:
      37          yield
      38      finally:
      39          os.chdir(orig)
      40  
      41  
      42  @contextlib.contextmanager
      43  def tempdir_as_cwd():
      44      with tempdir() as tmp:
      45          with save_cwd():
      46              os.chdir(str(tmp))
      47              yield tmp
      48  
      49  
      50  @contextlib.contextmanager
      51  def install_finder(finder):
      52      sys.meta_path.append(finder)
      53      try:
      54          yield
      55      finally:
      56          sys.meta_path.remove(finder)
      57  
      58  
      59  class ESC[4;38;5;81mFixtures:
      60      def setUp(self):
      61          self.fixtures = contextlib.ExitStack()
      62          self.addCleanup(self.fixtures.close)
      63  
      64  
      65  class ESC[4;38;5;81mSiteDir(ESC[4;38;5;149mFixtures):
      66      def setUp(self):
      67          super().setUp()
      68          self.site_dir = self.fixtures.enter_context(tempdir())
      69  
      70  
      71  class ESC[4;38;5;81mOnSysPath(ESC[4;38;5;149mFixtures):
      72      @staticmethod
      73      @contextlib.contextmanager
      74      def add_sys_path(dir):
      75          sys.path[:0] = [str(dir)]
      76          try:
      77              yield
      78          finally:
      79              sys.path.remove(str(dir))
      80  
      81      def setUp(self):
      82          super().setUp()
      83          self.fixtures.enter_context(self.add_sys_path(self.site_dir))
      84  
      85  
      86  # Except for python/mypy#731, prefer to define
      87  # FilesDef = Dict[str, Union['FilesDef', str]]
      88  FilesDef = Dict[str, Union[Dict[str, Union[Dict[str, str], str]], str]]
      89  
      90  
      91  class ESC[4;38;5;81mDistInfoPkg(ESC[4;38;5;149mOnSysPath, ESC[4;38;5;149mSiteDir):
      92      files: FilesDef = {
      93          "distinfo_pkg-1.0.0.dist-info": {
      94              "METADATA": """
      95                  Name: distinfo-pkg
      96                  Author: Steven Ma
      97                  Version: 1.0.0
      98                  Requires-Dist: wheel >= 1.0
      99                  Requires-Dist: pytest; extra == 'test'
     100                  Keywords: sample package
     101  
     102                  Once upon a time
     103                  There was a distinfo pkg
     104                  """,
     105              "RECORD": "mod.py,sha256=abc,20\n",
     106              "entry_points.txt": """
     107                  [entries]
     108                  main = mod:main
     109                  ns:sub = mod:main
     110              """,
     111          },
     112          "mod.py": """
     113              def main():
     114                  print("hello world")
     115              """,
     116      }
     117  
     118      def setUp(self):
     119          super().setUp()
     120          build_files(DistInfoPkg.files, self.site_dir)
     121  
     122      def make_uppercase(self):
     123          """
     124          Rewrite metadata with everything uppercase.
     125          """
     126          shutil.rmtree(self.site_dir / "distinfo_pkg-1.0.0.dist-info")
     127          files = copy.deepcopy(DistInfoPkg.files)
     128          info = files["distinfo_pkg-1.0.0.dist-info"]
     129          info["METADATA"] = info["METADATA"].upper()
     130          build_files(files, self.site_dir)
     131  
     132  
     133  class ESC[4;38;5;81mDistInfoPkgWithDot(ESC[4;38;5;149mOnSysPath, ESC[4;38;5;149mSiteDir):
     134      files: FilesDef = {
     135          "pkg_dot-1.0.0.dist-info": {
     136              "METADATA": """
     137                  Name: pkg.dot
     138                  Version: 1.0.0
     139                  """,
     140          },
     141      }
     142  
     143      def setUp(self):
     144          super().setUp()
     145          build_files(DistInfoPkgWithDot.files, self.site_dir)
     146  
     147  
     148  class ESC[4;38;5;81mDistInfoPkgWithDotLegacy(ESC[4;38;5;149mOnSysPath, ESC[4;38;5;149mSiteDir):
     149      files: FilesDef = {
     150          "pkg.dot-1.0.0.dist-info": {
     151              "METADATA": """
     152                  Name: pkg.dot
     153                  Version: 1.0.0
     154                  """,
     155          },
     156          "pkg.lot.egg-info": {
     157              "METADATA": """
     158                  Name: pkg.lot
     159                  Version: 1.0.0
     160                  """,
     161          },
     162      }
     163  
     164      def setUp(self):
     165          super().setUp()
     166          build_files(DistInfoPkgWithDotLegacy.files, self.site_dir)
     167  
     168  
     169  class ESC[4;38;5;81mDistInfoPkgOffPath(ESC[4;38;5;149mSiteDir):
     170      def setUp(self):
     171          super().setUp()
     172          build_files(DistInfoPkg.files, self.site_dir)
     173  
     174  
     175  class ESC[4;38;5;81mEggInfoPkg(ESC[4;38;5;149mOnSysPath, ESC[4;38;5;149mSiteDir):
     176      files: FilesDef = {
     177          "egginfo_pkg.egg-info": {
     178              "PKG-INFO": """
     179                  Name: egginfo-pkg
     180                  Author: Steven Ma
     181                  License: Unknown
     182                  Version: 1.0.0
     183                  Classifier: Intended Audience :: Developers
     184                  Classifier: Topic :: Software Development :: Libraries
     185                  Keywords: sample package
     186                  Description: Once upon a time
     187                          There was an egginfo package
     188                  """,
     189              "SOURCES.txt": """
     190                  mod.py
     191                  egginfo_pkg.egg-info/top_level.txt
     192              """,
     193              "entry_points.txt": """
     194                  [entries]
     195                  main = mod:main
     196              """,
     197              "requires.txt": """
     198                  wheel >= 1.0; python_version >= "2.7"
     199                  [test]
     200                  pytest
     201              """,
     202              "top_level.txt": "mod\n",
     203          },
     204          "mod.py": """
     205              def main():
     206                  print("hello world")
     207              """,
     208      }
     209  
     210      def setUp(self):
     211          super().setUp()
     212          build_files(EggInfoPkg.files, prefix=self.site_dir)
     213  
     214  
     215  class ESC[4;38;5;81mEggInfoFile(ESC[4;38;5;149mOnSysPath, ESC[4;38;5;149mSiteDir):
     216      files: FilesDef = {
     217          "egginfo_file.egg-info": """
     218              Metadata-Version: 1.0
     219              Name: egginfo_file
     220              Version: 0.1
     221              Summary: An example package
     222              Home-page: www.example.com
     223              Author: Eric Haffa-Vee
     224              Author-email: eric@example.coms
     225              License: UNKNOWN
     226              Description: UNKNOWN
     227              Platform: UNKNOWN
     228              """,
     229      }
     230  
     231      def setUp(self):
     232          super().setUp()
     233          build_files(EggInfoFile.files, prefix=self.site_dir)
     234  
     235  
     236  def build_files(file_defs, prefix=pathlib.Path()):
     237      """Build a set of files/directories, as described by the
     238  
     239      file_defs dictionary.  Each key/value pair in the dictionary is
     240      interpreted as a filename/contents pair.  If the contents value is a
     241      dictionary, a directory is created, and the dictionary interpreted
     242      as the files within it, recursively.
     243  
     244      For example:
     245  
     246      {"README.txt": "A README file",
     247       "foo": {
     248          "__init__.py": "",
     249          "bar": {
     250              "__init__.py": "",
     251          },
     252          "baz.py": "# Some code",
     253       }
     254      }
     255      """
     256      for name, contents in file_defs.items():
     257          full_name = prefix / name
     258          if isinstance(contents, dict):
     259              full_name.mkdir()
     260              build_files(contents, prefix=full_name)
     261          else:
     262              if isinstance(contents, bytes):
     263                  with full_name.open('wb') as f:
     264                      f.write(contents)
     265              else:
     266                  with full_name.open('w', encoding='utf-8') as f:
     267                      f.write(DALS(contents))
     268  
     269  
     270  class ESC[4;38;5;81mFileBuilder:
     271      def unicode_filename(self):
     272          return FS_NONASCII or self.skip("File system does not support non-ascii.")
     273  
     274  
     275  def DALS(str):
     276      "Dedent and left-strip"
     277      return textwrap.dedent(str).lstrip()
     278  
     279  
     280  class ESC[4;38;5;81mNullFinder:
     281      def find_module(self, name):
     282          pass
     283  
     284  
     285  @requires_zlib()
     286  class ESC[4;38;5;81mZipFixtures:
     287      root = 'test.test_importlib.data'
     288  
     289      def _fixture_on_path(self, filename):
     290          pkg_file = resources.files(self.root).joinpath(filename)
     291          file = self.resources.enter_context(resources.as_file(pkg_file))
     292          assert file.name.startswith('example'), file.name
     293          sys.path.insert(0, str(file))
     294          self.resources.callback(sys.path.pop, 0)
     295  
     296      def setUp(self):
     297          # Add self.zip_name to the front of sys.path.
     298          self.resources = contextlib.ExitStack()
     299          self.addCleanup(self.resources.close)
     300  
     301  
     302  def parameterize(*args_set):
     303      """Run test method with a series of parameters."""
     304  
     305      def wrapper(func):
     306          @functools.wraps(func)
     307          def _inner(self):
     308              for args in args_set:
     309                  with self.subTest(**args):
     310                      func(self, **args)
     311  
     312          return _inner
     313  
     314      return wrapper