Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-63301: Set exit code when tabnanny CLI exits on error #7699

Merged
merged 4 commits into from
Mar 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions Lib/tabnanny.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def errprint(*args):
sys.stderr.write(sep + str(arg))
sep = " "
sys.stderr.write("\n")
sys.exit(1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can the whole errprint() be replaced with this:

def errprint(*args):
    sys.exit(' '.join(str(arg) for arg in args))

?


def main():
import getopt
Expand All @@ -44,15 +45,13 @@ def main():
opts, args = getopt.getopt(sys.argv[1:], "qv")
except getopt.error as msg:
errprint(msg)
return
for o, a in opts:
if o == '-q':
filename_only = filename_only + 1
if o == '-v':
verbose = verbose + 1
if not args:
errprint("Usage:", sys.argv[0], "[-v] file_or_directory ...")
return
for arg in args:
check(arg)

Expand Down
30 changes: 19 additions & 11 deletions Lib/test/test_tabnanny.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,10 @@ def test_errprint(self):

for args, expected in tests:
with self.subTest(arguments=args, expected=expected):
with captured_stderr() as stderr:
tabnanny.errprint(*args)
self.assertEqual(stderr.getvalue() , expected)
with self.assertRaises(SystemExit):
with captured_stderr() as stderr:
tabnanny.errprint(*args)
self.assertEqual(stderr.getvalue() , expected)


class TestNannyNag(TestCase):
Expand Down Expand Up @@ -203,14 +204,16 @@ def test_when_wrong_indented(self):
err = ('unindent does not match any outer indentation level'
' (<tokenize>, line 3)\n')
err = f"{file_path!r}: Indentation Error: {err}"
self.verify_tabnanny_check(file_path, err=err)
with self.assertRaises(SystemExit):
self.verify_tabnanny_check(file_path, err=err)

def test_when_tokenize_tokenerror(self):
"""A python source code file eligible for raising 'tokenize.TokenError'."""
with TemporaryPyFile(SOURCE_CODES["incomplete_expression"]) as file_path:
err = "('EOF in multi-line statement', (7, 0))\n"
err = f"{file_path!r}: Token Error: {err}"
self.verify_tabnanny_check(file_path, err=err)
with self.assertRaises(SystemExit):
self.verify_tabnanny_check(file_path, err=err)

def test_when_nannynag_error_verbose(self):
"""A python source code file eligible for raising `tabnanny.NannyNag`.
Expand All @@ -236,7 +239,8 @@ def test_when_no_file(self):
path = 'no_file.py'
err = (f"{path!r}: I/O Error: [Errno {errno.ENOENT}] "
f"{os.strerror(errno.ENOENT)}: {path!r}\n")
self.verify_tabnanny_check(path, err=err)
with self.assertRaises(SystemExit):
self.verify_tabnanny_check(path, err=err)

def test_errored_directory(self):
"""Directory containing wrongly indented python source code files."""
Expand All @@ -251,7 +255,8 @@ def test_errored_directory(self):
err = ('unindent does not match any outer indentation level'
' (<tokenize>, line 3)\n')
err = f"{e_file!r}: Indentation Error: {err}"
self.verify_tabnanny_check(tmp_dir, err=err)
with self.assertRaises(SystemExit):
self.verify_tabnanny_check(tmp_dir, err=err)


class TestProcessTokens(TestCase):
Expand Down Expand Up @@ -287,9 +292,12 @@ def test_with_errored_codes_samples(self):
class TestCommandLine(TestCase):
"""Tests command line interface of `tabnanny`."""

def validate_cmd(self, *args, stdout="", stderr="", partial=False):
def validate_cmd(self, *args, stdout="", stderr="", partial=False, expect_failure=False):
"""Common function to assert the behaviour of command line interface."""
_, out, err = script_helper.assert_python_ok('-m', 'tabnanny', *args)
if expect_failure:
_, out, err = script_helper.assert_python_failure('-m', 'tabnanny', *args)
else:
_, out, err = script_helper.assert_python_ok('-m', 'tabnanny', *args)
# Note: The `splitlines()` will solve the problem of CRLF(\r) added
# by OS Windows.
out = os.fsdecode(out)
Expand All @@ -310,7 +318,7 @@ def test_with_errored_file(self):
stderr = f"{file_path!r}: Indentation Error: "
stderr += ('unindent does not match any outer indentation level'
' (<tokenize>, line 3)')
self.validate_cmd(file_path, stderr=stderr)
self.validate_cmd(file_path, stderr=stderr, expect_failure=True)

def test_with_error_free_file(self):
"""Should not display anything if python file is correctly indented."""
Expand All @@ -321,7 +329,7 @@ def test_command_usage(self):
"""Should display usage on no arguments."""
path = findfile('tabnanny.py')
stderr = f"Usage: {path} [-v] file_or_directory ..."
self.validate_cmd(stderr=stderr)
self.validate_cmd(stderr=stderr, expect_failure=True)

def test_quiet_flag(self):
"""Should display less when quite mode is on."""
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Set exit code when :mod:`tabnanny` CLI exits on error.