Skip to content

Commit 0780bf7

Browse files
authored
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.
1 parent a5b4ea1 commit 0780bf7

File tree

4 files changed

+45
-13
lines changed

4 files changed

+45
-13
lines changed

Doc/library/zipapp.rst

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ The module defines two convenience functions:
9999

100100

101101
.. function:: create_archive(source, target=None, interpreter=None, main=None,
102-
include_file=None)
102+
filter=None)
103103

104104
Create an application archive from *source*. The source can be any
105105
of the following:
@@ -144,9 +144,10 @@ The module defines two convenience functions:
144144
contain a ``__main__.py`` file, as otherwise the resulting archive
145145
would not be executable.
146146

147-
The *include_file* argument specifies a callback function that is passed the
148-
relative path to the file in order to determine which files to store when
149-
being called against a directory.
147+
The optional *filter* argument specifies a callback function that
148+
is passed a Path object representing the path to the file being added
149+
(relative to the source directory). It should return ``True`` if the
150+
file is to be added.
150151

151152
If a file object is specified for *source* or *target*, it is the
152153
caller's responsibility to close it after calling create_archive.
@@ -157,6 +158,9 @@ The module defines two convenience functions:
157158
passed to the ``zipfile.ZipFile`` class, and must supply the methods
158159
needed by that class.
159160

161+
.. versionadded:: 3.7
162+
Added the *filter* argument.
163+
160164
.. function:: get_interpreter(archive)
161165

162166
Return the interpreter specified in the ``#!`` line at the start of the

Doc/whatsnew/3.7.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,13 @@ Function :func:`~uu.encode` now accepts an optional *backtick*
258258
keyword argument. When it's true, zeros are represented by ``'`'``
259259
instead of spaces. (Contributed by Xiang Zhang in :issue:`30103`.)
260260

261+
zipapp
262+
------
263+
264+
Function :func:`zipapp.create_archive` now accepts an optional *filter*
265+
argument, to allow the user to select which files should be included in the
266+
archive.
267+
261268

262269
Optimizations
263270
=============

Lib/test/test_zipapp.py

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,23 +53,44 @@ def test_create_archive_with_subdirs(self):
5353
self.assertIn('foo/', z.namelist())
5454
self.assertIn('bar/', z.namelist())
5555

56-
def test_create_archive_with_include_file(self):
57-
# Test packing a directory and using include_file to specify which files to include.
58-
def skip_pyc_files(file):
59-
return '.pyc' not in str(file)
56+
def test_create_archive_with_filter(self):
57+
# Test packing a directory and using filter to specify
58+
# which files to include.
59+
def skip_pyc_files(path):
60+
return path.suffix != '.pyc'
6061
source = self.tmpdir / 'source'
6162
source.mkdir()
6263
(source / '__main__.py').touch()
6364
(source / 'test.py').touch()
6465
(source / 'test.pyc').touch()
6566
target = self.tmpdir / 'source.pyz'
6667

67-
zipapp.create_archive(source, target, include_file=skip_pyc_files)
68+
zipapp.create_archive(source, target, filter=skip_pyc_files)
6869
with zipfile.ZipFile(target, 'r') as z:
6970
self.assertIn('__main__.py', z.namelist())
7071
self.assertIn('test.py', z.namelist())
7172
self.assertNotIn('test.pyc', z.namelist())
7273

74+
def test_create_archive_filter_exclude_dir(self):
75+
# Test packing a directory and using a filter to exclude a
76+
# subdirectory (ensures that the path supplied to include
77+
# is relative to the source location, as expected).
78+
def skip_dummy_dir(path):
79+
return path.parts[0] != 'dummy'
80+
source = self.tmpdir / 'source'
81+
source.mkdir()
82+
(source / '__main__.py').touch()
83+
(source / 'test.py').touch()
84+
(source / 'dummy').mkdir()
85+
(source / 'dummy' / 'test2.py').touch()
86+
target = self.tmpdir / 'source.pyz'
87+
88+
zipapp.create_archive(source, target, filter=skip_dummy_dir)
89+
with zipfile.ZipFile(target, 'r') as z:
90+
self.assertEqual(len(z.namelist()), 2)
91+
self.assertIn('__main__.py', z.namelist())
92+
self.assertIn('test.py', z.namelist())
93+
7394
def test_create_archive_default_target(self):
7495
# Test packing a directory to the default name.
7596
source = self.tmpdir / 'source'

Lib/zipapp.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ def _copy_archive(archive, new_archive, interpreter=None):
7474

7575

7676
def create_archive(source, target=None, interpreter=None, main=None,
77-
include_file=None):
77+
filter=None):
7878
"""Create an application archive from SOURCE.
7979
8080
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,
135135
_write_file_prefix(fd, interpreter)
136136
with zipfile.ZipFile(fd, 'w') as z:
137137
for child in source.rglob('*'):
138-
arcname = child.relative_to(source).as_posix()
139-
if include_file is None or include_file(pathlib.Path(arcname)):
140-
z.write(child, arcname)
138+
arcname = child.relative_to(source)
139+
if filter is None or filter(arcname):
140+
z.write(child, arcname.as_posix())
141141
if main_py:
142142
z.writestr('__main__.py', main_py.encode('utf-8'))
143143

0 commit comments

Comments
 (0)