Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

gh-84013: normalize directory contents during import#113447

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
ronaldoussoren wants to merge11 commits intopython:main
base:main
Choose a base branch
Loading
fromronaldoussoren:gh-84013
Open
Show file tree
Hide file tree
Changes from1 commit
Commits
Show all changes
11 commits
Select commitHold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
NextNext commit
gh-84013: normalize directory contents during import
Identifiers in Python code are normalized to NFKC andthere is no guarantee that names in the file system arenormalized.Teach the FileFinder class about normalization, but onlydo this when the to-be-imported name contains non-ASCIIcharacters.
  • Loading branch information
@ronaldoussoren
ronaldoussoren committedDec 24, 2023
commitb7ba38900fda11d65603f6d85adc664e17fef99f
32 changes: 30 additions & 2 deletionsLib/importlib/_bootstrap_external.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -1594,6 +1594,12 @@ def __init__(self, path, *loader_details):
self._path_cache = set()
self._relaxed_path_cache = set()

# Cache in NFKC normalization for imports of non-ASCII
# names. The regular cache is not kept in NFKC format
# to avoid circular dependencies during startup.
self._norm_path_cache = None
self._norm_relaxed_path_cache = None

def invalidate_caches(self):
"""Invalidate the directory mtime."""
self._path_mtime = -1
Expand All@@ -1619,11 +1625,23 @@ def find_spec(self, fullname, target=None):
self._path_mtime = mtime
# tail_module keeps the original casing, for __file__ and friends
if _relax_case():
cache = self._relaxed_path_cache
cache_module = tail_module.lower()

if cache_module.isascii():
cache = self._relaxed_path_cache
else:
if self._norm_relaxed_path_cache is None:
self._fill_norm_cache()
cache = self._norm_relaxed_path_cache
else:
cache = self._path_cache
cache_module = tail_module

if cache_module.isascii():
cache = self._path_cache
else:
if self._norm_path_cache is None:
self._fill_norm_cache()
cache = self._norm_path_cache
# Check if the module is the name of a directory (and thus a package).
if cache_module in cache:
base_path = _path_join(self.path, tail_module)
Expand DownExpand Up@@ -1685,6 +1703,16 @@ def _fill_cache(self):
if sys.platform.startswith(_CASE_INSENSITIVE_PLATFORMS):
self._relaxed_path_cache = {fn.lower() for fn in contents}

self._norm_path_cache = None
self._norm_relaxed_path_cache = None

def _fill_norm_cache(self):
from unicodedata import normalize

self._norm_path_cache = { normalize('NFKC', p) for p in self._path_cache }
self._norm_relaxed_path_cache = { normalize('NFKC', p) for p in self._relaxed_path_cache }


@classmethod
def path_hook(cls, *loader_details):
"""A class method which returns a closure to use on sys.path_hook
Expand Down
38 changes: 38 additions & 0 deletionsLib/test/test_import/__init__.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,6 +19,7 @@
import threading
import time
import types
import unicodedata
import unittest
from unittest import mock
import _imp
Expand DownExpand Up@@ -2701,6 +2702,43 @@ def test_pyimport_addmodule_create(self):
mod = _testcapi.check_pyimport_addmodule(name)
self.assertIs(mod, sys.modules[name])

class TestImportAccented(unittest.TestCase):
# XXX: There should be tests with PYTHONCASEOK as well
# (for those platforms where this is relevant)
dir_name = os.path.abspath(TESTFN)

def setUp(self):
self.sys_path = sys.path[:]
os.mkdir(self.dir_name)
sys.path.insert(0, self.dir_name)
importlib.invalidate_caches()

def tearDown(self):
sys.path[:] = self.sys_path
importlib.invalidate_caches()
rmtree(self.dir_name)

def assert_importing_possible(self, name):
filename = os.path.join(self.dir_name, f"{name}.py")
with open(filename, "w") as stream:
stream.write("SPAM = 'spam'\n")

values = {}
exec(f"from {name} import SPAM", values, values)
self.assertEqual(values["SPAM"], "spam")
del sys.modules[unicodedata.normalize('NFKC', name)]

def test_import_precomposed(self):
name = 'M\u00E4dchen'
self.assert_importing_possible(name)

def test_import_normalized(self):
name = 'M\u0061\u0308dchen'
self.assert_importing_possible(name)

def test_import_macos_input(self):
name = 'Mädchen'
self.assert_importing_possible(name)

if __name__ == '__main__':
# Test needs to be a package, so we can do relative imports.
Expand Down

[8]ページ先頭

©2009-2025 Movatter.jp