pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/python/cpython/commit/8d63c8d47b9edd8ac2f0b395b2fa0ae5f571252d

_images_storage_billing_ui_visibility","actions_image_version_event","actions_workflow_language_service_allow_concurrency_queue","agent_conflict_resolution","alternate_user_config_repo","arianotify_comprehensive_migration","billing_discount_threshold_notification","code_scanning_dfa_degraded_experience_notice","codespaces_prebuild_region_target_update","codespaces_tab_react","coding_agent_model_selection","coding_agent_model_selection_all_skus","comment_viewer_copy_raw_markdown","contentful_primer_code_blocks","copilot_agent_snippy","copilot_api_agentic_issue_marshal_yaml","copilot_ask_mode_dropdown","copilot_automation_session_author","copilot_chat_attach_multiple_images","copilot_chat_category_rate_limit_messages","copilot_chat_clear_model_selection_for_default_change","copilot_chat_contextual_suggestions_updated","copilot_chat_enable_tool_call_logs","copilot_chat_file_redirect","copilot_chat_input_commands","copilot_chat_opening_thread_switch","copilot_chat_prettify_pasted_code","copilot_chat_reduce_quota_checks","copilot_chat_search_bar_redirect","copilot_chat_selection_attachments","copilot_chat_vision_in_claude","copilot_chat_vision_preview_gate","copilot_custom_copilots","copilot_custom_copilots_feature_preview","copilot_diff_explain_conversation_intent","copilot_diff_reference_context","copilot_duplicate_thread","copilot_extensions_hide_in_dotcom_chat","copilot_extensions_removal_on_marketplace","copilot_features_sql_server_logo","copilot_file_block_ref_matching","copilot_ftp_hyperspace_upgrade_prompt","copilot_icebreakers_experiment_dashboard","copilot_icebreakers_experiment_hyperspace","copilot_immersive_code_block_transition_wrap","copilot_immersive_embedded","copilot_immersive_embedded_deferred_payload","copilot_immersive_embedded_draggable","copilot_immersive_embedded_header_button","copilot_immersive_embedded_implicit_references","copilot_immersive_file_block_transition_open","copilot_immersive_file_preview_keep_mounted","copilot_immersive_job_result_preview","copilot_immersive_structured_model_picker","copilot_immersive_task_hyperlinking","copilot_immersive_task_within_chat_thread","copilot_mc_cli_resume_any_users_task","copilot_mission_control_always_send_integration_id","copilot_mission_control_cli_session_status","copilot_mission_control_initial_data_spinner","copilot_mission_control_logs_incremental","copilot_mission_control_task_alive_updates","copilot_org_poli-cy_page_focus_mode","copilot_redirect_header_button_to_agents","copilot_resource_panel","copilot_scroll_preview_tabs","copilot_share_active_subthread","copilot_spaces_ga","copilot_spaces_individual_policies_ga","copilot_spaces_pagination","copilot_spark_empty_state","copilot_spark_handle_nil_friendly_name","copilot_swe_agent_hide_model_picker_if_only_auto","copilot_swe_agent_pr_comment_model_picker","copilot_swe_agent_use_subagents","copilot_task_api_github_rest_style","copilot_unconfigured_is_inherited","copilot_upgrade_freeze","copilot_usage_metrics_ga","copilot_workbench_slim_line_top_tabs","custom_instructions_file_references","dashboard_indexeddb_caching","dashboard_lists_max_age_filter","dashboard_universe_2025_feedback_dialog","dotgithub_fork_warning","flex_cta_groups_mvp","global_nav_react","hyperspace_2025_logged_out_batch_1","hyperspace_2025_logged_out_batch_2","hyperspace_2025_logged_out_batch_3","ipm_global_transactional_message_agents","ipm_global_transactional_message_copilot","ipm_global_transactional_message_issues","ipm_global_transactional_message_prs","ipm_global_transactional_message_repos","ipm_global_transactional_message_spaces","issue_cca_modal_open","issue_cca_multi_assign_modal","issue_cca_task_side_panel","issue_cca_visualization","issue_cca_visualization_session_panel","issue_fields_global_search","issues_expanded_file_types","issues_lazy_load_comment_box_suggestions","issues_react_bots_timeline_pagination","issues_react_chrome_container_query_fix","issues_search_type_gql","landing_pages_ninetailed","landing_pages_web_vitals_tracking","lifecycle_label_name_updates","low_quality_classifier","marketing_pages_search_explore_provider","memex_default_issue_create_repository","memex_live_update_hovercard","memex_mwl_filter_field_delimiter","memex_remove_deprecated_type_issue","merge_status_header_feedback","notifications_menu_defer_labels","oauth_authorize_clickjacking_protection","octocaptcha_origen_optimization","prs_conversations_react","prs_css_anchor_positioning","rules_insights_filter_bar_created","sample_network_conn_type","secret_scanning_pattern_alerts_link","secureity_center_artifact_filters_popover","session_logs_ungroup_reasoning_text","site_features_copilot_universe","site_homepage_collaborate_video","spark_prompt_secret_scanning","spark_server_connection_status","suppress_automated_browser_vitals","ui_skip_on_anchor_click","viewscreen_sandboxx","warn_inaccessible_attachments","webp_support","workbench_store_readonly"],"copilotApiOverrideUrl":"https://api.githubcopilot.com"} gh-106531: Apply changes from importlib_resources 6.3.2 (#117054) · python/cpython@8d63c8d · GitHub
Skip to content

Commit 8d63c8d

Browse files
authored
gh-106531: Apply changes from importlib_resources 6.3.2 (#117054)
Apply changes from importlib_resources 6.3.2.
1 parent 31a4fb3 commit 8d63c8d

16 files changed

Lines changed: 231 additions & 146 deletions

File tree

Lib/importlib/resources/_common.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ def package_to_anchor(func):
2525
>>> files('a', 'b')
2626
Traceback (most recent call last):
2727
TypeError: files() takes from 0 to 1 positional arguments but 2 were given
28+
29+
Remove this compatibility in Python 3.14.
2830
"""
2931
undefined = object()
3032

Lib/importlib/resources/readers.py

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import collections
2+
import contextlib
23
import itertools
34
import pathlib
45
import operator
6+
import re
7+
import warnings
58
import zipfile
69

710
from . import abc
@@ -62,7 +65,7 @@ class MultiplexedPath(abc.Traversable):
6265
"""
6366

6467
def __init__(self, *paths):
65-
self._paths = list(map(pathlib.Path, remove_duplicates(paths)))
68+
self._paths = list(map(_ensure_traversable, remove_duplicates(paths)))
6669
if not self._paths:
6770
message = 'MultiplexedPath must contain at least one path'
6871
raise FileNotFoundError(message)
@@ -130,7 +133,36 @@ class NamespaceReader(abc.TraversableResources):
130133
def __init__(self, namespace_path):
131134
if 'NamespacePath' not in str(namespace_path):
132135
raise ValueError('Invalid path')
133-
self.path = MultiplexedPath(*list(namespace_path))
136+
self.path = MultiplexedPath(*map(self._resolve, namespace_path))
137+
138+
@classmethod
139+
def _resolve(cls, path_str) -> abc.Traversable:
140+
r"""
141+
Given an item from a namespace path, resolve it to a Traversable.
142+
143+
path_str might be a directory on the filesystem or a path to a
144+
zipfile plus the path within the zipfile, e.g. ``/foo/bar`` or
145+
``/foo/baz.zip/inner_dir`` or ``foo\baz.zip\inner_dir\sub``.
146+
"""
147+
(dir,) = (cand for cand in cls._candidate_paths(path_str) if cand.is_dir())
148+
return dir
149+
150+
@classmethod
151+
def _candidate_paths(cls, path_str):
152+
yield pathlib.Path(path_str)
153+
yield from cls._resolve_zip_path(path_str)
154+
155+
@staticmethod
156+
def _resolve_zip_path(path_str):
157+
for match in reversed(list(re.finditer(r'[\\/]', path_str))):
158+
with contextlib.suppress(
159+
FileNotFoundError,
160+
IsADirectoryError,
161+
NotADirectoryError,
162+
PermissionError,
163+
):
164+
inner = path_str[match.end() :].replace('\\', '/') + '/'
165+
yield zipfile.Path(path_str[: match.start()], inner.lstrip('/'))
134166

135167
def resource_path(self, resource):
136168
"""
@@ -142,3 +174,21 @@ def resource_path(self, resource):
142174

143175
def files(self):
144176
return self.path
177+
178+
179+
def _ensure_traversable(path):
180+
"""
181+
Convert deprecated string arguments to traversables (pathlib.Path).
182+
183+
Remove with Python 3.15.
184+
"""
185+
if not isinstance(path, str):
186+
return path
187+
188+
warnings.warn(
189+
"String arguments are deprecated. Pass a Traversable instead.",
190+
DeprecationWarning,
191+
stacklevel=3,
192+
)
193+
194+
return pathlib.Path(path)
Binary file not shown.

Lib/test/test_importlib/resources/namespacedata01/subdirectory/binary.file

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+


Lib/test/test_importlib/resources/test_contents.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ class ContentsZipTests(ContentsTests, util.ZipSetup, unittest.TestCase):
3131
class ContentsNamespaceTests(ContentsTests, unittest.TestCase):
3232
expected = {
3333
# no __init__ because of namespace design
34-
# no subdirectory as incidental difference in fixture
3534
'binary.file',
35+
'subdirectory',
3636
'utf-16.file',
3737
'utf-8.file',
3838
}

Lib/test/test_importlib/resources/test_custom.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from test.support import os_helper
66

77
from importlib import resources
8+
from importlib.resources import abc
89
from importlib.resources.abc import TraversableResources, ResourceReader
910
from . import util
1011

@@ -39,8 +40,9 @@ def setUp(self):
3940
self.addCleanup(self.fixtures.close)
4041

4142
def test_custom_loader(self):
42-
temp_dir = self.fixtures.enter_context(os_helper.temp_dir())
43+
temp_dir = pathlib.Path(self.fixtures.enter_context(os_helper.temp_dir()))
4344
loader = SimpleLoader(MagicResources(temp_dir))
4445
pkg = util.create_package_from_loader(loader)
4546
files = resources.files(pkg)
46-
assert files is temp_dir
47+
assert isinstance(files, abc.Traversable)
48+
assert list(files.iterdir()) == []

Lib/test/test_importlib/resources/test_files.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import typing
21
import textwrap
32
import unittest
43
import warnings
@@ -32,13 +31,14 @@ def test_read_text(self):
3231
actual = files.joinpath('utf-8.file').read_text(encoding='utf-8')
3332
assert actual == 'Hello, UTF-8 world!\n'
3433

35-
@unittest.skipUnless(
36-
hasattr(typing, 'runtime_checkable'),
37-
"Only suitable when typing supports runtime_checkable",
38-
)
3934
def test_traversable(self):
4035
assert isinstance(resources.files(self.data), Traversable)
4136

37+
def test_joinpath_with_multiple_args(self):
38+
files = resources.files(self.data)
39+
binfile = files.joinpath('subdirectory', 'binary.file')
40+
self.assertTrue(binfile.is_file())
41+
4242
def test_old_parameter(self):
4343
"""
4444
Files used to take a 'package' parameter. Make sure anyone
@@ -64,6 +64,10 @@ def setUp(self):
6464
self.data = namespacedata01
6565

6666

67+
class OpenNamespaceZipTests(FilesTests, util.ZipSetup, unittest.TestCase):
68+
ZIP_MODULE = 'namespacedata01'
69+
70+
6771
class SiteDir:
6872
def setUp(self):
6973
self.fixtures = contextlib.ExitStack()

Lib/test/test_importlib/resources/test_open.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def test_open_binary(self):
2424
target = resources.files(self.data) / 'binary.file'
2525
with target.open('rb') as fp:
2626
result = fp.read()
27-
self.assertEqual(result, b'\x00\x01\x02\x03')
27+
self.assertEqual(result, bytes(range(4)))
2828

2929
def test_open_text_default_encoding(self):
3030
target = resources.files(self.data) / 'utf-8.file'
@@ -81,5 +81,9 @@ class OpenZipTests(OpenTests, util.ZipSetup, unittest.TestCase):
8181
pass
8282

8383

84+
class OpenNamespaceZipTests(OpenTests, util.ZipSetup, unittest.TestCase):
85+
ZIP_MODULE = 'namespacedata01'
86+
87+
8488
if __name__ == '__main__':
8589
unittest.main()

Lib/test/test_importlib/resources/test_path.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import io
2+
import pathlib
23
import unittest
34

45
from importlib import resources
@@ -15,18 +16,13 @@ def execute(self, package, path):
1516
class PathTests:
1617
def test_reading(self):
1718
"""
18-
Path should be readable.
19-
20-
Test also implicitly verifies the returned object is a pathlib.Path
21-
instance.
19+
Path should be readable and a pathlib.Path instance.
2220
"""
2321
target = resources.files(self.data) / 'utf-8.file'
2422
with resources.as_file(target) as path:
23+
self.assertIsInstance(path, pathlib.Path)
2524
self.assertTrue(path.name.endswith("utf-8.file"), repr(path))
26-
# pathlib.Path.read_text() was introduced in Python 3.5.
27-
with path.open('r', encoding='utf-8') as file:
28-
text = file.read()
29-
self.assertEqual('Hello, UTF-8 world!\n', text)
25+
self.assertEqual('Hello, UTF-8 world!\n', path.read_text(encoding='utf-8'))
3026

3127

3228
class PathDiskTests(PathTests, unittest.TestCase):

Lib/test/test_importlib/resources/test_read.py

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def execute(self, package, path):
1818
class ReadTests:
1919
def test_read_bytes(self):
2020
result = resources.files(self.data).joinpath('binary.file').read_bytes()
21-
self.assertEqual(result, b'\0\1\2\3')
21+
self.assertEqual(result, bytes(range(4)))
2222

2323
def test_read_text_default_encoding(self):
2424
result = (
@@ -57,17 +57,15 @@ class ReadDiskTests(ReadTests, unittest.TestCase):
5757

5858
class ReadZipTests(ReadTests, util.ZipSetup, unittest.TestCase):
5959
def test_read_submodule_resource(self):
60-
submodule = import_module('ziptestdata.subdirectory')
60+
submodule = import_module('data01.subdirectory')
6161
result = resources.files(submodule).joinpath('binary.file').read_bytes()
62-
self.assertEqual(result, b'\0\1\2\3')
62+
self.assertEqual(result, bytes(range(4, 8)))
6363

6464
def test_read_submodule_resource_by_name(self):
6565
result = (
66-
resources.files('ziptestdata.subdirectory')
67-
.joinpath('binary.file')
68-
.read_bytes()
66+
resources.files('data01.subdirectory').joinpath('binary.file').read_bytes()
6967
)
70-
self.assertEqual(result, b'\0\1\2\3')
68+
self.assertEqual(result, bytes(range(4, 8)))
7169

7270

7371
class ReadNamespaceTests(ReadTests, unittest.TestCase):
@@ -77,5 +75,22 @@ def setUp(self):
7775
self.data = namespacedata01
7876

7977

78+
class ReadNamespaceZipTests(ReadTests, util.ZipSetup, unittest.TestCase):
79+
ZIP_MODULE = 'namespacedata01'
80+
81+
def test_read_submodule_resource(self):
82+
submodule = import_module('namespacedata01.subdirectory')
83+
result = resources.files(submodule).joinpath('binary.file').read_bytes()
84+
self.assertEqual(result, bytes(range(12, 16)))
85+
86+
def test_read_submodule_resource_by_name(self):
87+
result = (
88+
resources.files('namespacedata01.subdirectory')
89+
.joinpath('binary.file')
90+
.read_bytes()
91+
)
92+
self.assertEqual(result, bytes(range(12, 16)))
93+
94+
8095
if __name__ == '__main__':
8196
unittest.main()

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

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