Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1e3c3e9

Browse files
committed
Issue #25768: Make compileall functions return booleans and document
the return values as well as test them. Thanks to Nicholas Chammas for the bug report and initial patch.
1 parent 4a4ca7c commit 1e3c3e9

6 files changed

Lines changed: 49 additions & 14 deletions

File tree

Doc/library/compileall.rst

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,8 @@ Public functions
103103
.. function:: compile_dir(dir, maxlevels=10, ddir=None, force=False, rx=None, quiet=0, legacy=False, optimize=-1, workers=1)
104104

105105
Recursively descend the directory tree named by *dir*, compiling all :file:`.py`
106-
files along the way.
106+
files along the way. Return a true value if all the files compiled successfully,
107+
and a false value otherwise.
107108

108109
The *maxlevels* parameter is used to limit the depth of the recursion; it
109110
defaults to ``10``.
@@ -155,7 +156,8 @@ Public functions
155156

156157
.. function:: compile_file(fullname, ddir=None, force=False, rx=None, quiet=0, legacy=False, optimize=-1)
157158

158-
Compile the file with path *fullname*.
159+
Compile the file with path *fullname*. Return a true value if the file
160+
compiled successfully, and a false value otherwise.
159161

160162
If *ddir* is given, it is prepended to the path to the file being compiled
161163
for use in compilation time tracebacks, and is also compiled in to the
@@ -191,8 +193,10 @@ Public functions
191193

192194
.. function:: compile_path(skip_curdir=True, maxlevels=0, force=False, quiet=0, legacy=False, optimize=-1)
193195

194-
Byte-compile all the :file:`.py` files found along ``sys.path``. If
195-
*skip_curdir* is true (the default), the current directory is not included
196+
Byte-compile all the :file:`.py` files found along ``sys.path``. Return a
197+
true value if all the files compiled successfully, and a false value otherwise.
198+
199+
If *skip_curdir* is true (the default), the current directory is not included
196200
in the search. All other parameters are passed to the :func:`compile_dir`
197201
function. Note that unlike the other compile functions, ``maxlevels``
198202
defaults to ``0``.

Doc/whatsnew/3.6.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,11 @@ that may require changes to your code.
230230
Changes in the Python API
231231
-------------------------
232232

233+
* The functions in the :mod:`compileall` module now return booleans instead
234+
of ``1`` or ``0`` to represent success or failure, respectively. Thanks to
235+
booleans being a subclass of integers, this should only be an issue if you
236+
were doing identity checks for ``1`` or ``0``. See :issue:`25768`.
237+
233238
* Reading the :attr:`~urllib.parse.SplitResult.port` attribute of
234239
:func:`urllib.parse.urlsplit` and :func:`~urllib.parse.urlparse` results
235240
now raises :exc:`ValueError` for out-of-range values, rather than

Lib/compileall.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def compile_dir(dir, maxlevels=10, ddir=None, force=False, rx=None,
6868
"""
6969
files = _walk_dir(dir, quiet=quiet, maxlevels=maxlevels,
7070
ddir=ddir)
71-
success = 1
71+
success = True
7272
if workers is not None and workers != 1 and ProcessPoolExecutor is not None:
7373
if workers < 0:
7474
raise ValueError('workers must be greater or equal to 0')
@@ -81,12 +81,12 @@ def compile_dir(dir, maxlevels=10, ddir=None, force=False, rx=None,
8181
legacy=legacy,
8282
optimize=optimize),
8383
files)
84-
success = min(results, default=1)
84+
success = min(results, default=True)
8585
else:
8686
for file in files:
8787
if not compile_file(file, ddir, force, rx, quiet,
8888
legacy, optimize):
89-
success = 0
89+
success = False
9090
return success
9191

9292
def compile_file(fullname, ddir=None, force=False, rx=None, quiet=0,
@@ -104,7 +104,7 @@ def compile_file(fullname, ddir=None, force=False, rx=None, quiet=0,
104104
legacy: if True, produce legacy pyc paths instead of PEP 3147 paths
105105
optimize: optimization level or -1 for level of the interpreter
106106
"""
107-
success = 1
107+
success = True
108108
name = os.path.basename(fullname)
109109
if ddir is not None:
110110
dfile = os.path.join(ddir, name)
@@ -144,7 +144,7 @@ def compile_file(fullname, ddir=None, force=False, rx=None, quiet=0,
144144
ok = py_compile.compile(fullname, cfile, dfile, True,
145145
optimize=optimize)
146146
except py_compile.PyCompileError as err:
147-
success = 0
147+
success = False
148148
if quiet >= 2:
149149
return success
150150
elif quiet:
@@ -157,7 +157,7 @@ def compile_file(fullname, ddir=None, force=False, rx=None, quiet=0,
157157
msg = msg.decode(sys.stdout.encoding)
158158
print(msg)
159159
except (SyntaxError, UnicodeError, OSError) as e:
160-
success = 0
160+
success = False
161161
if quiet >= 2:
162162
return success
163163
elif quiet:
@@ -167,7 +167,7 @@ def compile_file(fullname, ddir=None, force=False, rx=None, quiet=0,
167167
print(e.__class__.__name__ + ':', e)
168168
else:
169169
if ok == 0:
170-
success = 0
170+
success = False
171171
return success
172172

173173
def compile_path(skip_curdir=1, maxlevels=0, force=False, quiet=0,
@@ -183,7 +183,7 @@ def compile_path(skip_curdir=1, maxlevels=0, force=False, quiet=0,
183183
legacy: as for compile_dir() (default False)
184184
optimize: as for compile_dir() (default -1)
185185
"""
186-
success = 1
186+
success = True
187187
for dir in sys.path:
188188
if (not dir or dir == os.curdir) and skip_curdir:
189189
if quiet < 2:

Lib/test/test_compileall.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import sys
22
import compileall
33
import importlib.util
4+
import test.test_importlib.util
45
import os
56
import pathlib
67
import py_compile
@@ -40,6 +41,11 @@ def setUp(self):
4041
def tearDown(self):
4142
shutil.rmtree(self.directory)
4243

44+
def add_bad_source_file(self):
45+
self.bad_source_path = os.path.join(self.directory, '_test_bad.py')
46+
with open(self.bad_source_path, 'w') as file:
47+
file.write('x (\n')
48+
4349
def data(self):
4450
with open(self.bc_path, 'rb') as file:
4551
data = file.read(8)
@@ -78,15 +84,31 @@ def test_compile_files(self):
7884
os.unlink(fn)
7985
except:
8086
pass
81-
compileall.compile_file(self.source_path, force=False, quiet=True)
87+
self.assertTrue(compileall.compile_file(self.source_path,
88+
force=False, quiet=True))
8289
self.assertTrue(os.path.isfile(self.bc_path) and
8390
not os.path.isfile(self.bc_path2))
8491
os.unlink(self.bc_path)
85-
compileall.compile_dir(self.directory, force=False, quiet=True)
92+
self.assertTrue(compileall.compile_dir(self.directory, force=False,
93+
quiet=True))
8694
self.assertTrue(os.path.isfile(self.bc_path) and
8795
os.path.isfile(self.bc_path2))
8896
os.unlink(self.bc_path)
8997
os.unlink(self.bc_path2)
98+
# Test against bad files
99+
self.add_bad_source_file()
100+
self.assertFalse(compileall.compile_file(self.bad_source_path,
101+
force=False, quiet=2))
102+
self.assertFalse(compileall.compile_dir(self.directory,
103+
force=False, quiet=2))
104+
105+
def test_compile_path(self):
106+
self.assertTrue(compileall.compile_path(quiet=2))
107+
108+
with test.test_importlib.util.import_state(path=[self.directory]):
109+
self.add_bad_source_file()
110+
self.assertFalse(compileall.compile_path(skip_curdir=False,
111+
force=True, quiet=2))
90112

91113
def test_no_pycache_in_non_package(self):
92114
# Bug 8563 reported that __pycache__ directories got created by

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ Octavian Cerna
235235
Michael Cetrulo
236236
Dave Chambers
237237
Pascal Chambon
238+
Nicholas Chammas
238239
John Chandler
239240
Hye-Shik Chang
240241
Jeffrey Chang

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@ Core and Builtins
123123
Library
124124
-------
125125

126+
- Issue #25768: Have the functions in compileall return booleans instead of
127+
ints and add proper documentation and tests for the return values.
128+
126129
- Issue #24103: Fixed possible use after free in ElementTree.XMLPullParser.
127130

128131
- Issue #25860: os.fwalk() no longer skips remaining directories when error

0 commit comments

Comments
 (0)