|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
#! /usr/bin/env python
|
|
|
|
|
|
|
|
|
|
# $Id: test_utils.py 8141 2017-07-08 17:05:18Z goodger $
|
|
|
|
|
# Author: David Goodger <goodger@python.org>
|
|
|
|
|
# Copyright: This module has been placed in the public domain.
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
Test module for utils/__init__.py.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
import unittest
|
|
|
|
|
import sys
|
|
|
|
|
import os
|
|
|
|
|
from DocutilsTestSupport import docutils, utils, nodes
|
|
|
|
|
try:
|
|
|
|
|
from io import StringIO
|
|
|
|
|
except ImportError: # io is new in Python 2.6
|
|
|
|
|
from StringIO import StringIO
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ReporterTests(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
stream = StringIO()
|
|
|
|
|
reporter = utils.Reporter('test data', 2, 4, stream, 1)
|
|
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
|
self.stream.seek(0)
|
|
|
|
|
self.stream.truncate()
|
|
|
|
|
|
|
|
|
|
def test_level0(self):
|
|
|
|
|
sw = self.reporter.system_message(0, 'debug output')
|
|
|
|
|
self.assertEqual(sw.pformat(), """\
|
|
|
|
|
<system_message level="0" source="test data" type="DEBUG">
|
|
|
|
|
<paragraph>
|
|
|
|
|
debug output
|
|
|
|
|
""")
|
|
|
|
|
self.assertEqual(self.stream.getvalue(),
|
|
|
|
|
'test data:: (DEBUG/0) debug output\n')
|
|
|
|
|
|
|
|
|
|
def test_level1(self):
|
|
|
|
|
sw = self.reporter.system_message(1, 'a little reminder')
|
|
|
|
|
self.assertEqual(sw.pformat(), """\
|
|
|
|
|
<system_message level="1" source="test data" type="INFO">
|
|
|
|
|
<paragraph>
|
|
|
|
|
a little reminder
|
|
|
|
|
""")
|
|
|
|
|
self.assertEqual(self.stream.getvalue(), '')
|
|
|
|
|
|
|
|
|
|
def test_level2(self):
|
|
|
|
|
sw = self.reporter.system_message(2, 'a warning')
|
|
|
|
|
self.assertEqual(sw.pformat(), """\
|
|
|
|
|
<system_message level="2" source="test data" type="WARNING">
|
|
|
|
|
<paragraph>
|
|
|
|
|
a warning
|
|
|
|
|
""")
|
|
|
|
|
self.assertEqual(self.stream.getvalue(),
|
|
|
|
|
'test data:: (WARNING/2) a warning\n')
|
|
|
|
|
|
|
|
|
|
def test_level3(self):
|
|
|
|
|
sw = self.reporter.system_message(3, 'an error')
|
|
|
|
|
self.assertEqual(sw.pformat(), """\
|
|
|
|
|
<system_message level="3" source="test data" type="ERROR">
|
|
|
|
|
<paragraph>
|
|
|
|
|
an error
|
|
|
|
|
""")
|
|
|
|
|
self.assertEqual(self.stream.getvalue(),
|
|
|
|
|
'test data:: (ERROR/3) an error\n')
|
|
|
|
|
|
|
|
|
|
def test_level4(self):
|
|
|
|
|
self.assertRaises(utils.SystemMessage, self.reporter.system_message, 4,
|
|
|
|
|
'a severe error, raises an exception')
|
|
|
|
|
self.assertEqual(self.stream.getvalue(), 'test data:: (SEVERE/4) '
|
|
|
|
|
'a severe error, raises an exception\n')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_unicode_message(self):
|
|
|
|
|
sw = self.reporter.system_message(0, u'mesidʒ')
|
|
|
|
|
self.assertEqual(sw.pformat(), u"""\
|
|
|
|
|
<system_message level="0" source="test data" type="DEBUG">
|
|
|
|
|
<paragraph>
|
|
|
|
|
mesidʒ
|
|
|
|
|
""")
|
|
|
|
|
|
|
|
|
|
def test_unicode_message_from_exception(self):
|
|
|
|
|
"""Workaround for Python < 2.6 bug:
|
|
|
|
|
unicode(<exception instance>) uses __str__
|
|
|
|
|
and hence fails with unicode message"""
|
|
|
|
|
try:
|
|
|
|
|
raise Exception(u'mesidʒ')
|
|
|
|
|
except Exception, err:
|
|
|
|
|
sw = self.reporter.system_message(0, err)
|
|
|
|
|
self.assertEqual(sw.pformat(), u"""\
|
|
|
|
|
<system_message level="0" source="test data" type="DEBUG">
|
|
|
|
|
<paragraph>
|
|
|
|
|
mesidʒ
|
|
|
|
|
""")
|
|
|
|
|
|
|
|
|
|
class QuietReporterTests(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
stream = StringIO()
|
|
|
|
|
reporter = utils.Reporter('test data', 5, 5, stream, 0)
|
|
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
|
self.stream.seek(0)
|
|
|
|
|
self.stream.truncate()
|
|
|
|
|
|
|
|
|
|
def test_debug(self):
|
|
|
|
|
sw = self.reporter.debug('a debug message')
|
|
|
|
|
# None because debug is disabled.
|
|
|
|
|
self.assertEqual(sw, None)
|
|
|
|
|
self.assertEqual(self.stream.getvalue(), '')
|
|
|
|
|
|
|
|
|
|
def test_info(self):
|
|
|
|
|
sw = self.reporter.info('an informational message')
|
|
|
|
|
self.assertEqual(sw.pformat(), """\
|
|
|
|
|
<system_message level="1" source="test data" type="INFO">
|
|
|
|
|
<paragraph>
|
|
|
|
|
an informational message
|
|
|
|
|
""")
|
|
|
|
|
self.assertEqual(self.stream.getvalue(), '')
|
|
|
|
|
|
|
|
|
|
def test_warning(self):
|
|
|
|
|
sw = self.reporter.warning('a warning')
|
|
|
|
|
self.assertEqual(sw.pformat(), """\
|
|
|
|
|
<system_message level="2" source="test data" type="WARNING">
|
|
|
|
|
<paragraph>
|
|
|
|
|
a warning
|
|
|
|
|
""")
|
|
|
|
|
self.assertEqual(self.stream.getvalue(), '')
|
|
|
|
|
|
|
|
|
|
def test_error(self):
|
|
|
|
|
sw = self.reporter.error('an error')
|
|
|
|
|
self.assertEqual(sw.pformat(), """\
|
|
|
|
|
<system_message level="3" source="test data" type="ERROR">
|
|
|
|
|
<paragraph>
|
|
|
|
|
an error
|
|
|
|
|
""")
|
|
|
|
|
self.assertEqual(self.stream.getvalue(), '')
|
|
|
|
|
|
|
|
|
|
def test_severe(self):
|
|
|
|
|
sw = self.reporter.severe('a severe error')
|
|
|
|
|
self.assertEqual(sw.pformat(), """\
|
|
|
|
|
<system_message level="4" source="test data" type="SEVERE">
|
|
|
|
|
<paragraph>
|
|
|
|
|
a severe error
|
|
|
|
|
""")
|
|
|
|
|
self.assertEqual(self.stream.getvalue(), '')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class NameValueTests(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
def test_extract_name_value(self):
|
|
|
|
|
self.assertRaises(utils.NameValueError, utils.extract_name_value,
|
|
|
|
|
'hello')
|
|
|
|
|
self.assertRaises(utils.NameValueError, utils.extract_name_value,
|
|
|
|
|
'hello')
|
|
|
|
|
self.assertRaises(utils.NameValueError, utils.extract_name_value,
|
|
|
|
|
'=hello')
|
|
|
|
|
self.assertRaises(utils.NameValueError, utils.extract_name_value,
|
|
|
|
|
'hello=')
|
|
|
|
|
self.assertRaises(utils.NameValueError, utils.extract_name_value,
|
|
|
|
|
'hello="')
|
|
|
|
|
self.assertRaises(utils.NameValueError, utils.extract_name_value,
|
|
|
|
|
'hello="something')
|
|
|
|
|
self.assertRaises(utils.NameValueError, utils.extract_name_value,
|
|
|
|
|
'hello="something"else')
|
|
|
|
|
output = utils.extract_name_value(
|
|
|
|
|
"""att1=val1 att2=val2 att3="value number '3'" att4=val4""")
|
|
|
|
|
self.assertEqual(output, [('att1', 'val1'), ('att2', 'val2'),
|
|
|
|
|
('att3', "value number '3'"),
|
|
|
|
|
('att4', 'val4')])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ExtensionOptionTests(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
optionspec = {'a': int, 'bbb': float, 'cdef': (lambda x: x),
|
|
|
|
|
'empty': (lambda x: x)}
|
|
|
|
|
|
|
|
|
|
def test_assemble_option_dict(self):
|
|
|
|
|
input = utils.extract_name_value('a=1 bbb=2.0 cdef=hol%s' % chr(224))
|
|
|
|
|
self.assertEqual(
|
|
|
|
|
utils.assemble_option_dict(input, self.optionspec),
|
|
|
|
|
{'a': 1, 'bbb': 2.0, 'cdef': ('hol%s' % chr(224))})
|
|
|
|
|
input = utils.extract_name_value('a=1 b=2.0 c=hol%s' % chr(224))
|
|
|
|
|
self.assertRaises(KeyError, utils.assemble_option_dict,
|
|
|
|
|
input, self.optionspec)
|
|
|
|
|
input = utils.extract_name_value('a=1 bbb=two cdef=hol%s' % chr(224))
|
|
|
|
|
self.assertRaises(ValueError, utils.assemble_option_dict,
|
|
|
|
|
input, self.optionspec)
|
|
|
|
|
|
|
|
|
|
def test_extract_extension_options(self):
|
|
|
|
|
field_list = nodes.field_list()
|
|
|
|
|
field_list += nodes.field(
|
|
|
|
|
'', nodes.field_name('', 'a'),
|
|
|
|
|
nodes.field_body('', nodes.paragraph('', '1')))
|
|
|
|
|
field_list += nodes.field(
|
|
|
|
|
'', nodes.field_name('', 'bbb'),
|
|
|
|
|
nodes.field_body('', nodes.paragraph('', '2.0')))
|
|
|
|
|
field_list += nodes.field(
|
|
|
|
|
'', nodes.field_name('', 'cdef'),
|
|
|
|
|
nodes.field_body('', nodes.paragraph('', u'hol\u00e0')))
|
|
|
|
|
field_list += nodes.field(
|
|
|
|
|
'', nodes.field_name('', 'empty'), nodes.field_body())
|
|
|
|
|
self.assertEqual(
|
|
|
|
|
utils.extract_extension_options(field_list, self.optionspec),
|
|
|
|
|
{'a': 1, 'bbb': 2.0,
|
|
|
|
|
'cdef': u'hol\u00e0',
|
|
|
|
|
'empty': None})
|
|
|
|
|
self.assertRaises(KeyError, utils.extract_extension_options,
|
|
|
|
|
field_list, {})
|
|
|
|
|
field_list += nodes.field(
|
|
|
|
|
'', nodes.field_name('', 'cdef'),
|
|
|
|
|
nodes.field_body('', nodes.paragraph('', 'one'),
|
|
|
|
|
nodes.paragraph('', 'two')))
|
|
|
|
|
self.assertRaises(utils.BadOptionDataError,
|
|
|
|
|
utils.extract_extension_options,
|
|
|
|
|
field_list, self.optionspec)
|
|
|
|
|
field_list[-1] = nodes.field(
|
|
|
|
|
'', nodes.field_name('', 'cdef bad'),
|
|
|
|
|
nodes.field_body('', nodes.paragraph('', 'no arguments')))
|
|
|
|
|
self.assertRaises(utils.BadOptionError,
|
|
|
|
|
utils.extract_extension_options,
|
|
|
|
|
field_list, self.optionspec)
|
|
|
|
|
field_list[-1] = nodes.field(
|
|
|
|
|
'', nodes.field_name('', 'cdef'),
|
|
|
|
|
nodes.field_body('', nodes.paragraph('', 'duplicate')))
|
|
|
|
|
self.assertRaises(utils.DuplicateOptionError,
|
|
|
|
|
utils.extract_extension_options,
|
|
|
|
|
field_list, self.optionspec)
|
|
|
|
|
field_list[-2] = nodes.field(
|
|
|
|
|
'', nodes.field_name('', 'unkown'),
|
|
|
|
|
nodes.field_body('', nodes.paragraph('', 'unknown')))
|
|
|
|
|
self.assertRaises(KeyError, utils.extract_extension_options,
|
|
|
|
|
field_list, self.optionspec)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class HelperFunctionsTests(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
def test_version_identifier(self):
|
|
|
|
|
"""
|
|
|
|
|
docutils.utils.version_identifier() depends on
|
|
|
|
|
docutils.__version_info__, so this also tests that
|
|
|
|
|
docutils.__version__ is equivalent to docutils.__version_info__.
|
|
|
|
|
"""
|
|
|
|
|
self.assertEqual(utils.version_identifier(), docutils.__version__)
|
|
|
|
|
|
|
|
|
|
def test_normalize_language_tag(self):
|
|
|
|
|
self.assertEqual(utils.normalize_language_tag('de'), ['de'])
|
|
|
|
|
self.assertEqual(utils.normalize_language_tag('de-AT'),
|
|
|
|
|
['de-at', 'de'])
|
|
|
|
|
self.assertEqual(utils.normalize_language_tag('de-AT-1901'),
|
|
|
|
|
['de-at-1901', 'de-at', 'de-1901', 'de'])
|
|
|
|
|
self.assertEqual(utils.normalize_language_tag('de-AT-1901-frak'),
|
|
|
|
|
['de-at-1901-frak', 'de-at-1901', 'de-at-frak',
|
|
|
|
|
'de-1901-frak', 'de-at', 'de-1901', 'de-frak', 'de'])
|
|
|
|
|
self.assertEqual(utils.normalize_language_tag('grc-ibycus-x-altquot'),
|
|
|
|
|
['grc-ibycus-x-altquot', 'grc-ibycus',
|
|
|
|
|
'grc-x-altquot', 'grc'])
|
|
|
|
|
|
|
|
|
|
def test_column_width(self):
|
|
|
|
|
self.assertEqual(utils.column_width(u'de'), 2)
|
|
|
|
|
self.assertEqual(utils.column_width(u'dâ'), 2) # pre-composed
|
|
|
|
|
self.assertEqual(utils.column_width(u'dâ'), 2) # combining
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_relative_path(self):
|
|
|
|
|
# Build and return a path to `target`, relative to `source`:
|
|
|
|
|
# Use '/' as path sep in result.
|
|
|
|
|
self.assertEqual(utils.relative_path('spam', 'spam'), '')
|
|
|
|
|
source = os.path.join('h\xE4m', 'spam', 'fileA')
|
|
|
|
|
target = os.path.join('h\xE4m', 'spam', 'fileB')
|
|
|
|
|
self.assertEqual(utils.relative_path(source, target), 'fileB')
|
|
|
|
|
source = os.path.join('h\xE4m', 'spam', 'fileA')
|
|
|
|
|
target = os.path.join('h\xE4m', 'fileB')
|
|
|
|
|
self.assertEqual(utils.relative_path(source, target), '../fileB')
|
|
|
|
|
# if source is None, default to the cwd:
|
|
|
|
|
target = os.path.join('eggs', 'fileB')
|
|
|
|
|
self.assertEqual(utils.relative_path(None, target), 'eggs/fileB')
|
|
|
|
|
# If there is no common prefix, return the absolute path to `target`:
|
|
|
|
|
# source = '/foo/bar/fileA' # POSIX
|
|
|
|
|
# TODO: how to specify an absolute path independent of the OS?
|
|
|
|
|
# target = os.path.join('eggs', 'fileB')
|
|
|
|
|
# self.assertEqual(utils.relative_path(source, target),
|
|
|
|
|
# os.path.abspath('fileB'))
|
|
|
|
|
# Correctly process unicode instances:
|
|
|
|
|
self.assertEqual(utils.relative_path(u'spam', u'spam'), u'')
|
|
|
|
|
source = os.path.join(u'h\xE4m', u'spam', u'fileA')
|
|
|
|
|
target = os.path.join(u'h\xE4m', u'spam', u'fileB')
|
|
|
|
|
self.assertEqual(utils.relative_path(source, target), u'fileB')
|
|
|
|
|
source = os.path.join(u'h\xE4m', u'spam', u'fileA')
|
|
|
|
|
target = os.path.join(u'h\xE4m', u'fileB')
|
|
|
|
|
self.assertEqual(utils.relative_path(source, target), u'../fileB')
|
|
|
|
|
# if source is None, default to the cwd:
|
|
|
|
|
target = os.path.join(u'eggs', u'fileB')
|
|
|
|
|
self.assertEqual(utils.relative_path(None, target), u'eggs/fileB')
|
|
|
|
|
|
|
|
|
|
def test_find_file_in_dirs(self):
|
|
|
|
|
# Search for file `path` in the sequence of directories `dirs`.
|
|
|
|
|
# Return the first expansion that matches an existing file.
|
|
|
|
|
dirs = ('nonex', '.', '..')
|
|
|
|
|
found = utils.find_file_in_dirs('HISTORY.txt', dirs)
|
|
|
|
|
# returns
|
|
|
|
|
# '..\\HISTORY.txt' on windows
|
|
|
|
|
# '../HISTORY.txt' on other platforms
|
|
|
|
|
# 'HISTORY.txt' if not called from docutils directory.
|
|
|
|
|
self.assertTrue(found.startswith('..'))
|
|
|
|
|
# Return `path` if the file exists in the cwd or if there is no match
|
|
|
|
|
self.assertEqual(utils.find_file_in_dirs('alltests.py', dirs),
|
|
|
|
|
'alltests.py')
|
|
|
|
|
self.assertEqual(utils.find_file_in_dirs('gibts/nicht.txt', dirs),
|
|
|
|
|
'gibts/nicht.txt')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
unittest.main()
|