1""" 2 test_util 3 ~~~~~~~~~~~~~~~ 4 5 Tests util functions. 6 7 :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. 8 :license: BSD, see LICENSE for details. 9""" 10 11import os 12import tempfile 13from unittest.mock import patch 14 15import pytest 16 17from sphinx.errors import ExtensionError 18from sphinx.testing.util import strip_escseq 19from sphinx.util import (SkipProgressMessage, display_chunk, encode_uri, ensuredir, 20 import_object, logging, parselinenos, progress_message, 21 status_iterator, xmlname_checker) 22 23 24def test_encode_uri(): 25 expected = ('https://ru.wikipedia.org/wiki/%D0%A1%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%B0_' 26 '%D1%83%D0%BF%D1%80%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F_' 27 '%D0%B1%D0%B0%D0%B7%D0%B0%D0%BC%D0%B8_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85') 28 uri = ('https://ru.wikipedia.org/wiki' 29 '/Система_управления_базами_данных') 30 assert expected == encode_uri(uri) 31 32 expected = ('https://github.com/search?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+is%3A' 33 'sprint-friendly+user%3Ajupyter&type=Issues&ref=searchresults') 34 uri = ('https://github.com/search?utf8=✓&q=is%3Aissue+is%3Aopen+is%3A' 35 'sprint-friendly+user%3Ajupyter&type=Issues&ref=searchresults') 36 assert expected == encode_uri(uri) 37 38 39def test_ensuredir(): 40 with tempfile.TemporaryDirectory() as tmp_path: 41 # Does not raise an exception for an existing directory. 42 ensuredir(tmp_path) 43 44 path = os.path.join(tmp_path, 'a', 'b', 'c') 45 ensuredir(path) 46 assert os.path.isdir(path) 47 48 with tempfile.NamedTemporaryFile() as tmp: 49 with pytest.raises(OSError): 50 ensuredir(tmp.name) 51 52 53def test_display_chunk(): 54 assert display_chunk('hello') == 'hello' 55 assert display_chunk(['hello']) == 'hello' 56 assert display_chunk(['hello', 'sphinx', 'world']) == 'hello .. world' 57 assert display_chunk(('hello',)) == 'hello' 58 assert display_chunk(('hello', 'sphinx', 'world')) == 'hello .. world' 59 60 61def test_import_object(): 62 module = import_object('sphinx') 63 assert module.__name__ == 'sphinx' 64 65 module = import_object('sphinx.application') 66 assert module.__name__ == 'sphinx.application' 67 68 obj = import_object('sphinx.application.Sphinx') 69 assert obj.__name__ == 'Sphinx' 70 71 with pytest.raises(ExtensionError) as exc: 72 import_object('sphinx.unknown_module') 73 assert exc.value.args[0] == 'Could not import sphinx.unknown_module' 74 75 with pytest.raises(ExtensionError) as exc: 76 import_object('sphinx.unknown_module', 'my extension') 77 assert exc.value.args[0] == ('Could not import sphinx.unknown_module ' 78 '(needed for my extension)') 79 80 81@pytest.mark.sphinx('dummy') 82@patch('sphinx.util.console._tw', 40) # terminal width = 40 83def test_status_iterator(app, status, warning): 84 logging.setup(app, status, warning) 85 86 # test for old_status_iterator 87 status.truncate(0) 88 yields = list(status_iterator(['hello', 'sphinx', 'world'], 'testing ... ')) 89 output = strip_escseq(status.getvalue()) 90 assert 'testing ... hello sphinx world \n' in output 91 assert yields == ['hello', 'sphinx', 'world'] 92 93 # test for status_iterator (verbosity=0) 94 status.truncate(0) 95 yields = list(status_iterator(['hello', 'sphinx', 'world'], 'testing ... ', 96 length=3, verbosity=0)) 97 output = strip_escseq(status.getvalue()) 98 assert 'testing ... [ 33%] hello \r' in output 99 assert 'testing ... [ 66%] sphinx \r' in output 100 assert 'testing ... [100%] world \r\n' in output 101 assert yields == ['hello', 'sphinx', 'world'] 102 103 # test for status_iterator (verbosity=1) 104 status.truncate(0) 105 yields = list(status_iterator(['hello', 'sphinx', 'world'], 'testing ... ', 106 length=3, verbosity=1)) 107 output = strip_escseq(status.getvalue()) 108 assert 'testing ... [ 33%] hello\n' in output 109 assert 'testing ... [ 66%] sphinx\n' in output 110 assert 'testing ... [100%] world\n\n' in output 111 assert yields == ['hello', 'sphinx', 'world'] 112 113 114def test_parselinenos(): 115 assert parselinenos('1,2,3', 10) == [0, 1, 2] 116 assert parselinenos('4, 5, 6', 10) == [3, 4, 5] 117 assert parselinenos('-4', 10) == [0, 1, 2, 3] 118 assert parselinenos('7-9', 10) == [6, 7, 8] 119 assert parselinenos('7-', 10) == [6, 7, 8, 9] 120 assert parselinenos('1,7-', 10) == [0, 6, 7, 8, 9] 121 assert parselinenos('7-7', 10) == [6] 122 assert parselinenos('11-', 10) == [10] 123 with pytest.raises(ValueError): 124 parselinenos('1-2-3', 10) 125 with pytest.raises(ValueError): 126 parselinenos('abc-def', 10) 127 with pytest.raises(ValueError): 128 parselinenos('-', 10) 129 with pytest.raises(ValueError): 130 parselinenos('3-1', 10) 131 132 133def test_progress_message(app, status, warning): 134 logging.setup(app, status, warning) 135 logger = logging.getLogger(__name__) 136 137 # standard case 138 with progress_message('testing'): 139 logger.info('blah ', nonl=True) 140 141 output = strip_escseq(status.getvalue()) 142 assert 'testing... blah done\n' in output 143 144 # skipping case 145 with progress_message('testing'): 146 raise SkipProgressMessage('Reason: %s', 'error') 147 148 output = strip_escseq(status.getvalue()) 149 assert 'testing... skipped\nReason: error\n' in output 150 151 # error case 152 try: 153 with progress_message('testing'): 154 raise 155 except Exception: 156 pass 157 158 output = strip_escseq(status.getvalue()) 159 assert 'testing... failed\n' in output 160 161 # decorator 162 @progress_message('testing') 163 def func(): 164 logger.info('in func ', nonl=True) 165 166 func() 167 output = strip_escseq(status.getvalue()) 168 assert 'testing... in func done\n' in output 169 170 171def test_xmlname_check(): 172 checker = xmlname_checker() 173 assert checker.match('id-pub') 174 assert checker.match('webpage') 175 assert not checker.match('1bfda21') 176