diff options
-rw-r--r-- | MANIFEST.in | 3 | ||||
-rw-r--r-- | makefile | 8 | ||||
-rw-r--r-- | markdown/test_tools.py | 125 | ||||
-rwxr-xr-x | run-tests.py | 23 | ||||
-rw-r--r-- | setup.cfg | 2 | ||||
-rw-r--r-- | test-requirements.txt | 1 | ||||
-rw-r--r-- | tests/__init__.py | 189 | ||||
-rw-r--r-- | tests/basic/benchmark.dat | 20 | ||||
-rw-r--r-- | tests/extensions/extra/test.cfg | 36 | ||||
-rw-r--r-- | tests/extensions/test.cfg | 73 | ||||
-rw-r--r-- | tests/options/test.cfg | 11 | ||||
-rw-r--r-- | tests/php/extra/test.cfg | 7 | ||||
-rw-r--r-- | tests/php/test.cfg | 50 | ||||
-rw-r--r-- | tests/pl/Tests_2004/test.cfg | 10 | ||||
-rw-r--r-- | tests/pl/Tests_2007/test.cfg | 25 | ||||
-rw-r--r-- | tests/plugins.py | 127 | ||||
-rw-r--r-- | tests/safe_mode/test.cfg | 8 | ||||
-rw-r--r-- | tests/test_legacy.py | 213 | ||||
-rw-r--r-- | tox.ini | 4 |
19 files changed, 342 insertions, 593 deletions
diff --git a/MANIFEST.in b/MANIFEST.in index c3d529d..a14d4ea 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,9 +1,8 @@ recursive-include markdown *.py recursive-include docs * -recursive-include tests *.txt *.html *.cfg *.py +recursive-include tests *.txt *.html *.py include setup.py include setup.cfg -include run-tests.py include tox.ini include makefile include LICENSE.md @@ -11,7 +11,6 @@ help: @echo ' build-win Build a Windows exe distribution' @echo ' docs Build documentation' @echo ' test Run all tests' - @echo ' update-tests Generate html files for updated text files in tests' @echo ' clean Clean up the source directories' .PHONY : install @@ -38,11 +37,8 @@ docs: .PHONY : test test: - tox - -.PHONY : update-tests -update-tests: - python run-tests.py update + coverage run --source=markdown -m unittest discover tests + coverage report --show-missing .PHONY : clean clean: diff --git a/markdown/test_tools.py b/markdown/test_tools.py index cebb2bb..9324bd4 100644 --- a/markdown/test_tools.py +++ b/markdown/test_tools.py @@ -1,6 +1,16 @@ +from __future__ import absolute_import +import os +import io import unittest import textwrap -from markdown import markdown +from . import markdown + +try: + import tidylib +except ImportError: + tidylib = None + +__all__ = ['TestCase', 'LegacyTestCase', 'Kwargs'] class TestCase(unittest.TestCase): @@ -42,3 +52,116 @@ class TestCase(unittest.TestCase): # TODO: If/when actual output ends with a newline, then use: # return textwrap.dedent(text.strip('/n')) return textwrap.dedent(text).strip() + + +######################### +# Legacy Test Framework # +######################### + + +class Kwargs(dict): + """ A dict like class for holding keyword arguments. """ + pass + + +def _normalize_whitespace(text): + """ Normalize whitespace for a string of html using tidylib. """ + output, errors = tidylib.tidy_fragment(text, options={ + 'drop_empty_paras': 0, + 'fix_backslash': 0, + 'fix_bad_comments': 0, + 'fix_uri': 0, + 'join_styles': 0, + 'lower_literals': 0, + 'merge_divs': 0, + 'output_xhtml': 1, + 'quote_ampersand': 0, + 'newline': 'LF' + }) + return output + + +class LegacyTestMeta(type): + def __new__(cls, name, bases, dct): + + def generate_test(infile, outfile, normalize, kwargs): + def test(self): + with io.open(infile, encoding="utf-8") as f: + input = f.read() + with io.open(outfile, encoding="utf-8") as f: + # Normalize line endings + # (on Windows, git may have altered line endings). + expected = f.read().replace("\r\n", "\n") + output = markdown(input, **kwargs) + if tidylib and normalize: + expected = _normalize_whitespace(expected) + output = _normalize_whitespace(output) + elif normalize: + self.skipTest('Tidylib not available.') + self.assertMultiLineEqual(output, expected) + return test + + location = dct.get('location', '') + exclude = dct.get('exclude', []) + normalize = dct.get('normalize', False) + input_ext = dct.get('input_ext', '.txt') + output_ext = dct.get('output_ext', '.html') + kwargs = dct.get('default_kwargs', Kwargs()) + + if os.path.isdir(location): + for file in os.listdir(location): + infile = os.path.join(location, file) + if os.path.isfile(infile): + tname, ext = os.path.splitext(file) + if ext == input_ext: + outfile = os.path.join(location, tname + output_ext) + tname = tname.replace(' ', '_').replace('-', '_') + kws = kwargs.copy() + if tname in dct: + kws.update(dct[tname]) + test_name = 'test_%s' % tname + if tname not in exclude: + dct[test_name] = generate_test(infile, outfile, normalize, kws) + else: + dct[test_name] = unittest.skip('Excluded')(lambda: None) + + return type.__new__(cls, name, bases, dct) + + +# Define LegacyTestCase class with metaclass in Py2 & Py3 compatable way. +# See https://stackoverflow.com/a/38668373/866026 +# TODO: If/when py2 support is dropped change to: +# class LegacyTestCase(unittest.Testcase, metaclass=LegacyTestMeta) + + +class LegacyTestCase(LegacyTestMeta('LegacyTestCase', (unittest.TestCase,), {'__slots__': ()})): + """ + A `unittest.TestCase` subclass for running Markdown's legacy file-based tests. + + A subclass should define various properties which point to a directory of + text-based test files and define various behaviors/defaults for those tests. + The following properties are supported: + + location: A path to the directory fo test files. An absolute path is prefered. + exclude: A list of tests to exclude. Each test name should comprise the filename + without an extension. + normalize: A boolean value indicating if the HTML should be normalized. + Default: `False`. + input_ext: A string containing the file extension of input files. Default: `.txt`. + ouput_ext: A string containing the file extension of expected output files. + Default: `html`. + default_kwargs: A `Kwargs` instance which stores the default set of keyword + arguments for all test files in the directory. + + In addition, properties can be defined for each individual set of test files within + the directory. The property should be given the name of the file wihtout the file + extension. Any spaces and dashes in the filename should be replaced with + underscores. The value of the property should be a `Kwargs` instance which + contains the keyword arguments that should be passed to `Markdown` for that + test file. The keyword arguments will "update" the `default_kwargs`. + + When the class instance is created, it will walk the given directory and create + a seperate unitttest for each set of test files using the naming scheme: + `test_filename`. One unittest will be run for each set of input and output files. + """ + pass diff --git a/run-tests.py b/run-tests.py deleted file mode 100755 index 5748953..0000000 --- a/run-tests.py +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env python - -import tests -import os -import sys - -if len(sys.argv) > 1 and sys.argv[1] == "update": - if len(sys.argv) > 2: - config = tests.get_config(os.path.dirname(sys.argv[2])) - root, ext = os.path.splitext(sys.argv[2]) - if ext == config.get( - config.get_section(os.path.basename(root)), 'input_ext' - ): - tests.generate(root, config) - else: - print( - sys.argv[2], - 'does not have a valid file extension. Check config.' - ) - else: - tests.generate_all() -else: - tests.run() @@ -1,5 +1,3 @@ -[nosetests] - [bdist_wheel] universal=1 diff --git a/test-requirements.txt b/test-requirements.txt index 65bfae0..12244ab 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,4 +1,3 @@ -nose coverage<4.0 pyyaml pytidylib diff --git a/tests/__init__.py b/tests/__init__.py index 6826ff3..e69de29 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,189 +0,0 @@ -import os -import markdown -import codecs -import difflib -import warnings -try: - import nose -except ImportError as e: - msg = e.args[0] - msg = msg + ". The nose testing framework is required to run the Python-" \ - "Markdown tests. Run `pip install nose` to install the latest version." - e.args = (msg,) + e.args[1:] - raise -from .plugins import HtmlOutput, Markdown, MarkdownSyntaxError -try: - import tidylib -except ImportError: - tidylib = None -try: - import yaml -except ImportError as e: - msg = e.args[0] - msg = msg + ". A YAML library is required to run the Python-Markdown " \ - "tests. Run `pip install pyyaml` to install the latest version." - e.args = (msg,) + e.args[1:] - raise - -test_dir = os.path.abspath(os.path.dirname(__file__)) - - -class YamlConfig(): - def __init__(self, defaults, filename): - """ Set defaults and load config file if it exists. """ - self.DEFAULT_SECTION = 'DEFAULT' - self._defaults = defaults - self._config = {} - if os.path.exists(filename): - with codecs.open(filename, encoding="utf-8") as f: - self._config = yaml.load(f) - - def get(self, section, option): - """ Get config value for given section and option key. """ - if section in self._config and option in self._config[section]: - return self._config[section][option] - return self._defaults[option] - - def get_section(self, file): - """ Get name of config section for given file. """ - filename = os.path.basename(file) - if filename in self._config: - return filename - else: - return self.DEFAULT_SECTION - - def get_args(self, file): - """ Get args to pass to markdown from config for a given file. """ - args = {} - section = self.get_section(file) - if section in self._config: - for key in self._config[section].keys(): - # Filter out args unique to testing framework - if key not in self._defaults.keys(): - args[key] = self.get(section, key) - return args - - -def get_config(dir_name): - """ Get config for given directory name. """ - defaults = { - 'normalize': False, - 'skip': False, - 'input_ext': '.txt', - 'output_ext': '.html' - } - config = YamlConfig(defaults, os.path.join(dir_name, 'test.cfg')) - return config - - -def normalize(text): - """ Normalize whitespace for a string of html using tidylib. """ - output, errors = tidylib.tidy_fragment(text, options={ - 'drop_empty_paras': 0, - 'fix_backslash': 0, - 'fix_bad_comments': 0, - 'fix_uri': 0, - 'join_styles': 0, - 'lower_literals': 0, - 'merge_divs': 0, - 'output_xhtml': 1, - 'quote_ampersand': 0, - 'newline': 'LF' - }) - return output - - -class CheckSyntax(object): - def __init__(self, description=None): - if description: - self.description = 'TestSyntax: "%s"' % description - - def __call__(self, file, config): - """ Compare expected output to actual output and report result. """ - cfg_section = config.get_section(file) - if config.get(cfg_section, 'skip'): - raise nose.plugins.skip.SkipTest('Test skipped per config.') - input_file = file + config.get(cfg_section, 'input_ext') - with codecs.open(input_file, encoding="utf-8") as f: - input = f.read() - output_file = file + config.get(cfg_section, 'output_ext') - with codecs.open(output_file, encoding="utf-8") as f: - # Normalize line endings - # (on windows, git may have altered line endings). - expected_output = f.read().replace("\r\n", "\n") - output = markdown.markdown(input, **config.get_args(file)) - if tidylib and config.get(cfg_section, 'normalize'): - # Normalize whitespace with tidylib before comparing. - expected_output = normalize(expected_output) - output = normalize(output) - elif config.get(cfg_section, 'normalize'): - # Tidylib is not available. Skip this test. - raise nose.plugins.skip.SkipTest( - 'Test skipped. Tidylib not available on system.' - ) - diff = [l for l in difflib.unified_diff( - expected_output.splitlines(True), - output.splitlines(True), - output_file, - 'actual_output.html', - n=3 - )] - if diff: - raise MarkdownSyntaxError( - 'Output from "%s" failed to match expected ' - 'output.\n\n%s' % (input_file, ''.join(diff)) - ) - - -def TestSyntax(): - for dir_name, sub_dirs, files in os.walk(test_dir): - # Get dir specific config settings. - config = get_config(dir_name) - # Loop through files and generate tests. - for file in files: - root, ext = os.path.splitext(file) - if ext == config.get(config.get_section(file), 'input_ext'): - path = os.path.join(dir_name, root) - check_syntax = CheckSyntax( - description=os.path.relpath(path, test_dir) - ) - yield check_syntax, path, config - - -def generate(file, config): - """ Write expected output file for given input. """ - cfg_section = config.get_section(file) - if config.get(cfg_section, 'skip') or config.get(cfg_section, 'normalize'): - print('Skipping:', file) - return None - input_file = file + config.get(cfg_section, 'input_ext') - output_file = file + config.get(cfg_section, 'output_ext') - if not os.path.isfile(output_file) or \ - os.path.getmtime(output_file) < os.path.getmtime(input_file): - print('Generating:', file) - markdown.markdownFromFile(input=input_file, output=output_file, - encoding='utf-8', **config.get_args(file)) - else: - print('Already up-to-date:', file) - - -def generate_all(): - """ Generate expected output for all outdated tests. """ - for dir_name, sub_dirs, files in os.walk(test_dir): - # Get dir specific config settings. - config = get_config(dir_name) - # Loop through files and generate tests. - for file in files: - root, ext = os.path.splitext(file) - if ext == config.get(config.get_section(file), 'input_ext'): - generate(os.path.join(dir_name, root), config) - - -def run(): - # Warnings should cause tests to fail... - warnings.simplefilter('error') - # Except for the warnings that shouldn't - warnings.filterwarnings('default', category=PendingDeprecationWarning) - warnings.filterwarnings('default', category=DeprecationWarning, module='markdown') - - nose.main(addplugins=[HtmlOutput(), Markdown()]) diff --git a/tests/basic/benchmark.dat b/tests/basic/benchmark.dat deleted file mode 100644 index 3d549dd..0000000 --- a/tests/basic/benchmark.dat +++ /dev/null @@ -1,20 +0,0 @@ -construction:0.000000:0.000000 -amps-and-angle-encoding:0.070000:131072.000000 -auto-links:0.080000:397312.000000 -backlash-escapes:0.270000:884736.000000 -blockquotes-with-dode-blocks:0.020000:0.000000 -hard-wrapped:0.020000:0.000000 -horizontal-rules:0.180000:135168.000000 -inline-html-advanced:0.070000:0.000000 -inline-html-comments:0.080000:0.000000 -inline-html-simple:0.210000:0.000000 -links-inline:0.140000:0.000000 -links-reference:0.170000:0.000000 -literal-quotes:0.090000:0.000000 -markdown-documentation-basics:0.690000:1806336.000000 -markdown-syntax:3.310000:6696960.000000 -nested-blockquotes:0.200000:0.000000 -ordered-and-unordered-list:0.530000:0.000000 -strong-and-em-together:0.200000:0.000000 -tabs:0.200000:0.000000 -tidyness:0.200000:0.000000 diff --git a/tests/extensions/extra/test.cfg b/tests/extensions/extra/test.cfg deleted file mode 100644 index d956e2a..0000000 --- a/tests/extensions/extra/test.cfg +++ /dev/null @@ -1,36 +0,0 @@ -DEFAULT: - extensions: - - markdown.extensions.extra - -loose_def_list: - extensions: - - markdown.extensions.def_list - -simple_def-lists: - extensions: - - markdown.extensions.def_list - -abbr: - extensions: - - markdown.extensions.abbr - -footnotes: - extensions: - - markdown.extensions.footnotes - -tables: - extensions: - - markdown.extensions.tables - -tables_and_attr_list: - extensions: - - markdown.extensions.tables - - markdown.extensions.attr_list - -extra_config: - extensions: - - markdown.extensions.extra - extension_configs: - markdown.extensions.extra: - markdown.extensions.footnotes: - PLACE_MARKER: ~~~placemarker~~~ diff --git a/tests/extensions/test.cfg b/tests/extensions/test.cfg deleted file mode 100644 index ce66cfc..0000000 --- a/tests/extensions/test.cfg +++ /dev/null @@ -1,73 +0,0 @@ -attr_list: - extensions: - - markdown.extensions.attr_list - - markdown.extensions.def_list - - markdown.extensions.smarty - -codehilite: - extensions: - - markdown.extensions.codehilite - # This passes or not based on version of pygments. - skip: True - -toc: - extensions: - - markdown.extensions.toc - -toc_invalid: - extensions: - - markdown.extensions.toc - -toc_out_of_order: - extensions: - - markdown.extensions.toc - -toc_nested: - extensions: - - markdown.extensions.toc - extension_configs: - markdown.extensions.toc: - permalink: True - -toc_nested2: - extensions: - - markdown.extensions.toc - extension_configs: - markdown.extensions.toc: - permalink: "[link]" - -toc_nested_list: - extensions: - - markdown.extensions.toc - -wikilinks: - extensions: - - markdown.extensions.wikilinks - -fenced_code: - extensions: - - markdown.extensions.fenced_code - -github_flavored: - extensions: - - markdown.extensions.fenced_code - -sane_lists: - extensions: - - markdown.extensions.sane_lists - -nl2br_w_attr_list: - extensions: - - markdown.extensions.nl2br - - markdown.extensions.attr_list - -admonition: - extensions: - - markdown.extensions.admonition - -smarty: - extensions: - - markdown.extensions.smarty - extension_configs: - markdown.extensions.smarty: - smart_angled_quotes: True
\ No newline at end of file diff --git a/tests/options/test.cfg b/tests/options/test.cfg deleted file mode 100644 index 2e14f1f..0000000 --- a/tests/options/test.cfg +++ /dev/null @@ -1,11 +0,0 @@ -lazy_ol_off: - lazy_ol: False - -html4: - output_format: html4 - -no-attributes: - enable_attributes: False - -no-smart-emphasis: - smart_emphasis: False
\ No newline at end of file diff --git a/tests/php/extra/test.cfg b/tests/php/extra/test.cfg deleted file mode 100644 index c6011d6..0000000 --- a/tests/php/extra/test.cfg +++ /dev/null @@ -1,7 +0,0 @@ -DEFAULT: - extensions: - - extra - normalize: True - input_ext: .text - output_ext: .xhtml - skip: True diff --git a/tests/php/test.cfg b/tests/php/test.cfg deleted file mode 100644 index 70c2601..0000000 --- a/tests/php/test.cfg +++ /dev/null @@ -1,50 +0,0 @@ -DEFAULT: - normalize: True - input_ext: .text - output_ext: .xhtml - #skip: True - -Quotes in attributes: - # attributes get output in differant order - skip: True - -Inline HTML (Span): - # Backtick in raw HTML attribute TODO: fixme - skip: True - -Backslash escapes: - # Weird whitespace issue in output - skip: True - -Ins & del: - # Our behavior follows markdown.pl I think PHP is wrong here - skip: True - -Auto Links: - # TODO: fix raw HTML so is doesn't match <hr@example.com> as a <hr>. - skip: True - -Empty List Item: - # We match markdown.pl here. Maybe someday we'll support this - skip: True - -Headers: - # TODO: fix headers to not require blank line before - skip: True - -Mixed OLs and ULs: - # We match markdown.pl here. I think PHP is wrong here - skip: True - -Emphasis: - # We have various minor differances in combined & incorrect em markup. - # Maybe fix a few of them - but most aren't too important - skip: True - -Code block in a list item: - # We match markdown.pl - not sure how php gets that output?? - skip: True - -PHP-Specific Bugs: - # Not sure what to make of the escaping stuff here. Why is PHP not removing a blackslash? - skip: True diff --git a/tests/pl/Tests_2004/test.cfg b/tests/pl/Tests_2004/test.cfg deleted file mode 100644 index 80f48e5..0000000 --- a/tests/pl/Tests_2004/test.cfg +++ /dev/null @@ -1,10 +0,0 @@ -DEFAULT: - input_ext: .text - normalize: True - # comment out next line to run these tests - #skip: True - -Yuri-Footnotes: - extensions: footnotes - skip: True - diff --git a/tests/pl/Tests_2007/test.cfg b/tests/pl/Tests_2007/test.cfg deleted file mode 100644 index 097aa0d..0000000 --- a/tests/pl/Tests_2007/test.cfg +++ /dev/null @@ -1,25 +0,0 @@ -DEFAULT: - input_ext: .text - normalize: True - # comment out next line to run these tests - #skip: True - -Images: - # the attributes don't get ordered the same so we skip this - skip: True - -Code Blocks: - # some weird whitespace issue - skip: True - -Links, reference style: - # weird issue with nested brackets TODO: fixme - skip: True - -Backslash escapes: - # backticks in raw html attributes TODO: fixme - skip: True - -Code Spans: - # more backticks in raw html attributes TODO: fixme - skip: True diff --git a/tests/plugins.py b/tests/plugins.py deleted file mode 100644 index 4e7af97..0000000 --- a/tests/plugins.py +++ /dev/null @@ -1,127 +0,0 @@ -import traceback -from nose.plugins import Plugin -from nose.plugins.errorclass import ErrorClass, ErrorClassPlugin - - -class MarkdownSyntaxError(Exception): - pass - - -class Markdown(ErrorClassPlugin): - """ Add MarkdownSyntaxError and ensure proper formatting. """ - mdsyntax = ErrorClass( - MarkdownSyntaxError, - label='MarkdownSyntaxError', - isfailure=True - ) - enabled = True - - def configure(self, options, conf): - self.conf = conf - - def addError(self, test, err): - """ Ensure other plugins see the error by returning nothing here. """ - pass - - def formatError(self, test, err): - """ Remove unnessecary and unhelpful traceback from error report. """ - et, ev, tb = err - if et.__name__ == 'MarkdownSyntaxError': - return et, ev, '' - return err - - -def escape(html): - """ Escape HTML for display as source within HTML. """ - html = html.replace('&', '&') - html = html.replace('<', '<') - html = html.replace('>', '>') - return html - - -class HtmlOutput(Plugin): - """Output test results as ugly, unstyled html. """ - - name = 'html-output' - score = 2 # run late - enabled = True - - def __init__(self): - super(HtmlOutput, self).__init__() - self.html = [ - '<html><head>', - '<title>Test output</title>', - '</head><body>' - ] - - def configure(self, options, conf): - self.conf = conf - - def addSuccess(self, test): - self.html.append('<span>ok</span>') - - def addError(self, test, err): - err = self.formatErr(err) - self.html.append('<span>ERROR</span>') - self.html.append('<pre>%s</pre>' % escape(err)) - - def addFailure(self, test, err): - err = self.formatErr(err) - self.html.append('<span>FAIL</span>') - self.html.append('<pre>%s</pre>' % escape(err)) - - def finalize(self, result): - self.html.append('<div>') - self.html.append( - "Ran %d test%s" % - (result.testsRun, result.testsRun != 1 and "s" or "") - ) - self.html.append('</div>') - self.html.append('<div>') - if not result.wasSuccessful(): - self.html.extend(['<span>FAILED (', - 'failures=%d ' % len(result.failures), - 'errors=%d' % len(result.errors)]) - for cls in list(result.errorClasses.keys()): - storage, label, isfail = result.errorClasses[cls] - if len(storage): - self.html.append(' %ss=%d' % (label, len(storage))) - self.html.append(')</span>') - else: - self.html.append('OK') - self.html.append('</div></body></html>') - f = open('test-output.html', 'w') - for l in self.html: - f.write(l) - f.close() - - def formatErr(self, err): - exctype, value, tb = err - if not isinstance(value, exctype): - value = exctype(value) - return ''.join(traceback.format_exception(exctype, value, tb)) - - def startContext(self, ctx): - try: - n = ctx.__name__ - except AttributeError: - n = str(ctx).replace('<', '').replace('>', '') - self.html.extend(['<fieldset>', '<legend>', n, '</legend>']) - try: - path = ctx.__file__.replace('.pyc', '.py') - self.html.extend(['<div>', path, '</div>']) - except AttributeError: - pass - - def stopContext(self, ctx): - self.html.append('</fieldset>') - - def startTest(self, test): - self.html.extend([ - '<div><span>', - test.shortDescription() or str(test), - '</span>' - ]) - - def stopTest(self, test): - self.html.append('</div>') diff --git a/tests/safe_mode/test.cfg b/tests/safe_mode/test.cfg deleted file mode 100644 index 4e1720e..0000000 --- a/tests/safe_mode/test.cfg +++ /dev/null @@ -1,8 +0,0 @@ -DEFAULT: - safe_mode: escape - -remove: - safe_mode: remove - -replace: - safe_mode: replace diff --git a/tests/test_legacy.py b/tests/test_legacy.py new file mode 100644 index 0000000..17c4282 --- /dev/null +++ b/tests/test_legacy.py @@ -0,0 +1,213 @@ +from markdown.test_tools import LegacyTestCase, Kwargs +import os +import warnings + +# Warnings should cause tests to fail... +warnings.simplefilter('error') +# Except for the warnings that shouldn't +warnings.filterwarnings('default', category=PendingDeprecationWarning) +warnings.filterwarnings('default', category=DeprecationWarning, module='markdown') + +parent_test_dir = os.path.abspath(os.path.dirname(__file__)) + + +class TestBasic(LegacyTestCase): + location = os.path.join(parent_test_dir, 'basic') + + +class TestMisc(LegacyTestCase): + location = os.path.join(parent_test_dir, 'misc') + + +class TestOptions(LegacyTestCase): + location = os.path.join(parent_test_dir, 'options') + + lazy_ol_off = Kwargs(lazy_ol=False) + + html4 = Kwargs(output_format='html4') + + no_attributes = Kwargs(enable_attributes=False) + + no_smart_emphasis = Kwargs(smart_emphasis=False) + + +class TestSafeMode(LegacyTestCase): + location = os.path.join(parent_test_dir, 'safe_mode') + default_kwargs = Kwargs(safe_mode='escape') + + remove = Kwargs(safe_mode='remove') + + replace = Kwargs(safe_mode='replace') + + +class TestPhp(LegacyTestCase): + """ + Notes on "excluded" tests: + + Quotes in attributes: attributes get output in differant order + + Inline HTML (Span): Backtick in raw HTML attribute TODO: fixme + + Backslash escapes: Weird whitespace issue in output + + Ins & del: Our behavior follows markdown.pl I think PHP is wrong here + + Auto Links: TODO: fix raw HTML so is doesn't match <hr@example.com> as a <hr>. + + Empty List Item: We match markdown.pl here. Maybe someday we'll support this + + Headers: TODO: fix headers to not require blank line before + + Mixed OLs and ULs: We match markdown.pl here. I think PHP is wrong here + + Emphasis: We have various minor differances in combined & incorrect em markup. + Maybe fix a few of them - but most aren't too important + + Code block in a list item: We match markdown.pl - not sure how php gets that output?? + + PHP-Specific Bugs: Not sure what to make of the escaping stuff here. + Why is PHP not removing a blackslash? + """ + location = os.path.join(parent_test_dir, 'php') + normalize = True + input_ext = '.text' + output_ext = '.xhtml' + exclude = [ + 'Quotes_in_attributes', + 'Inline_HTML_(Span)', + 'Backslash_escapes', + 'Ins_&_del', + 'Auto_Links', + 'Empty_List_Item', + 'Headers', + 'Mixed_OLs_and_ULs', + 'Emphasis', + 'Code_block_in_a_list_item', + 'PHP_Specific_Bugs' + ] + + +# class TestPhpExtra(LegacyTestCase): +# location = os.path.join(parent_test_dir, 'php/extra') +# normalize = True +# input_ext = '.text' +# output_ext = '.xhtml' +# default_kwargs = Kwargs(extensions=['extra']) + + +class TestPl2004(LegacyTestCase): + location = os.path.join(parent_test_dir, 'pl/Tests_2004') + normalize = True + input_ext = '.text' + exclude = ['Yuri_Footnotes'] + + +class TestPl2007(LegacyTestCase): + """ + Notes on "excluded" tests: + + Images: the attributes don't get ordered the same so we skip this + + Code Blocks: some weird whitespace issue + + Links, reference style: weird issue with nested brackets TODO: fixme + + Backslash escapes: backticks in raw html attributes TODO: fixme + + Code Spans: more backticks in raw html attributes TODO: fixme + """ + location = os.path.join(parent_test_dir, 'pl/Tests_2007') + normalize = True + input_ext = '.text' + exclude = [ + 'Images', + 'Code_Blocks', + 'Links,_reference_style', + 'Backslash_escapes', + 'Code_Spans' + ] + + +class TestExtensions(LegacyTestCase): + location = os.path.join(parent_test_dir, 'extensions') + exclude = ['codehilite'] + + attr_list = Kwargs( + extensions=[ + 'markdown.extensions.attr_list', + 'markdown.extensions.def_list', + 'markdown.extensions.smarty' + ] + ) + + codehilite = Kwargs(extensions=['markdown.extensions.codehilite']) + + toc = Kwargs(extensions=['markdown.extensions.toc']) + + toc_invalid = Kwargs(extensions=['markdown.extensions.toc']) + + toc_out_of_order = Kwargs(extensions=['markdown.extensions.toc']) + + toc_nested = Kwargs( + extensions=['markdown.extensions.toc'], + extension_configs={'markdown.extensions.toc': {'permalink': True}} + ) + + toc_nested2 = Kwargs( + extensions=['markdown.extensions.toc'], + extension_configs={'markdown.extensions.toc': {'permalink': "[link]"}} + ) + + toc_nested_list = Kwargs(extensions=['markdown.extensions.toc']) + + wikilinks = Kwargs(extensions=['markdown.extensions.wikilinks']) + + fenced_code = Kwargs(extensions=['markdown.extensions.fenced_code']) + + github_flavored = Kwargs(extensions=['markdown.extensions.fenced_code']) + + sane_lists = Kwargs(extensions=['markdown.extensions.sane_lists']) + + nl2br_w_attr_list = Kwargs( + extensions=[ + 'markdown.extensions.nl2br', + 'markdown.extensions.attr_list' + ] + ) + + admonition = Kwargs(extensions=['markdown.extensions.admonition']) + + smarty = Kwargs( + extensions=['markdown.extensions.smarty'], + extension_configs={'markdown.extensions.smarty': {'smart_angled_quotes': True}} + ) + + +class TestExtensionsExtra(LegacyTestCase): + location = os.path.join(parent_test_dir, 'extensions/extra') + default_kwargs = Kwargs(extensions=['markdown.extensions.extra']) + + loose_def_list = Kwargs(extensions=['markdown.extensions.def_list']) + + simple_def_lists = Kwargs(extensions=['markdown.extensions.def_list']) + + abbr = Kwargs(extensions=['markdown.extensions.abbr']) + + footnotes = Kwargs(extensions=['markdown.extensions.footnotes']) + + tables = Kwargs(extensions=['markdown.extensions.tables']) + + tables_and_attr_list = Kwargs( + extensions=['markdown.extensions.tables', 'markdown.extensions.attr_list'] + ) + + extra_config = Kwargs( + extensions=['markdown.extensions.extra'], + extension_configs={ + 'markdown.extensions.extra': { + 'markdown.extensions.footnotes': { + 'PLACE_MARKER': '~~~placemarker~~~' + } + } + } + ) @@ -3,12 +3,12 @@ envlist = py27, py32, py33, py34, py35, py36, pypy, flake8, checkspelling [testenv] deps = -rtest-requirements.txt -commands = coverage run --source=markdown {toxinidir}/run-tests.py {posargs} +commands = coverage run --source=markdown -m unittest discover {toxinidir}/tests coverage report --show-missing [testenv:flake8] deps = flake8 -commands = flake8 {toxinidir}/markdown {toxinidir}/tests {toxinidir}/setup.py {toxinidir}/run-tests.py +commands = flake8 {toxinidir}/markdown {toxinidir}/tests {toxinidir}/setup.py [testenv:checkspelling] deps = |