test_fs.py 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037
  1. # coding=utf-8
  2. import errno
  3. import os
  4. import pytest
  5. import shutil
  6. import six
  7. import library.python.fs
  8. import library.python.strings
  9. import library.python.tmp
  10. import library.python.windows
  11. import yatest.common
  12. def in_env(case):
  13. def wrapped_case(*args, **kwargs):
  14. with library.python.tmp.temp_dir() as temp_dir:
  15. case(lambda path: os.path.join(temp_dir, path))
  16. return wrapped_case
  17. def mkfile(path, data=''):
  18. with open(path, 'wb') as f:
  19. if data:
  20. f.write(data) if isinstance(data, six.binary_type) else f.write(
  21. data.encode(library.python.strings.fs_encoding())
  22. )
  23. def mktree_example(path, name):
  24. os.mkdir(path(name))
  25. mkfile(path(name + '/file1'), 'FILE1')
  26. os.mkdir(path(name + '/dir1'))
  27. os.mkdir(path(name + '/dir2'))
  28. mkfile(path(name + '/dir2/file2'), 'FILE2')
  29. mkfile(path(name + '/dir2/file3'), 'FILE3')
  30. def file_data(path):
  31. with open(path, 'rb') as f:
  32. return f.read().decode('utf-8')
  33. def serialize_tree(path):
  34. if os.path.isfile(path):
  35. return file_data(path)
  36. data = {'dirs': set(), 'files': {}}
  37. for dirpath, dirnames, filenames in os.walk(path):
  38. dirpath_rel = os.path.relpath(dirpath, path)
  39. if dirpath_rel == '.':
  40. dirpath_rel = ''
  41. data['dirs'].update(set(os.path.join(dirpath_rel, x) for x in dirnames))
  42. data['files'].update({os.path.join(dirpath_rel, x): file_data(os.path.join(dirpath, x)) for x in filenames})
  43. return data
  44. def trees_equal(dir1, dir2):
  45. return serialize_tree(dir1) == serialize_tree(dir2)
  46. def inodes_unsupported():
  47. return library.python.windows.on_win()
  48. def inodes_equal(path1, path2):
  49. return os.stat(path1).st_ino == os.stat(path2).st_ino
  50. def gen_error_access_denied():
  51. if library.python.windows.on_win():
  52. err = WindowsError()
  53. err.errno = errno.EACCES
  54. err.strerror = ''
  55. err.winerror = library.python.windows.ERRORS['ACCESS_DENIED']
  56. else:
  57. err = OSError()
  58. err.errno = errno.EACCES
  59. err.strerror = os.strerror(err.errno)
  60. err.filename = 'unknown/file'
  61. raise err
  62. def test_errorfix_win():
  63. @library.python.fs.errorfix_win
  64. def erroneous_func():
  65. gen_error_access_denied()
  66. with pytest.raises(OSError) as errinfo:
  67. erroneous_func()
  68. assert errinfo.value.errno == errno.EACCES
  69. assert errinfo.value.filename == 'unknown/file'
  70. # See transcode_error, which encodes strerror, in library/python/windows/__init__.py
  71. assert isinstance(errinfo.value.strerror, (six.binary_type, six.text_type))
  72. assert errinfo.value.strerror
  73. def test_custom_fs_error():
  74. with pytest.raises(OSError) as errinfo:
  75. raise library.python.fs.CustomFsError(errno.EACCES, filename='some/file')
  76. assert errinfo.value.errno == errno.EACCES
  77. # See transcode_error, which encodes strerror, in library/python/windows/__init__.py
  78. assert isinstance(errinfo.value.strerror, (six.binary_type, six.text_type))
  79. assert errinfo.value.filename == 'some/file'
  80. @in_env
  81. def test_ensure_dir(path):
  82. library.python.fs.ensure_dir(path('dir/subdir'))
  83. assert os.path.isdir(path('dir'))
  84. assert os.path.isdir(path('dir/subdir'))
  85. @in_env
  86. def test_ensure_dir_exists(path):
  87. os.makedirs(path('dir/subdir'))
  88. library.python.fs.ensure_dir(path('dir/subdir'))
  89. assert os.path.isdir(path('dir'))
  90. assert os.path.isdir(path('dir/subdir'))
  91. @in_env
  92. def test_ensure_dir_exists_partly(path):
  93. os.mkdir(path('dir'))
  94. library.python.fs.ensure_dir(path('dir/subdir'))
  95. assert os.path.isdir(path('dir'))
  96. assert os.path.isdir(path('dir/subdir'))
  97. @in_env
  98. def test_ensure_dir_exists_file(path):
  99. mkfile(path('dir'))
  100. with pytest.raises(OSError) as errinfo:
  101. library.python.fs.ensure_dir(path('dir/subdir'))
  102. # ENOENT on Windows!
  103. assert errinfo.value.errno in (errno.ENOTDIR, errno.ENOENT)
  104. assert os.path.isfile(path('dir'))
  105. @in_env
  106. def test_create_dirs(path):
  107. assert library.python.fs.create_dirs(path('dir/subdir')) == path('dir/subdir')
  108. assert os.path.isdir(path('dir'))
  109. assert os.path.isdir(path('dir/subdir'))
  110. @in_env
  111. def test_move_file(path):
  112. mkfile(path('src'), 'SRC')
  113. library.python.fs.move(path('src'), path('dst'))
  114. assert not os.path.isfile(path('src'))
  115. assert os.path.isfile(path('dst'))
  116. assert file_data(path('dst')) == 'SRC'
  117. @in_env
  118. def test_move_file_no_src(path):
  119. with pytest.raises(OSError) as errinfo:
  120. library.python.fs.move(path('src'), path('dst'))
  121. assert errinfo.value.errno == errno.ENOENT
  122. @in_env
  123. def test_move_file_exists(path):
  124. mkfile(path('src'), 'SRC')
  125. mkfile(path('dst'), 'DST')
  126. if library.python.windows.on_win():
  127. # move is platform-dependent, use replace_file for dst replacement on all platforms
  128. with pytest.raises(OSError) as errinfo:
  129. library.python.fs.move(path('src'), path('dst'))
  130. assert errinfo.value.errno == errno.EEXIST
  131. assert os.path.isfile(path('src'))
  132. assert os.path.isfile(path('dst'))
  133. assert file_data(path('dst')) == 'DST'
  134. else:
  135. library.python.fs.move(path('src'), path('dst'))
  136. assert not os.path.isfile(path('src'))
  137. assert os.path.isfile(path('dst'))
  138. assert file_data(path('dst')) == 'SRC'
  139. @in_env
  140. def test_move_file_exists_dir_empty(path):
  141. mkfile(path('src'), 'SRC')
  142. os.mkdir(path('dst'))
  143. with pytest.raises(OSError) as errinfo:
  144. library.python.fs.move(path('src'), path('dst'))
  145. assert errinfo.value.errno in (errno.EEXIST, errno.EISDIR)
  146. assert os.path.isfile(path('src'))
  147. assert os.path.isdir(path('dst'))
  148. assert not os.path.isfile(path('dst/src'))
  149. @in_env
  150. def test_move_file_exists_dir_nonempty(path):
  151. mkfile(path('src'), 'SRC')
  152. os.mkdir(path('dst'))
  153. mkfile(path('dst/dst_file'))
  154. with pytest.raises(OSError) as errinfo:
  155. library.python.fs.move(path('src'), path('dst'))
  156. assert errinfo.value.errno in (errno.EEXIST, errno.EISDIR)
  157. assert os.path.isfile(path('src'))
  158. assert os.path.isdir(path('dst'))
  159. assert os.path.isfile(path('dst/dst_file'))
  160. assert not os.path.isfile(path('dst/src'))
  161. @in_env
  162. def test_move_dir(path):
  163. os.mkdir(path('src'))
  164. mkfile(path('src/src_file'))
  165. library.python.fs.move(path('src'), path('dst'))
  166. assert not os.path.isdir(path('src'))
  167. assert os.path.isdir(path('dst'))
  168. assert os.path.isfile(path('dst/src_file'))
  169. @in_env
  170. def test_move_dir_exists_empty(path):
  171. os.mkdir(path('src'))
  172. mkfile(path('src/src_file'))
  173. os.mkdir(path('dst'))
  174. if library.python.windows.on_win():
  175. # move is platform-dependent, use non-atomic replace for directory replacement
  176. with pytest.raises(OSError) as errinfo:
  177. library.python.fs.move(path('src'), path('dst'))
  178. assert errinfo.value.errno == errno.EEXIST
  179. assert os.path.isdir(path('src'))
  180. assert os.path.isdir(path('dst'))
  181. assert not os.path.isfile(path('dst/src_file'))
  182. else:
  183. library.python.fs.move(path('src'), path('dst'))
  184. assert not os.path.isdir(path('src'))
  185. assert os.path.isdir(path('dst'))
  186. assert os.path.isfile(path('dst/src_file'))
  187. @in_env
  188. def test_move_dir_exists_nonempty(path):
  189. os.mkdir(path('src'))
  190. mkfile(path('src/src_file'))
  191. os.mkdir(path('dst'))
  192. mkfile(path('dst/dst_file'))
  193. with pytest.raises(OSError) as errinfo:
  194. library.python.fs.move(path('src'), path('dst'))
  195. assert errinfo.value.errno in (errno.EEXIST, errno.ENOTEMPTY)
  196. assert os.path.isdir(path('src'))
  197. assert os.path.isfile(path('src/src_file'))
  198. assert os.path.isdir(path('dst'))
  199. assert not os.path.isfile(path('dst/src_file'))
  200. assert os.path.isfile(path('dst/dst_file'))
  201. @in_env
  202. def test_move_dir_exists_file(path):
  203. os.mkdir(path('src'))
  204. mkfile(path('src/src_file'))
  205. mkfile(path('dst'), 'DST')
  206. with pytest.raises(OSError) as errinfo:
  207. library.python.fs.move(path('src'), path('dst'))
  208. assert errinfo.value.errno in (errno.EEXIST, errno.ENOTDIR)
  209. assert os.path.isdir(path('src'))
  210. assert os.path.isfile(path('dst'))
  211. assert file_data(path('dst')) == 'DST'
  212. @in_env
  213. def test_replace_file(path):
  214. mkfile(path('src'), 'SRC')
  215. library.python.fs.replace_file(path('src'), path('dst'))
  216. assert not os.path.isfile(path('src'))
  217. assert os.path.isfile(path('dst'))
  218. assert file_data(path('dst')) == 'SRC'
  219. mkfile(path('src'), 'SRC')
  220. library.python.fs.replace(path('src'), path('dst2'))
  221. assert not os.path.isfile(path('src'))
  222. assert os.path.isfile(path('dst2'))
  223. assert file_data(path('dst2')) == 'SRC'
  224. @in_env
  225. def test_replace_file_no_src(path):
  226. with pytest.raises(OSError) as errinfo:
  227. library.python.fs.replace_file(path('src'), path('dst'))
  228. assert errinfo.value.errno == errno.ENOENT
  229. with pytest.raises(OSError) as errinfo2:
  230. library.python.fs.replace(path('src'), path('dst2'))
  231. assert errinfo2.value.errno == errno.ENOENT
  232. @in_env
  233. def test_replace_file_exists(path):
  234. mkfile(path('src'), 'SRC')
  235. mkfile(path('dst'), 'DST')
  236. library.python.fs.replace_file(path('src'), path('dst'))
  237. assert not os.path.isfile(path('src'))
  238. assert os.path.isfile(path('dst'))
  239. assert file_data(path('dst')) == 'SRC'
  240. mkfile(path('src'), 'SRC')
  241. mkfile(path('dst2'), 'DST')
  242. library.python.fs.replace(path('src'), path('dst2'))
  243. assert not os.path.isfile(path('src'))
  244. assert os.path.isfile(path('dst2'))
  245. assert file_data(path('dst2')) == 'SRC'
  246. @in_env
  247. def test_replace_file_exists_dir_empty(path):
  248. mkfile(path('src'), 'SRC')
  249. os.mkdir(path('dst'))
  250. with pytest.raises(OSError) as errinfo:
  251. library.python.fs.replace_file(path('src'), path('dst'))
  252. assert errinfo.value.errno in (errno.EISDIR, errno.EACCES)
  253. assert os.path.isfile(path('src'))
  254. assert os.path.isdir(path('dst'))
  255. assert not os.path.isfile(path('dst/src'))
  256. @in_env
  257. def test_replace_file_exists_dir_empty_overwrite(path):
  258. mkfile(path('src'), 'SRC')
  259. os.mkdir(path('dst'))
  260. library.python.fs.replace(path('src'), path('dst'))
  261. assert not os.path.isfile(path('src'))
  262. assert os.path.isfile(path('dst'))
  263. assert file_data(path('dst')) == 'SRC'
  264. @in_env
  265. def test_replace_file_exists_dir_nonempty(path):
  266. mkfile(path('src'), 'SRC')
  267. os.mkdir(path('dst'))
  268. mkfile(path('dst/dst_file'))
  269. with pytest.raises(OSError) as errinfo:
  270. library.python.fs.replace_file(path('src'), path('dst'))
  271. assert errinfo.value.errno in (errno.EISDIR, errno.EACCES)
  272. assert os.path.isfile(path('src'))
  273. assert os.path.isdir(path('dst'))
  274. assert os.path.isfile(path('dst/dst_file'))
  275. assert not os.path.isfile(path('dst/src'))
  276. @in_env
  277. def test_replace_file_exists_dir_nonempty_overwrite(path):
  278. mkfile(path('src'), 'SRC')
  279. os.mkdir(path('dst'))
  280. mkfile(path('dst/dst_file'))
  281. library.python.fs.replace(path('src'), path('dst'))
  282. assert not os.path.isfile(path('src'))
  283. assert os.path.isfile(path('dst'))
  284. assert file_data(path('dst')) == 'SRC'
  285. @in_env
  286. def test_replace_dir(path):
  287. os.mkdir(path('src'))
  288. mkfile(path('src/src_file'))
  289. library.python.fs.replace(path('src'), path('dst'))
  290. assert not os.path.isdir(path('src'))
  291. assert os.path.isdir(path('dst'))
  292. assert os.path.isfile(path('dst/src_file'))
  293. @in_env
  294. def test_replace_dir_exists_empty(path):
  295. os.mkdir(path('src'))
  296. mkfile(path('src/src_file'))
  297. os.mkdir(path('dst'))
  298. library.python.fs.replace(path('src'), path('dst'))
  299. assert not os.path.isdir(path('src'))
  300. assert os.path.isdir(path('dst'))
  301. assert os.path.isfile(path('dst/src_file'))
  302. @in_env
  303. def test_replace_dir_exists_nonempty(path):
  304. os.mkdir(path('src'))
  305. mkfile(path('src/src_file'))
  306. os.mkdir(path('dst'))
  307. mkfile(path('dst/dst_file'))
  308. library.python.fs.replace(path('src'), path('dst'))
  309. assert not os.path.isdir(path('src'))
  310. assert os.path.isdir(path('dst'))
  311. assert os.path.isfile(path('dst/src_file'))
  312. assert not os.path.isfile(path('dst/dst_file'))
  313. @in_env
  314. def test_replace_dir_exists_file(path):
  315. os.mkdir(path('src'))
  316. mkfile(path('src/src_file'))
  317. mkfile(path('dst'), 'DST')
  318. library.python.fs.replace(path('src'), path('dst'))
  319. assert not os.path.isdir(path('src'))
  320. assert os.path.isdir(path('dst'))
  321. assert os.path.isfile(path('dst/src_file'))
  322. @in_env
  323. def test_remove_file(path):
  324. mkfile(path('path'))
  325. library.python.fs.remove_file(path('path'))
  326. assert not os.path.exists(path('path'))
  327. @in_env
  328. def test_remove_file_no(path):
  329. with pytest.raises(OSError) as errinfo:
  330. library.python.fs.remove_file(path('path'))
  331. assert errinfo.value.errno == errno.ENOENT
  332. @in_env
  333. def test_remove_file_exists_dir(path):
  334. os.mkdir(path('path'))
  335. with pytest.raises(OSError) as errinfo:
  336. library.python.fs.remove_file(path('path'))
  337. assert errinfo.value.errno in (errno.EISDIR, errno.EACCES)
  338. assert os.path.isdir(path('path'))
  339. @in_env
  340. def test_remove_dir(path):
  341. os.mkdir(path('path'))
  342. library.python.fs.remove_dir(path('path'))
  343. assert not os.path.exists(path('path'))
  344. @in_env
  345. def test_remove_dir_no(path):
  346. with pytest.raises(OSError) as errinfo:
  347. library.python.fs.remove_dir(path('path'))
  348. assert errinfo.value.errno == errno.ENOENT
  349. @in_env
  350. def test_remove_dir_exists_file(path):
  351. mkfile(path('path'))
  352. with pytest.raises(OSError) as errinfo:
  353. library.python.fs.remove_dir(path('path'))
  354. assert errinfo.value.errno in (errno.ENOTDIR, errno.EINVAL)
  355. assert os.path.isfile(path('path'))
  356. @in_env
  357. def test_remove_tree(path):
  358. mktree_example(path, 'path')
  359. library.python.fs.remove_tree(path('path'))
  360. assert not os.path.exists(path('path'))
  361. @in_env
  362. def test_remove_tree_empty(path):
  363. os.mkdir(path('path'))
  364. library.python.fs.remove_tree(path('path'))
  365. assert not os.path.exists(path('path'))
  366. @in_env
  367. def test_remove_tree_file(path):
  368. mkfile(path('path'))
  369. library.python.fs.remove_tree(path('path'))
  370. assert not os.path.exists(path('path'))
  371. @in_env
  372. def test_remove_tree_no(path):
  373. with pytest.raises(OSError) as errinfo:
  374. library.python.fs.remove_tree(path('path'))
  375. assert errinfo.value.errno == errno.ENOENT
  376. @in_env
  377. def test_remove_tree_safe(path):
  378. library.python.fs.remove_tree_safe(path('path'))
  379. @in_env
  380. def test_ensure_removed(path):
  381. library.python.fs.ensure_removed(path('path'))
  382. @in_env
  383. def test_ensure_removed_exists(path):
  384. os.makedirs(path('dir/subdir'))
  385. library.python.fs.ensure_removed(path('dir'))
  386. assert not os.path.exists(path('dir'))
  387. @in_env
  388. def test_ensure_removed_exists_precise(path):
  389. os.makedirs(path('dir/subdir'))
  390. library.python.fs.ensure_removed(path('dir/subdir'))
  391. assert os.path.exists(path('dir'))
  392. assert not os.path.exists(path('dir/subdir'))
  393. @in_env
  394. def test_hardlink_file(path):
  395. mkfile(path('src'), 'SRC')
  396. library.python.fs.hardlink(path('src'), path('dst'))
  397. assert os.path.isfile(path('src'))
  398. assert os.path.isfile(path('dst'))
  399. assert file_data(path('dst')) == 'SRC'
  400. assert inodes_unsupported() or inodes_equal(path('src'), path('dst'))
  401. @in_env
  402. def test_hardlink_file_no_src(path):
  403. with pytest.raises(OSError) as errinfo:
  404. library.python.fs.hardlink(path('src'), path('dst'))
  405. assert errinfo.value.errno == errno.ENOENT
  406. @in_env
  407. def test_hardlink_file_exists(path):
  408. mkfile(path('src'), 'SRC')
  409. mkfile(path('dst'), 'DST')
  410. with pytest.raises(OSError) as errinfo:
  411. library.python.fs.hardlink(path('src'), path('dst'))
  412. assert errinfo.value.errno == errno.EEXIST
  413. assert os.path.isfile(path('src'))
  414. assert os.path.isfile(path('dst'))
  415. assert file_data(path('dst')) == 'DST'
  416. assert inodes_unsupported() or not inodes_equal(path('src'), path('dst'))
  417. @in_env
  418. def test_hardlink_file_exists_dir(path):
  419. mkfile(path('src'), 'SRC')
  420. os.mkdir(path('dst'))
  421. with pytest.raises(OSError) as errinfo:
  422. library.python.fs.hardlink(path('src'), path('dst'))
  423. assert errinfo.value.errno == errno.EEXIST
  424. assert os.path.isfile(path('src'))
  425. assert os.path.isdir(path('dst'))
  426. assert not os.path.isfile(path('dst/src'))
  427. @in_env
  428. def test_hardlink_dir(path):
  429. os.mkdir(path('src'))
  430. mkfile(path('src/src_file'))
  431. with pytest.raises(OSError) as errinfo:
  432. library.python.fs.hardlink(path('src'), path('dst'))
  433. assert errinfo.value.errno in (errno.EPERM, errno.EACCES)
  434. assert os.path.isdir(path('src'))
  435. assert not os.path.isdir(path('dst'))
  436. @pytest.mark.skipif(library.python.windows.on_win(), reason='Symlinks disabled on Windows')
  437. @in_env
  438. def test_symlink_file(path):
  439. mkfile(path('src'), 'SRC')
  440. library.python.fs.symlink(path('src'), path('dst'))
  441. assert os.path.isfile(path('src'))
  442. assert os.path.isfile(path('dst'))
  443. assert os.path.islink(path('dst'))
  444. assert file_data(path('dst')) == 'SRC'
  445. @pytest.mark.skipif(library.python.windows.on_win(), reason='Symlinks disabled on Windows')
  446. @in_env
  447. def test_symlink_file_no_src(path):
  448. library.python.fs.symlink(path('src'), path('dst'))
  449. assert not os.path.isfile(path('src'))
  450. assert not os.path.isfile(path('dst'))
  451. assert os.path.islink(path('dst'))
  452. @pytest.mark.skipif(library.python.windows.on_win(), reason='Symlinks disabled on Windows')
  453. @in_env
  454. def test_symlink_file_exists(path):
  455. mkfile(path('src'), 'SRC')
  456. mkfile(path('dst'), 'DST')
  457. with pytest.raises(OSError) as errinfo:
  458. library.python.fs.symlink(path('src'), path('dst'))
  459. assert errinfo.value.errno == errno.EEXIST
  460. assert os.path.isfile(path('src'))
  461. assert os.path.isfile(path('dst'))
  462. assert not os.path.islink(path('dst'))
  463. assert file_data(path('dst')) == 'DST'
  464. @pytest.mark.skipif(library.python.windows.on_win(), reason='Symlinks disabled on Windows')
  465. @in_env
  466. def test_symlink_file_exists_dir(path):
  467. mkfile(path('src'), 'SRC')
  468. os.mkdir(path('dst'))
  469. with pytest.raises(OSError) as errinfo:
  470. library.python.fs.symlink(path('src'), path('dst'))
  471. assert errinfo.value.errno == errno.EEXIST
  472. assert os.path.isfile(path('src'))
  473. assert os.path.isdir(path('dst'))
  474. assert not os.path.islink(path('dst'))
  475. assert not os.path.isfile(path('dst/src'))
  476. @pytest.mark.skipif(library.python.windows.on_win(), reason='Symlinks disabled on Windows')
  477. @in_env
  478. def test_symlink_dir(path):
  479. os.mkdir(path('src'))
  480. mkfile(path('src/src_file'))
  481. library.python.fs.symlink(path('src'), path('dst'))
  482. assert os.path.isdir(path('src'))
  483. assert os.path.isdir(path('dst'))
  484. assert os.path.islink(path('dst'))
  485. assert os.path.isfile(path('dst/src_file'))
  486. @pytest.mark.skipif(library.python.windows.on_win(), reason='Symlinks disabled on Windows')
  487. @in_env
  488. def test_symlink_dir_no_src(path):
  489. library.python.fs.symlink(path('src'), path('dst'))
  490. assert not os.path.isdir(path('src'))
  491. assert not os.path.isdir(path('dst'))
  492. assert os.path.islink(path('dst'))
  493. @pytest.mark.skipif(library.python.windows.on_win(), reason='Symlinks disabled on Windows')
  494. @in_env
  495. def test_symlink_dir_exists(path):
  496. os.mkdir(path('src'))
  497. mkfile(path('src/src_file'))
  498. os.mkdir(path('dst'))
  499. with pytest.raises(OSError) as errinfo:
  500. library.python.fs.symlink(path('src'), path('dst'))
  501. assert errinfo.value.errno == errno.EEXIST
  502. assert os.path.isdir(path('src'))
  503. assert os.path.isdir(path('dst'))
  504. assert not os.path.islink(path('dst'))
  505. assert not os.path.isfile(path('dst/src_file'))
  506. @pytest.mark.skipif(library.python.windows.on_win(), reason='Symlinks disabled on Windows')
  507. @in_env
  508. def test_symlink_dir_exists_file(path):
  509. os.mkdir(path('src'))
  510. mkfile(path('src/src_file'))
  511. mkfile(path('dst'), 'DST')
  512. with pytest.raises(OSError) as errinfo:
  513. library.python.fs.symlink(path('src'), path('dst'))
  514. assert errinfo.value.errno == errno.EEXIST
  515. assert os.path.isdir(path('src'))
  516. assert os.path.isfile(path('dst'))
  517. assert not os.path.islink(path('dst'))
  518. @in_env
  519. def test_hardlink_tree(path):
  520. mktree_example(path, 'src')
  521. library.python.fs.hardlink_tree(path('src'), path('dst'))
  522. assert trees_equal(path('src'), path('dst'))
  523. @in_env
  524. def test_hardlink_tree_empty(path):
  525. os.mkdir(path('src'))
  526. library.python.fs.hardlink_tree(path('src'), path('dst'))
  527. assert trees_equal(path('src'), path('dst'))
  528. @in_env
  529. def test_hardlink_tree_file(path):
  530. mkfile(path('src'), 'SRC')
  531. library.python.fs.hardlink_tree(path('src'), path('dst'))
  532. assert trees_equal(path('src'), path('dst'))
  533. @in_env
  534. def test_hardlink_tree_no_src(path):
  535. with pytest.raises(OSError) as errinfo:
  536. library.python.fs.hardlink_tree(path('src'), path('dst'))
  537. assert errinfo.value.errno == errno.ENOENT
  538. @in_env
  539. def test_hardlink_tree_exists(path):
  540. mktree_example(path, 'src')
  541. os.mkdir(path('dst_dir'))
  542. with pytest.raises(OSError) as errinfo:
  543. library.python.fs.hardlink_tree(path('src'), path('dst_dir'))
  544. assert errinfo.value.errno == errno.EEXIST
  545. mkfile(path('dst_file'), 'DST')
  546. with pytest.raises(OSError) as errinfo:
  547. library.python.fs.hardlink_tree(path('src'), path('dst_file'))
  548. assert errinfo.value.errno == errno.EEXIST
  549. @in_env
  550. def test_hardlink_tree_file_exists(path):
  551. mkfile(path('src'), 'SRC')
  552. os.mkdir(path('dst_dir'))
  553. with pytest.raises(OSError) as errinfo:
  554. library.python.fs.hardlink_tree(path('src'), path('dst_dir'))
  555. assert errinfo.value.errno == errno.EEXIST
  556. mkfile(path('dst_file'), 'DST')
  557. with pytest.raises(OSError) as errinfo:
  558. library.python.fs.hardlink_tree(path('src'), path('dst_file'))
  559. assert errinfo.value.errno == errno.EEXIST
  560. @in_env
  561. def test_copy_file(path):
  562. mkfile(path('src'), 'SRC')
  563. library.python.fs.copy_file(path('src'), path('dst'))
  564. assert os.path.isfile(path('src'))
  565. assert os.path.isfile(path('dst'))
  566. assert file_data(path('dst')) == 'SRC'
  567. @in_env
  568. def test_copy_file_no_src(path):
  569. with pytest.raises(EnvironmentError):
  570. library.python.fs.copy_file(path('src'), path('dst'))
  571. @in_env
  572. def test_copy_file_exists(path):
  573. mkfile(path('src'), 'SRC')
  574. mkfile(path('dst'), 'DST')
  575. library.python.fs.copy_file(path('src'), path('dst'))
  576. assert os.path.isfile(path('src'))
  577. assert os.path.isfile(path('dst'))
  578. assert file_data(path('dst')) == 'SRC'
  579. @in_env
  580. def test_copy_file_exists_dir_empty(path):
  581. mkfile(path('src'), 'SRC')
  582. os.mkdir(path('dst'))
  583. with pytest.raises(EnvironmentError):
  584. library.python.fs.copy_file(path('src'), path('dst'))
  585. assert os.path.isfile(path('src'))
  586. assert os.path.isdir(path('dst'))
  587. assert not os.path.isfile(path('dst/src'))
  588. @in_env
  589. def test_copy_file_exists_dir_nonempty(path):
  590. mkfile(path('src'), 'SRC')
  591. os.mkdir(path('dst'))
  592. mkfile(path('dst/dst_file'))
  593. with pytest.raises(EnvironmentError):
  594. library.python.fs.copy_file(path('src'), path('dst'))
  595. assert os.path.isfile(path('src'))
  596. assert os.path.isdir(path('dst'))
  597. assert os.path.isfile(path('dst/dst_file'))
  598. assert not os.path.isfile(path('dst/src'))
  599. @in_env
  600. def test_copy_tree(path):
  601. mktree_example(path, 'src')
  602. library.python.fs.copy_tree(path('src'), path('dst'))
  603. assert trees_equal(path('src'), path('dst'))
  604. @in_env
  605. def test_copy_tree_empty(path):
  606. os.mkdir(path('src'))
  607. library.python.fs.copy_tree(path('src'), path('dst'))
  608. assert trees_equal(path('src'), path('dst'))
  609. @in_env
  610. def test_copy_tree_file(path):
  611. mkfile(path('src'), 'SRC')
  612. library.python.fs.copy_tree(path('src'), path('dst'))
  613. assert trees_equal(path('src'), path('dst'))
  614. @in_env
  615. def test_copy_tree_no_src(path):
  616. with pytest.raises(EnvironmentError):
  617. library.python.fs.copy_tree(path('src'), path('dst'))
  618. @in_env
  619. def test_copy_tree_exists(path):
  620. mktree_example(path, 'src')
  621. os.mkdir(path('dst_dir'))
  622. with pytest.raises(EnvironmentError):
  623. library.python.fs.copy_tree(path('src'), path('dst_dir'))
  624. mkfile(path('dst_file'), 'DST')
  625. with pytest.raises(EnvironmentError):
  626. library.python.fs.copy_tree(path('src'), path('dst_file'))
  627. @in_env
  628. def test_copy_tree_file_exists(path):
  629. mkfile(path('src'), 'SRC')
  630. os.mkdir(path('dst_dir'))
  631. with pytest.raises(EnvironmentError):
  632. library.python.fs.copy_tree(path('src'), path('dst_dir'))
  633. mkfile(path('dst_file'), 'DST')
  634. library.python.fs.copy_tree(path('src'), path('dst_file'))
  635. assert trees_equal(path('src'), path('dst_file'))
  636. @in_env
  637. def test_read_file(path):
  638. mkfile(path('src'), 'SRC')
  639. assert library.python.fs.read_file(path('src')).decode(library.python.strings.fs_encoding()) == 'SRC'
  640. assert library.python.fs.read_file(path('src'), binary=False) == 'SRC'
  641. @in_env
  642. def test_read_file_empty(path):
  643. mkfile(path('src'))
  644. assert library.python.fs.read_file(path('src')).decode(library.python.strings.fs_encoding()) == ''
  645. assert library.python.fs.read_file(path('src'), binary=False) == ''
  646. @in_env
  647. def test_read_file_multiline(path):
  648. mkfile(path('src'), 'SRC line 1\nSRC line 2\n')
  649. assert (
  650. library.python.fs.read_file(path('src')).decode(library.python.strings.fs_encoding())
  651. == 'SRC line 1\nSRC line 2\n'
  652. )
  653. assert library.python.fs.read_file(path('src'), binary=False) == 'SRC line 1\nSRC line 2\n'
  654. @in_env
  655. def test_read_file_multiline_crlf(path):
  656. mkfile(path('src'), 'SRC line 1\r\nSRC line 2\r\n')
  657. assert (
  658. library.python.fs.read_file(path('src')).decode(library.python.strings.fs_encoding())
  659. == 'SRC line 1\r\nSRC line 2\r\n'
  660. )
  661. if library.python.windows.on_win() or six.PY3: # universal newlines are by default in text mode in python3
  662. assert library.python.fs.read_file(path('src'), binary=False) == 'SRC line 1\nSRC line 2\n'
  663. else:
  664. assert library.python.fs.read_file(path('src'), binary=False) == 'SRC line 1\r\nSRC line 2\r\n'
  665. @in_env
  666. def test_read_file_unicode(path):
  667. s = u'АБВ'
  668. mkfile(path('src'), s.encode('utf-8'))
  669. mkfile(path('src_cp1251'), s.encode('cp1251'))
  670. assert library.python.fs.read_file_unicode(path('src')) == s
  671. assert library.python.fs.read_file_unicode(path('src_cp1251'), enc='cp1251') == s
  672. assert library.python.fs.read_file_unicode(path('src'), binary=False) == s
  673. assert library.python.fs.read_file_unicode(path('src_cp1251'), binary=False, enc='cp1251') == s
  674. @in_env
  675. def test_read_file_unicode_empty(path):
  676. mkfile(path('src'))
  677. mkfile(path('src_cp1251'))
  678. assert library.python.fs.read_file_unicode(path('src')) == ''
  679. assert library.python.fs.read_file_unicode(path('src_cp1251'), enc='cp1251') == ''
  680. assert library.python.fs.read_file_unicode(path('src'), binary=False) == ''
  681. assert library.python.fs.read_file_unicode(path('src_cp1251'), binary=False, enc='cp1251') == ''
  682. @in_env
  683. def test_read_file_unicode_multiline(path):
  684. s = u'АБВ\nИ еще\n'
  685. mkfile(path('src'), s.encode('utf-8'))
  686. mkfile(path('src_cp1251'), s.encode('cp1251'))
  687. assert library.python.fs.read_file_unicode(path('src')) == s
  688. assert library.python.fs.read_file_unicode(path('src_cp1251'), enc='cp1251') == s
  689. assert library.python.fs.read_file_unicode(path('src'), binary=False) == s
  690. assert library.python.fs.read_file_unicode(path('src_cp1251'), binary=False, enc='cp1251') == s
  691. @in_env
  692. def test_read_file_unicode_multiline_crlf(path):
  693. s = u'АБВ\r\nИ еще\r\n'
  694. mkfile(path('src'), s.encode('utf-8'))
  695. mkfile(path('src_cp1251'), s.encode('cp1251'))
  696. assert library.python.fs.read_file_unicode(path('src')) == s
  697. assert library.python.fs.read_file_unicode(path('src_cp1251'), enc='cp1251') == s
  698. if library.python.windows.on_win() or six.PY3: # universal newlines are by default in text mode in python3
  699. assert library.python.fs.read_file_unicode(path('src'), binary=False) == u'АБВ\nИ еще\n'
  700. assert library.python.fs.read_file_unicode(path('src_cp1251'), binary=False, enc='cp1251') == u'АБВ\nИ еще\n'
  701. else:
  702. assert library.python.fs.read_file_unicode(path('src'), binary=False) == s
  703. assert library.python.fs.read_file_unicode(path('src_cp1251'), binary=False, enc='cp1251') == s
  704. @in_env
  705. def test_write_file(path):
  706. library.python.fs.write_file(path('src'), 'SRC')
  707. assert file_data(path('src')) == 'SRC'
  708. library.python.fs.write_file(path('src2'), 'SRC', binary=False)
  709. assert file_data(path('src2')) == 'SRC'
  710. @in_env
  711. def test_write_file_empty(path):
  712. library.python.fs.write_file(path('src'), '')
  713. assert file_data(path('src')) == ''
  714. library.python.fs.write_file(path('src2'), '', binary=False)
  715. assert file_data(path('src2')) == ''
  716. @in_env
  717. def test_write_file_multiline(path):
  718. library.python.fs.write_file(path('src'), 'SRC line 1\nSRC line 2\n')
  719. assert file_data(path('src')) == 'SRC line 1\nSRC line 2\n'
  720. library.python.fs.write_file(path('src2'), 'SRC line 1\nSRC line 2\n', binary=False)
  721. if library.python.windows.on_win():
  722. assert file_data(path('src2')) == 'SRC line 1\r\nSRC line 2\r\n'
  723. else:
  724. assert file_data(path('src2')) == 'SRC line 1\nSRC line 2\n'
  725. @in_env
  726. def test_write_file_multiline_crlf(path):
  727. library.python.fs.write_file(path('src'), 'SRC line 1\r\nSRC line 2\r\n')
  728. assert file_data(path('src')) == 'SRC line 1\r\nSRC line 2\r\n'
  729. library.python.fs.write_file(path('src2'), 'SRC line 1\r\nSRC line 2\r\n', binary=False)
  730. if library.python.windows.on_win():
  731. assert file_data(path('src2')) == 'SRC line 1\r\r\nSRC line 2\r\r\n'
  732. else:
  733. assert file_data(path('src2')) == 'SRC line 1\r\nSRC line 2\r\n'
  734. @in_env
  735. def test_get_file_size(path):
  736. mkfile(path('one.txt'), '22')
  737. assert library.python.fs.get_file_size(path('one.txt')) == 2
  738. @in_env
  739. def test_get_file_size_empty(path):
  740. mkfile(path('one.txt'))
  741. assert library.python.fs.get_file_size(path('one.txt')) == 0
  742. @in_env
  743. def test_get_tree_size(path):
  744. os.makedirs(path('deeper'))
  745. mkfile(path('one.txt'), '1')
  746. mkfile(path('deeper/two.txt'), '22')
  747. assert library.python.fs.get_tree_size(path('one.txt')) == 1
  748. assert library.python.fs.get_tree_size(path('')) == 1
  749. assert library.python.fs.get_tree_size(path(''), recursive=True) == 3
  750. @pytest.mark.skipif(library.python.windows.on_win(), reason='Symlinks disabled on Windows')
  751. @in_env
  752. def test_get_tree_size_dangling_symlink(path):
  753. os.makedirs(path('deeper'))
  754. mkfile(path('one.txt'), '1')
  755. mkfile(path('deeper/two.txt'), '22')
  756. os.symlink(path('deeper/two.txt'), path("deeper/link.txt"))
  757. os.remove(path('deeper/two.txt'))
  758. # does not fail
  759. assert library.python.fs.get_tree_size(path(''), recursive=True) == 1
  760. @pytest.mark.skipif(not library.python.windows.on_win(), reason='Test hardlinks on windows')
  761. def test_hardlink_or_copy():
  762. max_allowed_hard_links = 1023
  763. def run(hardlink_function, dir):
  764. src = r"test.txt"
  765. with open(src, "w") as f:
  766. f.write("test")
  767. for i in range(max_allowed_hard_links + 1):
  768. hardlink_function(src, os.path.join(dir, "{}.txt".format(i)))
  769. dir1 = library.python.fs.create_dirs("one")
  770. with pytest.raises(WindowsError) as e:
  771. run(library.python.fs.hardlink, dir1)
  772. assert e.value.winerror == 1142
  773. assert len(os.listdir(dir1)) == max_allowed_hard_links
  774. dir2 = library.python.fs.create_dirs("two")
  775. run(library.python.fs.hardlink_or_copy, dir2)
  776. assert len(os.listdir(dir2)) == max_allowed_hard_links + 1
  777. def test_remove_tree_unicode():
  778. path = u"test_remove_tree_unicode/русский".encode("utf-8")
  779. os.makedirs(path)
  780. library.python.fs.remove_tree(six.text_type("test_remove_tree_unicode"))
  781. assert not os.path.exists("test_remove_tree_unicode")
  782. def test_remove_tree_safe_unicode():
  783. path = u"test_remove_tree_safe_unicode/русский".encode("utf-8")
  784. os.makedirs(path)
  785. library.python.fs.remove_tree_safe(six.text_type("test_remove_tree_safe_unicode"))
  786. assert not os.path.exists("test_remove_tree_safe_unicode")
  787. def test_copy_tree_custom_copy_function():
  788. library.python.fs.create_dirs("test_copy_tree_src/deepper/inner")
  789. library.python.fs.write_file("test_copy_tree_src/deepper/deepper.txt", "deepper.txt")
  790. library.python.fs.write_file("test_copy_tree_src/deepper/inner/inner.txt", "inner.txt")
  791. copied = []
  792. def copy_function(src, dst):
  793. shutil.copy2(src, dst)
  794. copied.append(dst)
  795. library.python.fs.copy_tree(
  796. "test_copy_tree_src", yatest.common.work_path("test_copy_tree_dst"), copy_function=copy_function
  797. )
  798. assert len(copied) == 2
  799. assert yatest.common.work_path("test_copy_tree_dst/deepper/deepper.txt") in copied
  800. assert yatest.common.work_path("test_copy_tree_dst/deepper/inner/inner.txt") in copied
  801. def test_copy2():
  802. library.python.fs.symlink("non-existent", "link")
  803. library.python.fs.copy2("link", "link2", follow_symlinks=False)
  804. assert os.path.islink("link2")
  805. assert os.readlink("link2") == "non-existent"
  806. def test_commonpath():
  807. pj = os.path.join
  808. pja = lambda *x: os.path.abspath(pj(*x))
  809. assert library.python.fs.commonpath(['a', 'b']) == ''
  810. assert library.python.fs.commonpath([pj('t', '1')]) == pj('t', '1')
  811. assert library.python.fs.commonpath([pj('t', '1'), pj('t', '2')]) == pj('t')
  812. assert library.python.fs.commonpath([pj('t', '1', '2'), pj('t', '1', '2')]) == pj('t', '1', '2')
  813. assert library.python.fs.commonpath([pj('t', '1', '1'), pj('t', '1', '2')]) == pj('t', '1')
  814. assert library.python.fs.commonpath([pj('t', '1', '1'), pj('t', '1', '2'), pj('t', '1', '3')]) == pj('t', '1')
  815. assert library.python.fs.commonpath([pja('t', '1', '1'), pja('t', '1', '2')]) == pja('t', '1')
  816. assert library.python.fs.commonpath({pj('t', '1'), pj('t', '2')}) == pj('t')