Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
9da3961f
Commit
9da3961f
authored
Sep 19, 2018
by
Serhiy Storchaka
Committed by
GitHub
Sep 19, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
bpo-25711: Move _ZipImportResourceReader from importlib to zipimport. (GH-9406)
parent
2a9c3805
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
1067 additions
and
952 deletions
+1067
-952
Lib/importlib/resources.py
Lib/importlib/resources.py
+0
-84
Lib/zipimport.py
Lib/zipimport.py
+81
-2
Python/importlib_zipimport.h
Python/importlib_zipimport.h
+986
-866
No files found.
Lib/importlib/resources.py
View file @
9da3961f
...
@@ -257,87 +257,3 @@ def contents(package: Package) -> Iterable[str]:
...
@@ -257,87 +257,3 @@ def contents(package: Package) -> Iterable[str]:
else
:
else
:
package_directory
=
Path
(
package
.
__spec__
.
origin
).
parent
package_directory
=
Path
(
package
.
__spec__
.
origin
).
parent
return
os
.
listdir
(
package_directory
)
return
os
.
listdir
(
package_directory
)
# Private implementation of ResourceReader and get_resource_reader() called
# from zipimport.c. Don't use these directly! We're implementing these in
# Python because 1) it's easier, 2) zipimport may get rewritten in Python
# itself at some point, so doing this all in C would difficult and a waste of
# effort.
class
_ZipImportResourceReader
(
resources_abc
.
ResourceReader
):
"""Private class used to support ZipImport.get_resource_reader().
This class is allowed to reference all the innards and private parts of
the zipimporter.
"""
def
__init__
(
self
,
zipimporter
,
fullname
):
self
.
zipimporter
=
zipimporter
self
.
fullname
=
fullname
def
open_resource
(
self
,
resource
):
fullname_as_path
=
self
.
fullname
.
replace
(
'.'
,
'/'
)
path
=
f'
{
fullname_as_path
}
/
{
resource
}
'
try
:
return
BytesIO
(
self
.
zipimporter
.
get_data
(
path
))
except
OSError
:
raise
FileNotFoundError
(
path
)
def
resource_path
(
self
,
resource
):
# All resources are in the zip file, so there is no path to the file.
# Raising FileNotFoundError tells the higher level API to extract the
# binary data and create a temporary file.
raise
FileNotFoundError
def
is_resource
(
self
,
name
):
# Maybe we could do better, but if we can get the data, it's a
# resource. Otherwise it isn't.
fullname_as_path
=
self
.
fullname
.
replace
(
'.'
,
'/'
)
path
=
f'
{
fullname_as_path
}
/
{
name
}
'
try
:
self
.
zipimporter
.
get_data
(
path
)
except
OSError
:
return
False
return
True
def
contents
(
self
):
# This is a bit convoluted, because fullname will be a module path,
# but _files is a list of file names relative to the top of the
# archive's namespace. We want to compare file paths to find all the
# names of things inside the module represented by fullname. So we
# turn the module path of fullname into a file path relative to the
# top of the archive, and then we iterate through _files looking for
# names inside that "directory".
fullname_path
=
Path
(
self
.
zipimporter
.
get_filename
(
self
.
fullname
))
relative_path
=
fullname_path
.
relative_to
(
self
.
zipimporter
.
archive
)
# Don't forget that fullname names a package, so its path will include
# __init__.py, which we want to ignore.
assert
relative_path
.
name
==
'__init__.py'
package_path
=
relative_path
.
parent
subdirs_seen
=
set
()
for
filename
in
self
.
zipimporter
.
_files
:
try
:
relative
=
Path
(
filename
).
relative_to
(
package_path
)
except
ValueError
:
continue
# If the path of the file (which is relative to the top of the zip
# namespace), relative to the package given when the resource
# reader was created, has a parent, then it's a name in a
# subdirectory and thus we skip it.
parent_name
=
relative
.
parent
.
name
if
len
(
parent_name
)
==
0
:
yield
relative
.
name
elif
parent_name
not
in
subdirs_seen
:
subdirs_seen
.
add
(
parent_name
)
yield
parent_name
# Called from zipimport.c
def
_zipimport_get_resource_reader
(
zipimporter
,
fullname
):
try
:
if
not
zipimporter
.
is_package
(
fullname
):
return
None
except
ZipImportError
:
return
None
return
_ZipImportResourceReader
(
zipimporter
,
fullname
)
Lib/zipimport.py
View file @
9da3961f
...
@@ -272,8 +272,16 @@ class zipimporter:
...
@@ -272,8 +272,16 @@ class zipimporter:
If 'fullname' is a package within the zip file, return the
If 'fullname' is a package within the zip file, return the
'ResourceReader' object for the package. Otherwise return None.
'ResourceReader' object for the package. Otherwise return None.
"""
"""
from
importlib
import
resources
try
:
return
resources
.
_zipimport_get_resource_reader
(
self
,
fullname
)
if
not
self
.
is_package
(
fullname
):
return
None
except
ZipImportError
:
return
None
if
not
_ZipImportResourceReader
.
_registered
:
from
importlib.abc
import
ResourceReader
ResourceReader
.
register
(
_ZipImportResourceReader
)
_ZipImportResourceReader
.
_registered
=
True
return
_ZipImportResourceReader
(
self
,
fullname
)
def
__repr__
(
self
):
def
__repr__
(
self
):
...
@@ -648,3 +656,74 @@ def _get_module_code(self, fullname):
...
@@ -648,3 +656,74 @@ def _get_module_code(self, fullname):
return
code
,
ispackage
,
modpath
return
code
,
ispackage
,
modpath
else
:
else
:
raise
ZipImportError
(
f"can't find module
{
fullname
!
r
}
"
,
name
=
fullname
)
raise
ZipImportError
(
f"can't find module
{
fullname
!
r
}
"
,
name
=
fullname
)
class
_ZipImportResourceReader
:
"""Private class used to support ZipImport.get_resource_reader().
This class is allowed to reference all the innards and private parts of
the zipimporter.
"""
_registered
=
False
def
__init__
(
self
,
zipimporter
,
fullname
):
self
.
zipimporter
=
zipimporter
self
.
fullname
=
fullname
def
open_resource
(
self
,
resource
):
fullname_as_path
=
self
.
fullname
.
replace
(
'.'
,
'/'
)
path
=
f'
{
fullname_as_path
}
/
{
resource
}
'
from
io
import
BytesIO
try
:
return
BytesIO
(
self
.
zipimporter
.
get_data
(
path
))
except
OSError
:
raise
FileNotFoundError
(
path
)
def
resource_path
(
self
,
resource
):
# All resources are in the zip file, so there is no path to the file.
# Raising FileNotFoundError tells the higher level API to extract the
# binary data and create a temporary file.
raise
FileNotFoundError
def
is_resource
(
self
,
name
):
# Maybe we could do better, but if we can get the data, it's a
# resource. Otherwise it isn't.
fullname_as_path
=
self
.
fullname
.
replace
(
'.'
,
'/'
)
path
=
f'
{
fullname_as_path
}
/
{
name
}
'
try
:
self
.
zipimporter
.
get_data
(
path
)
except
OSError
:
return
False
return
True
def
contents
(
self
):
# This is a bit convoluted, because fullname will be a module path,
# but _files is a list of file names relative to the top of the
# archive's namespace. We want to compare file paths to find all the
# names of things inside the module represented by fullname. So we
# turn the module path of fullname into a file path relative to the
# top of the archive, and then we iterate through _files looking for
# names inside that "directory".
from
pathlib
import
Path
fullname_path
=
Path
(
self
.
zipimporter
.
get_filename
(
self
.
fullname
))
relative_path
=
fullname_path
.
relative_to
(
self
.
zipimporter
.
archive
)
# Don't forget that fullname names a package, so its path will include
# __init__.py, which we want to ignore.
assert
relative_path
.
name
==
'__init__.py'
package_path
=
relative_path
.
parent
subdirs_seen
=
set
()
for
filename
in
self
.
zipimporter
.
_files
:
try
:
relative
=
Path
(
filename
).
relative_to
(
package_path
)
except
ValueError
:
continue
# If the path of the file (which is relative to the top of the zip
# namespace), relative to the package given when the resource
# reader was created, has a parent, then it's a name in a
# subdirectory and thus we skip it.
parent_name
=
relative
.
parent
.
name
if
len
(
parent_name
)
==
0
:
yield
relative
.
name
elif
parent_name
not
in
subdirs_seen
:
subdirs_seen
.
add
(
parent_name
)
yield
parent_name
Python/importlib_zipimport.h
View file @
9da3961f
This source diff could not be displayed because it is too large. You can
view the blob
instead.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment