8000 gh-116608: Bring back importlib.resources functional API by encukou · Pull Request #116609 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

gh-116608: Bring back importlib.resources functional API #116609

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Apr 5, 2024
Prev Previous commit
Next Next commit
Fix issues & nitbicks found in backport
  • Loading branch information
encukou committed Mar 21, 2024
commit a520a78f5ceddb9e0a7c219783c21d30d8dd05c7
3 changes: 0 additions & 3 deletions Lib/importlib/resources/functional.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
"""Simplified function-based API for importlib.resources


"""

import os
import warnings

from ._common import files, as_file
Expand Down
84 changes: 43 additions & 41 deletions Lib/test/test_importlib/resources/test_functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from test.support.warnings_helper import ignore_warnings, check_warnings

import importlib.resources
import importlib.resources as resources

# Since the functional API forwards to Traversable, we only test
# filesystem resources here -- not zip files, namespace packages etc.
Expand All @@ -16,8 +16,8 @@ class StringAnchorMixin:


class ModuleAnchorMixin:
from test.test_importlib.resources import data01 as anchor01
from test.test_importlib.resources import data02 as anchor02
from . import data01 as anchor01
from . import data02 as anchor02


class FunctionalAPIBase():
Expand All @@ -34,39 +34,39 @@ def _gen_resourcetxt_path_parts(self):

def test_read_text(self):
self.assertEqual(
importlib.resources.read_text(self.anchor01, 'utf-8.file'),
resources.read_text(self.anchor01, 'utf-8.file'),
'Hello, UTF-8 world!\n',
)
self.assertEqual(
importlib.resources.read_text(
resources.read_text(
self.anchor02, 'subdirectory', 'subsubdir', 'resource.txt',
encoding='utf-8',
),
'a resource',
)
for path_parts in self._gen_resourcetxt_path_parts():
self.assertEqual(
importlib.resources.read_text(
resources.read_text(
self.anchor02, *path_parts, encoding='utf-8',
),
'a resource',
)
# Use generic OSError, since e.g. attempting to read a directory can
# fail with PermissionError rather than IsADirectoryError
with self.assertRaises(OSError):
importlib.resources.read_text(self.anchor01)
resources.read_text(self.anchor01)
with self.assertRaises(OSError):
importlib.resources.read_text(self.anchor01, 'no-such-file')
resources.read_text(self.anchor01, 'no-such-file')
with self.assertRaises(UnicodeDecodeError):
importlib.resources.read_text(self.anchor01, 'utf-16.file')
resources.read_text(self.anchor01, 'utf-16.file')
self.assertEqual(
importlib.resources.read_text(
resources.read_text(
self.anchor01, 'binary.file', encoding='latin1',
),
'\x00\x01\x02\x03',
)
self.assertEqual(
importlib.resources.read_text(
resources.read_text(
self.anchor01, 'utf-16.file',
errors='backslashreplace',
),
Expand All @@ -77,38 +77,38 @@ def test_read_text(self):

def test_read_binary(self):
self.assertEqual(
importlib.resources.read_binary(self.anchor01, 'utf-8.file'),
resources.read_binary(self.anchor01, 'utf-8.file'),
b'Hello, UTF-8 world!\n',
)
for path_parts in self._gen_resourcet 8000 xt_path_parts():
self.assertEqual(
importlib.resources.read_binary(self.anchor02, *path_parts),
resources.read_binary(self.anchor02, *path_parts),
b'a resource',
)

def test_open_text(self):
with importlib.resources.open_text(self.anchor01, 'utf-8.file') as f:
with resources.open_text(self.anchor01, 'utf-8.file') as f:
self.assertEqual(f.read(), 'Hello, UTF-8 world!\n')
for path_parts in self._gen_resourcetxt_path_parts():
with importlib.resources.open_text(
with resources.open_text(
self.anchor02, *path_parts,
encoding='utf-8',
) as f:
self.assertEqual(f.read(), 'a resource')
# Use generic OSError, since e.g. attempting to read a directory can
# fail with PermissionError rather than IsADirectoryError
with self.assertRaises(OSError):
importlib.resources.open_text(self.anchor01)
resources.open_text(self.anchor01)
with self.assertRaises(OSError):
importlib.resources.open_text(self.anchor01, 'no-such-file')
with importlib.resources.open_text(self.anchor01, 'utf-16.file') as f:
resources.open_text(self.anchor01, 'no-such-file')
with resources.open_text(self.anchor01, 'utf-16.file') as f:
with self.assertRaises(UnicodeDecodeError):
f.read()
with importlib.resources.open_text(
with resources.open_text(
self.anchor01, 'binary.file', encoding='latin1',
) as f:
self.assertEqual(f.read(), '\x00\x01\x02\x03')
with importlib.resources.open_text(
with resources.open_text(
self.anchor01, 'utf-16.file',
errors='backslashreplace',
) as f:
Expand All @@ -120,24 +120,24 @@ def test_open_text(self):
)

def test_open_binary(self):
with importlib.resources.open_binary(self.anchor01, 'utf-8.file') as f:
with resources.open_binary(self.anchor01, 'utf-8.file') as f:
self.assertEqual(f.read(), b'Hello, UTF-8 world!\n')
for path_parts in self._gen_resourcetxt_path_parts():
with importlib.resources.open_binary(
with resources.open_binary(
self.anchor02, *path_parts,
) as f:
self.assertEqual(f.read(), b'a resource')

def test_path(self):
with importlib.resources.path(self.anchor01, 'utf-8.file') as path:
with resources.path(self.anchor01, 'utf-8.file') as path:
with open(str(path)) as f:
self.assertEqual(f.read(), 'Hello, UTF-8 world!\n')
with importlib.resources.path(self.anchor01) as path:
with resources.path(self.anchor01) as path:
with open(os.path.join(path, 'utf-8.file')) as f:
self.assertEqual(f.read(), 'Hello, UTF-8 world!\n')

def test_is_resource(self):
is_resource = importlib.resources.is_resource
is_resource = resources.is_resource
self.assertTrue(is_resource(self.anchor01, 'utf-8.file'))
self.assertFalse(is_resource(self.anchor01, 'no_such_file'))
self.assertFalse(is_resource(self.anchor01))
Expand All @@ -146,24 +146,26 @@ def test_is_resource(self):
self.assertTrue(is_resource(self.anchor02, *path_parts))

def test_contents(self):
is_resource = importlib.resources.is_resource
is_resource = resources.is_resource
with check_warnings((".*contents.*", DeprecationWarning)):
c = importlib.resources.contents(self.anchor01)
c = resources.contents(self.anchor01)
self.assertGreaterEqual(
set(c),
{'utf-8.file', 'utf-16.file', 'binary.file', 'subdirectory'},
)
with (self.assertRaises(OSError),
with (
self.assertRaises(OSError),
check_warnings((".*contents.*", DeprecationWarning)),
):
importlib.resources.contents(self.anchor01, 'utf-8.file')
list(resources.contents(self.anchor01, 'utf-8.file'))
for path_parts in self._gen_resourcetxt_path_parts():
with (self.assertRaises(OSError),
with (
self.assertRaises(OSError),
check_warnings((".*contents.*", DeprecationWarning)),
):
importlib.resources.contents(self.anchor01, *path_parts)
list(resources.contents(self.anchor01, *path_parts))
with check_warnings((".*contents.*", DeprecationWarning)):
c = importlib.resources.contents(self.anchor01, 'subdirectory')
c = resources.contents(self.anchor01, 'subdirectory')
self.assertGreaterEqual(
set(c),
{'binary.file'},
Expand All @@ -172,13 +174,13 @@ def test_contents(self):
@ignore_warnings(category=DeprecationWarning)
def test_common_errors(self):
for func in (
importlib.resources.read_text,
importlib.resources.read_binary,
importlib.resources.open_text,
importlib.resources.open_binary,
importlib.resources.path,
importlib.resources.is_resource,
importlib.resources.contents,
resources.read_text,
resources.read_binary,
resources.open_text,
resources.open_binary,
resources.path,
resources.is_resource,
resources.contents,
):
with self.subTest(func=func):
# Rejecting None anchor
Expand All @@ -193,8 +195,8 @@ def test_common_errors(self):

def test_text_errors(self):
for func in (
importlib.resources.read_text,
importlib.resources.open_text,
resources.read_text,
resources.open_text,
):
with self.subTest(func=func):
# Multiple path arguments need explicit encoding argument.
Expand Down
0