Skip to content

Commit be38279

Browse files
authored
Merge pull request python#9 from brettcannon/implement-read
Implement read()
2 parents 61c76ef + 53747f5 commit be38279

File tree

5 files changed

+90
-4
lines changed

5 files changed

+90
-4
lines changed

importlib_resources/__init__.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,21 @@ def open(package: Package, file_name: Path) -> BinaryIO:
5454
loader = typing.cast(importlib.abc.ResourceLoader, package.__spec__.loader)
5555
data = loader.get_data(full_path)
5656
return io.BytesIO(data)
57+
58+
59+
def read(package: Package, file_name: Path, encoding: str = 'utf-8',
60+
errors: str = 'strict') -> str:
61+
"""Return the decoded string of the resource.
62+
63+
The decoding-related arguments have the same semantics as those of
64+
bytes.decode().
65+
"""
66+
file_name = _normalize_path(file_name)
67+
package = _get_package(package)
68+
# Note this is **not** builtins.open()!
69+
with open(package, file_name) as binary_file:
70+
# Decoding from io.TextIOWrapper() instead of str.decode() in hopes that
71+
# the former will be smarter about memory usage.
72+
text_file = io.TextIOWrapper(binary_file, encoding=encoding,
73+
errors=errors)
74+
return text_file.read()
44 Bytes
Binary file not shown.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Hello, world!
1+
Hello, UTF-8 world!

importlib_resources/tests/test_open.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def test_pathlib_path(self):
3535

3636
def test_absolute_path(self):
3737
# An absolute path is a ValueError.
38-
path = pathlib.Path(__spec__.origin)
38+
path = pathlib.Path(__file__)
3939
full_path = path.parent/'utf-8.file'
4040
with self.assertRaises(ValueError):
4141
with resources.open(data, str(full_path)) as file:
@@ -65,13 +65,13 @@ class OpenTests(unittest.TestCase):
6565
def test_opened_for_reading(self):
6666
# The file-like object is ready for reading.
6767
with resources.open(data, 'utf-8.file') as file:
68-
self.assertEqual(b"Hello, world!\n", file.read())
68+
self.assertEqual(b"Hello, UTF-8 world!\n", file.read())
6969

7070
def test_wrap_for_text(self):
7171
# The file-like object can be wrapped for text reading.
7272
with resources.open(data, 'utf-8.file') as file:
7373
text_file = io.TextIOWrapper(file, encoding='utf-8')
74-
self.assertEqual('Hello, world!\n', text_file.read())
74+
self.assertEqual('Hello, UTF-8 world!\n', text_file.read())
7575

7676

7777
if __name__ == '__main__':
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import io
2+
import os.path
3+
import pathlib
4+
import sys
5+
import unittest
6+
7+
import importlib_resources as resources
8+
from importlib_resources.tests import data
9+
10+
11+
class CommonTests(unittest.TestCase):
12+
13+
def test_package_name(self):
14+
# Passing in the package name should succeed.
15+
resources.read(data.__name__, 'utf-8.file')
16+
17+
def test_package_object(self):
18+
# Passing in the package itself should succeed.
19+
resources.read(data, 'utf-8.file')
20+
21+
def test_string_path(self):
22+
path = 'utf-8.file'
23+
# Passing in a string for the path should succeed.
24+
resources.read(data, path)
25+
26+
@unittest.skipIf(sys.version_info < (3, 6), 'requires os.PathLike support')
27+
def test_pathlib_path(self):
28+
# Passing in a pathlib.PurePath object for the path should succeed.
29+
path = pathlib.PurePath('utf-8.file')
30+
resources.read(data, path)
31+
32+
def test_absolute_path(self):
33+
# An absolute path is a ValueError.
34+
path = pathlib.Path(__file__)
35+
full_path = path.parent/'utf-8.file'
36+
with self.assertRaises(ValueError):
37+
resources.read(data, str(full_path))
38+
39+
def test_relative_path(self):
40+
# A reative path is a ValueError.
41+
with self.assertRaises(ValueError):
42+
resources.read(data, '../data/utf-8.file')
43+
44+
def test_importing_module_as_side_effect(self):
45+
# The anchor package can already be imported.
46+
del sys.modules[data.__name__]
47+
resources.read(data.__name__, 'utf-8.file')
48+
49+
def test_non_package(self):
50+
# The anchor package cannot be a module.
51+
with self.assertRaises(TypeError):
52+
resources.read(__spec__.name, 'utf-8.file')
53+
54+
55+
class ReadTests(unittest.TestCase):
56+
57+
def test_default_encoding(self):
58+
result = resources.read(data, 'utf-8.file')
59+
self.assertEqual("Hello, UTF-8 world!\n", result)
60+
61+
def test_encoding(self):
62+
result = resources.read(data, 'utf-16.file', encoding='utf-16')
63+
self.assertEqual("Hello, UTF-16 world!\n", result)
64+
65+
def test_errors(self):
66+
# Raises UnicodeError without the 'errors' argument.
67+
result = resources.read(data, 'utf-16.file', encoding='utf-8',
68+
errors='ignore')

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy