1  import abc
       2  import importlib
       3  import io
       4  import sys
       5  import types
       6  import pathlib
       7  
       8  from . import data01
       9  from . import zipdata01
      10  from importlib.resources.abc import ResourceReader
      11  from test.support import import_helper
      12  
      13  
      14  from importlib.machinery import ModuleSpec
      15  
      16  
      17  class ESC[4;38;5;81mReader(ESC[4;38;5;149mResourceReader):
      18      def __init__(self, **kwargs):
      19          vars(self).update(kwargs)
      20  
      21      def get_resource_reader(self, package):
      22          return self
      23  
      24      def open_resource(self, path):
      25          self._path = path
      26          if isinstance(self.file, Exception):
      27              raise self.file
      28          return self.file
      29  
      30      def resource_path(self, path_):
      31          self._path = path_
      32          if isinstance(self.path, Exception):
      33              raise self.path
      34          return self.path
      35  
      36      def is_resource(self, path_):
      37          self._path = path_
      38          if isinstance(self.path, Exception):
      39              raise self.path
      40  
      41          def part(entry):
      42              return entry.split('/')
      43  
      44          return any(
      45              len(parts) == 1 and parts[0] == path_ for parts in map(part, self._contents)
      46          )
      47  
      48      def contents(self):
      49          if isinstance(self.path, Exception):
      50              raise self.path
      51          yield from self._contents
      52  
      53  
      54  def create_package_from_loader(loader, is_package=True):
      55      name = 'testingpackage'
      56      module = types.ModuleType(name)
      57      spec = ModuleSpec(name, loader, origin='does-not-exist', is_package=is_package)
      58      module.__spec__ = spec
      59      module.__loader__ = loader
      60      return module
      61  
      62  
      63  def create_package(file=None, path=None, is_package=True, contents=()):
      64      return create_package_from_loader(
      65          Reader(file=file, path=path, _contents=contents),
      66          is_package,
      67      )
      68  
      69  
      70  class ESC[4;38;5;81mCommonTests(metaclass=ESC[4;38;5;149mabcESC[4;38;5;149m.ESC[4;38;5;149mABCMeta):
      71      """
      72      Tests shared by test_open, test_path, and test_read.
      73      """
      74  
      75      @abc.abstractmethod
      76      def execute(self, package, path):
      77          """
      78          Call the pertinent legacy API function (e.g. open_text, path)
      79          on package and path.
      80          """
      81  
      82      def test_package_name(self):
      83          """
      84          Passing in the package name should succeed.
      85          """
      86          self.execute(data01.__name__, 'utf-8.file')
      87  
      88      def test_package_object(self):
      89          """
      90          Passing in the package itself should succeed.
      91          """
      92          self.execute(data01, 'utf-8.file')
      93  
      94      def test_string_path(self):
      95          """
      96          Passing in a string for the path should succeed.
      97          """
      98          path = 'utf-8.file'
      99          self.execute(data01, path)
     100  
     101      def test_pathlib_path(self):
     102          """
     103          Passing in a pathlib.PurePath object for the path should succeed.
     104          """
     105          path = pathlib.PurePath('utf-8.file')
     106          self.execute(data01, path)
     107  
     108      def test_importing_module_as_side_effect(self):
     109          """
     110          The anchor package can already be imported.
     111          """
     112          del sys.modules[data01.__name__]
     113          self.execute(data01.__name__, 'utf-8.file')
     114  
     115      def test_missing_path(self):
     116          """
     117          Attempting to open or read or request the path for a
     118          non-existent path should succeed if open_resource
     119          can return a viable data stream.
     120          """
     121          bytes_data = io.BytesIO(b'Hello, world!')
     122          package = create_package(file=bytes_data, path=FileNotFoundError())
     123          self.execute(package, 'utf-8.file')
     124          self.assertEqual(package.__loader__._path, 'utf-8.file')
     125  
     126      def test_extant_path(self):
     127          # Attempting to open or read or request the path when the
     128          # path does exist should still succeed. Does not assert
     129          # anything about the result.
     130          bytes_data = io.BytesIO(b'Hello, world!')
     131          # any path that exists
     132          path = __file__
     133          package = create_package(file=bytes_data, path=path)
     134          self.execute(package, 'utf-8.file')
     135          self.assertEqual(package.__loader__._path, 'utf-8.file')
     136  
     137      def test_useless_loader(self):
     138          package = create_package(file=FileNotFoundError(), path=FileNotFoundError())
     139          with self.assertRaises(FileNotFoundError):
     140              self.execute(package, 'utf-8.file')
     141  
     142  
     143  class ESC[4;38;5;81mZipSetupBase:
     144      ZIP_MODULE = None
     145  
     146      @classmethod
     147      def setUpClass(cls):
     148          data_path = pathlib.Path(cls.ZIP_MODULE.__file__)
     149          data_dir = data_path.parent
     150          cls._zip_path = str(data_dir / 'ziptestdata.zip')
     151          sys.path.append(cls._zip_path)
     152          cls.data = importlib.import_module('ziptestdata')
     153  
     154      @classmethod
     155      def tearDownClass(cls):
     156          try:
     157              sys.path.remove(cls._zip_path)
     158          except ValueError:
     159              pass
     160  
     161          try:
     162              del sys.path_importer_cache[cls._zip_path]
     163              del sys.modules[cls.data.__name__]
     164          except KeyError:
     165              pass
     166  
     167          try:
     168              del cls.data
     169              del cls._zip_path
     170          except AttributeError:
     171              pass
     172  
     173      def setUp(self):
     174          modules = import_helper.modules_setup()
     175          self.addCleanup(import_helper.modules_cleanup, *modules)
     176  
     177  
     178  class ESC[4;38;5;81mZipSetup(ESC[4;38;5;149mZipSetupBase):
     179      ZIP_MODULE = zipdata01  # type: ignore