From 101671ae44e1686680c80cd07b452aabeb88fb63 Mon Sep 17 00:00:00 2001 From: goodger Date: Sat, 20 Apr 2002 03:01:52 +0000 Subject: Initial revision git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@18 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 373 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 373 insertions(+) create mode 100644 docutils/utils.py (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py new file mode 100644 index 000000000..a92c8fb97 --- /dev/null +++ b/docutils/utils.py @@ -0,0 +1,373 @@ +#! /usr/bin/env python + +""" +:Author: David Goodger +:Contact: goodger@users.sourceforge.net +:Revision: $Revision$ +:Date: $Date$ +:Copyright: This module has been placed in the public domain. + +Miscellaneous utilities for the documentation utilities. +""" + +import sys, re +import nodes + + +class SystemMessage(Exception): + + def __init__(self, system_message): + Exception.__init__(self, system_message.astext()) + + +class Reporter: + + """ + Info/warning/error reporter and ``system_message`` element generator. + + Five levels of system messages are defined, along with corresponding + methods: `debug()`, `info()`, `warning()`, `error()`, and `severe()`. + + There is typically one Reporter object per process. A Reporter object is + instantiated with thresholds for generating warnings and errors (raising + exceptions), a switch to turn debug output on or off, and an I/O stream + for warnings. These are stored in the default reporting category, '' + (zero-length string). + + Multiple reporting categories [#]_ may be set, each with its own warning + and error thresholds, debugging switch, and warning stream (collectively a + `ConditionSet`). Categories are hierarchically-named strings that look + like attribute references: 'spam', 'spam.eggs', 'neeeow.wum.ping'. The + 'spam' category is the ancestor of 'spam.bacon.eggs'. Unset categories + inherit stored conditions from their closest ancestor category that has + been set. + + When a system message is generated, the stored conditions from its + category (or ancestor if unset) are retrieved. The system message level is + compared to the thresholds stored in the category, and a warning or error + is generated as appropriate. Debug messages are produced iff the stored + debug switch is on. Message output is sent to the stored warning stream. + + The default category is '' (empty string). By convention, Writers should + retrieve reporting conditions from the 'writer' category (which, unless + explicitly set, defaults to the conditions of the default category). + + .. [#] The concept of "categories" was inspired by the log4j project: + http://jakarta.apache.org/log4j/. + """ + + levels = 'DEBUG INFO WARNING ERROR SEVERE'.split() + """List of names for system message levels, indexed by level.""" + + def __init__(self, warninglevel, errorlevel, stream=None, debug=0): + """ + Initialize the `ConditionSet` forthe `Reporter`'s default category. + + :Parameters: + + - `warninglevel`: The level at or above which warning output will + be sent to `stream`. + - `errorlevel`: The level at or above which `SystemMessage` + exceptions will be raised. + - `debug`: Show debug (level=0) system messages? + - `stream`: Where warning output is sent (`None` implies + `sys.stderr`). + """ + + if stream is None: + stream = sys.stderr + + self.categories = {'': ConditionSet(debug, warninglevel, errorlevel, + stream)} + """Mapping of category names to conditions. Default category is ''.""" + + def setconditions(self, category, warninglevel, errorlevel, + stream=None, debug=0): + if stream is None: + stream = sys.stderr + self.categories[category] = ConditionSet(debug, warninglevel, + errorlevel, stream) + + def unsetconditions(self, category): + if category and self.categories.has_key(category): + del self.categories[category] + + __delitem__ = unsetconditions + + def getconditions(self, category): + while not self.categories.has_key(category): + category = category[:category.rfind('.') + 1][:-1] + return self.categories[category] + + __getitem__ = getconditions + + def system_message(self, level, comment=None, category='', + *children, **attributes): + """ + Return a system_message object. + + Raise an exception or generate a warning if appropriate. + """ + msg = nodes.system_message(comment, level=level, + type=self.levels[level], + *children, **attributes) + debug, warninglevel, errorlevel, stream = self[category].astuple() + if level >= warninglevel or debug and level == 0: + if category: + print >>stream, 'Reporter "%s":' % category, msg.astext() + else: + print >>stream, 'Reporter:', msg.astext() + if level >= errorlevel: + raise SystemMessage(msg) + return msg + + def debug(self, comment=None, category='', *children, **attributes): + """ + Level-0, "DEBUG": an internal reporting issue. Typically, there is no + effect on the processing. Level-0 system messages are handled + separately from the others. + """ + return self.system_message( + 0, comment, category, *children, **attributes) + + def info(self, comment=None, category='', *children, **attributes): + """ + Level-1, "INFO": a minor issue that can be ignored. Typically there is + no effect on processing, and level-1 system messages are not reported. + """ + return self.system_message( + 1, comment, category, *children, **attributes) + + def warning(self, comment=None, category='', *children, **attributes): + """ + Level-2, "WARNING": an issue that should be addressed. If ignored, + there may be unpredictable problems with the output. + """ + return self.system_message( + 2, comment, category, *children, **attributes) + + def error(self, comment=None, category='', *children, **attributes): + """ + Level-3, "ERROR": an error that should be addressed. If ignored, the + output will contain errors. + """ + return self.system_message( + 3, comment, category, *children, **attributes) + + def severe(self, comment=None, category='', *children, **attributes): + """ + Level-4, "SEVERE": a severe error that must be addressed. If ignored, + the output will contain severe errors. Typically level-4 system + messages are turned into exceptions which halt processing. + """ + return self.system_message( + 4, comment, category, *children, **attributes) + + +class ConditionSet: + + """ + A set of thresholds, switches, and streams corresponding to one `Reporter` + category. + """ + + def __init__(self, debug, warninglevel, errorlevel, stream): + self.debug = debug + self.warninglevel = warninglevel + self.errorlevel = errorlevel + self.stream = stream + + def astuple(self): + return (self.debug, self.warninglevel, self.errorlevel, + self.stream) + + +class ExtensionAttributeError(Exception): pass +class BadAttributeError(ExtensionAttributeError): pass +class BadAttributeDataError(ExtensionAttributeError): pass +class DuplicateAttributeError(ExtensionAttributeError): pass + + +def extract_extension_attributes(field_list, attribute_spec): + """ + Return a dictionary mapping extension attribute names to converted values. + + :Parameters: + - `field_list`: A flat field list without field arguments, where each + field body consists of a single paragraph only. + - `attribute_spec`: Dictionary mapping known attribute names to a + conversion function such as `int` or `float`. + + :Exceptions: + - `KeyError` for unknown attribute names. + - `ValueError` for invalid attribute values (raised by the conversion + function). + - `DuplicateAttributeError` for duplicate attributes. + - `BadAttributeError` for invalid fields. + - `BadAttributeDataError` for invalid attribute data (missing name, + missing data, bad quotes, etc.). + """ + attlist = extract_attributes(field_list) + attdict = assemble_attribute_dict(attlist, attribute_spec) + return attdict + +def extract_attributes(field_list): + """ + Return a list of attribute (name, value) pairs from field names & bodies. + + :Parameter: + `field_list`: A flat field list without field arguments, where each + field body consists of a single paragraph only. + + :Exceptions: + - `BadAttributeError` for invalid fields. + - `BadAttributeDataError` for invalid attribute data (missing name, + missing data, bad quotes, etc.). + """ + attlist = [] + for field in field_list: + if len(field) != 2: + raise BadAttributeError( + 'extension attribute field may not contain field arguments') + name = field[0].astext().lower() + body = field[1] + if len(body) == 0: + data = None + elif len(body) > 1 or not isinstance(body[0], nodes.paragraph) \ + or len(body[0]) != 1 or not isinstance(body[0][0], nodes.Text): + raise BadAttributeDataError( + 'extension attribute field body may contain\n' + 'a single paragraph only (attribute "%s")' % name) + else: + data = body[0][0].astext() + attlist.append((name, data)) + return attlist + +def assemble_attribute_dict(attlist, attspec): + """ + Return a mapping of attribute names to values. + + :Parameters: + - `attlist`: A list of (name, value) pairs (the output of + `extract_attributes()`). + - `attspec`: Dictionary mapping known attribute names to a + conversion function such as `int` or `float`. + + :Exceptions: + - `KeyError` for unknown attribute names. + - `DuplicateAttributeError` for duplicate attributes. + - `ValueError` for invalid attribute values (raised by conversion + function). + """ + attributes = {} + for name, value in attlist: + convertor = attspec[name] # raises KeyError if unknown + if attributes.has_key(name): + raise DuplicateAttributeError('duplicate attribute "%s"' % name) + try: + attributes[name] = convertor(value) + except (ValueError, TypeError), detail: + raise detail.__class__('(attribute "%s", value "%r") %s' + % (name, value, detail)) + return attributes + + +class NameValueError(Exception): pass + + +def extract_name_value(line): + """ + Return a list of (name, value) from a line of the form "name=value ...". + + :Exception: + `NameValueError` for invalid input (missing name, missing data, bad + quotes, etc.). + """ + attlist = [] + while line: + equals = line.find('=') + if equals == -1: + raise NameValueError('missing "="') + attname = line[:equals].strip() + if equals == 0 or not attname: + raise NameValueError( + 'missing attribute name before "="') + line = line[equals+1:].lstrip() + if not line: + raise NameValueError( + 'missing value after "%s="' % attname) + if line[0] in '\'"': + endquote = line.find(line[0], 1) + if endquote == -1: + raise NameValueError( + 'attribute "%s" missing end quote (%s)' + % (attname, line[0])) + if len(line) > endquote + 1 and line[endquote + 1].strip(): + raise NameValueError( + 'attribute "%s" end quote (%s) not followed by ' + 'whitespace' % (attname, line[0])) + data = line[1:endquote] + line = line[endquote+1:].lstrip() + else: + space = line.find(' ') + if space == -1: + data = line + line = '' + else: + data = line[:space] + line = line[space+1:].lstrip() + attlist.append((attname.lower(), data)) + return attlist + + +def normname(name): + """Return a case- and whitespace-normalized name.""" + return ' '.join(name.lower().split()) + +def id(string): + """ + Convert `string` into an identifier and return it. + + Docutils identifiers will conform to the regular expression + ``[a-z][-a-z0-9]*``. For CSS compatibility, identifiers (the "class" and + "id" attributes) should have no underscores, colons, or periods. Hyphens + may be used. + + - The `HTML 4.01 spec`_ defines identifiers based on SGML tokens: + + ID and NAME tokens must begin with a letter ([A-Za-z]) and may be + followed by any number of letters, digits ([0-9]), hyphens ("-"), + underscores ("_"), colons (":"), and periods ("."). + + - However the `CSS1 spec`_ defines identifiers based on the "name" token, + a tighter interpretation ("flex" tokenizer notation; "latin1" and + "escape" 8-bit characters have been replaced with entities):: + + unicode \\[0-9a-f]{1,4} + latin1 [¡-ÿ] + escape {unicode}|\\[ -~¡-ÿ] + nmchar [-a-z0-9]|{latin1}|{escape} + name {nmchar}+ + + The CSS1 "nmchar" rule does not include underscores ("_"), colons (":"), + or periods ("."), therefore "class" and "id" attributes should not contain + these characters. They should be replaced with hyphens ("-"). Combined + with HTML's requirements (the first character must be a letter; no + "unicode", "latin1", or "escape" characters), this results in the + ``[a-z][-a-z0-9]*`` pattern. + + .. _HTML 4.01 spec: http://www.w3.org/TR/html401 + .. _CSS1 spec: http://www.w3.org/TR/REC-CSS1 + """ + id = non_id_chars.sub('-', normname(string)) + id = non_id_at_ends.sub('', id) + return str(id) + +non_id_chars = re.compile('[^a-z0-9]+') +non_id_at_ends = re.compile('^[-0-9]+|-+$') + +def newdocument(languagecode='en', warninglevel=2, errorlevel=4, + stream=None, debug=0): + reporter = Reporter(warninglevel, errorlevel, stream, debug) + document = nodes.document(languagecode=languagecode, reporter=reporter) + return document -- cgit v1.2.1 From 23a164fa2084631177b50039af76e424b16db2d1 Mon Sep 17 00:00:00 2001 From: goodger Date: Sun, 5 May 2002 15:36:03 +0000 Subject: refactored; improved compound names git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@86 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 66 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 28 deletions(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index a92c8fb97..0602b8d64 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -12,9 +12,10 @@ Miscellaneous utilities for the documentation utilities. import sys, re import nodes +from docutils import ApplicationError, DataError -class SystemMessage(Exception): +class SystemMessage(ApplicationError): def __init__(self, system_message): Exception.__init__(self, system_message.astext()) @@ -59,15 +60,15 @@ class Reporter: levels = 'DEBUG INFO WARNING ERROR SEVERE'.split() """List of names for system message levels, indexed by level.""" - def __init__(self, warninglevel, errorlevel, stream=None, debug=0): + def __init__(self, warning_level, error_level, stream=None, debug=0): """ Initialize the `ConditionSet` forthe `Reporter`'s default category. :Parameters: - - `warninglevel`: The level at or above which warning output will + - `warning_level`: The level at or above which warning output will be sent to `stream`. - - `errorlevel`: The level at or above which `SystemMessage` + - `error_level`: The level at or above which `SystemMessage` exceptions will be raised. - `debug`: Show debug (level=0) system messages? - `stream`: Where warning output is sent (`None` implies @@ -77,29 +78,29 @@ class Reporter: if stream is None: stream = sys.stderr - self.categories = {'': ConditionSet(debug, warninglevel, errorlevel, + self.categories = {'': ConditionSet(debug, warning_level, error_level, stream)} """Mapping of category names to conditions. Default category is ''.""" - def setconditions(self, category, warninglevel, errorlevel, - stream=None, debug=0): + def set_conditions(self, category, warning_level, error_level, + stream=None, debug=0): if stream is None: stream = sys.stderr - self.categories[category] = ConditionSet(debug, warninglevel, - errorlevel, stream) + self.categories[category] = ConditionSet(debug, warning_level, + error_level, stream) - def unsetconditions(self, category): + def unset_conditions(self, category): if category and self.categories.has_key(category): del self.categories[category] - __delitem__ = unsetconditions + __delitem__ = unset_conditions - def getconditions(self, category): + def get_conditions(self, category): while not self.categories.has_key(category): category = category[:category.rfind('.') + 1][:-1] return self.categories[category] - __getitem__ = getconditions + __getitem__ = get_conditions def system_message(self, level, comment=None, category='', *children, **attributes): @@ -111,13 +112,13 @@ class Reporter: msg = nodes.system_message(comment, level=level, type=self.levels[level], *children, **attributes) - debug, warninglevel, errorlevel, stream = self[category].astuple() - if level >= warninglevel or debug and level == 0: + debug, warning_level, error_level, stream = self[category].astuple() + if level >= warning_level or debug and level == 0: if category: print >>stream, 'Reporter "%s":' % category, msg.astext() else: print >>stream, 'Reporter:', msg.astext() - if level >= errorlevel: + if level >= error_level: raise SystemMessage(msg) return msg @@ -171,18 +172,18 @@ class ConditionSet: category. """ - def __init__(self, debug, warninglevel, errorlevel, stream): + def __init__(self, debug, warning_level, error_level, stream): self.debug = debug - self.warninglevel = warninglevel - self.errorlevel = errorlevel + self.warning_level = warning_level + self.error_level = error_level self.stream = stream def astuple(self): - return (self.debug, self.warninglevel, self.errorlevel, + return (self.debug, self.warning_level, self.error_level, self.stream) -class ExtensionAttributeError(Exception): pass +class ExtensionAttributeError(DataError): pass class BadAttributeError(ExtensionAttributeError): pass class BadAttributeDataError(ExtensionAttributeError): pass class DuplicateAttributeError(ExtensionAttributeError): pass @@ -272,7 +273,7 @@ def assemble_attribute_dict(attlist, attspec): return attributes -class NameValueError(Exception): pass +class NameValueError(DataError): pass def extract_name_value(line): @@ -320,7 +321,7 @@ def extract_name_value(line): return attlist -def normname(name): +def normalize_name(name): """Return a case- and whitespace-normalized name.""" return ' '.join(name.lower().split()) @@ -359,15 +360,24 @@ def id(string): .. _HTML 4.01 spec: http://www.w3.org/TR/html401 .. _CSS1 spec: http://www.w3.org/TR/REC-CSS1 """ - id = non_id_chars.sub('-', normname(string)) + id = non_id_chars.sub('-', normalize_name(string)) id = non_id_at_ends.sub('', id) return str(id) non_id_chars = re.compile('[^a-z0-9]+') non_id_at_ends = re.compile('^[-0-9]+|-+$') -def newdocument(languagecode='en', warninglevel=2, errorlevel=4, - stream=None, debug=0): - reporter = Reporter(warninglevel, errorlevel, stream, debug) - document = nodes.document(languagecode=languagecode, reporter=reporter) +def new_document(language_code='en', warning_level=2, error_level=4, + stream=None, debug=0): + reporter = Reporter(warning_level, error_level, stream, debug) + document = nodes.document(language_code=language_code, reporter=reporter) return document + +def clean_rcs_keywords(paragraph, keyword_substitutions): + if len(paragraph) == 1 and isinstance(paragraph[0], nodes.Text): + textnode = paragraph[0] + for pattern, substitution in keyword_substitutions: + match = pattern.match(textnode.data) + if match: + textnode.data = pattern.sub(substitution, textnode.data) + return -- cgit v1.2.1 From 060ae1cc18c6362cbfc28c6ee525ff32616ad1fb Mon Sep 17 00:00:00 2001 From: goodger Date: Fri, 24 May 2002 03:08:09 +0000 Subject: - Changed names of Reporter's thresholds: warning_level -> report_level; error_level -> halt_level. git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@143 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 71 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 36 insertions(+), 35 deletions(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index 0602b8d64..9f9130b5e 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -29,27 +29,28 @@ class Reporter: Five levels of system messages are defined, along with corresponding methods: `debug()`, `info()`, `warning()`, `error()`, and `severe()`. - There is typically one Reporter object per process. A Reporter object is - instantiated with thresholds for generating warnings and errors (raising - exceptions), a switch to turn debug output on or off, and an I/O stream - for warnings. These are stored in the default reporting category, '' - (zero-length string). - - Multiple reporting categories [#]_ may be set, each with its own warning - and error thresholds, debugging switch, and warning stream (collectively a - `ConditionSet`). Categories are hierarchically-named strings that look - like attribute references: 'spam', 'spam.eggs', 'neeeow.wum.ping'. The - 'spam' category is the ancestor of 'spam.bacon.eggs'. Unset categories - inherit stored conditions from their closest ancestor category that has - been set. + There is typically one Reporter object per process. A Reporter object is + instantiated with thresholds for reporting (generating warnings) and + halting processing (raising exceptions), a switch to turn debug output on + or off, and an I/O stream for warnings. These are stored in the default + reporting category, '' (zero-length string). + + Multiple reporting categories [#]_ may be set, each with its own reporting + and halting thresholds, debugging switch, and warning stream + (collectively a `ConditionSet`). Categories are hierarchical dotted-name + strings that look like attribute references: 'spam', 'spam.eggs', + 'neeeow.wum.ping'. The 'spam' category is the ancestor of + 'spam.bacon.eggs'. Unset categories inherit stored conditions from their + closest ancestor category that has been set. When a system message is generated, the stored conditions from its - category (or ancestor if unset) are retrieved. The system message level is - compared to the thresholds stored in the category, and a warning or error - is generated as appropriate. Debug messages are produced iff the stored - debug switch is on. Message output is sent to the stored warning stream. + category (or ancestor if unset) are retrieved. The system message level + is compared to the thresholds stored in the category, and a warning or + error is generated as appropriate. Debug messages are produced iff the + stored debug switch is on. Message output is sent to the stored warning + stream. - The default category is '' (empty string). By convention, Writers should + The default category is '' (empty string). By convention, Writers should retrieve reporting conditions from the 'writer' category (which, unless explicitly set, defaults to the conditions of the default category). @@ -60,16 +61,16 @@ class Reporter: levels = 'DEBUG INFO WARNING ERROR SEVERE'.split() """List of names for system message levels, indexed by level.""" - def __init__(self, warning_level, error_level, stream=None, debug=0): + def __init__(self, report_level, halt_level, stream=None, debug=0): """ Initialize the `ConditionSet` forthe `Reporter`'s default category. :Parameters: - - `warning_level`: The level at or above which warning output will + - `report_level`: The level at or above which warning output will be sent to `stream`. - - `error_level`: The level at or above which `SystemMessage` - exceptions will be raised. + - `halt_level`: The level at or above which `SystemMessage` + exceptions will be raised, halting execution. - `debug`: Show debug (level=0) system messages? - `stream`: Where warning output is sent (`None` implies `sys.stderr`). @@ -78,16 +79,16 @@ class Reporter: if stream is None: stream = sys.stderr - self.categories = {'': ConditionSet(debug, warning_level, error_level, + self.categories = {'': ConditionSet(debug, report_level, halt_level, stream)} """Mapping of category names to conditions. Default category is ''.""" - def set_conditions(self, category, warning_level, error_level, + def set_conditions(self, category, report_level, halt_level, stream=None, debug=0): if stream is None: stream = sys.stderr - self.categories[category] = ConditionSet(debug, warning_level, - error_level, stream) + self.categories[category] = ConditionSet(debug, report_level, + halt_level, stream) def unset_conditions(self, category): if category and self.categories.has_key(category): @@ -112,13 +113,13 @@ class Reporter: msg = nodes.system_message(comment, level=level, type=self.levels[level], *children, **attributes) - debug, warning_level, error_level, stream = self[category].astuple() - if level >= warning_level or debug and level == 0: + debug, report_level, halt_level, stream = self[category].astuple() + if level >= report_level or debug and level == 0: if category: print >>stream, 'Reporter "%s":' % category, msg.astext() else: print >>stream, 'Reporter:', msg.astext() - if level >= error_level: + if level >= halt_level: raise SystemMessage(msg) return msg @@ -172,14 +173,14 @@ class ConditionSet: category. """ - def __init__(self, debug, warning_level, error_level, stream): + def __init__(self, debug, report_level, halt_level, stream): self.debug = debug - self.warning_level = warning_level - self.error_level = error_level + self.report_level = report_level + self.halt_level = halt_level self.stream = stream def astuple(self): - return (self.debug, self.warning_level, self.error_level, + return (self.debug, self.report_level, self.halt_level, self.stream) @@ -367,9 +368,9 @@ def id(string): non_id_chars = re.compile('[^a-z0-9]+') non_id_at_ends = re.compile('^[-0-9]+|-+$') -def new_document(language_code='en', warning_level=2, error_level=4, +def new_document(language_code='en', report_level=2, halt_level=4, stream=None, debug=0): - reporter = Reporter(warning_level, error_level, stream, debug) + reporter = Reporter(report_level, halt_level, stream, debug) document = nodes.document(language_code=language_code, reporter=reporter) return document -- cgit v1.2.1 From 677a4213e1d8a8c3ccfa01bfbcb67a5264adb129 Mon Sep 17 00:00:00 2001 From: goodger Date: Thu, 30 May 2002 02:14:23 +0000 Subject: - Moved ``utils.id()`` to ``nodes.make_id()``. - Added support for an option values object which carries default settings and overrides (from command-line options and library use). - Cleaned up imports: no more relative package imports or comma-separated lists of top-level modules. git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@152 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 68 +++++++++++++------------------------------------------ 1 file changed, 16 insertions(+), 52 deletions(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index 9f9130b5e..d276b671f 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -10,9 +10,12 @@ Miscellaneous utilities for the documentation utilities. """ -import sys, re -import nodes +__docformat__ = 'reStructuredText' + +import sys +from types import StringTypes from docutils import ApplicationError, DataError +from docutils import frontend, nodes class SystemMessage(ApplicationError): @@ -72,12 +75,14 @@ class Reporter: - `halt_level`: The level at or above which `SystemMessage` exceptions will be raised, halting execution. - `debug`: Show debug (level=0) system messages? - - `stream`: Where warning output is sent (`None` implies - `sys.stderr`). + - `stream`: Where warning output is sent. Can be file-like (has a + ``.write`` method), a string (file name, opened for writing), or + `None` (implies `sys.stderr`; default). """ - if stream is None: stream = sys.stderr + elif type(stream) in StringTypes: + raise NotImplementedError('This should open a file for writing.') self.categories = {'': ConditionSet(debug, report_level, halt_level, stream)} @@ -321,57 +326,16 @@ def extract_name_value(line): attlist.append((attname.lower(), data)) return attlist - def normalize_name(name): """Return a case- and whitespace-normalized name.""" return ' '.join(name.lower().split()) -def id(string): - """ - Convert `string` into an identifier and return it. - - Docutils identifiers will conform to the regular expression - ``[a-z][-a-z0-9]*``. For CSS compatibility, identifiers (the "class" and - "id" attributes) should have no underscores, colons, or periods. Hyphens - may be used. - - - The `HTML 4.01 spec`_ defines identifiers based on SGML tokens: - - ID and NAME tokens must begin with a letter ([A-Za-z]) and may be - followed by any number of letters, digits ([0-9]), hyphens ("-"), - underscores ("_"), colons (":"), and periods ("."). - - - However the `CSS1 spec`_ defines identifiers based on the "name" token, - a tighter interpretation ("flex" tokenizer notation; "latin1" and - "escape" 8-bit characters have been replaced with entities):: - - unicode \\[0-9a-f]{1,4} - latin1 [¡-ÿ] - escape {unicode}|\\[ -~¡-ÿ] - nmchar [-a-z0-9]|{latin1}|{escape} - name {nmchar}+ - - The CSS1 "nmchar" rule does not include underscores ("_"), colons (":"), - or periods ("."), therefore "class" and "id" attributes should not contain - these characters. They should be replaced with hyphens ("-"). Combined - with HTML's requirements (the first character must be a letter; no - "unicode", "latin1", or "escape" characters), this results in the - ``[a-z][-a-z0-9]*`` pattern. - - .. _HTML 4.01 spec: http://www.w3.org/TR/html401 - .. _CSS1 spec: http://www.w3.org/TR/REC-CSS1 - """ - id = non_id_chars.sub('-', normalize_name(string)) - id = non_id_at_ends.sub('', id) - return str(id) - -non_id_chars = re.compile('[^a-z0-9]+') -non_id_at_ends = re.compile('^[-0-9]+|-+$') - -def new_document(language_code='en', report_level=2, halt_level=4, - stream=None, debug=0): - reporter = Reporter(report_level, halt_level, stream, debug) - document = nodes.document(language_code=language_code, reporter=reporter) +def new_document(options=None): + if options is None: + options = frontend.OptionParser().get_default_values() + reporter = Reporter(options.report_level, options.halt_level, + options.warning_stream, options.debug) + document = nodes.document(options=options, reporter=reporter) return document def clean_rcs_keywords(paragraph, keyword_substitutions): -- cgit v1.2.1 From f58fb865a3aea6a7b87ca716fd16a0ba2cdd9ac6 Mon Sep 17 00:00:00 2001 From: goodger Date: Thu, 30 May 2002 03:14:26 +0000 Subject: removed 2.2ism git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@162 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index d276b671f..da9c49512 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -13,7 +13,7 @@ Miscellaneous utilities for the documentation utilities. __docformat__ = 'reStructuredText' import sys -from types import StringTypes +from types import StringType, UnicodeType from docutils import ApplicationError, DataError from docutils import frontend, nodes @@ -81,7 +81,7 @@ class Reporter: """ if stream is None: stream = sys.stderr - elif type(stream) in StringTypes: + elif type(stream) in (StringType, UnicodeType): raise NotImplementedError('This should open a file for writing.') self.categories = {'': ConditionSet(debug, report_level, halt_level, -- cgit v1.2.1 From 52f3b32ff8b86bfee7f2415e0d1e6db5dc5a1acc Mon Sep 17 00:00:00 2001 From: goodger Date: Sat, 1 Jun 2002 01:43:35 +0000 Subject: docstring git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@172 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index da9c49512..161526fa0 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -174,7 +174,8 @@ class Reporter: class ConditionSet: """ - A set of thresholds, switches, and streams corresponding to one `Reporter` + A set of two thresholds (`report_level` & `halt_level`), a switch + (`debug`), and an I/O stream (`stream`), corresponding to one `Reporter` category. """ -- cgit v1.2.1 From 8772c081ae9e24fd5ee41211847ed9afc8cf1872 Mon Sep 17 00:00:00 2001 From: goodger Date: Fri, 28 Jun 2002 04:18:12 +0000 Subject: - Added support for input and output encodings and for internal Unicode support. git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@220 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index 161526fa0..c2418d91c 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -237,7 +237,7 @@ def extract_attributes(field_list): if len(field) != 2: raise BadAttributeError( 'extension attribute field may not contain field arguments') - name = field[0].astext().lower() + name = str(field[0].astext().lower()) body = field[1] if len(body) == 0: data = None @@ -275,7 +275,7 @@ def assemble_attribute_dict(attlist, attspec): try: attributes[name] = convertor(value) except (ValueError, TypeError), detail: - raise detail.__class__('(attribute "%s", value "%r") %s' + raise detail.__class__('(attribute "%s", value "%s") %s' % (name, value, detail)) return attributes -- cgit v1.2.1 From 513862cec4707b0b5f1f54460052a23e36ba7ecb Mon Sep 17 00:00:00 2001 From: goodger Date: Wed, 24 Jul 2002 01:42:01 +0000 Subject: Changed format of directive attribute error. git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@359 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index c2418d91c..8b1d7ddf9 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -275,7 +275,7 @@ def assemble_attribute_dict(attlist, attspec): try: attributes[name] = convertor(value) except (ValueError, TypeError), detail: - raise detail.__class__('(attribute "%s", value "%s") %s' + raise detail.__class__('(attribute: "%s"; value: %r)\n%s' % (name, value, detail)) return attributes -- cgit v1.2.1 From fe66cb1cd619d5abd815be4b235b116cd3c43807 Mon Sep 17 00:00:00 2001 From: goodger Date: Sun, 28 Jul 2002 15:35:28 +0000 Subject: Added ``relative_uri(source, target)``. git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@396 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index 8b1d7ddf9..44a537667 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -13,6 +13,8 @@ Miscellaneous utilities for the documentation utilities. __docformat__ = 'reStructuredText' import sys +import os +import os.path from types import StringType, UnicodeType from docutils import ApplicationError, DataError from docutils import frontend, nodes @@ -347,3 +349,24 @@ def clean_rcs_keywords(paragraph, keyword_substitutions): if match: textnode.data = pattern.sub(substitution, textnode.data) return + +def relative_uri(source, target): + """ + Build and return a URI to `target`, relative to `source`. + + If there is no common prefix, return the absolute path to `target`. + """ + source_parts = os.path.abspath(source).split(os.sep) + target_parts = os.path.abspath(target).split(os.sep) + if source_parts[:2] != target_parts[:2]: + # Nothing in common between paths. Return absolute path. + return '/'.join(target_parts) + source_parts.reverse() + target_parts.reverse() + while source_parts[-1] == target_parts[-1]: + # Remove path components in common: + source_parts.pop() + target_parts.pop() + target_parts.reverse() + parts = ['..'] * (len(source_parts) - 1) + target_parts + return '/'.join(parts) -- cgit v1.2.1 From c3dd163385425e7e2df847faef58c3bdb22d19a4 Mon Sep 17 00:00:00 2001 From: goodger Date: Wed, 31 Jul 2002 01:39:19 +0000 Subject: bugfix git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@422 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index 44a537667..c8a0be2ba 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -363,7 +363,8 @@ def relative_uri(source, target): return '/'.join(target_parts) source_parts.reverse() target_parts.reverse() - while source_parts[-1] == target_parts[-1]: + while (source_parts and target_parts + and source_parts[-1] == target_parts[-1]): # Remove path components in common: source_parts.pop() target_parts.pop() -- cgit v1.2.1 From 4223ee697fe8de32b95b79d996eaf805424d6737 Mon Sep 17 00:00:00 2001 From: goodger Date: Wed, 21 Aug 2002 02:43:46 +0000 Subject: Added a ``source`` attribute to Reporter instances and ``system_message`` elements. git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@568 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index c8a0be2ba..84133f650 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -66,12 +66,14 @@ class Reporter: levels = 'DEBUG INFO WARNING ERROR SEVERE'.split() """List of names for system message levels, indexed by level.""" - def __init__(self, report_level, halt_level, stream=None, debug=0): + def __init__(self, source, report_level, halt_level, stream=None, + debug=0): """ Initialize the `ConditionSet` forthe `Reporter`'s default category. :Parameters: + - `source`: The path to or description of the source data. - `report_level`: The level at or above which warning output will be sent to `stream`. - `halt_level`: The level at or above which `SystemMessage` @@ -81,6 +83,9 @@ class Reporter: ``.write`` method), a string (file name, opened for writing), or `None` (implies `sys.stderr`; default). """ + self.source = source + """The path to or description of the source data.""" + if stream is None: stream = sys.stderr elif type(stream) in (StringType, UnicodeType): @@ -120,6 +125,7 @@ class Reporter: msg = nodes.system_message(comment, level=level, type=self.levels[level], *children, **attributes) + msg['source'] = self.source debug, report_level, halt_level, stream = self[category].astuple() if level >= report_level or debug and level == 0: if category: @@ -333,12 +339,12 @@ def normalize_name(name): """Return a case- and whitespace-normalized name.""" return ' '.join(name.lower().split()) -def new_document(options=None): +def new_document(source, options=None): if options is None: options = frontend.OptionParser().get_default_values() - reporter = Reporter(options.report_level, options.halt_level, + reporter = Reporter(source, options.report_level, options.halt_level, options.warning_stream, options.debug) - document = nodes.document(options=options, reporter=reporter) + document = nodes.document(options, reporter, source=source) return document def clean_rcs_keywords(paragraph, keyword_substitutions): -- cgit v1.2.1 From 323e641db71eb83083577685200302a739d84e71 Mon Sep 17 00:00:00 2001 From: goodger Date: Fri, 23 Aug 2002 01:51:15 +0000 Subject: Renamed ``relative_uri`` to ``relative_path``, & fixed logic (thanks to Kenichi Sato). git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@575 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index 84133f650..293f3d61c 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -356,15 +356,15 @@ def clean_rcs_keywords(paragraph, keyword_substitutions): textnode.data = pattern.sub(substitution, textnode.data) return -def relative_uri(source, target): +def relative_path(source, target): """ - Build and return a URI to `target`, relative to `source`. + Build and return a path to `target`, relative to `source`. If there is no common prefix, return the absolute path to `target`. """ source_parts = os.path.abspath(source).split(os.sep) target_parts = os.path.abspath(target).split(os.sep) - if source_parts[:2] != target_parts[:2]: + if source_parts[:1] != target_parts[:1]: # Nothing in common between paths. Return absolute path. return '/'.join(target_parts) source_parts.reverse() -- cgit v1.2.1 From f14be8cb9b05636ef65e921923ecd74a7cd8304d Mon Sep 17 00:00:00 2001 From: goodger Date: Tue, 27 Aug 2002 00:40:51 +0000 Subject: Changed "attribute" to "option" for directives/extensions. git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@597 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 72 +++++++++++++++++++++++++++---------------------------- 1 file changed, 36 insertions(+), 36 deletions(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index 293f3d61c..98ede8ac8 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -198,94 +198,94 @@ class ConditionSet: self.stream) -class ExtensionAttributeError(DataError): pass -class BadAttributeError(ExtensionAttributeError): pass -class BadAttributeDataError(ExtensionAttributeError): pass -class DuplicateAttributeError(ExtensionAttributeError): pass +class ExtensionOptionError(DataError): pass +class BadOptionError(ExtensionOptionError): pass +class BadOptionDataError(ExtensionOptionError): pass +class DuplicateOptionError(ExtensionOptionError): pass -def extract_extension_attributes(field_list, attribute_spec): +def extract_extension_options(field_list, option_spec): """ - Return a dictionary mapping extension attribute names to converted values. + Return a dictionary mapping extension option names to converted values. :Parameters: - `field_list`: A flat field list without field arguments, where each field body consists of a single paragraph only. - - `attribute_spec`: Dictionary mapping known attribute names to a + - `option_spec`: Dictionary mapping known option names to a conversion function such as `int` or `float`. :Exceptions: - - `KeyError` for unknown attribute names. - - `ValueError` for invalid attribute values (raised by the conversion + - `KeyError` for unknown option names. + - `ValueError` for invalid option values (raised by the conversion function). - - `DuplicateAttributeError` for duplicate attributes. - - `BadAttributeError` for invalid fields. - - `BadAttributeDataError` for invalid attribute data (missing name, + - `DuplicateOptionError` for duplicate options. + - `BadOptionError` for invalid fields. + - `BadOptionDataError` for invalid option data (missing name, missing data, bad quotes, etc.). """ - attlist = extract_attributes(field_list) - attdict = assemble_attribute_dict(attlist, attribute_spec) + attlist = extract_options(field_list) + attdict = assemble_option_dict(attlist, option_spec) return attdict -def extract_attributes(field_list): +def extract_options(field_list): """ - Return a list of attribute (name, value) pairs from field names & bodies. + Return a list of option (name, value) pairs from field names & bodies. :Parameter: `field_list`: A flat field list without field arguments, where each field body consists of a single paragraph only. :Exceptions: - - `BadAttributeError` for invalid fields. - - `BadAttributeDataError` for invalid attribute data (missing name, + - `BadOptionError` for invalid fields. + - `BadOptionDataError` for invalid option data (missing name, missing data, bad quotes, etc.). """ attlist = [] for field in field_list: if len(field) != 2: - raise BadAttributeError( - 'extension attribute field may not contain field arguments') + raise BadOptionError( + 'extension option field may not contain field arguments') name = str(field[0].astext().lower()) body = field[1] if len(body) == 0: data = None elif len(body) > 1 or not isinstance(body[0], nodes.paragraph) \ or len(body[0]) != 1 or not isinstance(body[0][0], nodes.Text): - raise BadAttributeDataError( - 'extension attribute field body may contain\n' - 'a single paragraph only (attribute "%s")' % name) + raise BadOptionDataError( + 'extension option field body may contain\n' + 'a single paragraph only (option "%s")' % name) else: data = body[0][0].astext() attlist.append((name, data)) return attlist -def assemble_attribute_dict(attlist, attspec): +def assemble_option_dict(attlist, attspec): """ - Return a mapping of attribute names to values. + Return a mapping of option names to values. :Parameters: - `attlist`: A list of (name, value) pairs (the output of - `extract_attributes()`). - - `attspec`: Dictionary mapping known attribute names to a + `extract_options()`). + - `attspec`: Dictionary mapping known option names to a conversion function such as `int` or `float`. :Exceptions: - - `KeyError` for unknown attribute names. - - `DuplicateAttributeError` for duplicate attributes. - - `ValueError` for invalid attribute values (raised by conversion + - `KeyError` for unknown option names. + - `DuplicateOptionError` for duplicate options. + - `ValueError` for invalid option values (raised by conversion function). """ - attributes = {} + options = {} for name, value in attlist: convertor = attspec[name] # raises KeyError if unknown - if attributes.has_key(name): - raise DuplicateAttributeError('duplicate attribute "%s"' % name) + if options.has_key(name): + raise DuplicateOptionError('duplicate option "%s"' % name) try: - attributes[name] = convertor(value) + options[name] = convertor(value) except (ValueError, TypeError), detail: - raise detail.__class__('(attribute: "%s"; value: %r)\n%s' + raise detail.__class__('(option: "%s"; value: %r)\n%s' % (name, value, detail)) - return attributes + return options class NameValueError(DataError): pass -- cgit v1.2.1 From 721328bfaa518d9a511a43d78ad422a58308fad3 Mon Sep 17 00:00:00 2001 From: goodger Date: Wed, 28 Aug 2002 00:22:19 +0000 Subject: Finished changing "attribute" (or "attr") to "option" for directives/extensions. git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@600 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index 98ede8ac8..1f33f2908 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -223,9 +223,9 @@ def extract_extension_options(field_list, option_spec): - `BadOptionDataError` for invalid option data (missing name, missing data, bad quotes, etc.). """ - attlist = extract_options(field_list) - attdict = assemble_option_dict(attlist, option_spec) - return attdict + option_list = extract_options(field_list) + option_dict = assemble_option_dict(option_list, option_spec) + return option_dict def extract_options(field_list): """ @@ -240,7 +240,7 @@ def extract_options(field_list): - `BadOptionDataError` for invalid option data (missing name, missing data, bad quotes, etc.). """ - attlist = [] + option_list = [] for field in field_list: if len(field) != 2: raise BadOptionError( @@ -256,17 +256,17 @@ def extract_options(field_list): 'a single paragraph only (option "%s")' % name) else: data = body[0][0].astext() - attlist.append((name, data)) - return attlist + option_list.append((name, data)) + return option_list -def assemble_option_dict(attlist, attspec): +def assemble_option_dict(option_list, option_spec): """ Return a mapping of option names to values. :Parameters: - - `attlist`: A list of (name, value) pairs (the output of + - `option_list`: A list of (name, value) pairs (the output of `extract_options()`). - - `attspec`: Dictionary mapping known option names to a + - `option_spec`: Dictionary mapping known option names to a conversion function such as `int` or `float`. :Exceptions: @@ -276,8 +276,8 @@ def assemble_option_dict(attlist, attspec): function). """ options = {} - for name, value in attlist: - convertor = attspec[name] # raises KeyError if unknown + for name, value in option_list: + convertor = option_spec[name] # raises KeyError if unknown if options.has_key(name): raise DuplicateOptionError('duplicate option "%s"' % name) try: -- cgit v1.2.1 From 9bd2d1956e361d262b8cbd2bf4e84daad6d16597 Mon Sep 17 00:00:00 2001 From: goodger Date: Thu, 5 Sep 2002 03:07:45 +0000 Subject: - Added an observer pattern to ``utils.Reporter`` to keep track of system messages. - Fixed a bug in ``relative_path()``. git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@628 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index 1f33f2908..395374e7d 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -59,8 +59,18 @@ class Reporter: retrieve reporting conditions from the 'writer' category (which, unless explicitly set, defaults to the conditions of the default category). + The Reporter class also employs a modified form of the "Observer" pattern + [GoF95]_ to track system messages generated. The `attach_observer` method + should be called before parsing, with a bound method or function which + accepts system messages. The observer can be removed with + `detach_observer`, and another added in its place. + .. [#] The concept of "categories" was inspired by the log4j project: http://jakarta.apache.org/log4j/. + + .. [GoF95] Gamma, Helm, Johnson, Vlissides. *Design Patterns: Elements of + Reusable Object-Oriented Software*. Addison-Wesley, Reading, MA, USA, + 1995. """ levels = 'DEBUG INFO WARNING ERROR SEVERE'.split() @@ -95,6 +105,10 @@ class Reporter: stream)} """Mapping of category names to conditions. Default category is ''.""" + self.observers = [] + """List of bound methods or functions to call with each system_message + created.""" + def set_conditions(self, category, report_level, halt_level, stream=None, debug=0): if stream is None: @@ -115,6 +129,20 @@ class Reporter: __getitem__ = get_conditions + def attach_observer(self, observer): + """ + The `observer` parameter is a function or bound method which takes one + argument, a `nodes.system_message` instance. + """ + self.observers.append(observer) + + def detach_observer(self, observer): + self.observers.remove(observer) + + def notify_observers(self, message): + for observer in self.observers: + observer(message) + def system_message(self, level, comment=None, category='', *children, **attributes): """ @@ -134,6 +162,8 @@ class Reporter: print >>stream, 'Reporter:', msg.astext() if level >= halt_level: raise SystemMessage(msg) + if level > 0 or debug: + self.notify_observers(msg) return msg def debug(self, comment=None, category='', *children, **attributes): @@ -362,7 +392,7 @@ def relative_path(source, target): If there is no common prefix, return the absolute path to `target`. """ - source_parts = os.path.abspath(source).split(os.sep) + source_parts = os.path.abspath(source or '').split(os.sep) target_parts = os.path.abspath(target).split(os.sep) if source_parts[:1] != target_parts[:1]: # Nothing in common between paths. Return absolute path. -- cgit v1.2.1 From 2ba8fffc2b3bf0e74aedfd33533f10a54a5b77be Mon Sep 17 00:00:00 2001 From: goodger Date: Wed, 11 Sep 2002 02:54:23 +0000 Subject: updated git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@665 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index 395374e7d..edeb26109 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -262,8 +262,8 @@ def extract_options(field_list): Return a list of option (name, value) pairs from field names & bodies. :Parameter: - `field_list`: A flat field list without field arguments, where each - field body consists of a single paragraph only. + `field_list`: A flat field list, where each field name is a single + word and each field body consists of a single paragraph only. :Exceptions: - `BadOptionError` for invalid fields. @@ -272,9 +272,9 @@ def extract_options(field_list): """ option_list = [] for field in field_list: - if len(field) != 2: + if len(field[0].astext().split()) != 1: raise BadOptionError( - 'extension option field may not contain field arguments') + 'extension option field name may not contain multiple words') name = str(field[0].astext().lower()) body = field[1] if len(body) == 0: -- cgit v1.2.1 From 1aa202a450e403c6451909598132d1bf4a2cb162 Mon Sep 17 00:00:00 2001 From: goodger Date: Tue, 24 Sep 2002 02:15:39 +0000 Subject: Added support for improved diagnostics. git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@712 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index edeb26109..c48dc4e20 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -1,12 +1,10 @@ -#! /usr/bin/env python +# Author: David Goodger +# Contact: goodger@users.sourceforge.net +# Revision: $Revision$ +# Date: $Date$ +# Copyright: This module has been placed in the public domain. """ -:Author: David Goodger -:Contact: goodger@users.sourceforge.net -:Revision: $Revision$ -:Date: $Date$ -:Copyright: This module has been placed in the public domain. - Miscellaneous utilities for the documentation utilities. """ @@ -375,6 +373,7 @@ def new_document(source, options=None): reporter = Reporter(source, options.report_level, options.halt_level, options.warning_stream, options.debug) document = nodes.document(options, reporter, source=source) + document.note_source(source) return document def clean_rcs_keywords(paragraph, keyword_substitutions): -- cgit v1.2.1 From 32fd41aa1be5a9e8d356d08a67bf38a036c2af08 Mon Sep 17 00:00:00 2001 From: goodger Date: Tue, 8 Oct 2002 01:28:06 +0000 Subject: Improved Reporter diagnostics (line numbers on almost all system messages). Changed Reporter method API slightly. Added ``get_source_line()`` function. git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@772 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 58 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 21 deletions(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index c48dc4e20..2f2c4c9f1 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -141,70 +141,75 @@ class Reporter: for observer in self.observers: observer(message) - def system_message(self, level, comment=None, category='', - *children, **attributes): + def system_message(self, level, message, *children, **kwargs): """ Return a system_message object. Raise an exception or generate a warning if appropriate. """ - msg = nodes.system_message(comment, level=level, + attributes = kwargs.copy() + category = kwargs.get('category', '') + if kwargs.has_key('category'): + del attributes['category'] + if kwargs.has_key('base_node'): + source, line = get_source_line(kwargs['base_node']) + del attributes['base_node'] + if source is not None: + attributes.setdefault('source', source) + if line is not None: + attributes.setdefault('line', line) + attributes.setdefault('source', self.source) + msg = nodes.system_message(message, level=level, type=self.levels[level], *children, **attributes) - msg['source'] = self.source debug, report_level, halt_level, stream = self[category].astuple() if level >= report_level or debug and level == 0: if category: - print >>stream, 'Reporter "%s":' % category, msg.astext() + print >>stream, msg.astext(), '[%s]' % category else: - print >>stream, 'Reporter:', msg.astext() + print >>stream, msg.astext() if level >= halt_level: raise SystemMessage(msg) if level > 0 or debug: self.notify_observers(msg) return msg - def debug(self, comment=None, category='', *children, **attributes): + def debug(self, *args, **kwargs): """ Level-0, "DEBUG": an internal reporting issue. Typically, there is no effect on the processing. Level-0 system messages are handled separately from the others. """ - return self.system_message( - 0, comment, category, *children, **attributes) + return self.system_message(0, *args, **kwargs) - def info(self, comment=None, category='', *children, **attributes): + def info(self, *args, **kwargs): """ Level-1, "INFO": a minor issue that can be ignored. Typically there is no effect on processing, and level-1 system messages are not reported. """ - return self.system_message( - 1, comment, category, *children, **attributes) + return self.system_message(1, *args, **kwargs) - def warning(self, comment=None, category='', *children, **attributes): + def warning(self, *args, **kwargs): """ Level-2, "WARNING": an issue that should be addressed. If ignored, there may be unpredictable problems with the output. """ - return self.system_message( - 2, comment, category, *children, **attributes) + return self.system_message(2, *args, **kwargs) - def error(self, comment=None, category='', *children, **attributes): + def error(self, *args, **kwargs): """ Level-3, "ERROR": an error that should be addressed. If ignored, the output will contain errors. """ - return self.system_message( - 3, comment, category, *children, **attributes) + return self.system_message(3, *args, **kwargs) - def severe(self, comment=None, category='', *children, **attributes): + def severe(self, *args, **kwargs): """ Level-4, "SEVERE": a severe error that must be addressed. If ignored, the output will contain severe errors. Typically level-4 system messages are turned into exceptions which halt processing. """ - return self.system_message( - 4, comment, category, *children, **attributes) + return self.system_message(4, *args, **kwargs) class ConditionSet: @@ -406,3 +411,14 @@ def relative_path(source, target): target_parts.reverse() parts = ['..'] * (len(source_parts) - 1) + target_parts return '/'.join(parts) + +def get_source_line(node): + """ + Return the "source" and "line" attributes from the `node` given or from + it's closest ancestor. + """ + while node: + if node.source or node.line: + return node.source, node.line + node = node.parent + return None, None -- cgit v1.2.1 From ddf130508e6c446a3d2f7afbd5fba383acffc2b6 Mon Sep 17 00:00:00 2001 From: goodger Date: Fri, 18 Oct 2002 04:43:18 +0000 Subject: Fixed a bug in ``relative_path()``; updated. git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@822 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index 2f2c4c9f1..bbd08c6a2 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -237,14 +237,14 @@ class BadOptionDataError(ExtensionOptionError): pass class DuplicateOptionError(ExtensionOptionError): pass -def extract_extension_options(field_list, option_spec): +def extract_extension_options(field_list, options_spec): """ Return a dictionary mapping extension option names to converted values. :Parameters: - `field_list`: A flat field list without field arguments, where each field body consists of a single paragraph only. - - `option_spec`: Dictionary mapping known option names to a + - `options_spec`: Dictionary mapping known option names to a conversion function such as `int` or `float`. :Exceptions: @@ -257,7 +257,7 @@ def extract_extension_options(field_list, option_spec): missing data, bad quotes, etc.). """ option_list = extract_options(field_list) - option_dict = assemble_option_dict(option_list, option_spec) + option_dict = assemble_option_dict(option_list, options_spec) return option_dict def extract_options(field_list): @@ -292,14 +292,14 @@ def extract_options(field_list): option_list.append((name, data)) return option_list -def assemble_option_dict(option_list, option_spec): +def assemble_option_dict(option_list, options_spec): """ Return a mapping of option names to values. :Parameters: - `option_list`: A list of (name, value) pairs (the output of `extract_options()`). - - `option_spec`: Dictionary mapping known option names to a + - `options_spec`: Dictionary mapping known option names to a conversion function such as `int` or `float`. :Exceptions: @@ -310,7 +310,7 @@ def assemble_option_dict(option_list, option_spec): """ options = {} for name, value in option_list: - convertor = option_spec[name] # raises KeyError if unknown + convertor = options_spec[name] # raises KeyError if unknown if options.has_key(name): raise DuplicateOptionError('duplicate option "%s"' % name) try: @@ -372,12 +372,12 @@ def normalize_name(name): """Return a case- and whitespace-normalized name.""" return ' '.join(name.lower().split()) -def new_document(source, options=None): - if options is None: - options = frontend.OptionParser().get_default_values() - reporter = Reporter(source, options.report_level, options.halt_level, - options.warning_stream, options.debug) - document = nodes.document(options, reporter, source=source) +def new_document(source, settings=None): + if settings is None: + settings = frontend.OptionParser().get_default_values() + reporter = Reporter(source, settings.report_level, settings.halt_level, + settings.warning_stream, settings.debug) + document = nodes.document(settings, reporter, source=source) document.note_source(source) return document @@ -398,8 +398,10 @@ def relative_path(source, target): """ source_parts = os.path.abspath(source or '').split(os.sep) target_parts = os.path.abspath(target).split(os.sep) - if source_parts[:1] != target_parts[:1]: - # Nothing in common between paths. Return absolute path. + # Check first 2 parts because '/dir'.split('/') == ['', 'dir']: + if source_parts[:2] != target_parts[:2]: + # Nothing in common between paths. + # Return absolute path, using '/' for URLs: return '/'.join(target_parts) source_parts.reverse() target_parts.reverse() -- cgit v1.2.1 From 47e460c659b1e295d43604762eff2e9147d7df6c Mon Sep 17 00:00:00 2001 From: goodger Date: Fri, 8 Nov 2002 01:38:11 +0000 Subject: updated git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@917 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index bbd08c6a2..a216e114a 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -378,7 +378,7 @@ def new_document(source, settings=None): reporter = Reporter(source, settings.report_level, settings.halt_level, settings.warning_stream, settings.debug) document = nodes.document(settings, reporter, source=source) - document.note_source(source) + document.note_source(source, -1) return document def clean_rcs_keywords(paragraph, keyword_substitutions): -- cgit v1.2.1 From f5e7d4b1ce7cb79a5f2b987c9833d952a843bc41 Mon Sep 17 00:00:00 2001 From: goodger Date: Thu, 21 Nov 2002 02:27:00 +0000 Subject: added docstring git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@971 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index a216e114a..809511cba 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -373,6 +373,15 @@ def normalize_name(name): return ' '.join(name.lower().split()) def new_document(source, settings=None): + """ + Return a new empty document object. + + :Parameters: + `source` : string + The path to or description of the source text of the document. + `settings` : optparse.Values object + Runtime settings. If none provided, a default set will be used. + """ if settings is None: settings = frontend.OptionParser().get_default_values() reporter = Reporter(source, settings.report_level, settings.halt_level, -- cgit v1.2.1 From 5636e4d3f02f20e89be705d779a53d9bbd50cd31 Mon Sep 17 00:00:00 2001 From: goodger Date: Fri, 10 Jan 2003 02:11:51 +0000 Subject: Fixed bug in ``relative_path()``. git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@1077 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index 809511cba..eb3dc4932 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -420,7 +420,7 @@ def relative_path(source, target): source_parts.pop() target_parts.pop() target_parts.reverse() - parts = ['..'] * (len(source_parts) - 1) + target_parts + parts = ['..'] * len(source_parts) + target_parts return '/'.join(parts) def get_source_line(node): -- cgit v1.2.1 From d5a43d9bb3e0e052c1b83cb66e2360b23be520bd Mon Sep 17 00:00:00 2001 From: goodger Date: Fri, 10 Jan 2003 23:28:26 +0000 Subject: real fix git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@1094 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index eb3dc4932..0ab9f27e0 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -405,7 +405,7 @@ def relative_path(source, target): If there is no common prefix, return the absolute path to `target`. """ - source_parts = os.path.abspath(source or '').split(os.sep) + source_parts = os.path.abspath(source or 'dummy_file').split(os.sep) target_parts = os.path.abspath(target).split(os.sep) # Check first 2 parts because '/dir'.split('/') == ['', 'dir']: if source_parts[:2] != target_parts[:2]: @@ -420,7 +420,7 @@ def relative_path(source, target): source_parts.pop() target_parts.pop() target_parts.reverse() - parts = ['..'] * len(source_parts) + target_parts + parts = ['..'] * (len(source_parts) - 1) + target_parts return '/'.join(parts) def get_source_line(node): -- cgit v1.2.1 From adf281a00341eae13815afb97acf04ded5fa6f2d Mon Sep 17 00:00:00 2001 From: goodger Date: Thu, 27 Mar 2003 00:28:07 +0000 Subject: beginnings of substitution case-sensitizing git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@1235 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 4 ---- 1 file changed, 4 deletions(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index 0ab9f27e0..01c365cb9 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -368,10 +368,6 @@ def extract_name_value(line): attlist.append((attname.lower(), data)) return attlist -def normalize_name(name): - """Return a case- and whitespace-normalized name.""" - return ' '.join(name.lower().split()) - def new_document(source, settings=None): """ Return a new empty document object. -- cgit v1.2.1 From 02e2060de0b8eb721746ea5a4815d29f3519390e Mon Sep 17 00:00:00 2001 From: goodger Date: Tue, 3 Jun 2003 02:14:05 +0000 Subject: Added support for encoding Reporter stderr output, and encoding error handlers. git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@1371 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index 01c365cb9..152d5067c 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -75,7 +75,7 @@ class Reporter: """List of names for system message levels, indexed by level.""" def __init__(self, source, report_level, halt_level, stream=None, - debug=0): + debug=0, encoding='ascii:replace'): """ Initialize the `ConditionSet` forthe `Reporter`'s default category. @@ -90,6 +90,8 @@ class Reporter: - `stream`: Where warning output is sent. Can be file-like (has a ``.write`` method), a string (file name, opened for writing), or `None` (implies `sys.stderr`; default). + - `encoding`: The encoding and error handler (colon-separated) + for stderr output. """ self.source = source """The path to or description of the source data.""" @@ -99,6 +101,14 @@ class Reporter: elif type(stream) in (StringType, UnicodeType): raise NotImplementedError('This should open a file for writing.') + encoding, error_handler = (encoding.split(':') + ['replace'])[:2] + + self.encoding = encoding + """The character encoding for the stderr output.""" + + self.error_handler = error_handler + """The character encoding error handler.""" + self.categories = {'': ConditionSet(debug, report_level, halt_level, stream)} """Mapping of category names to conditions. Default category is ''.""" @@ -164,10 +174,11 @@ class Reporter: *children, **attributes) debug, report_level, halt_level, stream = self[category].astuple() if level >= report_level or debug and level == 0: + msgtext = msg.astext().encode(self.encoding, self.error_handler) if category: - print >>stream, msg.astext(), '[%s]' % category + print >>stream, msgtext, '[%s]' % category else: - print >>stream, msg.astext() + print >>stream, msgtext if level >= halt_level: raise SystemMessage(msg) if level > 0 or debug: @@ -381,7 +392,8 @@ def new_document(source, settings=None): if settings is None: settings = frontend.OptionParser().get_default_values() reporter = Reporter(source, settings.report_level, settings.halt_level, - settings.warning_stream, settings.debug) + stream=settings.warning_stream, debug=settings.debug, + encoding=settings.error_encoding) document = nodes.document(settings, reporter, source=source) document.note_source(source, -1) return document @@ -422,7 +434,7 @@ def relative_path(source, target): def get_source_line(node): """ Return the "source" and "line" attributes from the `node` given or from - it's closest ancestor. + its closest ancestor. """ while node: if node.source or node.line: -- cgit v1.2.1 From bb2f2713e8cdf461d76b7354dc14525ae733545a Mon Sep 17 00:00:00 2001 From: goodger Date: Sun, 8 Jun 2003 20:58:58 +0000 Subject: updated git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@1401 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index 152d5067c..f8ca2c0af 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -75,7 +75,7 @@ class Reporter: """List of names for system message levels, indexed by level.""" def __init__(self, source, report_level, halt_level, stream=None, - debug=0, encoding='ascii:replace'): + debug=0, encoding='ascii', error_handler='replace'): """ Initialize the `ConditionSet` forthe `Reporter`'s default category. @@ -90,8 +90,8 @@ class Reporter: - `stream`: Where warning output is sent. Can be file-like (has a ``.write`` method), a string (file name, opened for writing), or `None` (implies `sys.stderr`; default). - - `encoding`: The encoding and error handler (colon-separated) - for stderr output. + - `encoding`: The encoding for stderr output. + - `error_handler`: The error handler for stderr output encoding. """ self.source = source """The path to or description of the source data.""" @@ -101,8 +101,6 @@ class Reporter: elif type(stream) in (StringType, UnicodeType): raise NotImplementedError('This should open a file for writing.') - encoding, error_handler = (encoding.split(':') + ['replace'])[:2] - self.encoding = encoding """The character encoding for the stderr output.""" @@ -393,7 +391,8 @@ def new_document(source, settings=None): settings = frontend.OptionParser().get_default_values() reporter = Reporter(source, settings.report_level, settings.halt_level, stream=settings.warning_stream, debug=settings.debug, - encoding=settings.error_encoding) + encoding=settings.error_encoding, + error_handler=settings.error_encoding_error_handler) document = nodes.document(settings, reporter, source=source) document.note_source(source, -1) return document -- cgit v1.2.1 From 94ffb6485491c20aed76aa9d4fe366cdf12aa17c Mon Sep 17 00:00:00 2001 From: goodger Date: Mon, 16 Jun 2003 17:31:18 +0000 Subject: Reporter keeps track of the highest level system message yet generated. git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@1478 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index f8ca2c0af..e50a3de07 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -115,6 +115,9 @@ class Reporter: """List of bound methods or functions to call with each system_message created.""" + self.max_level = -1 + """The highest level system message generated so far.""" + def set_conditions(self, category, report_level, halt_level, stream=None, debug=0): if stream is None: @@ -181,6 +184,7 @@ class Reporter: raise SystemMessage(msg) if level > 0 or debug: self.notify_observers(msg) + self.max_level = max(level, self.max_level) return msg def debug(self, *args, **kwargs): -- cgit v1.2.1 From 6d04c86a41e129af514fb6b670353e0229788259 Mon Sep 17 00:00:00 2001 From: goodger Date: Mon, 16 Jun 2003 21:29:34 +0000 Subject: updated git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@1484 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index e50a3de07..aa97e71c1 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -412,7 +412,7 @@ def clean_rcs_keywords(paragraph, keyword_substitutions): def relative_path(source, target): """ - Build and return a path to `target`, relative to `source`. + Build and return a path to `target`, relative to `source` (both files). If there is no common prefix, return the absolute path to `target`. """ -- cgit v1.2.1 From e84dbccb28c6fb0f1415fa0149c6f3e5d6abdf83 Mon Sep 17 00:00:00 2001 From: goodger Date: Sun, 29 Jun 2003 04:54:42 +0000 Subject: add "level" attribute to SystemMessage exception git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@1525 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index aa97e71c1..2e60a6c6f 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -20,8 +20,9 @@ from docutils import frontend, nodes class SystemMessage(ApplicationError): - def __init__(self, system_message): + def __init__(self, system_message, level): Exception.__init__(self, system_message.astext()) + self.level = level class Reporter: @@ -181,7 +182,7 @@ class Reporter: else: print >>stream, msgtext if level >= halt_level: - raise SystemMessage(msg) + raise SystemMessage(msg, level) if level > 0 or debug: self.notify_observers(msg) self.max_level = max(level, self.max_level) -- cgit v1.2.1 From cac4685cb0442239fe73d2bd9b007ffb3a7317f4 Mon Sep 17 00:00:00 2001 From: fdrake Date: Tue, 30 Mar 2004 22:17:25 +0000 Subject: - allow RCS/CVS $keywords$ to be handled even if there is other text in the relevant docinfo fields (closes SF bug #926198) - make the tests of the RCS/CVS $keyword$ handling less fragile in the face of non-default -k options (closes SF bug #921085) git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@1898 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index 2e60a6c6f..148845330 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -406,7 +406,7 @@ def clean_rcs_keywords(paragraph, keyword_substitutions): if len(paragraph) == 1 and isinstance(paragraph[0], nodes.Text): textnode = paragraph[0] for pattern, substitution in keyword_substitutions: - match = pattern.match(textnode.data) + match = pattern.search(textnode.data) if match: textnode.data = pattern.sub(substitution, textnode.data) return -- cgit v1.2.1 From 2e594eab0b980f2357c83ab560bc07c0d5779117 Mon Sep 17 00:00:00 2001 From: goodger Date: Tue, 27 Apr 2004 19:53:19 +0000 Subject: updated git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@2002 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index 148845330..70da14c7e 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -324,7 +324,9 @@ def assemble_option_dict(option_list, options_spec): """ options = {} for name, value in option_list: - convertor = options_spec[name] # raises KeyError if unknown + convertor = options_spec[name] # raises KeyError if unknown + if convertor is None: + raise KeyError(name) # or if explicitly disabled if options.has_key(name): raise DuplicateOptionError('duplicate option "%s"' % name) try: -- cgit v1.2.1 From dea94526d6cba0d4538178fc7a8377697997dbe6 Mon Sep 17 00:00:00 2001 From: goodger Date: Thu, 17 Jun 2004 02:08:48 +0000 Subject: docstrings git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@2290 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index 70da14c7e..e43c0dfaa 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -321,6 +321,8 @@ def assemble_option_dict(option_list, options_spec): - `DuplicateOptionError` for duplicate options. - `ValueError` for invalid option values (raised by conversion function). + - `TypeError` for invalid option value types (raised by conversion + function). """ options = {} for name, value in option_list: -- cgit v1.2.1 From a26033a9a9d2b2355ae1d3052663c73ee74b9b10 Mon Sep 17 00:00:00 2001 From: goodger Date: Thu, 17 Jun 2004 02:51:31 +0000 Subject: docstrings git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@2291 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index e43c0dfaa..d14f6342a 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -265,6 +265,8 @@ def extract_extension_options(field_list, options_spec): - `KeyError` for unknown option names. - `ValueError` for invalid option values (raised by the conversion function). + - `TypeError` for invalid option value types (raised by conversion + function). - `DuplicateOptionError` for duplicate options. - `BadOptionError` for invalid fields. - `BadOptionDataError` for invalid option data (missing name, -- cgit v1.2.1 From eb06322ee79b43a063be327aa475db57d4089e2c Mon Sep 17 00:00:00 2001 From: goodger Date: Thu, 17 Jun 2004 21:46:50 +0000 Subject: support for CSV directive implementation git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@2299 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index d14f6342a..4639e0e71 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -25,6 +25,9 @@ class SystemMessage(ApplicationError): self.level = level +class SystemMessagePropagation(ApplicationError): pass + + class Reporter: """ -- cgit v1.2.1 From 3baae021442aeda1655134389c8573f9c4ed350f Mon Sep 17 00:00:00 2001 From: wiemann Date: Sun, 20 Jun 2004 16:03:17 +0000 Subject: make warning_stream work git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@2322 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index 4639e0e71..87bcac9ba 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -55,7 +55,7 @@ class Reporter: is compared to the thresholds stored in the category, and a warning or error is generated as appropriate. Debug messages are produced iff the stored debug switch is on. Message output is sent to the stored warning - stream. + stream if not set to ''. The default category is '' (empty string). By convention, Writers should retrieve reporting conditions from the 'writer' category (which, unless @@ -92,7 +92,8 @@ class Reporter: exceptions will be raised, halting execution. - `debug`: Show debug (level=0) system messages? - `stream`: Where warning output is sent. Can be file-like (has a - ``.write`` method), a string (file name, opened for writing), or + ``.write`` method), a string (file name, opened for writing), + '' (empty string, for discarding all stream messages) or `None` (implies `sys.stderr`; default). - `encoding`: The encoding for stderr output. - `error_handler`: The error handler for stderr output encoding. @@ -103,7 +104,12 @@ class Reporter: if stream is None: stream = sys.stderr elif type(stream) in (StringType, UnicodeType): - raise NotImplementedError('This should open a file for writing.') + # Leave stream untouched if it's ''. + if stream != '': + if type(stream) == StringType: + stream = open(stream, 'w') + elif type(stream) == UnicodeType: + stream = open(stream.encode(), 'w') self.encoding = encoding """The character encoding for the stderr output.""" @@ -178,7 +184,7 @@ class Reporter: type=self.levels[level], *children, **attributes) debug, report_level, halt_level, stream = self[category].astuple() - if level >= report_level or debug and level == 0: + if (level >= report_level or debug and level == 0) and stream: msgtext = msg.astext().encode(self.encoding, self.error_handler) if category: print >>stream, msgtext, '[%s]' % category -- cgit v1.2.1 From 3964d77d7d15405e64ad2079356e6ba77628df0f Mon Sep 17 00:00:00 2001 From: wiemann Date: Sat, 25 Sep 2004 23:33:58 +0000 Subject: added DependencyList class git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@2644 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index 87bcac9ba..e73f0f0ed 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -460,3 +460,32 @@ def get_source_line(node): return node.source, node.line node = node.parent return None, None + + +class DependencyList: + + def __init__(self, output_file=None, dependencies=[]): + self.list = [] + self.set_output(output_file) + for i in dependencies: + self.add(i) + + def set_output(self, output_file): + if output_file == '-': + self.file = sys.stdout + elif output_file: + self.file = open(output_file, 'w') + else: + self.file = None + + def add(self, filename): + if not filename in self.list: + self.list.append(filename) + if self.file is not None: + print >>self.file, filename + + def __repr__(self): + data = repr(self.list) + if len(data) > 60: + data = data[:56] + ' ...' + return '<%s: %s>' % (self.__class__.__name__, data) -- cgit v1.2.1 From 465b9e552af2ecd5a1d5df8d042ebc9ca2258ff2 Mon Sep 17 00:00:00 2001 From: wiemann Date: Tue, 28 Sep 2004 11:53:41 +0000 Subject: added get_stylesheet_reference(); added documentation for DependencyList; made DependencyList.set_output() clear the list of already added dependencies git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@2663 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index e73f0f0ed..91b01f530 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -450,6 +450,19 @@ def relative_path(source, target): parts = ['..'] * (len(source_parts) - 1) + target_parts return '/'.join(parts) +def get_stylesheet_reference(settings, relative_to=None): + """ + Retrieve a stylesheet reference from the settings object. + """ + if settings.stylesheet_path: + assert not settings.stylesheet, \ + 'stylesheet and stylesheet_path are mutually exclusive.' + if relative_to == None: + relative_to = settings._destination + return relative_path(relative_to, settings.stylesheet_path) + else: + return settings.stylesheet + def get_source_line(node): """ Return the "source" and "line" attributes from the `node` given or from @@ -464,13 +477,32 @@ def get_source_line(node): class DependencyList: + """ + List of dependencies, with file recording support. + """ + def __init__(self, output_file=None, dependencies=[]): - self.list = [] + """ + Initialize the dependency list, automatically setting the + output file to `output_file` (see `set_output()`) and adding + all supplied dependencies. + """ self.set_output(output_file) for i in dependencies: self.add(i) def set_output(self, output_file): + """ + Set the output file and clear the list of already added + dependencies. + + `output_file` must be a string. The specified file is + immediately overwritten. + + If output_file is '-', the output will be written to stdout. + If it is None, no file output is done when calling add(). + """ + self.list = [] if output_file == '-': self.file = sys.stdout elif output_file: @@ -479,6 +511,11 @@ class DependencyList: self.file = None def add(self, filename): + """ + If the dependency `filename` has not already been added, + append it to self.list and print it to self.file if self.file + is not None. + """ if not filename in self.list: self.list.append(filename) if self.file is not None: -- cgit v1.2.1 From a642b1e99d0a3c417ef1422e3866ea450332bcc9 Mon Sep 17 00:00:00 2001 From: wiemann Date: Wed, 29 Sep 2004 18:01:09 +0000 Subject: added close() method for DependencyList git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@2670 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index 91b01f530..4227b8d15 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -479,6 +479,9 @@ class DependencyList: """ List of dependencies, with file recording support. + + Note that the output file is not automatically closed. You have + to explicitly call the close() method. """ def __init__(self, output_file=None, dependencies=[]): @@ -521,6 +524,13 @@ class DependencyList: if self.file is not None: print >>self.file, filename + def close(self): + """ + Close the output file. + """ + self.file.close() + self.file = None + def __repr__(self): data = repr(self.list) if len(data) > 60: -- cgit v1.2.1 From 28b8294d62333bc4e217cdf430a42be0750211b8 Mon Sep 17 00:00:00 2001 From: goodger Date: Thu, 30 Sep 2004 03:01:20 +0000 Subject: improved DependencyList.__repr__; whitespace git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@2672 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index 4227b8d15..7e515070f 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -92,7 +92,7 @@ class Reporter: exceptions will be raised, halting execution. - `debug`: Show debug (level=0) system messages? - `stream`: Where warning output is sent. Can be file-like (has a - ``.write`` method), a string (file name, opened for writing), + ``.write`` method), a string (file name, opened for writing), '' (empty string, for discarding all stream messages) or `None` (implies `sys.stderr`; default). - `encoding`: The encoding for stderr output. @@ -100,7 +100,7 @@ class Reporter: """ self.source = source """The path to or description of the source data.""" - + if stream is None: stream = sys.stderr elif type(stream) in (StringType, UnicodeType): @@ -476,14 +476,14 @@ def get_source_line(node): class DependencyList: - + """ List of dependencies, with file recording support. Note that the output file is not automatically closed. You have to explicitly call the close() method. """ - + def __init__(self, output_file=None, dependencies=[]): """ Initialize the dependency list, automatically setting the @@ -532,7 +532,8 @@ class DependencyList: self.file = None def __repr__(self): - data = repr(self.list) - if len(data) > 60: - data = data[:56] + ' ...' - return '<%s: %s>' % (self.__class__.__name__, data) + if self.file: + output_file = self.file.name + else: + output_file = None + return '%s(%r, %s)' % (self.__class__.__name__, output_file, self.list) -- cgit v1.2.1 From 124f37c038f86eb6c3b1344150840b5fd2a1cdbd Mon Sep 17 00:00:00 2001 From: wiemann Date: Thu, 30 Sep 2004 13:47:59 +0000 Subject: setting footnote_references to "superscript" or "brackets" now causes footnote-reference-space to be trimmed or not, resp. git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@2681 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index 7e515070f..ed0a36543 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -463,6 +463,21 @@ def get_stylesheet_reference(settings, relative_to=None): else: return settings.stylesheet +def get_trim_footnote_ref_space(settings): + """ + Return whether or not to trim footnote space. + + If trim_footnote_reference_space is not None, return it. + + If trim_footnote_reference_space is None, return False unless the + footnote reference style is 'superscript'. + """ + if settings.trim_footnote_reference_space is None: + return hasattr(settings, 'footnote_references') and \ + settings.footnote_references == 'superscript' + else: + return settings.trim_footnote_reference_space + def get_source_line(node): """ Return the "source" and "line" attributes from the `node` given or from -- cgit v1.2.1 From f12819e3506c1c414747b811d21ebfaaedd8893f Mon Sep 17 00:00:00 2001 From: goodger Date: Sat, 6 Nov 2004 19:51:58 +0000 Subject: moved ``escape2null`` and ``unescape`` functions from docutils/parsers/rst/states.py git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@2815 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index ed0a36543..ccc6a4f20 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -489,6 +489,31 @@ def get_source_line(node): node = node.parent return None, None +def escape2null(text): + """Return a string with escape-backslashes converted to nulls.""" + parts = [] + start = 0 + while 1: + found = text.find('\\', start) + if found == -1: + parts.append(text[start:]) + return ''.join(parts) + parts.append(text[start:found]) + parts.append('\x00' + text[found+1:found+2]) + start = found + 2 # skip character after escape + +def unescape(text, restore_backslashes=0): + """ + Return a string with nulls removed or restored to backslashes. + Backslash-escaped spaces are also removed. + """ + if restore_backslashes: + return text.replace('\x00', '\\') + else: + for sep in ['\x00 ', '\x00\n', '\x00']: + text = ''.join(text.split(sep)) + return text + class DependencyList: -- cgit v1.2.1 From 1e6c8b451a03a5f4dfc4662505a42ef230f0b13b Mon Sep 17 00:00:00 2001 From: wiemann Date: Mon, 28 Mar 2005 12:40:55 +0000 Subject: made issuing debug-system_messages conditional git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@3143 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index ccc6a4f20..848e231fe 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -203,7 +203,8 @@ class Reporter: effect on the processing. Level-0 system messages are handled separately from the others. """ - return self.system_message(0, *args, **kwargs) + if self.categories[''].debug: + return self.system_message(0, *args, **kwargs) def info(self, *args, **kwargs): """ -- cgit v1.2.1 From a9cb01249ed3351c1e3ba36caa9fc45d0522b842 Mon Sep 17 00:00:00 2001 From: goodger Date: Tue, 5 Apr 2005 15:26:16 +0000 Subject: merged reporter-categories branch into trunk: removed docutils.utils.Reporter.categories, docutils.utils.ConditionSet, and all references to them, to simplify error reporting git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@3171 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 120 +++++++++++++++--------------------------------------- 1 file changed, 33 insertions(+), 87 deletions(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index 848e231fe..c61aedd4e 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -39,27 +39,14 @@ class Reporter: There is typically one Reporter object per process. A Reporter object is instantiated with thresholds for reporting (generating warnings) and halting processing (raising exceptions), a switch to turn debug output on - or off, and an I/O stream for warnings. These are stored in the default - reporting category, '' (zero-length string). - - Multiple reporting categories [#]_ may be set, each with its own reporting - and halting thresholds, debugging switch, and warning stream - (collectively a `ConditionSet`). Categories are hierarchical dotted-name - strings that look like attribute references: 'spam', 'spam.eggs', - 'neeeow.wum.ping'. The 'spam' category is the ancestor of - 'spam.bacon.eggs'. Unset categories inherit stored conditions from their - closest ancestor category that has been set. - - When a system message is generated, the stored conditions from its - category (or ancestor if unset) are retrieved. The system message level - is compared to the thresholds stored in the category, and a warning or - error is generated as appropriate. Debug messages are produced iff the - stored debug switch is on. Message output is sent to the stored warning - stream if not set to ''. - - The default category is '' (empty string). By convention, Writers should - retrieve reporting conditions from the 'writer' category (which, unless - explicitly set, defaults to the conditions of the default category). + or off, and an I/O stream for warnings. These are stored as instance + attributes. + + When a system message is generated, its level is compared to the stored + thresholds, and a warning or error is generated as appropriate. Debug + messages are produced iff the stored debug switch is on, independently of + other thresholds. Message output is sent to the stored warning stream if + not set to ''. The Reporter class also employs a modified form of the "Observer" pattern [GoF95]_ to track system messages generated. The `attach_observer` method @@ -67,9 +54,6 @@ class Reporter: accepts system messages. The observer can be removed with `detach_observer`, and another added in its place. - .. [#] The concept of "categories" was inspired by the log4j project: - http://jakarta.apache.org/log4j/. - .. [GoF95] Gamma, Helm, Johnson, Vlissides. *Design Patterns: Elements of Reusable Object-Oriented Software*. Addison-Wesley, Reading, MA, USA, 1995. @@ -81,10 +65,7 @@ class Reporter: def __init__(self, source, report_level, halt_level, stream=None, debug=0, encoding='ascii', error_handler='replace'): """ - Initialize the `ConditionSet` forthe `Reporter`'s default category. - :Parameters: - - `source`: The path to or description of the source data. - `report_level`: The level at or above which warning output will be sent to `stream`. @@ -101,6 +82,23 @@ class Reporter: self.source = source """The path to or description of the source data.""" + self.encoding = encoding + """The character encoding for the stderr output.""" + + self.error_handler = error_handler + """The character encoding error handler.""" + + self.debug_flag = debug + """Show debug (level=0) system messages?""" + + self.report_level = report_level + """The level at or above which warning output will be sent + to `self.stream`.""" + + self.halt_level = halt_level + """The level at or above which `SystemMessage` exceptions + will be raised, halting execution.""" + if stream is None: stream = sys.stderr elif type(stream) in (StringType, UnicodeType): @@ -111,15 +109,8 @@ class Reporter: elif type(stream) == UnicodeType: stream = open(stream.encode(), 'w') - self.encoding = encoding - """The character encoding for the stderr output.""" - - self.error_handler = error_handler - """The character encoding error handler.""" - - self.categories = {'': ConditionSet(debug, report_level, halt_level, - stream)} - """Mapping of category names to conditions. Default category is ''.""" + self.stream = stream + """Where warning output is sent.""" self.observers = [] """List of bound methods or functions to call with each system_message @@ -128,26 +119,6 @@ class Reporter: self.max_level = -1 """The highest level system message generated so far.""" - def set_conditions(self, category, report_level, halt_level, - stream=None, debug=0): - if stream is None: - stream = sys.stderr - self.categories[category] = ConditionSet(debug, report_level, - halt_level, stream) - - def unset_conditions(self, category): - if category and self.categories.has_key(category): - del self.categories[category] - - __delitem__ = unset_conditions - - def get_conditions(self, category): - while not self.categories.has_key(category): - category = category[:category.rfind('.') + 1][:-1] - return self.categories[category] - - __getitem__ = get_conditions - def attach_observer(self, observer): """ The `observer` parameter is a function or bound method which takes one @@ -169,9 +140,6 @@ class Reporter: Raise an exception or generate a warning if appropriate. """ attributes = kwargs.copy() - category = kwargs.get('category', '') - if kwargs.has_key('category'): - del attributes['category'] if kwargs.has_key('base_node'): source, line = get_source_line(kwargs['base_node']) del attributes['base_node'] @@ -183,16 +151,13 @@ class Reporter: msg = nodes.system_message(message, level=level, type=self.levels[level], *children, **attributes) - debug, report_level, halt_level, stream = self[category].astuple() - if (level >= report_level or debug and level == 0) and stream: + if self.stream and (level >= self.report_level + or self.debug_flag and level == 0): msgtext = msg.astext().encode(self.encoding, self.error_handler) - if category: - print >>stream, msgtext, '[%s]' % category - else: - print >>stream, msgtext - if level >= halt_level: + print >>self.stream, msgtext + if level >= self.halt_level: raise SystemMessage(msg, level) - if level > 0 or debug: + if level > 0 or self.debug_flag: self.notify_observers(msg) self.max_level = max(level, self.max_level) return msg @@ -203,7 +168,7 @@ class Reporter: effect on the processing. Level-0 system messages are handled separately from the others. """ - if self.categories[''].debug: + if self.debug_flag: return self.system_message(0, *args, **kwargs) def info(self, *args, **kwargs): @@ -236,25 +201,6 @@ class Reporter: return self.system_message(4, *args, **kwargs) -class ConditionSet: - - """ - A set of two thresholds (`report_level` & `halt_level`), a switch - (`debug`), and an I/O stream (`stream`), corresponding to one `Reporter` - category. - """ - - def __init__(self, debug, report_level, halt_level, stream): - self.debug = debug - self.report_level = report_level - self.halt_level = halt_level - self.stream = stream - - def astuple(self): - return (self.debug, self.report_level, self.halt_level, - self.stream) - - class ExtensionOptionError(DataError): pass class BadOptionError(ExtensionOptionError): pass class BadOptionDataError(ExtensionOptionError): pass -- cgit v1.2.1 From 615d45718520914eb81f6436f9f2e418574b7e19 Mon Sep 17 00:00:00 2001 From: goodger Date: Sat, 16 Apr 2005 20:29:01 +0000 Subject: restored utils.Reporter.set_conditions (with deprecation warning) for compatibility git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@3223 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index c61aedd4e..674769815 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -13,6 +13,7 @@ __docformat__ = 'reStructuredText' import sys import os import os.path +import warnings from types import StringType, UnicodeType from docutils import ApplicationError, DataError from docutils import frontend, nodes @@ -119,6 +120,17 @@ class Reporter: self.max_level = -1 """The highest level system message generated so far.""" + def set_conditions(self, category, report_level, halt_level, + stream=None, debug=0): + warnings.warn('set attributes via configuration settings or directly', + DeprecationWarning, stacklevel=2) + self.report_level = report_level + self.halt_level = halt_level + if stream is None: + stream = sys.stderr + self.stream = stream + self.debug = debug + def attach_observer(self, observer): """ The `observer` parameter is a function or bound method which takes one -- cgit v1.2.1 From 23aec339aa4a72e246cfa3488b5bdd5a0def5969 Mon Sep 17 00:00:00 2001 From: goodger Date: Sun, 17 Apr 2005 03:10:05 +0000 Subject: clarified warning git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@3227 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index 674769815..b763c7c02 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -122,7 +122,8 @@ class Reporter: def set_conditions(self, category, report_level, halt_level, stream=None, debug=0): - warnings.warn('set attributes via configuration settings or directly', + warnings.warn('docutils.utils.Reporter.set_condition deprecated; ' + 'set attributes via configuration settings or directly', DeprecationWarning, stacklevel=2) self.report_level = report_level self.halt_level = halt_level -- cgit v1.2.1 From 40ccd0d9f29e9fb5a6eef4bc0b437ef1a4f8273a Mon Sep 17 00:00:00 2001 From: wiemann Date: Thu, 21 Apr 2005 16:18:45 +0000 Subject: typo git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@3235 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index b763c7c02..aeb882485 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -122,7 +122,7 @@ class Reporter: def set_conditions(self, category, report_level, halt_level, stream=None, debug=0): - warnings.warn('docutils.utils.Reporter.set_condition deprecated; ' + warnings.warn('docutils.utils.Reporter.set_conditions deprecated; ' 'set attributes via configuration settings or directly', DeprecationWarning, stacklevel=2) self.report_level = report_level -- cgit v1.2.1 From 3da860aec26788ffd148bdbbedeee98b53a1436a Mon Sep 17 00:00:00 2001 From: wiemann Date: Mon, 25 Apr 2005 15:08:01 +0000 Subject: str(Exception) doesn't work for anything but ASCII Exception texts, so '%s' % exception_instance is unsafe unless exception_instance.args contains only byte strings. The change in alltests.py is a first attempt to catch such cases where a str(Exception) is done with an Exception text which is not necessarily ASCII-only (i.e. with a unicode string in Exception.args), but since most input data (in the totest dicts) is passed in as byte strings, it doesn't catch much. git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@3253 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index aeb882485..a28b5326d 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -306,7 +306,7 @@ def assemble_option_dict(option_list, options_spec): options[name] = convertor(value) except (ValueError, TypeError), detail: raise detail.__class__('(option: "%s"; value: %r)\n%s' - % (name, value, detail)) + % (name, value, ' '.join(detail.args))) return options -- cgit v1.2.1 From d412180dc51d316654dce051ff669022a07dabc7 Mon Sep 17 00:00:00 2001 From: wiemann Date: Sun, 29 May 2005 07:58:10 +0000 Subject: applied patch to fix broken set_conditions method; closing https://sourceforge.net/tracker/?func=detail&atid=422030&aid=1210637&group_id=38414 git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@3408 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index a28b5326d..1d77d38d8 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -130,7 +130,7 @@ class Reporter: if stream is None: stream = sys.stderr self.stream = stream - self.debug = debug + self.debug_flag = debug def attach_observer(self, observer): """ -- cgit v1.2.1 From 835cd6732507e8e4c76b0ef437bcc74177a9d174 Mon Sep 17 00:00:00 2001 From: wiemann Date: Sun, 26 Jun 2005 22:20:27 +0000 Subject: merge trunk/docutils@3525 branches/blais_interrupt_render/docutils@HEAD trunk/docutils git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@3581 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index 1d77d38d8..cb018bd55 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -80,6 +80,7 @@ class Reporter: - `encoding`: The encoding for stderr output. - `error_handler`: The error handler for stderr output encoding. """ + self.source = source """The path to or description of the source data.""" @@ -357,7 +358,24 @@ def extract_name_value(line): attlist.append((attname.lower(), data)) return attlist -def new_document(source, settings=None): +def new_reporter(source_path, settings): + """ + Return a new Reporter object. + + :Parameters: + `source` : string + The path to or description of the source text of the document. + `settings` : optparse.Values object + Runtime settings. If none provided, a default set will be used. + """ + reporter = Reporter( + source_path, settings.report_level, settings.halt_level, + stream=settings.warning_stream, debug=settings.debug, + encoding=settings.error_encoding, + error_handler=settings.error_encoding_error_handler) + return reporter + +def new_document(source_path, settings=None): """ Return a new empty document object. @@ -369,12 +387,9 @@ def new_document(source, settings=None): """ if settings is None: settings = frontend.OptionParser().get_default_values() - reporter = Reporter(source, settings.report_level, settings.halt_level, - stream=settings.warning_stream, debug=settings.debug, - encoding=settings.error_encoding, - error_handler=settings.error_encoding_error_handler) - document = nodes.document(settings, reporter, source=source) - document.note_source(source, -1) + reporter = new_reporter(source_path, settings) + document = nodes.document(settings, reporter, source=source_path) + document.note_source(source_path, -1) return document def clean_rcs_keywords(paragraph, keyword_substitutions): -- cgit v1.2.1 From 225cfed60f15481726d5a3d68beb3383e4a52a7a Mon Sep 17 00:00:00 2001 From: wiemann Date: Mon, 27 Jun 2005 01:13:51 +0000 Subject: fixed some docstrings git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@3592 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index cb018bd55..100f8671d 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -366,7 +366,7 @@ def new_reporter(source_path, settings): `source` : string The path to or description of the source text of the document. `settings` : optparse.Values object - Runtime settings. If none provided, a default set will be used. + Runtime settings. """ reporter = Reporter( source_path, settings.report_level, settings.halt_level, -- cgit v1.2.1 From e571eb6f3616063e8cc1096b3451aa6f3e659858 Mon Sep 17 00:00:00 2001 From: goodger Date: Wed, 7 Dec 2005 23:46:30 +0000 Subject: added East Asian double-width character support; thanks to Frank Bennett for inspiration on ``docutils.utils.east_asian_column_width()`` git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@4152 929543f6-e4f2-0310-98a6-ba3bd3dd1d04 --- docutils/utils.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'docutils/utils.py') diff --git a/docutils/utils.py b/docutils/utils.py index 100f8671d..24c4986f0 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -13,7 +13,9 @@ __docformat__ = 'reStructuredText' import sys import os import os.path +import types import warnings +import unicodedata from types import StringType, UnicodeType from docutils import ApplicationError, DataError from docutils import frontend, nodes @@ -489,6 +491,30 @@ def unescape(text, restore_backslashes=0): text = ''.join(text.split(sep)) return text +east_asian_widths = {'W': 2, # Wide + 'F': 2, # Full-width (wide) + 'Na': 1, # Narrow + 'H': 1, # Half-width (narrow) + 'N': 1, # Neutral (not East Asian, treated as narrow) + 'A': 1} # Ambiguous (s/b wide in East Asian context, + # narrow otherwise, but that doesn't work) +"""Mapping of result codes from `unicodedata.east_asian_width()` to character +column widths.""" + +def east_asian_column_width(text): + if isinstance(text, types.UnicodeType): + total = 0 + for c in text: + total += east_asian_widths[unicodedata.east_asian_width(c)] + return total + else: + return len(text) + +if hasattr(unicodedata, 'east_asian_width'): + column_width = east_asian_column_width +else: + column_width = len + class DependencyList: -- cgit v1.2.1