From 14b493c2d88e1b687950223bc2b8449765da37db Mon Sep 17 00:00:00 2001 From: milde Date: Fri, 12 Oct 2012 11:54:01 +0000 Subject: [PATCH] New setting validators, code cleanup. (validate_comma_separated_string_list, validate_ternary) git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@7526 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docs/user/config.txt | 11 +++++--- docutils/frontend.py | 74 ++++++++++++++++++++++++++++++++++++++------------- test/test_settings.py | 9 ++++--- 3 files changed, 67 insertions(+), 27 deletions(-) diff --git a/docs/user/config.txt b/docs/user/config.txt index 170fca0dd..a31634f89 100644 --- a/docs/user/config.txt +++ b/docs/user/config.txt @@ -92,8 +92,11 @@ recognized: :On: "true", "yes", "on", "1" :Off: "false", "no", "off", "0", "" (no value) -List values are comma-delimited. Whitespace around list values is -stripped. :: +List values can be comma- or colon-delimited. + +strip_classes_, strip_elements_with_classes_, stylesheet_, and +stylesheet_path_ use the comma as delimiter, +whitespace around list values is stripped. :: strip-classes: ham,eggs, strip-elements-with-classes: sugar, salt, flour @@ -102,8 +105,8 @@ stripped. :: style with spaces.css stylesheet-path: ../styles/my.css, ../styles/funny.css -expose_internals_ and prune_ use the colon as delimiter and do not strip -whitespace:: +expose_internals_, ignore_ and prune_ use the colon as delimiter and do not +strip whitespace:: expose_internals: b:c:d diff --git a/docutils/frontend.py b/docutils/frontend.py index b8087afe4..3e3fcf73d 100644 --- a/docutils/frontend.py +++ b/docutils/frontend.py @@ -18,8 +18,10 @@ Also exports the following functions: * Option callbacks: `store_multiple`, `read_config_file`. * Setting validators: `validate_encoding`, `validate_encoding_error_handler`, - `validate_encoding_and_error_handler`, `validate_boolean`, - `validate_threshold`, `validate_colon_separated_string_list`, + `validate_encoding_and_error_handler`, + `validate_boolean`, `validate_ternary`, `validate_threshold`, + `validate_colon_separated_string_list`, + `validate_comma_separated_string_list`, `validate_dependency_file`. * `make_paths_absolute`. * SettingSpec manipulation: `filter_settings_spec`. @@ -110,13 +112,33 @@ def validate_encoding_and_error_handler( def validate_boolean(setting, value, option_parser, config_parser=None, config_section=None): - if isinstance(value, unicode): - try: - return option_parser.booleans[value.strip().lower()] - except KeyError: - raise (LookupError('unknown boolean value: "%s"' % value), - None, sys.exc_info()[2]) - return value + """Check/normalize boolean settings: + True: '1', 'on', 'yes', 'true' + False: '0', 'off', 'no','false', '' + """ + if isinstance(value, bool): + return value + try: + return option_parser.booleans[value.strip().lower()] + except KeyError: + raise (LookupError('unknown boolean value: "%s"' % value), + None, sys.exc_info()[2]) + +def validate_ternary(setting, value, option_parser, + config_parser=None, config_section=None): + """Check/normalize three-value settings: + True: '1', 'on', 'yes', 'true' + False: '0', 'off', 'no','false', + None: any other value (including '') + """ + if isinstance(value, bool) or value is None: + return value + if value == '': + return None + try: + return option_parser.booleans[value.strip().lower()] + except KeyError: + return None def validate_nonnegative_int(setting, value, option_parser, config_parser=None, config_section=None): @@ -145,6 +167,22 @@ def validate_colon_separated_string_list( value.extend(last.split(':')) return value +def validate_comma_separated_list(setting, value, option_parser, + config_parser=None, config_section=None): + """Check/normalize list arguments (split at "," and strip whitespace). + """ + # `value` is already a list when given as command line option + # and "action" is "append" + if isinstance(value, unicode): + value = [value] + # this function is called for every option added to `value` + # -> split the last item and apped the result: + last = value.pop() + classes = [cls.strip(u' \t\n') for cls in last.split(',') + if cls.strip(u' \t\n')] + value.extend(classes) + return value + def validate_url_trailing_slash( setting, value, option_parser, config_parser=None, config_section=None): if not value: @@ -163,17 +201,15 @@ def validate_dependency_file(setting, value, option_parser, def validate_strip_class(setting, value, option_parser, config_parser=None, config_section=None): - # convert to list: - if isinstance(value, unicode): - value = [value] - class_values = filter(None, [v.strip() for v in value.pop().split(',')]) - # validate: - for class_value in class_values: - normalized = docutils.nodes.make_id(class_value) - if class_value != normalized: + # value is a comma separated string list: + value = validate_comma_separated_list(setting, value, option_parser, + config_parser, config_section) + # validate list elements: + for cls in value: + normalized = docutils.nodes.make_id(cls) + if cls != normalized: raise ValueError('invalid class value %r (perhaps %r?)' - % (class_value, normalized)) - value.extend(class_values) + % (cls, normalized)) return value def make_paths_absolute(pathdict, keys, base_path=None): diff --git a/test/test_settings.py b/test/test_settings.py index e5f0a2b22..5bff6a0f8 100755 --- a/test/test_settings.py +++ b/test/test_settings.py @@ -44,7 +44,7 @@ class ConfigFileTests(unittest.TestCase): u'python_home': u'http://www.python.org', u'source_link': 1, 'stylesheet': None, - u'stylesheet_path': fixpath(u'data/stylesheets/pep.css'), + u'stylesheet_path': [fixpath(u'data/stylesheets/pep.css')], 'template': fixpath(u'data/pep-html-template')}, 'one': {u'datestamp': u'%Y-%m-%d %H:%M UTC', u'generator': 1, @@ -54,15 +54,16 @@ class ConfigFileTests(unittest.TestCase): 'record_dependencies': utils.DependencyList(), u'source_link': 1, 'stylesheet': None, - u'stylesheet_path': fixpath(u'data/stylesheets/pep.css'), + u'stylesheet_path': [fixpath(u'data/stylesheets/pep.css')], u'tab_width': 8, u'template': fixpath(u'data/pep-html-template'), - u'trim_footnote_reference_space': 1}, + u'trim_footnote_reference_space': 1, + }, 'two': {u'footnote_references': u'superscript', u'generator': 0, 'record_dependencies': utils.DependencyList(), u'stylesheet': None, - u'stylesheet_path': fixpath(u'data/test.css'), + u'stylesheet_path': [fixpath(u'data/test.css')], 'trim_footnote_reference_space': None}, 'list': {u'expose_internals': [u'a', u'b', u'c', u'd', u'e'], u'strip_classes': [u'spam', u'pan', u'fun', u'parrot'], -- 2.11.4.GIT