Aluode/PerceptionLabPortable
0
1"""Tests for distutils.filelist."""2 3import logging4import os5import re6from distutils import debug, filelist7from distutils.errors import DistutilsTemplateError8from distutils.filelist import FileList, glob_to_re, translate_pattern9 10import jaraco.path11import pytest12 13from .compat import py39 as os_helper14 15MANIFEST_IN = """\16include ok17include xo18exclude xo19include foo.tmp20include buildout.cfg21global-include *.x22global-include *.txt23global-exclude *.tmp24recursive-include f *.oo25recursive-exclude global *.x26graft dir27prune dir328"""29 30 31def make_local_path(s):32 """Converts '/' in a string to os.sep"""33 return s.replace('/', os.sep)34 35 36class TestFileList:37 def assertNoWarnings(self, caplog):38 warnings = [rec for rec in caplog.records if rec.levelno == logging.WARNING]39 assert not warnings40 caplog.clear()41 42 def assertWarnings(self, caplog):43 warnings = [rec for rec in caplog.records if rec.levelno == logging.WARNING]44 assert warnings45 caplog.clear()46 47 def test_glob_to_re(self):48 sep = os.sep49 if os.sep == '\\':50 sep = re.escape(os.sep)51 52 for glob, regex in (53 # simple cases54 ('foo*', r'(?s:foo[^%(sep)s]*)\Z'),55 ('foo?', r'(?s:foo[^%(sep)s])\Z'),56 ('foo??', r'(?s:foo[^%(sep)s][^%(sep)s])\Z'),57 # special cases58 (r'foo\\*', r'(?s:foo\\\\[^%(sep)s]*)\Z'),59 (r'foo\\\*', r'(?s:foo\\\\\\[^%(sep)s]*)\Z'),60 ('foo????', r'(?s:foo[^%(sep)s][^%(sep)s][^%(sep)s][^%(sep)s])\Z'),61 (r'foo\\??', r'(?s:foo\\\\[^%(sep)s][^%(sep)s])\Z'),62 ):63 regex = regex % {'sep': sep}64 assert glob_to_re(glob) == regex65 66 def test_process_template_line(self):67 # testing all MANIFEST.in template patterns68 file_list = FileList()69 mlp = make_local_path70 71 # simulated file list72 file_list.allfiles = [73 'foo.tmp',74 'ok',75 'xo',76 'four.txt',77 'buildout.cfg',78 # filelist does not filter out VCS directories,79 # it's sdist that does80 mlp('.hg/last-message.txt'),81 mlp('global/one.txt'),82 mlp('global/two.txt'),83 mlp('global/files.x'),84 mlp('global/here.tmp'),85 mlp('f/o/f.oo'),86 mlp('dir/graft-one'),87 mlp('dir/dir2/graft2'),88 mlp('dir3/ok'),89 mlp('dir3/sub/ok.txt'),90 ]91 92 for line in MANIFEST_IN.split('\n'):93 if line.strip() == '':94 continue95 file_list.process_template_line(line)96 97 wanted = [98 'ok',99 'buildout.cfg',100 'four.txt',101 mlp('.hg/last-message.txt'),102 mlp('global/one.txt'),103 mlp('global/two.txt'),104 mlp('f/o/f.oo'),105 mlp('dir/graft-one'),106 mlp('dir/dir2/graft2'),107 ]108 109 assert file_list.files == wanted110 111 def test_debug_print(self, capsys, monkeypatch):112 file_list = FileList()113 file_list.debug_print('xxx')114 assert capsys.readouterr().out == ''115 116 monkeypatch.setattr(debug, 'DEBUG', True)117 file_list.debug_print('xxx')118 assert capsys.readouterr().out == 'xxx\n'119 120 def test_set_allfiles(self):121 file_list = FileList()122 files = ['a', 'b', 'c']123 file_list.set_allfiles(files)124 assert file_list.allfiles == files125 126 def test_remove_duplicates(self):127 file_list = FileList()128 file_list.files = ['a', 'b', 'a', 'g', 'c', 'g']129 # files must be sorted beforehand (sdist does it)130 file_list.sort()131 file_list.remove_duplicates()132 assert file_list.files == ['a', 'b', 'c', 'g']133 134 def test_translate_pattern(self):135 # not regex136 assert hasattr(translate_pattern('a', anchor=True, is_regex=False), 'search')137 138 # is a regex139 regex = re.compile('a')140 assert translate_pattern(regex, anchor=True, is_regex=True) == regex141 142 # plain string flagged as regex143 assert hasattr(translate_pattern('a', anchor=True, is_regex=True), 'search')144 145 # glob support146 assert translate_pattern('*.py', anchor=True, is_regex=False).search(147 'filelist.py'148 )149 150 def test_exclude_pattern(self):151 # return False if no match152 file_list = FileList()153 assert not file_list.exclude_pattern('*.py')154 155 # return True if files match156 file_list = FileList()157 file_list.files = ['a.py', 'b.py']158 assert file_list.exclude_pattern('*.py')159 160 # test excludes161 file_list = FileList()162 file_list.files = ['a.py', 'a.txt']163 file_list.exclude_pattern('*.py')164 assert file_list.files == ['a.txt']165 166 def test_include_pattern(self):167 # return False if no match168 file_list = FileList()169 file_list.set_allfiles([])170 assert not file_list.include_pattern('*.py')171 172 # return True if files match173 file_list = FileList()174 file_list.set_allfiles(['a.py', 'b.txt'])175 assert file_list.include_pattern('*.py')176 177 # test * matches all files178 file_list = FileList()179 assert file_list.allfiles is None180 file_list.set_allfiles(['a.py', 'b.txt'])181 file_list.include_pattern('*')182 assert file_list.allfiles == ['a.py', 'b.txt']183 184 def test_process_template(self, caplog):185 mlp = make_local_path186 # invalid lines187 file_list = FileList()188 for action in (189 'include',190 'exclude',191 'global-include',192 'global-exclude',193 'recursive-include',194 'recursive-exclude',195 'graft',196 'prune',197 'blarg',198 ):199 with pytest.raises(DistutilsTemplateError):200 file_list.process_template_line(action)201 202 # include203 file_list = FileList()204 file_list.set_allfiles(['a.py', 'b.txt', mlp('d/c.py')])205 206 file_list.process_template_line('include *.py')207 assert file_list.files == ['a.py']208 self.assertNoWarnings(caplog)209 210 file_list.process_template_line('include *.rb')211 assert file_list.files == ['a.py']212 self.assertWarnings(caplog)213 214 # exclude215 file_list = FileList()216 file_list.files = ['a.py', 'b.txt', mlp('d/c.py')]217 218 file_list.process_template_line('exclude *.py')219 assert file_list.files == ['b.txt', mlp('d/c.py')]220 self.assertNoWarnings(caplog)221 222 file_list.process_template_line('exclude *.rb')223 assert file_list.files == ['b.txt', mlp('d/c.py')]224 self.assertWarnings(caplog)225 226 # global-include227 file_list = FileList()228 file_list.set_allfiles(['a.py', 'b.txt', mlp('d/c.py')])229 230 file_list.process_template_line('global-include *.py')231 assert file_list.files == ['a.py', mlp('d/c.py')]232 self.assertNoWarnings(caplog)233 234 file_list.process_template_line('global-include *.rb')235 assert file_list.files == ['a.py', mlp('d/c.py')]236 self.assertWarnings(caplog)237 238 # global-exclude239 file_list = FileList()240 file_list.files = ['a.py', 'b.txt', mlp('d/c.py')]241 242 file_list.process_template_line('global-exclude *.py')243 assert file_list.files == ['b.txt']244 self.assertNoWarnings(caplog)245 246 file_list.process_template_line('global-exclude *.rb')247 assert file_list.files == ['b.txt']248 self.assertWarnings(caplog)249 250 # recursive-include251 file_list = FileList()252 file_list.set_allfiles(['a.py', mlp('d/b.py'), mlp('d/c.txt'), mlp('d/d/e.py')])253 254 file_list.process_template_line('recursive-include d *.py')255 assert file_list.files == [mlp('d/b.py'), mlp('d/d/e.py')]256 self.assertNoWarnings(caplog)257 258 file_list.process_template_line('recursive-include e *.py')259 assert file_list.files == [mlp('d/b.py'), mlp('d/d/e.py')]260 self.assertWarnings(caplog)261 262 # recursive-exclude263 file_list = FileList()264 file_list.files = ['a.py', mlp('d/b.py'), mlp('d/c.txt'), mlp('d/d/e.py')]265 266 file_list.process_template_line('recursive-exclude d *.py')267 assert file_list.files == ['a.py', mlp('d/c.txt')]268 self.assertNoWarnings(caplog)269 270 file_list.process_template_line('recursive-exclude e *.py')271 assert file_list.files == ['a.py', mlp('d/c.txt')]272 self.assertWarnings(caplog)273 274 # graft275 file_list = FileList()276 file_list.set_allfiles(['a.py', mlp('d/b.py'), mlp('d/d/e.py'), mlp('f/f.py')])277 278 file_list.process_template_line('graft d')279 assert file_list.files == [mlp('d/b.py'), mlp('d/d/e.py')]280 self.assertNoWarnings(caplog)281 282 file_list.process_template_line('graft e')283 assert file_list.files == [mlp('d/b.py'), mlp('d/d/e.py')]284 self.assertWarnings(caplog)285 286 # prune287 file_list = FileList()288 file_list.files = ['a.py', mlp('d/b.py'), mlp('d/d/e.py'), mlp('f/f.py')]289 290 file_list.process_template_line('prune d')291 assert file_list.files == ['a.py', mlp('f/f.py')]292 self.assertNoWarnings(caplog)293 294 file_list.process_template_line('prune e')295 assert file_list.files == ['a.py', mlp('f/f.py')]296 self.assertWarnings(caplog)297 298 299class TestFindAll:300 @os_helper.skip_unless_symlink301 def test_missing_symlink(self, temp_cwd):302 os.symlink('foo', 'bar')303 assert filelist.findall() == []304 305 def test_basic_discovery(self, temp_cwd):306 """307 When findall is called with no parameters or with308 '.' as the parameter, the dot should be omitted from309 the results.310 """311 jaraco.path.build({'foo': {'file1.txt': ''}, 'bar': {'file2.txt': ''}})312 file1 = os.path.join('foo', 'file1.txt')313 file2 = os.path.join('bar', 'file2.txt')314 expected = [file2, file1]315 assert sorted(filelist.findall()) == expected316 317 def test_non_local_discovery(self, tmp_path):318 """319 When findall is called with another path, the full320 path name should be returned.321 """322 jaraco.path.build({'file1.txt': ''}, tmp_path)323 expected = [str(tmp_path / 'file1.txt')]324 assert filelist.findall(tmp_path) == expected325 326 @os_helper.skip_unless_symlink327 def test_symlink_loop(self, tmp_path):328 jaraco.path.build(329 {330 'link-to-parent': jaraco.path.Symlink('.'),331 'somefile': '',332 },333 tmp_path,334 )335 files = filelist.findall(tmp_path)336 assert len(files) == 1337 