From 8bc4135947d9a2fc1749ebc4a8cdbd4d72d7a74e Mon Sep 17 00:00:00 2001 From: Craig de Stigter Date: Mon, 18 Apr 2011 16:51:12 +1200 Subject: sane logging. remove sys.exit() calls (libraries should never ever call sys.exit()) and raise appropriate exceptions instead. backwards incompatible insofar as custom extensions may need tweaks if they're using old markdown logging (but they shouldn't, it was gross) --- markdown/__init__.py | 42 +++++++++++++++++++---------------------- markdown/blockprocessors.py | 5 ++--- markdown/commandline.py | 9 +++++---- markdown/etree_loader.py | 12 +++--------- markdown/extensions/__init__.py | 3 --- markdown/extensions/headerid.py | 4 +--- markdown/md_logging.py | 36 ----------------------------------- 7 files changed, 30 insertions(+), 81 deletions(-) delete mode 100644 markdown/md_logging.py diff --git a/markdown/__init__.py b/markdown/__init__.py index 0774174..b397f1b 100644 --- a/markdown/__init__.py +++ b/markdown/__init__.py @@ -35,8 +35,7 @@ version_info = (2,1,0, "Dev") import re import codecs -from logging import DEBUG, INFO, WARN, ERROR, CRITICAL -from md_logging import message +import logging import util from preprocessors import build_preprocessors from blockprocessors import build_block_parser @@ -49,7 +48,10 @@ import html4 # For backwards compatibility in the 2.0.x series # The things defined in these modules started off in __init__.py so third # party code might need to access them here. -from util import * +#from util import * + + +logger = logging.getLogger('MARKDOWN') class Markdown: @@ -139,13 +141,10 @@ class Markdown: if isinstance(ext, basestring): ext = self.build_extension(ext, configs.get(ext, [])) if isinstance(ext, Extension): - try: - ext.extendMarkdown(self, globals()) - except NotImplementedError, e: - message(ERROR, e) + # might raise NotImplementedError, but that's the extension author's problem + ext.extendMarkdown(self, globals()) else: - message(ERROR, - 'Extension "%s.%s" must be of type: "markdown.Extension".' \ + raise ValueError('Extension "%s.%s" must be of type: "markdown.Extension".' \ % (ext.__class__.__module__, ext.__class__.__name__)) return self @@ -179,17 +178,18 @@ class Markdown: try: # Old style (mdx_) module = __import__(module_name_old_style) except ImportError: - message(WARN, "Failed loading extension '%s' from '%s' or '%s'" - % (ext_name, module_name_new_style, module_name_old_style)) - # Return None so we don't try to initiate none-existant extension - return None + logger.warn("Failed loading extension '%s' from '%s' or '%s'" + % (ext_name, module_name_new_style, module_name_old_style)) + # Return None so we don't try to initiate none-existant extension + return None # If the module is loaded successfully, we expect it to define a # function called makeExtension() try: return module.makeExtension(configs.items()) except AttributeError, e: - message(CRITICAL, "Failed to initiate extension '%s': %s" % (ext_name, e)) + logger.warn("Failed to initiate extension '%s': %s" % (ext_name, e)) + return None def registerExtension(self, extension): """ This gets called by the extension """ @@ -214,8 +214,7 @@ class Markdown: try: self.serializer = self.output_formats[format.lower()] except KeyError: - message(CRITICAL, - 'Invalid Output Format: "%s". Use one of %s.' \ + raise KeyError('Invalid Output Format: "%s". Use one of %s.' \ % (format, self.output_formats.keys())) return self @@ -244,12 +243,9 @@ class Markdown: # Fixup the source text if not source.strip(): return u"" # a blank unicode string - try: - source = unicode(source) - except UnicodeDecodeError: - message(CRITICAL, - 'UnicodeDecodeError: Markdown only accepts unicode or ascii input.') - return u"" + + # if this raises UnicodeDecodeError, that's the caller's fault. + source = unicode(source) source = source.replace(util.STX, "").replace(util.ETX, "") source = source.replace("\r\n", "\n").replace("\r", "\n") + "\n\n" @@ -283,7 +279,7 @@ class Markdown: output = '' else: # We have a serious problem - message(CRITICAL, 'Failed to strip top level tags.') + raise ValueError('Markdown failed to strip top-level tags. Document=%r' % output.strip()) # Run the text post-processors for pp in self.postprocessors.values(): diff --git a/markdown/blockprocessors.py b/markdown/blockprocessors.py index 77fbc71..10a0177 100644 --- a/markdown/blockprocessors.py +++ b/markdown/blockprocessors.py @@ -15,8 +15,7 @@ as they need to alter how markdown blocks are parsed. import re import util from blockparser import BlockParser -from logging import CRITICAL -from md_logging import message +from markdown import logger def build_block_parser(md_instance, **kwargs): @@ -408,7 +407,7 @@ class HashHeaderProcessor(BlockProcessor): blocks.insert(0, after) else: # This should never happen, but just in case... - message(CRITICAL, "We've got a problem header!") + logger.warn("We've got a problem header: %r" % block) class SetextHeaderProcessor(BlockProcessor): diff --git a/markdown/commandline.py b/markdown/commandline.py index 049d2be..eab23bb 100644 --- a/markdown/commandline.py +++ b/markdown/commandline.py @@ -7,8 +7,9 @@ COMMAND-LINE SPECIFIC STUFF import markdown import sys import optparse -import logging -from logging import DEBUG, INFO, WARN, ERROR, CRITICAL +from logging import DEBUG, INFO, CRITICAL + +from markdown import logger # default logging level for command-line use COMMAND_LINE_LOGGING_LEVEL = CRITICAL @@ -69,8 +70,8 @@ def run(): # Parse options and adjust logging level if necessary options, logging_level = parse_options() - if not options: sys.exit(0) - if logging_level: logging.getLogger('MARKDOWN').setLevel(logging_level) + if not options: sys.exit(2) + if logging_level: logger.setLevel(logging_level) # Run markdown.markdownFromFile(**options) diff --git a/markdown/etree_loader.py b/markdown/etree_loader.py index 64966b5..60719d8 100644 --- a/markdown/etree_loader.py +++ b/markdown/etree_loader.py @@ -1,6 +1,3 @@ -from logging import CRITICAL -from md_logging import message -import sys ## Import def importETree(): @@ -20,18 +17,15 @@ def importETree(): try: # An earlier version of Python with Python ElementTree? import elementtree.ElementTree as etree except ImportError: - message(CRITICAL, "Failed to import ElementTree") - sys.exit(1) + raise ImportError("Failed to import ElementTree") if etree_in_c: if etree_in_c.VERSION < "1.0": - message(CRITICAL, "cElementTree version 1.0 or higher is required.") - sys.exit(1) + raise RuntimeError("cElementTree version 1.0 or higher is required.") # Third party serializers (including ours) test with non-c Comment etree_in_c.test_comment = Comment return etree_in_c elif etree.VERSION < "1.1": - message(CRITICAL, "ElementTree version 1.1 or higher is required") - sys.exit(1) + raise RuntimeError("ElementTree version 1.1 or higher is required") else: return etree diff --git a/markdown/extensions/__init__.py b/markdown/extensions/__init__.py index 1cc4762..4c1dcba 100644 --- a/markdown/extensions/__init__.py +++ b/markdown/extensions/__init__.py @@ -1,6 +1,3 @@ -from markdown.md_logging import message -from logging import DEBUG, INFO, WARN, ERROR, CRITICAL - """ Extensions ----------------------------------------------------------------------------- diff --git a/markdown/extensions/headerid.py b/markdown/extensions/headerid.py index 5e9793e..6d64a43 100644 --- a/markdown/extensions/headerid.py +++ b/markdown/extensions/headerid.py @@ -67,8 +67,6 @@ Dependencies: import markdown from markdown.util import etree -from logging import CRITICAL -from markdown.md_logging import message import re from string import ascii_lowercase, digits, punctuation @@ -121,7 +119,7 @@ class HeaderIdProcessor(markdown.blockprocessors.BlockProcessor): blocks.insert(0, after) else: # This should never happen, but just in case... - message(CRITICAL, "We've got a problem header!") + raise ValueError("Encountered a problem header: %r" % block) def _get_meta(self): """ Return meta data suported by this ext as a tuple """ diff --git a/markdown/md_logging.py b/markdown/md_logging.py deleted file mode 100644 index 463be15..0000000 --- a/markdown/md_logging.py +++ /dev/null @@ -1,36 +0,0 @@ -# -*- coding: utf-8 -*- -import logging -from logging import DEBUG, INFO, WARN, ERROR, CRITICAL -import sys -import warnings - -# -# Exceptions -# - -class MarkdownException(Exception): - """ A Markdown Exception. """ - pass - - -class MarkdownWarning(Warning): - """ A Markdown Warning. """ - pass - - -# -# Global functions -# - -def message(level, text): - """ A wrapper method for logging debug messages. """ - logger = logging.getLogger('MARKDOWN') - if logger.handlers: - # The logger is configured - logger.log(level, text) - if level > WARN: - sys.exit(0) - elif level > WARN: - raise MarkdownException, text - else: - warnings.warn(text, MarkdownWarning) \ No newline at end of file -- cgit v1.2.3 From d2bb675211be2470a34cb62e36016c5171e6a20a Mon Sep 17 00:00:00 2001 From: Craig de Stigter Date: Mon, 18 Apr 2011 16:55:59 +1200 Subject: fix import loop when importing logger --- markdown/__init__.py | 3 +-- markdown/blockprocessors.py | 4 +++- markdown/commandline.py | 4 +++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/markdown/__init__.py b/markdown/__init__.py index b397f1b..0ca0509 100644 --- a/markdown/__init__.py +++ b/markdown/__init__.py @@ -48,8 +48,7 @@ import html4 # For backwards compatibility in the 2.0.x series # The things defined in these modules started off in __init__.py so third # party code might need to access them here. -#from util import * - +from util import * logger = logging.getLogger('MARKDOWN') diff --git a/markdown/blockprocessors.py b/markdown/blockprocessors.py index 10a0177..2f15578 100644 --- a/markdown/blockprocessors.py +++ b/markdown/blockprocessors.py @@ -12,10 +12,12 @@ as they need to alter how markdown blocks are parsed. """ +import logging import re import util from blockparser import BlockParser -from markdown import logger + +logger = logging.getLogger('MARKDOWN') def build_block_parser(md_instance, **kwargs): diff --git a/markdown/commandline.py b/markdown/commandline.py index eab23bb..3f2e009 100644 --- a/markdown/commandline.py +++ b/markdown/commandline.py @@ -7,9 +7,11 @@ COMMAND-LINE SPECIFIC STUFF import markdown import sys import optparse + +import logging from logging import DEBUG, INFO, CRITICAL -from markdown import logger +logger = logging.getLogger('MARKDOWN') # default logging level for command-line use COMMAND_LINE_LOGGING_LEVEL = CRITICAL -- cgit v1.2.3 From f87713c85d8c895dc15cf78c99673efce371a056 Mon Sep 17 00:00:00 2001 From: Waylan Limberg Date: Thu, 28 Apr 2011 20:40:05 -0400 Subject: Update tests for logging changes. No more message function. --- tests/test_apis.py | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/tests/test_apis.py b/tests/test_apis.py index ebbc24f..eecfbf6 100644 --- a/tests/test_apis.py +++ b/tests/test_apis.py @@ -13,8 +13,6 @@ import os import sys import types import markdown -from markdown.md_logging import MarkdownException, MarkdownWarning -from logging import DEBUG, INFO, WARN, ERROR, CRITICAL import warnings class TestMarkdownBasics(unittest.TestCase): @@ -226,47 +224,34 @@ class TestErrors(unittest.TestCase): # Reset warning behavior back to default warnings.simplefilter('default') - def testMessageWarn(self): - """ Test message WARN. """ - self.assertRaises(MarkdownWarning, markdown.md_logging.message, - WARN, 'This should raise a MardownWarning') - - def testMessageError(self): - """ Test message ERROR. """ - self.assertRaises(MarkdownException, markdown.md_logging.message, - ERROR, 'This should raise a MarkdownException') - def testNonUnicodeSource(self): """ Test falure on non-unicode source text. """ source = "foo".encode('utf-16') - self.assertRaises(MarkdownException, markdown.markdown, source) + self.assertRaises(UnicodeDecodeError, markdown.markdown, source) def testBadOutputFormat(self): """ Test failure on bad output_format. """ - self.assertRaises(MarkdownException, - markdown.Markdown, output_format='invalid') + self.assertRaises(KeyError, markdown.Markdown, output_format='invalid') def testLoadExtensionFailure(self): """ Test failure of an extension to load. """ - self.assertRaises(MarkdownWarning, + self.assertRaises(ValueError, markdown.Markdown, extensions=['non_existant_ext']) def testLoadBadExtension(self): """ Test loading of an Extension with no makeExtension function. """ _create_fake_extension(name='fake', has_factory_func=False) - self.assertRaises(MarkdownException, - markdown.Markdown, extensions=['fake']) + self.assertRaises(ValueError, markdown.Markdown, extensions=['fake']) def testNonExtension(self): """ Test loading a non Extension object as an extension. """ _create_fake_extension(name='fake', is_wrong_type=True) - self.assertRaises(MarkdownException, - markdown.Markdown, extensions=['fake']) + self.assertRaises(ValueError, markdown.Markdown, extensions=['fake']) def testBaseExtention(self): """ Test that the base Extension class will raise NotImplemented. """ _create_fake_extension(name='fake') - self.assertRaises(MarkdownException, + self.assertRaises(NotImplementedError, markdown.Markdown, extensions=['fake']) -- cgit v1.2.3 From 8c46de40ce949971c3a887f5ff9bf0da1a610d22 Mon Sep 17 00:00:00 2001 From: Waylan Limberg Date: Thu, 28 Apr 2011 21:39:30 -0400 Subject: Restored custom error message on UnicodeDecodeError. Otherwise we will be getting bug reports all the time. --- markdown/__init__.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/markdown/__init__.py b/markdown/__init__.py index 0ca0509..2bc7061 100644 --- a/markdown/__init__.py +++ b/markdown/__init__.py @@ -243,8 +243,12 @@ class Markdown: if not source.strip(): return u"" # a blank unicode string - # if this raises UnicodeDecodeError, that's the caller's fault. - source = unicode(source) + try: + source = unicode(source) + except UnicodeDecodeError, e: + # Customise error message while maintaining original trackback + e.reason += '. -- Note: Markdown only accepts unicode input!' + raise source = source.replace(util.STX, "").replace(util.ETX, "") source = source.replace("\r\n", "\n").replace("\r", "\n") + "\n\n" -- cgit v1.2.3 From c042da8ab693f981f4e0a2b0bded23a55b3b923f Mon Sep 17 00:00:00 2001 From: Waylan Limberg Date: Thu, 28 Apr 2011 21:48:42 -0400 Subject: Corrected behavior of headerid extension to match default behavior when "Weve got a problem header". We log a warning - not raise an exception. --- markdown/extensions/headerid.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/markdown/extensions/headerid.py b/markdown/extensions/headerid.py index 6d64a43..390a8ba 100644 --- a/markdown/extensions/headerid.py +++ b/markdown/extensions/headerid.py @@ -69,6 +69,9 @@ import markdown from markdown.util import etree import re from string import ascii_lowercase, digits, punctuation +import logging + +logger = logging.getLogger('MARKDOWN') ID_CHARS = ascii_lowercase + digits + '-_' IDCOUNT_RE = re.compile(r'^(.*)_([0-9]+)$') @@ -119,7 +122,7 @@ class HeaderIdProcessor(markdown.blockprocessors.BlockProcessor): blocks.insert(0, after) else: # This should never happen, but just in case... - raise ValueError("Encountered a problem header: %r" % block) + logger.warn("We've got a problem header: %r" % block) def _get_meta(self): """ Return meta data suported by this ext as a tuple """ -- cgit v1.2.3 From 54bb52137a795c8594690744e025558df397ba19 Mon Sep 17 00:00:00 2001 From: Waylan Limberg Date: Mon, 25 Apr 2011 22:12:24 -0400 Subject: Correctly specify minimum version of cElementTree. Fixes #5. --- markdown/etree_loader.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/markdown/etree_loader.py b/markdown/etree_loader.py index 60719d8..f605aa2 100644 --- a/markdown/etree_loader.py +++ b/markdown/etree_loader.py @@ -19,8 +19,8 @@ def importETree(): except ImportError: raise ImportError("Failed to import ElementTree") if etree_in_c: - if etree_in_c.VERSION < "1.0": - raise RuntimeError("cElementTree version 1.0 or higher is required.") + if etree_in_c.VERSION < "1.0.5": + raise RuntimeError("cElementTree version 1.0.5 or higher is required.") # Third party serializers (including ours) test with non-c Comment etree_in_c.test_comment = Comment return etree_in_c -- cgit v1.2.3 From 31ba5bec2170fff6cbf32eb6fb6c1e7782428f9d Mon Sep 17 00:00:00 2001 From: Waylan Limberg Date: Wed, 27 Apr 2011 07:42:31 -0700 Subject: Updated bug tracker to point to Github account. --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index d19a1ea..a429619 100644 --- a/README +++ b/README @@ -26,5 +26,5 @@ Support You may ask for help and discuss various other issues on the [mailing list][] and report bugs on the [bug tracker][]. [mailing list]: http://lists.sourceforge.net/lists/listinfo/python-markdown-discuss -[bug tracker]: http://www.freewisdom.org/projects/python-markdown/Tickets +[bug tracker]: http://github.com/waylan/Python-Markdown/issues -- cgit v1.2.3