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

Commit9da3961

Browse files
bpo-25711: Move _ZipImportResourceReader from importlib to zipimport. (GH-9406)
1 parent2a9c380 commit9da3961

File tree

3 files changed

+1067
-952
lines changed

3 files changed

+1067
-952
lines changed

‎Lib/importlib/resources.py

Lines changed: 0 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -257,87 +257,3 @@ def contents(package: Package) -> Iterable[str]:
257257
else:
258258
package_directory=Path(package.__spec__.origin).parent
259259
returnos.listdir(package_directory)
260-
261-
262-
# Private implementation of ResourceReader and get_resource_reader() called
263-
# from zipimport.c. Don't use these directly! We're implementing these in
264-
# Python because 1) it's easier, 2) zipimport may get rewritten in Python
265-
# itself at some point, so doing this all in C would difficult and a waste of
266-
# effort.
267-
268-
class_ZipImportResourceReader(resources_abc.ResourceReader):
269-
"""Private class used to support ZipImport.get_resource_reader().
270-
271-
This class is allowed to reference all the innards and private parts of
272-
the zipimporter.
273-
"""
274-
275-
def__init__(self,zipimporter,fullname):
276-
self.zipimporter=zipimporter
277-
self.fullname=fullname
278-
279-
defopen_resource(self,resource):
280-
fullname_as_path=self.fullname.replace('.','/')
281-
path=f'{fullname_as_path}/{resource}'
282-
try:
283-
returnBytesIO(self.zipimporter.get_data(path))
284-
exceptOSError:
285-
raiseFileNotFoundError(path)
286-
287-
defresource_path(self,resource):
288-
# All resources are in the zip file, so there is no path to the file.
289-
# Raising FileNotFoundError tells the higher level API to extract the
290-
# binary data and create a temporary file.
291-
raiseFileNotFoundError
292-
293-
defis_resource(self,name):
294-
# Maybe we could do better, but if we can get the data, it's a
295-
# resource. Otherwise it isn't.
296-
fullname_as_path=self.fullname.replace('.','/')
297-
path=f'{fullname_as_path}/{name}'
298-
try:
299-
self.zipimporter.get_data(path)
300-
exceptOSError:
301-
returnFalse
302-
returnTrue
303-
304-
defcontents(self):
305-
# This is a bit convoluted, because fullname will be a module path,
306-
# but _files is a list of file names relative to the top of the
307-
# archive's namespace. We want to compare file paths to find all the
308-
# names of things inside the module represented by fullname. So we
309-
# turn the module path of fullname into a file path relative to the
310-
# top of the archive, and then we iterate through _files looking for
311-
# names inside that "directory".
312-
fullname_path=Path(self.zipimporter.get_filename(self.fullname))
313-
relative_path=fullname_path.relative_to(self.zipimporter.archive)
314-
# Don't forget that fullname names a package, so its path will include
315-
# __init__.py, which we want to ignore.
316-
assertrelative_path.name=='__init__.py'
317-
package_path=relative_path.parent
318-
subdirs_seen=set()
319-
forfilenameinself.zipimporter._files:
320-
try:
321-
relative=Path(filename).relative_to(package_path)
322-
exceptValueError:
323-
continue
324-
# If the path of the file (which is relative to the top of the zip
325-
# namespace), relative to the package given when the resource
326-
# reader was created, has a parent, then it's a name in a
327-
# subdirectory and thus we skip it.
328-
parent_name=relative.parent.name
329-
iflen(parent_name)==0:
330-
yieldrelative.name
331-
elifparent_namenotinsubdirs_seen:
332-
subdirs_seen.add(parent_name)
333-
yieldparent_name
334-
335-
336-
# Called from zipimport.c
337-
def_zipimport_get_resource_reader(zipimporter,fullname):
338-
try:
339-
ifnotzipimporter.is_package(fullname):
340-
returnNone
341-
exceptZipImportError:
342-
returnNone
343-
return_ZipImportResourceReader(zipimporter,fullname)

‎Lib/zipimport.py

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,8 +272,16 @@ def get_resource_reader(self, fullname):
272272
If 'fullname' is a package within the zip file, return the
273273
'ResourceReader' object for the package. Otherwise return None.
274274
"""
275-
fromimportlibimportresources
276-
returnresources._zipimport_get_resource_reader(self,fullname)
275+
try:
276+
ifnotself.is_package(fullname):
277+
returnNone
278+
exceptZipImportError:
279+
returnNone
280+
ifnot_ZipImportResourceReader._registered:
281+
fromimportlib.abcimportResourceReader
282+
ResourceReader.register(_ZipImportResourceReader)
283+
_ZipImportResourceReader._registered=True
284+
return_ZipImportResourceReader(self,fullname)
277285

278286

279287
def__repr__(self):
@@ -648,3 +656,74 @@ def _get_module_code(self, fullname):
648656
returncode,ispackage,modpath
649657
else:
650658
raiseZipImportError(f"can't find module{fullname!r}",name=fullname)
659+
660+
661+
class_ZipImportResourceReader:
662+
"""Private class used to support ZipImport.get_resource_reader().
663+
664+
This class is allowed to reference all the innards and private parts of
665+
the zipimporter.
666+
"""
667+
_registered=False
668+
669+
def__init__(self,zipimporter,fullname):
670+
self.zipimporter=zipimporter
671+
self.fullname=fullname
672+
673+
defopen_resource(self,resource):
674+
fullname_as_path=self.fullname.replace('.','/')
675+
path=f'{fullname_as_path}/{resource}'
676+
fromioimportBytesIO
677+
try:
678+
returnBytesIO(self.zipimporter.get_data(path))
679+
exceptOSError:
680+
raiseFileNotFoundError(path)
681+
682+
defresource_path(self,resource):
683+
# All resources are in the zip file, so there is no path to the file.
684+
# Raising FileNotFoundError tells the higher level API to extract the
685+
# binary data and create a temporary file.
686+
raiseFileNotFoundError
687+
688+
defis_resource(self,name):
689+
# Maybe we could do better, but if we can get the data, it's a
690+
# resource. Otherwise it isn't.
691+
fullname_as_path=self.fullname.replace('.','/')
692+
path=f'{fullname_as_path}/{name}'
693+
try:
694+
self.zipimporter.get_data(path)
695+
exceptOSError:
696+
returnFalse
697+
returnTrue
698+
699+
defcontents(self):
700+
# This is a bit convoluted, because fullname will be a module path,
701+
# but _files is a list of file names relative to the top of the
702+
# archive's namespace. We want to compare file paths to find all the
703+
# names of things inside the module represented by fullname. So we
704+
# turn the module path of fullname into a file path relative to the
705+
# top of the archive, and then we iterate through _files looking for
706+
# names inside that "directory".
707+
frompathlibimportPath
708+
fullname_path=Path(self.zipimporter.get_filename(self.fullname))
709+
relative_path=fullname_path.relative_to(self.zipimporter.archive)
710+
# Don't forget that fullname names a package, so its path will include
711+
# __init__.py, which we want to ignore.
712+
assertrelative_path.name=='__init__.py'
713+
package_path=relative_path.parent
714+
subdirs_seen=set()
715+
forfilenameinself.zipimporter._files:
716+
try:
717+
relative=Path(filename).relative_to(package_path)
718+
exceptValueError:
719+
continue
720+
# If the path of the file (which is relative to the top of the zip
721+
# namespace), relative to the package given when the resource
722+
# reader was created, has a parent, then it's a name in a
723+
# subdirectory and thus we skip it.
724+
parent_name=relative.parent.name
725+
iflen(parent_name)==0:
726+
yieldrelative.name
727+
elifparent_namenotinsubdirs_seen:
728+
subdirs_seen.add(parent_name)
729+
yieldparent_name

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp