mirror of https://github.com/python/cpython
add a filterfunc to zip file.PyZipFile.writepy, issue 19274
This commit is contained in:
parent
47f1b762fd
commit
59202e5fc7
|
@ -382,7 +382,10 @@ The :class:`PyZipFile` constructor takes the same parameters as the
|
||||||
|
|
||||||
Instances have one method in addition to those of :class:`ZipFile` objects:
|
Instances have one method in addition to those of :class:`ZipFile` objects:
|
||||||
|
|
||||||
.. method:: PyZipFile.writepy(pathname, basename='')
|
.. method:: PyZipFile.writepy(pathname, basename='', filterfunc=None)
|
||||||
|
|
||||||
|
.. versionadded:: 3.4
|
||||||
|
The *filterfunc* parameter.
|
||||||
|
|
||||||
Search for files :file:`\*.py` and add the corresponding file to the
|
Search for files :file:`\*.py` and add the corresponding file to the
|
||||||
archive.
|
archive.
|
||||||
|
@ -404,7 +407,10 @@ The :class:`PyZipFile` constructor takes the same parameters as the
|
||||||
package directory, then all :file:`\*.py[co]` are added under the package
|
package directory, then all :file:`\*.py[co]` are added under the package
|
||||||
name as a file path, and if any subdirectories are package directories,
|
name as a file path, and if any subdirectories are package directories,
|
||||||
all of these are added recursively. *basename* is intended for internal
|
all of these are added recursively. *basename* is intended for internal
|
||||||
use only. The :meth:`writepy` method makes archives with file names like
|
use only. When *filterfunc(pathname)* is given, it will be called for every
|
||||||
|
invocation. When it returns a False value, that path and its subpaths will
|
||||||
|
be ignored.
|
||||||
|
The :meth:`writepy` method makes archives with file names like
|
||||||
this::
|
this::
|
||||||
|
|
||||||
string.pyc # Top level name
|
string.pyc # Top level name
|
||||||
|
|
|
@ -564,6 +564,16 @@ Add an event-driven parser for non-blocking applications,
|
||||||
|
|
||||||
(Contributed by Antoine Pitrou in :issue:`17741`.)
|
(Contributed by Antoine Pitrou in :issue:`17741`.)
|
||||||
|
|
||||||
|
|
||||||
|
zipfile.PyZipfile
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Add a filter function to ignore some packages (tests for instance),
|
||||||
|
:meth:`~zipfile.PyZipFile.writepy`.
|
||||||
|
|
||||||
|
(Contributed by Christian Tismer in :issue:`19274`.)
|
||||||
|
|
||||||
|
|
||||||
Other improvements
|
Other improvements
|
||||||
==================
|
==================
|
||||||
|
|
||||||
|
|
|
@ -591,6 +591,28 @@ class PyZipFileTests(unittest.TestCase):
|
||||||
self.assertCompiledIn('email/__init__.py', names)
|
self.assertCompiledIn('email/__init__.py', names)
|
||||||
self.assertCompiledIn('email/mime/text.py', names)
|
self.assertCompiledIn('email/mime/text.py', names)
|
||||||
|
|
||||||
|
def test_write_filtered_python_package(self):
|
||||||
|
import test
|
||||||
|
packagedir = os.path.dirname(test.__file__)
|
||||||
|
|
||||||
|
with TemporaryFile() as t, zipfile.PyZipFile(t, "w") as zipfp:
|
||||||
|
|
||||||
|
stdout = sys.stdout
|
||||||
|
|
||||||
|
# first make sure that the test folder gives error messages
|
||||||
|
sys.stdout = reportSIO = io.StringIO()
|
||||||
|
zipfp.writepy(packagedir)
|
||||||
|
reportStr = reportSIO.getvalue()
|
||||||
|
self.assertTrue('SyntaxError' in reportStr)
|
||||||
|
|
||||||
|
# then check that the filter works
|
||||||
|
sys.stdout = reportSIO = io.StringIO()
|
||||||
|
zipfp.writepy(packagedir, filterfunc=lambda whatever:False)
|
||||||
|
reportStr = reportSIO.getvalue()
|
||||||
|
self.assertTrue('SyntaxError' not in reportStr)
|
||||||
|
|
||||||
|
sys.stdout = stdout
|
||||||
|
|
||||||
def test_write_with_optimization(self):
|
def test_write_with_optimization(self):
|
||||||
import email
|
import email
|
||||||
packagedir = os.path.dirname(email.__file__)
|
packagedir = os.path.dirname(email.__file__)
|
||||||
|
|
|
@ -1566,7 +1566,7 @@ class PyZipFile(ZipFile):
|
||||||
allowZip64=allowZip64)
|
allowZip64=allowZip64)
|
||||||
self._optimize = optimize
|
self._optimize = optimize
|
||||||
|
|
||||||
def writepy(self, pathname, basename=""):
|
def writepy(self, pathname, basename="", filterfunc=None):
|
||||||
"""Add all files from "pathname" to the ZIP archive.
|
"""Add all files from "pathname" to the ZIP archive.
|
||||||
|
|
||||||
If pathname is a package directory, search the directory and
|
If pathname is a package directory, search the directory and
|
||||||
|
@ -1577,7 +1577,13 @@ class PyZipFile(ZipFile):
|
||||||
archive. Added modules are always module.pyo or module.pyc.
|
archive. Added modules are always module.pyo or module.pyc.
|
||||||
This method will compile the module.py into module.pyc if
|
This method will compile the module.py into module.pyc if
|
||||||
necessary.
|
necessary.
|
||||||
|
If filterfunc(pathname) is given, it is called with every argument.
|
||||||
|
When it is False, the file or directory is skipped.
|
||||||
"""
|
"""
|
||||||
|
if filterfunc and not filterfunc(pathname):
|
||||||
|
if self.debug:
|
||||||
|
print('pathname "%s" skipped by filterfunc' % pathname)
|
||||||
|
return
|
||||||
dir, name = os.path.split(pathname)
|
dir, name = os.path.split(pathname)
|
||||||
if os.path.isdir(pathname):
|
if os.path.isdir(pathname):
|
||||||
initname = os.path.join(pathname, "__init__.py")
|
initname = os.path.join(pathname, "__init__.py")
|
||||||
|
@ -1602,7 +1608,8 @@ class PyZipFile(ZipFile):
|
||||||
if os.path.isdir(path):
|
if os.path.isdir(path):
|
||||||
if os.path.isfile(os.path.join(path, "__init__.py")):
|
if os.path.isfile(os.path.join(path, "__init__.py")):
|
||||||
# This is a package directory, add it
|
# This is a package directory, add it
|
||||||
self.writepy(path, basename) # Recursive call
|
self.writepy(path, basename,
|
||||||
|
filterfunc=filterfunc) # Recursive call
|
||||||
elif ext == ".py":
|
elif ext == ".py":
|
||||||
fname, arcname = self._get_codename(path[0:-3],
|
fname, arcname = self._get_codename(path[0:-3],
|
||||||
basename)
|
basename)
|
||||||
|
|
Loading…
Reference in New Issue