closes #76920: don't crash in preprocess_option if some looked option has no value

while on is expected.

authorTorsten Marek
changesetf31cbe94d9c6
branchdefault
phasepublic
hiddenno
parent revision#f0886f3824cb closes #74747: don't crash when lookup up a special attribute in class scope
child revision#c30b0473b310 better message for E0202 (closes #77237)
files modified by this revision
ChangeLog
lint.py
test/unittest_lint.py
# HG changeset patch
# User Torsten Marek
# Date 1316790092 -7200
# Fri Sep 23 17:01:32 2011 +0200
# Node ID f31cbe94d9c6c1e50b30fadc0a88b92edc2b227f
# Parent f0886f3824cb9b96f5a2fa8288ccb76224c9130e
closes #76920: don't crash in preprocess_option if some looked option has no value

while on is expected.

diff --git a/ChangeLog b/ChangeLog
@@ -12,11 +12,13 @@
1      * #74745: make "too general" exception names configurable (patch by Google)
2 
3      * #74747: crash occurs when lookup up a special attribute in class scope
4        (patch by google)
5 
6 -	
7 +    * #76920: crash if on eg "pylint --rcfile"(patch by Torsten Marek)
8 +
9 +
10  2011-07-18  --  0.24.0
11      * #69738: add regular expressions support for "generated-members"
12 
13      * ids of logging and string_format checkers have been changed:
14        logging: 65 -> 12, string_format: 99 -> 13
diff --git a/lint.py b/lint.py
@@ -685,10 +685,14 @@
15      __builtins__._ = str
16  except AttributeError:
17      __builtins__['_'] = str
18 
19 
20 +class ArgumentPreprocessingError(Exception):
21 +    """Raised if an error occurs during argument preprocessing."""
22 +
23 +
24  def preprocess_options(args, search_for):
25      """look for some options (keys of <search_for>) which have to be processed
26      before others
27 
28      values of <search_for> are callback functions to call when the option is
@@ -704,10 +708,12 @@
29                  option, val = arg[2:], None
30              try:
31                  cb, takearg = search_for[option]
32                  del args[i]
33                  if takearg and val is None:
34 +                    if i >= len(args) or args[i].startswith('-'):
35 +                        raise ArgumentPreprocessingError(arg)
36                      val = args[i]
37                      del args[i]
38                  cb(option, val)
39              except KeyError:
40                  i += 1
@@ -726,15 +732,20 @@
41          )
42 
43      def __init__(self, args, reporter=None, exit=True):
44          self._rcfile = None
45          self._plugins = []
46 -        preprocess_options(args, {
47 -            # option: (callback, takearg)
48 -            'rcfile':       (self.cb_set_rcfile, True),
49 -            'load-plugins': (self.cb_add_plugins, True),
50 -            })
51 +        try:
52 +            preprocess_options(args, {
53 +                # option: (callback, takearg)
54 +                'rcfile':       (self.cb_set_rcfile, True),
55 +                'load-plugins': (self.cb_add_plugins, True),
56 +                })
57 +        except ArgumentPreprocessingError, e:
58 +            print >> sys.stderr, 'Argument %s expects a value.' % (e.args[0],)
59 +            sys.exit(32)
60 +
61          self.linter = linter = self.LinterClass((
62              ('rcfile',
63               {'action' : 'callback', 'callback' : lambda *args: 1,
64                'type': 'string', 'metavar': '<file>',
65                'help' : 'Specify a configuration file.'}),
diff --git a/test/unittest_lint.py b/test/unittest_lint.py
@@ -21,11 +21,12 @@
66 
67  from logilab.common.testlib import TestCase, unittest_main, create_files
68  from logilab.common.compat import reload
69 
70  from pylint import config
71 -from pylint.lint import PyLinter, Run, UnknownMessage
72 +from pylint.lint import PyLinter, Run, UnknownMessage, preprocess_options, \
73 +     ArgumentPreprocessingError
74  from pylint.utils import sort_msgs, PyLintASTWalker
75  from pylint import checkers
76 
77  class SortMessagesTC(TestCase):
78 
@@ -350,7 +351,33 @@
79              os.environ['HOME'] = home
80              rmtree(fake_home, ignore_errors=True)
81              os.chdir(HERE)
82              rmtree(chroot)
83 
84 +
85 +class PreprocessOptionsTC(TestCase):
86 +    def _callback(self, name, value):
87 +        self.args.append((name, value))
88 +
89 +    def test_preprocess(self):
90 +        self.args = []
91 +        preprocess_options(['--foo', '--bar=baz', '--qu=ux'],
92 +                           {'foo' : (self._callback, False),
93 +                            'qu' : (self._callback, True)})
94 +        self.assertEqual(
95 +            [('foo', None), ('qu', 'ux')], self.args)
96 +
97 +    def test_preprocessing_error(self):
98 +        self.assertRaises(
99 +            ArgumentPreprocessingError,
100 +            preprocess_options,
101 +            ['--foo', '--bar', '--qu=ux'],
102 +            {'bar' : (None, True)})
103 +        self.assertRaises(
104 +            ArgumentPreprocessingError,
105 +            preprocess_options,
106 +            ['--foo', '--bar'],
107 +            {'bar' : (None, True)})
108 +
109 +
110  if __name__ == '__main__':
111      unittest_main()