diff options
author | goodger <goodger@929543f6-e4f2-0310-98a6-ba3bd3dd1d04> | 2005-04-03 19:53:28 +0000 |
---|---|---|
committer | goodger <goodger@929543f6-e4f2-0310-98a6-ba3bd3dd1d04> | 2005-04-03 19:53:28 +0000 |
commit | deaa2766e465759d6170e365bb5138efc46aeda7 (patch) | |
tree | 786964b62a8275838cc9424422c7d8df61f76aab | |
parent | 57bf55dd3cd2653736fe9e1b90c2ffab7a5a91d7 (diff) | |
download | docutils-reporter-categories.tar.gz |
removed docutils.utils.Reporter.categories, docutils.utils.ConditionSet, and all references to them, to simplify error reportingreporter-categories
git-svn-id: http://svn.code.sf.net/p/docutils/code/branches/reporter-categories@3163 929543f6-e4f2-0310-98a6-ba3bd3dd1d04
-rw-r--r-- | docutils/nodes.py | 20 | ||||
-rw-r--r-- | docutils/parsers/rst/__init__.py | 3 | ||||
-rw-r--r-- | docutils/transforms/universal.py | 4 | ||||
-rw-r--r-- | docutils/utils.py | 120 | ||||
-rw-r--r-- | docutils/writers/html4css1.py | 2 | ||||
-rw-r--r-- | docutils/writers/latex2e.py | 2 | ||||
-rwxr-xr-x | test/test_utils.py | 81 |
7 files changed, 48 insertions, 184 deletions
diff --git a/docutils/nodes.py b/docutils/nodes.py index d347d9dda..e6bb52fac 100644 --- a/docutils/nodes.py +++ b/docutils/nodes.py @@ -111,8 +111,8 @@ class Node: ``visit`` implementation for each `Node` subclass encountered. """ visitor.document.reporter.debug( - 'calling dispatch_visit for %s' % self.__class__.__name__, - category='nodes.Node.walk') + 'docutils.nodes.Node.walk calling dispatch_visit for %s' + % self.__class__.__name__) try: visitor.dispatch_visit(self) except (SkipChildren, SkipNode): @@ -138,8 +138,8 @@ class Node: """ call_depart = 1 visitor.document.reporter.debug( - 'calling dispatch_visit for %s' % self.__class__.__name__, - category='nodes.Node.walkabout') + 'docutils.nodes.Node.walkabout calling dispatch_visit for %s' + % self.__class__.__name__) try: try: visitor.dispatch_visit(self) @@ -157,8 +157,8 @@ class Node: pass if call_depart: visitor.document.reporter.debug( - 'calling dispatch_departure for %s' % self.__class__.__name__, - category='nodes.Node.walkabout') + 'docutils.nodes.Node.walkabout calling dispatch_departure ' + 'for %s' % self.__class__.__name__) visitor.dispatch_departure(self) def traverse(self, condition=None, @@ -1409,8 +1409,8 @@ class NodeVisitor: node_name = node.__class__.__name__ method = getattr(self, 'visit_' + node_name, self.unknown_visit) self.document.reporter.debug( - 'calling %s for %s' % (method.__name__, node_name), - category='nodes.NodeVisitor.dispatch_visit') + 'docutils.nodes.NodeVisitor.dispatch_visit calling %s for %s' + % (method.__name__, node_name)) return method(node) def dispatch_departure(self, node): @@ -1422,8 +1422,8 @@ class NodeVisitor: node_name = node.__class__.__name__ method = getattr(self, 'depart_' + node_name, self.unknown_departure) self.document.reporter.debug( - 'calling %s for %s' % (method.__name__, node_name), - category='nodes.NodeVisitor.dispatch_departure') + 'docutils.nodes.NodeVisitor.dispatch_departure calling %s for %s' + % (method.__name__, node_name)) return method(node) def unknown_visit(self, node): diff --git a/docutils/parsers/rst/__init__.py b/docutils/parsers/rst/__init__.py index 8d7935be6..30825d7c4 100644 --- a/docutils/parsers/rst/__init__.py +++ b/docutils/parsers/rst/__init__.py @@ -144,11 +144,10 @@ class Parser(docutils.parsers.Parser): def parse(self, inputstring, document): """Parse `inputstring` and populate `document`, a document tree.""" self.setup_parse(inputstring, document) - debug = document.reporter[''].debug self.statemachine = states.RSTStateMachine( state_classes=self.state_classes, initial_state=self.initial_state, - debug=debug) + debug=document.reporter.debug_flag) inputlines = docutils.statemachine.string2lines( inputstring, tab_width=document.settings.tab_width, convert_whitespace=1) diff --git a/docutils/transforms/universal.py b/docutils/transforms/universal.py index 7d8a796cc..c77d72df8 100644 --- a/docutils/transforms/universal.py +++ b/docutils/transforms/universal.py @@ -97,7 +97,7 @@ class Messages(Transform): def apply(self): unfiltered = self.document.transform_messages - threshold = self.document.reporter['writer'].report_level + threshold = self.document.reporter.report_level messages = [] for msg in unfiltered: if msg['level'] >= threshold and not msg.parent: @@ -130,7 +130,7 @@ class SystemMessageFilterVisitor(nodes.SparseNodeVisitor): pass def visit_system_message(self, node): - if node['level'] < self.document.reporter['writer'].report_level: + if node['level'] < self.document.reporter.report_level: node.parent.remove(node) 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 diff --git a/docutils/writers/html4css1.py b/docutils/writers/html4css1.py index 4736f54e0..05dc1c12c 100644 --- a/docutils/writers/html4css1.py +++ b/docutils/writers/html4css1.py @@ -1162,7 +1162,7 @@ class HTMLTranslator(nodes.NodeVisitor): self.body.append('</sup>') def visit_system_message(self, node): - if node['level'] < self.document.reporter['writer'].report_level: + if node['level'] < self.document.reporter.report_level: # Level is too low to display: raise nodes.SkipNode self.body.append(self.starttag(node, 'div', CLASS='system-message')) diff --git a/docutils/writers/latex2e.py b/docutils/writers/latex2e.py index 1a488d88d..f756f1e39 100644 --- a/docutils/writers/latex2e.py +++ b/docutils/writers/latex2e.py @@ -1822,7 +1822,7 @@ class LaTeXTranslator(nodes.NodeVisitor): self.body.append(self.context.pop()) def visit_system_message(self, node): - if node['level'] < self.document.reporter['writer'].report_level: + if node['level'] < self.document.reporter.report_level: raise nodes.SkipNode def depart_system_message(self, node): diff --git a/test/test_utils.py b/test/test_utils.py index 7077757ba..006495ac9 100755 --- a/test/test_utils.py +++ b/test/test_utils.py @@ -123,87 +123,6 @@ class QuietReporterTests(unittest.TestCase): self.assertEquals(self.stream.getvalue(), '') -class ReporterCategoryTests(unittest.TestCase): - - stream = StringIO.StringIO() - - def setUp(self): - self.stream.seek(0) - self.stream.truncate() - self.reporter = utils.Reporter('test data', 2, 4, self.stream, 1) - self.reporter.set_conditions('lemon', 1, 3, self.stream, 0) - - def test_getset(self): - self.reporter.set_conditions('test', 5, 5, None, 0) - self.assertEquals(self.reporter.get_conditions('other').astuple(), - (1, 2, 4, self.stream)) - self.assertEquals(self.reporter.get_conditions('test').astuple(), - (0, 5, 5, sys.stderr)) - self.assertEquals(self.reporter.get_conditions('test.dummy').astuple(), - (0, 5, 5, sys.stderr)) - self.reporter.set_conditions('test.dummy.spam', 1, 2, self.stream, 1) - self.assertEquals( - self.reporter.get_conditions('test.dummy.spam').astuple(), - (1, 1, 2, self.stream)) - self.assertEquals(self.reporter.get_conditions('test.dummy').astuple(), - (0, 5, 5, sys.stderr)) - self.assertEquals( - self.reporter.get_conditions('test.dummy.spam.eggs').astuple(), - (1, 1, 2, self.stream)) - self.reporter.unset_conditions('test.dummy.spam') - self.assertEquals( - self.reporter.get_conditions('test.dummy.spam.eggs').astuple(), - (0, 5, 5, sys.stderr)) - - def test_debug(self): - sw = self.reporter.debug('debug output', category='lemon.curry') - self.assertEquals(self.stream.getvalue(), '') - sw = self.reporter.debug('debug output') - self.assertEquals(self.stream.getvalue(), - 'test data:: (DEBUG/0) debug output\n') - - def test_info(self): - sw = self.reporter.info('some info') - self.assertEquals(self.stream.getvalue(), '') - sw = self.reporter.info('some info', category='lemon.curry') - self.assertEquals( - self.stream.getvalue(), - 'test data:: (INFO/1) some info [lemon.curry]\n') - - def test_warning(self): - sw = self.reporter.warning('a warning') - self.assertEquals(self.stream.getvalue(), - 'test data:: (WARNING/2) a warning\n') - sw = self.reporter.warning('a warning', category='lemon.curry') - self.assertEquals(self.stream.getvalue(), """\ -test data:: (WARNING/2) a warning -test data:: (WARNING/2) a warning [lemon.curry] -""") - - def test_error(self): - sw = self.reporter.error('an error') - self.assertEquals(self.stream.getvalue(), - 'test data:: (ERROR/3) an error\n') - self.assertRaises(utils.SystemMessage, self.reporter.error, - 'an error', category='lemon.curry') - self.assertEquals(self.stream.getvalue(), """\ -test data:: (ERROR/3) an error -test data:: (ERROR/3) an error [lemon.curry] -""") - - def test_severe(self): - self.assertRaises(utils.SystemMessage, self.reporter.severe, - 'a severe error') - self.assertEquals(self.stream.getvalue(), - 'test data:: (SEVERE/4) a severe error\n') - self.assertRaises(utils.SystemMessage, self.reporter.severe, - 'a severe error', category='lemon.curry') - self.assertEquals(self.stream.getvalue(), """\ -test data:: (SEVERE/4) a severe error -test data:: (SEVERE/4) a severe error [lemon.curry] -""") - - class NameValueTests(unittest.TestCase): def test_extract_name_value(self): |