added podman, json and yaml
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,55 @@
|
||||
import unittest
|
||||
|
||||
from mkdocs.utils.babel_stub import Locale, UnknownLocaleError
|
||||
|
||||
|
||||
class BabelStubTests(unittest.TestCase):
|
||||
def test_locale_language_only(self):
|
||||
locale = Locale('es')
|
||||
self.assertEqual(locale.language, 'es')
|
||||
self.assertEqual(locale.territory, '')
|
||||
self.assertEqual(str(locale), 'es')
|
||||
|
||||
def test_locale_language_territory(self):
|
||||
locale = Locale('es', 'ES')
|
||||
self.assertEqual(locale.language, 'es')
|
||||
self.assertEqual(locale.territory, 'ES')
|
||||
self.assertEqual(str(locale), 'es_ES')
|
||||
|
||||
def test_parse_locale_language_only(self):
|
||||
locale = Locale.parse('fr', '_')
|
||||
self.assertEqual(locale.language, 'fr')
|
||||
self.assertEqual(locale.territory, '')
|
||||
self.assertEqual(str(locale), 'fr')
|
||||
|
||||
def test_parse_locale_language_territory(self):
|
||||
locale = Locale.parse('fr_FR', '_')
|
||||
self.assertEqual(locale.language, 'fr')
|
||||
self.assertEqual(locale.territory, 'FR')
|
||||
self.assertEqual(str(locale), 'fr_FR')
|
||||
|
||||
def test_parse_locale_language_territory_sep(self):
|
||||
locale = Locale.parse('fr-FR', '-')
|
||||
self.assertEqual(locale.language, 'fr')
|
||||
self.assertEqual(locale.territory, 'FR')
|
||||
self.assertEqual(str(locale), 'fr_FR')
|
||||
|
||||
def test_parse_locale_bad_type(self):
|
||||
with self.assertRaises(TypeError):
|
||||
Locale.parse(['list'], '_')
|
||||
|
||||
def test_parse_locale_invalid_characters(self):
|
||||
with self.assertRaises(ValueError):
|
||||
Locale.parse('42', '_')
|
||||
|
||||
def test_parse_locale_bad_format(self):
|
||||
with self.assertRaises(ValueError):
|
||||
Locale.parse('en-GB', '_')
|
||||
|
||||
def test_parse_locale_bad_format_sep(self):
|
||||
with self.assertRaises(ValueError):
|
||||
Locale.parse('en_GB', '-')
|
||||
|
||||
def test_parse_locale_unknown_locale(self):
|
||||
with self.assertRaises(UnknownLocaleError):
|
||||
Locale.parse('foo', '_')
|
||||
@ -0,0 +1,691 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import datetime
|
||||
import logging
|
||||
import os
|
||||
import posixpath
|
||||
import stat
|
||||
import unittest
|
||||
from unittest import mock
|
||||
|
||||
from mkdocs import exceptions, utils
|
||||
from mkdocs.structure.files import File
|
||||
from mkdocs.structure.pages import Page
|
||||
from mkdocs.tests.base import dedent, load_config, tempdir
|
||||
from mkdocs.utils import meta
|
||||
|
||||
BASEYML = """
|
||||
INHERIT: parent.yml
|
||||
foo: bar
|
||||
baz:
|
||||
sub1: replaced
|
||||
sub3: new
|
||||
deep1:
|
||||
deep2-1:
|
||||
deep3-1: replaced
|
||||
"""
|
||||
PARENTYML = """
|
||||
foo: foo
|
||||
baz:
|
||||
sub1: 1
|
||||
sub2: 2
|
||||
deep1:
|
||||
deep2-1:
|
||||
deep3-1: foo
|
||||
deep3-2: bar
|
||||
deep2-2: baz
|
||||
"""
|
||||
|
||||
|
||||
class UtilsTests(unittest.TestCase):
|
||||
def test_is_markdown_file(self):
|
||||
expected_results = {
|
||||
'index.md': True,
|
||||
'index.markdown': True,
|
||||
'index.MARKDOWN': False,
|
||||
'index.txt': False,
|
||||
'indexmd': False,
|
||||
}
|
||||
for path, expected_result in expected_results.items():
|
||||
with self.subTest(path):
|
||||
is_markdown = utils.is_markdown_file(path)
|
||||
self.assertEqual(is_markdown, expected_result)
|
||||
|
||||
def test_get_relative_url(self):
|
||||
for case in [
|
||||
dict(url='foo/bar', other='foo', expected='bar'),
|
||||
dict(url='foo/bar.txt', other='foo', expected='bar.txt'),
|
||||
dict(url='foo', other='foo/bar', expected='..'),
|
||||
dict(url='foo', other='foo/bar.txt', expected='.'),
|
||||
dict(url='foo/../../bar', other='.', expected='bar'),
|
||||
dict(url='foo/../../bar', other='foo', expected='../bar'),
|
||||
dict(url='foo//./bar/baz', other='foo/bar/baz', expected='.'),
|
||||
dict(url='a/b/.././../c', other='.', expected='c'),
|
||||
dict(url='a/b/c/d/ee', other='a/b/c/d/e', expected='../ee'),
|
||||
dict(url='a/b/c/d/ee', other='a/b/z/d/e', expected='../../../c/d/ee'),
|
||||
dict(url='foo', other='bar.', expected='foo'),
|
||||
dict(url='foo', other='bar./', expected='../foo'),
|
||||
dict(url='foo', other='foo/bar./', expected='..'),
|
||||
dict(url='foo', other='foo/bar./.', expected='..'),
|
||||
dict(url='foo', other='foo/bar././', expected='..'),
|
||||
dict(url='foo/', other='foo/bar././', expected='../'),
|
||||
dict(url='foo', other='foo', expected='.'),
|
||||
dict(url='.foo', other='.foo', expected='.foo'),
|
||||
dict(url='.foo/', other='.foo', expected='.foo/'),
|
||||
dict(url='.foo', other='.foo/', expected='.'),
|
||||
dict(url='.foo/', other='.foo/', expected='./'),
|
||||
dict(url='///', other='', expected='./'),
|
||||
dict(url='a///', other='', expected='a/'),
|
||||
dict(url='a///', other='a', expected='./'),
|
||||
dict(url='.', other='here', expected='..'),
|
||||
dict(url='..', other='here', expected='..'),
|
||||
dict(url='../..', other='here', expected='..'),
|
||||
dict(url='../../a', other='here', expected='../a'),
|
||||
dict(url='..', other='here.txt', expected='.'),
|
||||
dict(url='a', other='', expected='a'),
|
||||
dict(url='a', other='..', expected='a'),
|
||||
dict(url='a', other='b', expected='../a'),
|
||||
# The dots are considered a file. Documenting a long-standing bug:
|
||||
dict(url='a', other='b/..', expected='../a'),
|
||||
dict(url='a', other='b/../..', expected='a'),
|
||||
dict(url='a/..../b', other='a/../b', expected='../a/..../b'),
|
||||
dict(url='a/я/b', other='a/я/c', expected='../b'),
|
||||
dict(url='a/я/b', other='a/яя/c', expected='../../я/b'),
|
||||
]:
|
||||
url, other, expected = case['url'], case['other'], case['expected']
|
||||
with self.subTest(url=url, other=other):
|
||||
# Leading slash intentionally ignored
|
||||
self.assertEqual(utils.get_relative_url(url, other), expected)
|
||||
self.assertEqual(utils.get_relative_url('/' + url, other), expected)
|
||||
self.assertEqual(utils.get_relative_url(url, '/' + other), expected)
|
||||
self.assertEqual(utils.get_relative_url('/' + url, '/' + other), expected)
|
||||
|
||||
def test_get_relative_url_empty(self):
|
||||
for url in ['', '.', '/.']:
|
||||
for other in ['', '.', '/', '/.']:
|
||||
with self.subTest(url=url, other=other):
|
||||
self.assertEqual(utils.get_relative_url(url, other), '.')
|
||||
|
||||
self.assertEqual(utils.get_relative_url('/', ''), './')
|
||||
self.assertEqual(utils.get_relative_url('/', '/'), './')
|
||||
self.assertEqual(utils.get_relative_url('/', '.'), './')
|
||||
self.assertEqual(utils.get_relative_url('/', '/.'), './')
|
||||
|
||||
def test_create_media_urls(self):
|
||||
expected_results = {
|
||||
'https://media.cdn.org/jq.js': [
|
||||
'https://media.cdn.org/jq.js',
|
||||
'https://media.cdn.org/jq.js',
|
||||
'https://media.cdn.org/jq.js',
|
||||
],
|
||||
'http://media.cdn.org/jquery.js': [
|
||||
'http://media.cdn.org/jquery.js',
|
||||
'http://media.cdn.org/jquery.js',
|
||||
'http://media.cdn.org/jquery.js',
|
||||
],
|
||||
'//media.cdn.org/jquery.js': [
|
||||
'//media.cdn.org/jquery.js',
|
||||
'//media.cdn.org/jquery.js',
|
||||
'//media.cdn.org/jquery.js',
|
||||
],
|
||||
'media.cdn.org/jquery.js': [
|
||||
'media.cdn.org/jquery.js',
|
||||
'media.cdn.org/jquery.js',
|
||||
'../media.cdn.org/jquery.js',
|
||||
],
|
||||
'local/file/jquery.js': [
|
||||
'local/file/jquery.js',
|
||||
'local/file/jquery.js',
|
||||
'../local/file/jquery.js',
|
||||
],
|
||||
'image.png': [
|
||||
'image.png',
|
||||
'image.png',
|
||||
'../image.png',
|
||||
],
|
||||
'style.css?v=20180308c': [
|
||||
'style.css?v=20180308c',
|
||||
'style.css?v=20180308c',
|
||||
'../style.css?v=20180308c',
|
||||
],
|
||||
'#some_id': [
|
||||
'#some_id',
|
||||
'#some_id',
|
||||
'#some_id',
|
||||
],
|
||||
}
|
||||
|
||||
cfg = load_config(use_directory_urls=False)
|
||||
pages = [
|
||||
Page(
|
||||
'Home',
|
||||
File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
|
||||
cfg,
|
||||
),
|
||||
Page(
|
||||
'About',
|
||||
File('about.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
|
||||
cfg,
|
||||
),
|
||||
Page(
|
||||
'FooBar',
|
||||
File('foo/bar.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
|
||||
cfg,
|
||||
),
|
||||
]
|
||||
|
||||
for i, page in enumerate(pages):
|
||||
urls = utils.create_media_urls(expected_results.keys(), page)
|
||||
self.assertEqual([v[i] for v in expected_results.values()], urls)
|
||||
|
||||
def test_create_media_urls_use_directory_urls(self):
|
||||
expected_results = {
|
||||
'https://media.cdn.org/jq.js': [
|
||||
'https://media.cdn.org/jq.js',
|
||||
'https://media.cdn.org/jq.js',
|
||||
'https://media.cdn.org/jq.js',
|
||||
],
|
||||
'http://media.cdn.org/jquery.js': [
|
||||
'http://media.cdn.org/jquery.js',
|
||||
'http://media.cdn.org/jquery.js',
|
||||
'http://media.cdn.org/jquery.js',
|
||||
],
|
||||
'//media.cdn.org/jquery.js': [
|
||||
'//media.cdn.org/jquery.js',
|
||||
'//media.cdn.org/jquery.js',
|
||||
'//media.cdn.org/jquery.js',
|
||||
],
|
||||
'media.cdn.org/jquery.js': [
|
||||
'media.cdn.org/jquery.js',
|
||||
'../media.cdn.org/jquery.js',
|
||||
'../../media.cdn.org/jquery.js',
|
||||
],
|
||||
'local/file/jquery.js': [
|
||||
'local/file/jquery.js',
|
||||
'../local/file/jquery.js',
|
||||
'../../local/file/jquery.js',
|
||||
],
|
||||
'image.png': [
|
||||
'image.png',
|
||||
'../image.png',
|
||||
'../../image.png',
|
||||
],
|
||||
'style.css?v=20180308c': [
|
||||
'style.css?v=20180308c',
|
||||
'../style.css?v=20180308c',
|
||||
'../../style.css?v=20180308c',
|
||||
],
|
||||
'#some_id': [
|
||||
'#some_id',
|
||||
'#some_id',
|
||||
'#some_id',
|
||||
],
|
||||
}
|
||||
|
||||
cfg = load_config(use_directory_urls=True)
|
||||
pages = [
|
||||
Page(
|
||||
'Home',
|
||||
File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
|
||||
cfg,
|
||||
),
|
||||
Page(
|
||||
'About',
|
||||
File('about.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
|
||||
cfg,
|
||||
),
|
||||
Page(
|
||||
'FooBar',
|
||||
File('foo/bar.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
|
||||
cfg,
|
||||
),
|
||||
]
|
||||
|
||||
for i, page in enumerate(pages):
|
||||
urls = utils.create_media_urls(expected_results.keys(), page)
|
||||
self.assertEqual([v[i] for v in expected_results.values()], urls)
|
||||
|
||||
# TODO: This shouldn't pass on Linux
|
||||
# @unittest.skipUnless(sys.platform.startswith("win"), "requires Windows")
|
||||
def test_create_media_urls_windows(self):
|
||||
expected_results = {
|
||||
'local\\windows\\file\\jquery.js': [
|
||||
'local/windows/file/jquery.js',
|
||||
'local/windows/file/jquery.js',
|
||||
'../local/windows/file/jquery.js',
|
||||
],
|
||||
}
|
||||
|
||||
cfg = load_config(use_directory_urls=False)
|
||||
pages = [
|
||||
Page(
|
||||
'Home',
|
||||
File('index.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
|
||||
cfg,
|
||||
),
|
||||
Page(
|
||||
'About',
|
||||
File('about.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
|
||||
cfg,
|
||||
),
|
||||
Page(
|
||||
'FooBar',
|
||||
File('foo/bar.md', cfg['docs_dir'], cfg['site_dir'], cfg['use_directory_urls']),
|
||||
cfg,
|
||||
),
|
||||
]
|
||||
|
||||
with self.assertLogs('mkdocs', level='WARNING'):
|
||||
for i, page in enumerate(pages):
|
||||
urls = utils.create_media_urls(expected_results.keys(), page)
|
||||
self.assertEqual([v[i] for v in expected_results.values()], urls)
|
||||
|
||||
def test_reduce_list(self):
|
||||
self.assertEqual(
|
||||
utils.reduce_list([1, 2, 3, 4, 5, 5, 2, 4, 6, 7, 8]),
|
||||
[1, 2, 3, 4, 5, 6, 7, 8],
|
||||
)
|
||||
|
||||
def test_insort(self):
|
||||
a = [1, 2, 3]
|
||||
utils.insort(a, 5)
|
||||
self.assertEqual(a, [1, 2, 3, 5])
|
||||
utils.insort(a, -1)
|
||||
self.assertEqual(a, [-1, 1, 2, 3, 5])
|
||||
utils.insort(a, 2)
|
||||
self.assertEqual(a, [-1, 1, 2, 2, 3, 5])
|
||||
utils.insort(a, 4)
|
||||
self.assertEqual(a, [-1, 1, 2, 2, 3, 4, 5])
|
||||
|
||||
def test_insort_key(self):
|
||||
a = [(1, 'a'), (1, 'b'), (2, 'c')]
|
||||
utils.insort(a, (1, 'a'), key=lambda v: v[0])
|
||||
self.assertEqual(a, [(1, 'a'), (1, 'b'), (1, 'a'), (2, 'c')])
|
||||
|
||||
def test_get_themes(self):
|
||||
themes = utils.get_theme_names()
|
||||
self.assertIn('mkdocs', themes)
|
||||
self.assertIn('readthedocs', themes)
|
||||
|
||||
@mock.patch('mkdocs.utils.entry_points', autospec=True)
|
||||
def test_get_theme_dir(self, mock_iter):
|
||||
path = 'some/path'
|
||||
|
||||
theme = mock.Mock()
|
||||
theme.name = 'mkdocs2'
|
||||
theme.dist.name = 'mkdocs2'
|
||||
theme.load().__file__ = os.path.join(path, '__init__.py')
|
||||
|
||||
mock_iter.return_value = [theme]
|
||||
|
||||
self.assertEqual(utils.get_theme_dir(theme.name), os.path.abspath(path))
|
||||
|
||||
def test_get_theme_dir_keyerror(self):
|
||||
with self.assertRaises(KeyError):
|
||||
utils.get_theme_dir('nonexistanttheme')
|
||||
|
||||
@mock.patch('mkdocs.utils.entry_points', autospec=True)
|
||||
def test_get_theme_dir_importerror(self, mock_iter):
|
||||
theme = mock.Mock()
|
||||
theme.name = 'mkdocs2'
|
||||
theme.dist.name = 'mkdocs2'
|
||||
theme.load.side_effect = ImportError()
|
||||
|
||||
mock_iter.return_value = [theme]
|
||||
|
||||
with self.assertRaises(ImportError):
|
||||
utils.get_theme_dir(theme.name)
|
||||
|
||||
@mock.patch('mkdocs.utils.entry_points', autospec=True)
|
||||
def test_get_themes_warning(self, mock_iter):
|
||||
theme1 = mock.Mock()
|
||||
theme1.name = 'mkdocs2'
|
||||
theme1.dist.name = 'mkdocs2'
|
||||
theme1.load().__file__ = "some/path1"
|
||||
|
||||
theme2 = mock.Mock()
|
||||
theme2.name = 'mkdocs2'
|
||||
theme2.dist.name = 'mkdocs3'
|
||||
theme2.load().__file__ = "some/path2"
|
||||
|
||||
mock_iter.return_value = [theme1, theme2]
|
||||
|
||||
with self.assertLogs('mkdocs') as cm:
|
||||
theme_names = utils.get_theme_names()
|
||||
self.assertEqual(
|
||||
'\n'.join(cm.output),
|
||||
"WARNING:mkdocs.utils:A theme named 'mkdocs2' is provided by the Python "
|
||||
"packages 'mkdocs3' and 'mkdocs2'. The one in 'mkdocs3' will be used.",
|
||||
)
|
||||
self.assertCountEqual(theme_names, ['mkdocs2'])
|
||||
|
||||
@mock.patch('mkdocs.utils.entry_points', autospec=True)
|
||||
def test_get_themes_error(self, mock_iter):
|
||||
theme1 = mock.Mock()
|
||||
theme1.name = 'mkdocs'
|
||||
theme1.dist.name = 'mkdocs'
|
||||
theme1.load().__file__ = "some/path1"
|
||||
|
||||
theme2 = mock.Mock()
|
||||
theme2.name = 'mkdocs'
|
||||
theme2.dist.name = 'mkdocs2'
|
||||
theme2.load().__file__ = "some/path2"
|
||||
|
||||
mock_iter.return_value = [theme1, theme2]
|
||||
|
||||
with self.assertRaisesRegex(
|
||||
exceptions.ConfigurationError,
|
||||
"The theme 'mkdocs' is a builtin theme but the package 'mkdocs2' "
|
||||
"attempts to provide a theme with the same name.",
|
||||
):
|
||||
utils.get_theme_names()
|
||||
|
||||
def test_nest_paths(self, j=posixpath.join):
|
||||
result = utils.nest_paths(
|
||||
[
|
||||
'index.md',
|
||||
j('user-guide', 'configuration.md'),
|
||||
j('user-guide', 'styling-your-docs.md'),
|
||||
j('user-guide', 'writing-your-docs.md'),
|
||||
j('about', 'contributing.md'),
|
||||
j('about', 'license.md'),
|
||||
j('about', 'release-notes.md'),
|
||||
]
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
result,
|
||||
[
|
||||
'index.md',
|
||||
{
|
||||
'User guide': [
|
||||
j('user-guide', 'configuration.md'),
|
||||
j('user-guide', 'styling-your-docs.md'),
|
||||
j('user-guide', 'writing-your-docs.md'),
|
||||
]
|
||||
},
|
||||
{
|
||||
'About': [
|
||||
j('about', 'contributing.md'),
|
||||
j('about', 'license.md'),
|
||||
j('about', 'release-notes.md'),
|
||||
]
|
||||
},
|
||||
],
|
||||
)
|
||||
|
||||
def test_nest_paths_native(self):
|
||||
self.test_nest_paths(os.path.join)
|
||||
|
||||
def test_unicode_yaml(self):
|
||||
yaml_src = dedent(
|
||||
'''
|
||||
key: value
|
||||
key2:
|
||||
- value
|
||||
'''
|
||||
).encode('utf-8')
|
||||
|
||||
config = utils.yaml_load(yaml_src)
|
||||
self.assertTrue(isinstance(config['key'], str))
|
||||
self.assertTrue(isinstance(config['key2'][0], str))
|
||||
|
||||
@mock.patch.dict(os.environ, {'VARNAME': 'Hello, World!', 'BOOLVAR': 'false'})
|
||||
def test_env_var_in_yaml(self):
|
||||
yaml_src = dedent(
|
||||
'''
|
||||
key1: !ENV VARNAME
|
||||
key2: !ENV UNDEFINED
|
||||
key3: !ENV [UNDEFINED, default]
|
||||
key4: !ENV [UNDEFINED, VARNAME, default]
|
||||
key5: !ENV BOOLVAR
|
||||
'''
|
||||
)
|
||||
config = utils.yaml_load(yaml_src)
|
||||
self.assertEqual(config['key1'], 'Hello, World!')
|
||||
self.assertIsNone(config['key2'])
|
||||
self.assertEqual(config['key3'], 'default')
|
||||
self.assertEqual(config['key4'], 'Hello, World!')
|
||||
self.assertIs(config['key5'], False)
|
||||
|
||||
@tempdir(files={'base.yml': BASEYML, 'parent.yml': PARENTYML})
|
||||
def test_yaml_inheritance(self, tdir):
|
||||
expected = {
|
||||
'foo': 'bar',
|
||||
'baz': {
|
||||
'sub1': 'replaced',
|
||||
'sub2': 2,
|
||||
'sub3': 'new',
|
||||
},
|
||||
'deep1': {
|
||||
'deep2-1': {
|
||||
'deep3-1': 'replaced',
|
||||
'deep3-2': 'bar',
|
||||
},
|
||||
'deep2-2': 'baz',
|
||||
},
|
||||
}
|
||||
with open(os.path.join(tdir, 'base.yml')) as fd:
|
||||
result = utils.yaml_load(fd)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
@tempdir(files={'base.yml': BASEYML})
|
||||
def test_yaml_inheritance_missing_parent(self, tdir):
|
||||
with open(os.path.join(tdir, 'base.yml')) as fd:
|
||||
with self.assertRaises(exceptions.ConfigurationError):
|
||||
utils.yaml_load(fd)
|
||||
|
||||
@tempdir()
|
||||
@tempdir()
|
||||
def test_copy_files(self, src_dir, dst_dir):
|
||||
cases = [
|
||||
dict(
|
||||
src_path='foo.txt',
|
||||
dst_path='foo.txt',
|
||||
expected='foo.txt',
|
||||
),
|
||||
dict(
|
||||
src_path='bar.txt',
|
||||
dst_path='foo/', # ensure src filename is appended
|
||||
expected='foo/bar.txt',
|
||||
),
|
||||
dict(
|
||||
src_path='baz.txt',
|
||||
dst_path='foo/bar/baz.txt', # ensure missing dirs are created
|
||||
expected='foo/bar/baz.txt',
|
||||
),
|
||||
]
|
||||
|
||||
for case in cases:
|
||||
src, dst, expected = case['src_path'], case['dst_path'], case['expected']
|
||||
with self.subTest(src):
|
||||
src = os.path.join(src_dir, src)
|
||||
with open(src, 'w') as f:
|
||||
f.write('content')
|
||||
dst = os.path.join(dst_dir, dst)
|
||||
utils.copy_file(src, dst)
|
||||
self.assertTrue(os.path.isfile(os.path.join(dst_dir, expected)))
|
||||
|
||||
@tempdir()
|
||||
@tempdir()
|
||||
def test_copy_files_without_permissions(self, src_dir, dst_dir):
|
||||
cases = [
|
||||
dict(src_path='foo.txt', expected='foo.txt'),
|
||||
dict(src_path='bar.txt', expected='bar.txt'),
|
||||
dict(src_path='baz.txt', expected='baz.txt'),
|
||||
]
|
||||
|
||||
try:
|
||||
for case in cases:
|
||||
src, expected = case['src_path'], case['expected']
|
||||
with self.subTest(src):
|
||||
src = os.path.join(src_dir, src)
|
||||
with open(src, 'w') as f:
|
||||
f.write('content')
|
||||
# Set src file to read-only
|
||||
os.chmod(src, stat.S_IRUSR)
|
||||
utils.copy_file(src, dst_dir)
|
||||
self.assertTrue(os.path.isfile(os.path.join(dst_dir, expected)))
|
||||
self.assertNotEqual(
|
||||
os.stat(src).st_mode, os.stat(os.path.join(dst_dir, expected)).st_mode
|
||||
)
|
||||
# While src was read-only, dst must remain writable
|
||||
self.assertTrue(os.access(os.path.join(dst_dir, expected), os.W_OK))
|
||||
finally:
|
||||
for case in cases:
|
||||
# Undo read-only so we can delete temp files
|
||||
src = os.path.join(src_dir, case['src_path'])
|
||||
if os.path.exists(src):
|
||||
os.chmod(src, stat.S_IRUSR | stat.S_IWUSR)
|
||||
|
||||
def test_mm_meta_data(self):
|
||||
doc = dedent(
|
||||
"""
|
||||
Title: Foo Bar
|
||||
Date: 2018-07-10
|
||||
Summary: Line one
|
||||
Line two
|
||||
Tags: foo
|
||||
Tags: bar
|
||||
|
||||
Doc body
|
||||
"""
|
||||
)
|
||||
self.assertEqual(
|
||||
meta.get_data(doc),
|
||||
(
|
||||
"Doc body",
|
||||
{
|
||||
'title': 'Foo Bar',
|
||||
'date': '2018-07-10',
|
||||
'summary': 'Line one Line two',
|
||||
'tags': 'foo bar',
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
def test_mm_meta_data_blank_first_line(self):
|
||||
doc = '\nfoo: bar\nDoc body'
|
||||
self.assertEqual(meta.get_data(doc), (doc.lstrip(), {}))
|
||||
|
||||
def test_yaml_meta_data(self):
|
||||
doc = dedent(
|
||||
"""
|
||||
---
|
||||
Title: Foo Bar
|
||||
Date: 2018-07-10
|
||||
Summary: Line one
|
||||
Line two
|
||||
Tags:
|
||||
- foo
|
||||
- bar
|
||||
---
|
||||
Doc body
|
||||
"""
|
||||
)
|
||||
self.assertEqual(
|
||||
meta.get_data(doc),
|
||||
(
|
||||
"Doc body",
|
||||
{
|
||||
'Title': 'Foo Bar',
|
||||
'Date': datetime.date(2018, 7, 10),
|
||||
'Summary': 'Line one Line two',
|
||||
'Tags': ['foo', 'bar'],
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
def test_yaml_meta_data_not_dict(self):
|
||||
doc = dedent(
|
||||
"""
|
||||
---
|
||||
- List item
|
||||
---
|
||||
Doc body
|
||||
"""
|
||||
)
|
||||
self.assertEqual(meta.get_data(doc), (doc, {}))
|
||||
|
||||
def test_yaml_meta_data_invalid(self):
|
||||
doc = dedent(
|
||||
"""
|
||||
---
|
||||
foo: bar: baz
|
||||
---
|
||||
Doc body
|
||||
"""
|
||||
)
|
||||
self.assertEqual(meta.get_data(doc), (doc, {}))
|
||||
|
||||
def test_no_meta_data(self):
|
||||
doc = dedent(
|
||||
"""
|
||||
Doc body
|
||||
"""
|
||||
)
|
||||
self.assertEqual(meta.get_data(doc), (doc, {}))
|
||||
|
||||
|
||||
class LogCounterTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.log = logging.getLogger('dummy')
|
||||
self.log.propagate = False
|
||||
self.log.setLevel(1)
|
||||
self.counter = utils.CountHandler()
|
||||
self.log.addHandler(self.counter)
|
||||
|
||||
def tearDown(self):
|
||||
self.log.removeHandler(self.counter)
|
||||
|
||||
def test_default_values(self):
|
||||
self.assertEqual(self.counter.get_counts(), [])
|
||||
|
||||
def test_count_critical(self):
|
||||
self.assertEqual(self.counter.get_counts(), [])
|
||||
self.log.critical('msg')
|
||||
self.assertEqual(self.counter.get_counts(), [('CRITICAL', 1)])
|
||||
|
||||
def test_count_error(self):
|
||||
self.assertEqual(self.counter.get_counts(), [])
|
||||
self.log.error('msg')
|
||||
self.assertEqual(self.counter.get_counts(), [('ERROR', 1)])
|
||||
|
||||
def test_count_warning(self):
|
||||
self.assertEqual(self.counter.get_counts(), [])
|
||||
self.log.warning('msg')
|
||||
self.assertEqual(self.counter.get_counts(), [('WARNING', 1)])
|
||||
|
||||
def test_count_info(self):
|
||||
self.assertEqual(self.counter.get_counts(), [])
|
||||
self.log.info('msg')
|
||||
self.assertEqual(self.counter.get_counts(), [('INFO', 1)])
|
||||
|
||||
def test_count_debug(self):
|
||||
self.assertEqual(self.counter.get_counts(), [])
|
||||
self.log.debug('msg')
|
||||
self.assertEqual(self.counter.get_counts(), [('DEBUG', 1)])
|
||||
|
||||
def test_count_multiple(self):
|
||||
self.assertEqual(self.counter.get_counts(), [])
|
||||
self.log.warning('msg 1')
|
||||
self.assertEqual(self.counter.get_counts(), [('WARNING', 1)])
|
||||
self.log.warning('msg 2')
|
||||
self.assertEqual(self.counter.get_counts(), [('WARNING', 2)])
|
||||
self.log.debug('msg 3')
|
||||
self.assertEqual(self.counter.get_counts(), [('WARNING', 2), ('DEBUG', 1)])
|
||||
self.log.error('mdg 4')
|
||||
self.assertEqual(self.counter.get_counts(), [('ERROR', 1), ('WARNING', 2), ('DEBUG', 1)])
|
||||
|
||||
def test_log_level(self):
|
||||
self.assertEqual(self.counter.get_counts(), [])
|
||||
self.counter.setLevel(logging.ERROR)
|
||||
self.log.error('counted')
|
||||
self.log.warning('not counted')
|
||||
self.log.info('not counted')
|
||||
self.assertEqual(self.counter.get_counts(), [('ERROR', 1)])
|
||||
self.counter.setLevel(logging.WARNING)
|
||||
self.log.error('counted')
|
||||
self.log.warning('counted')
|
||||
self.log.info('not counted')
|
||||
self.assertEqual(self.counter.get_counts(), [('ERROR', 2), ('WARNING', 1)])
|
||||
Reference in New Issue
Block a user