summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgoodger <goodger@929543f6-e4f2-0310-98a6-ba3bd3dd1d04>2005-04-03 19:53:28 +0000
committergoodger <goodger@929543f6-e4f2-0310-98a6-ba3bd3dd1d04>2005-04-03 19:53:28 +0000
commitdeaa2766e465759d6170e365bb5138efc46aeda7 (patch)
tree786964b62a8275838cc9424422c7d8df61f76aab
parent57bf55dd3cd2653736fe9e1b90c2ffab7a5a91d7 (diff)
downloaddocutils-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.py20
-rw-r--r--docutils/parsers/rst/__init__.py3
-rw-r--r--docutils/transforms/universal.py4
-rw-r--r--docutils/utils.py120
-rw-r--r--docutils/writers/html4css1.py2
-rw-r--r--docutils/writers/latex2e.py2
-rwxr-xr-xtest/test_utils.py81
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):