[Python-checkins] bpo-31072: Rename the new filter argument for zipapp.create_archive. (#3049)

Paul Moore webhook-mailer at python.org
Sat Aug 26 13:04:15 EDT 2017


https://github.com/python/cpython/commit/0780bf7578dc4c9c3852dc5e869aba515a2c65b1
commit: 0780bf7578dc4c9c3852dc5e869aba515a2c65b1
branch: master
author: Paul Moore <p.f.moore at gmail.com>
committer: GitHub <noreply at github.com>
date: 2017-08-26T18:04:12+01:00
summary:

bpo-31072: Rename the new filter argument for zipapp.create_archive. (#3049)

bpo-31072: Rename the new filter argument for zipapp.create_archive (GH-3049)

* Rename the new argument to "filter"
* Improve tests for the new functionality
* Add a "What's New" entry.

files:
M Doc/library/zipapp.rst
M Doc/whatsnew/3.7.rst
M Lib/test/test_zipapp.py
M Lib/zipapp.py

diff --git a/Doc/library/zipapp.rst b/Doc/library/zipapp.rst
index 993c2ccc398..120bbbb6620 100644
--- a/Doc/library/zipapp.rst
+++ b/Doc/library/zipapp.rst
@@ -99,7 +99,7 @@ The module defines two convenience functions:
 
 
 .. function:: create_archive(source, target=None, interpreter=None, main=None,
-                             include_file=None)
+                             filter=None)
 
    Create an application archive from *source*.  The source can be any
    of the following:
@@ -144,9 +144,10 @@ The module defines two convenience functions:
    contain a ``__main__.py`` file, as otherwise the resulting archive
    would not be executable.
 
-   The *include_file* argument specifies a callback function that is passed the
-   relative path to the file in order to determine which files to store when
-   being called against a directory.
+   The optional *filter* argument specifies a callback function that
+   is passed a Path object representing the path to the file being added
+   (relative to the source directory).  It should return ``True`` if the
+   file is to be added.
 
    If a file object is specified for *source* or *target*, it is the
    caller's responsibility to close it after calling create_archive.
@@ -157,6 +158,9 @@ The module defines two convenience functions:
    passed to the ``zipfile.ZipFile`` class, and must supply the methods
    needed by that class.
 
+   .. versionadded:: 3.7
+      Added the *filter* argument.
+
 .. function:: get_interpreter(archive)
 
    Return the interpreter specified in the ``#!`` line at the start of the
diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst
index a92ad9f1df4..8547660e188 100644
--- a/Doc/whatsnew/3.7.rst
+++ b/Doc/whatsnew/3.7.rst
@@ -258,6 +258,13 @@ Function :func:`~uu.encode` now accepts an optional *backtick*
 keyword argument.  When it's true, zeros are represented by ``'`'``
 instead of spaces.  (Contributed by Xiang Zhang in :issue:`30103`.)
 
+zipapp
+------
+
+Function :func:`zipapp.create_archive` now accepts an optional *filter*
+argument, to allow the user to select which files should be included in the
+archive.
+
 
 Optimizations
 =============
diff --git a/Lib/test/test_zipapp.py b/Lib/test/test_zipapp.py
index 47eed5f4a6c..56cf37c9afa 100644
--- a/Lib/test/test_zipapp.py
+++ b/Lib/test/test_zipapp.py
@@ -53,10 +53,11 @@ def test_create_archive_with_subdirs(self):
             self.assertIn('foo/', z.namelist())
             self.assertIn('bar/', z.namelist())
 
-    def test_create_archive_with_include_file(self):
-        # Test packing a directory and using include_file to specify which files to include.
-        def skip_pyc_files(file):
-            return '.pyc' not in str(file)
+    def test_create_archive_with_filter(self):
+        # Test packing a directory and using filter to specify
+        # which files to include.
+        def skip_pyc_files(path):
+            return path.suffix != '.pyc'
         source = self.tmpdir / 'source'
         source.mkdir()
         (source / '__main__.py').touch()
@@ -64,12 +65,32 @@ def skip_pyc_files(file):
         (source / 'test.pyc').touch()
         target = self.tmpdir / 'source.pyz'
 
-        zipapp.create_archive(source, target, include_file=skip_pyc_files)
+        zipapp.create_archive(source, target, filter=skip_pyc_files)
         with zipfile.ZipFile(target, 'r') as z:
             self.assertIn('__main__.py', z.namelist())
             self.assertIn('test.py', z.namelist())
             self.assertNotIn('test.pyc', z.namelist())
 
+    def test_create_archive_filter_exclude_dir(self):
+        # Test packing a directory and using a filter to exclude a
+        # subdirectory (ensures that the path supplied to include
+        # is relative to the source location, as expected).
+        def skip_dummy_dir(path):
+            return path.parts[0] != 'dummy'
+        source = self.tmpdir / 'source'
+        source.mkdir()
+        (source / '__main__.py').touch()
+        (source / 'test.py').touch()
+        (source / 'dummy').mkdir()
+        (source / 'dummy' / 'test2.py').touch()
+        target = self.tmpdir / 'source.pyz'
+
+        zipapp.create_archive(source, target, filter=skip_dummy_dir)
+        with zipfile.ZipFile(target, 'r') as z:
+            self.assertEqual(len(z.namelist()), 2)
+            self.assertIn('__main__.py', z.namelist())
+            self.assertIn('test.py', z.namelist())
+
     def test_create_archive_default_target(self):
         # Test packing a directory to the default name.
         source = self.tmpdir / 'source'
diff --git a/Lib/zipapp.py b/Lib/zipapp.py
index bf15b6806dd..51d0290a901 100644
--- a/Lib/zipapp.py
+++ b/Lib/zipapp.py
@@ -74,7 +74,7 @@ def _copy_archive(archive, new_archive, interpreter=None):
 
 
 def create_archive(source, target=None, interpreter=None, main=None,
-                   include_file=None):
+                   filter=None):
     """Create an application archive from SOURCE.
 
     The SOURCE can be the name of a directory, or a filename or a file-like
@@ -135,9 +135,9 @@ def create_archive(source, target=None, interpreter=None, main=None,
         _write_file_prefix(fd, interpreter)
         with zipfile.ZipFile(fd, 'w') as z:
             for child in source.rglob('*'):
-                arcname = child.relative_to(source).as_posix()
-                if include_file is None or include_file(pathlib.Path(arcname)):
-                    z.write(child, arcname)
+                arcname = child.relative_to(source)
+                if filter is None or filter(arcname):
+                    z.write(child, arcname.as_posix())
             if main_py:
                 z.writestr('__main__.py', main_py.encode('utf-8'))
 



More information about the Python-checkins mailing list