aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWaylan Limberg <waylan.limberg@icloud.com>2014-08-27 13:34:19 -0400
committerWaylan Limberg <waylan.limberg@icloud.com>2014-08-27 13:34:19 -0400
commit44e718ed82ed4c8e8e0f0fe1dbdb73d441747b19 (patch)
tree4006dad4eb9fa86169ededd817ede082bf720270
parent8c29487fe973f9007510dd6c4f32083b8d4d0896 (diff)
downloadmarkdown-44e718ed82ed4c8e8e0f0fe1dbdb73d441747b19.tar.gz
markdown-44e718ed82ed4c8e8e0f0fe1dbdb73d441747b19.tar.bz2
markdown-44e718ed82ed4c8e8e0f0fe1dbdb73d441747b19.zip
Refactored extension importing.
We now use importlib which means we no longer support Python 2.6. Also, this refactor properly imports third party extensions which reside at the root of PYTHONPATH. Previously, either `markdown.extensions.` or `mdx_` would be appended to any extension name that did not contain a dot, which required third party extensions to either be in submodules or use the old `mdx_` naming convention. This commit is also in preperation for #336. It will now be much easier to deprecate (and later remove) support for the old ways of handling extension names.
-rw-r--r--.travis.yml1
-rw-r--r--docs/release-2.5.txt5
-rw-r--r--markdown/__init__.py38
-rwxr-xr-xsetup.py1
-rw-r--r--tests/test_apis.py25
-rw-r--r--tox.ini2
6 files changed, 45 insertions, 27 deletions
diff --git a/.travis.yml b/.travis.yml
index 1931a20..e912c73 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,5 @@
language: python
env:
- - TOXENV=py26
- TOXENV=py27
- TOXENV=py32
- TOXENV=py33
diff --git a/docs/release-2.5.txt b/docs/release-2.5.txt
index 0d895bb..eb9c44c 100644
--- a/docs/release-2.5.txt
+++ b/docs/release-2.5.txt
@@ -10,11 +10,14 @@ Python-Markdown 2.5 Release Notes
We are pleased to release Python-Markdown 2.5 which adds a few new features
and fixes various bugs. See the list of changes below for details.
-Python-Markdown supports Python versions 2.6, 2.7, 3.2, 3.3, and 3.4.
+Python-Markdown supports Python versions 2.7, 3.2, 3.3, and 3.4.
Backwards-incompatible Changes
------------------------------
+* Python-Markdown no longer supports Python version 2.6. You must be using Python 2.7+
+or Python-Markdown 2.5 will not load.
+
* The `force_linenos` config key on the [CodeHilite Extension] has been deprecated
and will raise a `KeyError` if provided. In the previous release (2.4), it was issuing
a `DeprecationWarning`. The [`linenums`][linenums] keyword should be used instead,
diff --git a/markdown/__init__.py b/markdown/__init__.py
index 59dda4c..6190dd2 100644
--- a/markdown/__init__.py
+++ b/markdown/__init__.py
@@ -36,6 +36,7 @@ from .__version__ import version, version_info
import codecs
import sys
import logging
+import importlib
from . import util
from .preprocessors import build_preprocessors
from .blockprocessors import build_block_parser
@@ -163,6 +164,8 @@ class Markdown(object):
ext = self.build_extension(ext, configs.get(ext, []))
if isinstance(ext, Extension):
ext.extendMarkdown(self, globals())
+ logger.info('Successfully loaded extension "%s.%s".'
+ % (ext.__class__.__module__, ext.__class__.__name__))
elif ext is not None:
raise TypeError(
'Extension "%s.%s" must be of type: "markdown.Extension"'
@@ -187,23 +190,28 @@ class Markdown(object):
pairs = [x.split("=") for x in ext_args.split(",")]
configs.update([(x.strip(), y.strip()) for (x, y) in pairs])
- # Setup the module name
- module_name = ext_name
- if '.' not in ext_name:
- module_name = '.'.join(['markdown.extensions', ext_name])
-
# Try loading the extension first from one place, then another
- try: # New style (markdown.extensions.<extension>)
- module = __import__(module_name, {}, {}, [str(module_name.rpartition('.')[0])])
+ try:
+ # Assume string uses dot syntax (`path.to.some.module`)
+ module = importlib.import_module(ext_name)
+ logger.debug('Successfuly imported extension module "%s".' % ext_name)
except ImportError:
- module_name_old_style = '_'.join(['mdx', ext_name])
- try: # Old style (mdx_<extension>)
- module = __import__(module_name_old_style)
- except ImportError as e:
- message = "Failed loading extension '%s' from '%s' or '%s'" \
- % (ext_name, module_name, module_name_old_style)
- e.args = (message,) + e.args[1:]
- raise
+ # Preppend `markdown.extensions.` to name
+ module_name = '.'.join(['markdown.extensions', ext_name])
+ try:
+ module = importlib.import_module(module_name)
+ logger.debug('Successfuly imported extension module "%s".' % module_name)
+ except ImportError:
+ # Preppend `mdx_` to name
+ module_name_old_style = '_'.join(['mdx', ext_name])
+ try:
+ module = importlib.import_module(module_name_old_style)
+ logger.debug('Successfuly imported extension module "%s".' % module_name_old_style)
+ except ImportError as e:
+ message = "Failed loading extension '%s' from '%s', '%s' or '%s'" \
+ % (ext_name, ext_name, module_name, module_name_old_style)
+ e.args = (message,) + e.args[1:]
+ raise
# If the module is loaded successfully, we expect it to define a
# function called makeExtension()
diff --git a/setup.py b/setup.py
index 568e8c5..f635b48 100755
--- a/setup.py
+++ b/setup.py
@@ -235,7 +235,6 @@ setup(
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 2',
- 'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.2',
diff --git a/tests/test_apis.py b/tests/test_apis.py
index a5e0d73..f0c7f3d 100644
--- a/tests/test_apis.py
+++ b/tests/test_apis.py
@@ -276,24 +276,33 @@ class TestErrors(unittest.TestCase):
def testLoadBadExtension(self):
""" Test loading of an Extension with no makeExtension function. """
- _create_fake_extension(name='fake', has_factory_func=False)
- self.assertRaises(AttributeError, markdown.Markdown, extensions=['fake'])
+ _create_fake_extension(name='fake_a', has_factory_func=False)
+ self.assertRaises(AttributeError, markdown.Markdown, extensions=['fake_a'])
def testNonExtension(self):
""" Test loading a non Extension object as an extension. """
- _create_fake_extension(name='fake', is_wrong_type=True)
- self.assertRaises(TypeError, markdown.Markdown, extensions=['fake'])
+ _create_fake_extension(name='fake_b', is_wrong_type=True)
+ self.assertRaises(TypeError, markdown.Markdown, extensions=['fake_b'])
def testBaseExtention(self):
""" Test that the base Extension class will raise NotImplemented. """
- _create_fake_extension(name='fake')
+ _create_fake_extension(name='fake_c')
self.assertRaises(NotImplementedError,
- markdown.Markdown, extensions=['fake'])
+ markdown.Markdown, extensions=['fake_c'])
+
+ def testDotSyntaxExtention(self):
+ """ Test that dot syntax imports properly (not using mdx_). """
+ _create_fake_extension(name='fake_d', use_old_style=False)
+ self.assertRaises(NotImplementedError,
+ markdown.Markdown, extensions=['fake_d'])
-def _create_fake_extension(name, has_factory_func=True, is_wrong_type=False):
+def _create_fake_extension(name, has_factory_func=True, is_wrong_type=False, use_old_style=True):
""" Create a fake extension module for testing. """
- mod_name = '_'.join(['mdx', name])
+ if use_old_style:
+ mod_name = '_'.join(['mdx', name])
+ else:
+ mod_name = name
if not PY3:
# mod_name must be bytes in Python 2.x
mod_name = bytes(mod_name)
diff --git a/tox.ini b/tox.ini
index 7968fba..5ccefce 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
[tox]
-envlist = py26, py27, py31, py32, py33, py34
+envlist = py27, py31, py32, py33, py34
[testenv]
downloadcache = {toxworkdir}/cache