From 69e9e07bbf6772a64dbdd3b6314fdacef4b42848 Mon Sep 17 00:00:00 2001 From: Jon Parise Date: Wed, 11 May 2016 16:17:17 -0700 Subject: [PATCH] Manually validate parser options The pep8 package unfortunately re-parses configuration file options and doesn't recognize optparse's "advanced" option types, like 'choices' and 'callback'. While using these options from the command line worked great, pep8 would blow up when it encounted them in the configuration file. We now parse and validate option values in the `parse_options()` plugin hook. --- flake8_author.py | 32 +++++++++++++++----------------- tests/test_checker.py | 4 ++-- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/flake8_author.py b/flake8_author.py index 99ff647..d541ffd 100644 --- a/flake8_author.py +++ b/flake8_author.py @@ -8,11 +8,10 @@ """ import ast -import optparse import re __author__ = 'Jon Parise' -__version__ = '1.0.0' +__version__ = '1.0.1' class Checker(object): @@ -28,33 +27,32 @@ def __init__(self, tree, filename): @classmethod def add_options(cls, parser): - def pattern_callback(option, opt_str, value, parser): - try: - setattr(parser.values, option.dest, re.compile(value)) - except re.error as e: - raise optparse.OptionValueError( - "option {}: '{}': {}".format(opt_str, value, e)) - parser.add_option( '--author-attribute', default='optional', - type='choice', - choices=['optional', 'required', 'forbidden'], help="__author__ attribute: optional, required, forbidden") parser.add_option( '--author-pattern', - default=re.compile(r'.*'), - type='string', - action="callback", - callback=pattern_callback, + default=r'.*', help="__author__ attribute validation pattern (regex)") parser.config_options.append('author-attribute') parser.config_options.append('author-pattern') @classmethod def parse_options(cls, options): - cls.options['attribute'] = options.author_attribute - cls.options['pattern'] = options.author_pattern + choices = ('optional', 'required', 'forbidden') + if options.author_attribute in choices: + cls.options['attribute'] = options.author_attribute + else: + raise ValueError( + "author-attribute: '{}' must be one of: {}".format( + options.author_attribute, ', '.join(choices))) + + try: + cls.options['pattern'] = re.compile(options.author_pattern) + except re.error as e: + raise ValueError("author-pattern: '{}': {}".format( + options.author_pattern, e)) def find_author_node(self, tree): for node in tree.body: diff --git a/tests/test_checker.py b/tests/test_checker.py index 279ea1b..7c0d96b 100644 --- a/tests/test_checker.py +++ b/tests/test_checker.py @@ -56,7 +56,7 @@ def test_author_forbidden_but_present(): def test_author_invalid_attribute(): - with pytest.raises(SystemExit): + with pytest.raises(ValueError): check('Jon Parise', attribute='invalid') @@ -75,5 +75,5 @@ def test_author_pattern_not_matched(): def test_author_pattern_invalid_regex(): - with pytest.raises(SystemExit): + with pytest.raises(ValueError): check('Jon Parise', pattern=r'[[[')