edq-utils 0.0.1__py3-none-any.whl → 0.0.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of edq-utils might be problematic. Click here for more details.
- edq/__init__.py +5 -1
- edq/py.typed +0 -0
- edq/testing/__init__.py +3 -0
- edq/testing/run.py +112 -0
- edq/testing/unittest.py +54 -0
- edq/util/__init__.py +3 -0
- edq/util/dirent.py +228 -44
- edq/util/dirent_test.py +823 -25
- edq/util/json.py +163 -0
- edq/util/json_test.py +228 -0
- edq/util/pyimport.py +73 -0
- edq/util/pyimport_test.py +83 -0
- edq/util/reflection.py +32 -0
- edq/util/testdata/dirent-operations/symlink_file_empty +0 -0
- edq/util/time.py +75 -0
- edq/util/time_test.py +107 -0
- {edq_utils-0.0.1.dist-info → edq_utils-0.0.3.dist-info}/METADATA +3 -1
- edq_utils-0.0.3.dist-info/RECORD +28 -0
- edq_utils-0.0.1.dist-info/RECORD +0 -16
- /edq/util/testdata/dirent-operations/{symlinklink_a.txt → symlink_a.txt} +0 -0
- /edq/util/testdata/dirent-operations/{symlinklink_dir_1 → symlink_dir_1}/b.txt +0 -0
- /edq/util/testdata/dirent-operations/{symlinklink_dir_1 → symlink_dir_1}/dir_2/c.txt +0 -0
- {edq_utils-0.0.1.dist-info → edq_utils-0.0.3.dist-info}/WHEEL +0 -0
- {edq_utils-0.0.1.dist-info → edq_utils-0.0.3.dist-info}/licenses/LICENSE +0 -0
- {edq_utils-0.0.1.dist-info → edq_utils-0.0.3.dist-info}/top_level.txt +0 -0
edq/util/dirent_test.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import os
|
|
2
|
-
import sys
|
|
3
|
-
import unittest
|
|
4
2
|
|
|
3
|
+
import edq.testing.unittest
|
|
5
4
|
import edq.util.dirent
|
|
6
5
|
|
|
7
6
|
THIS_DIR = os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
|
|
@@ -16,9 +15,10 @@ This test data directory is laid out as:
|
|
|
16
15
|
│ └── c.txt
|
|
17
16
|
├── dir_empty
|
|
18
17
|
├── file_empty
|
|
19
|
-
├──
|
|
20
|
-
├──
|
|
21
|
-
|
|
18
|
+
├── symlink_a.txt -> a.txt
|
|
19
|
+
├── symlink_dir_1 -> dir_1
|
|
20
|
+
├── symlink_dir_empty -> dir_empty
|
|
21
|
+
└── symlink_file_empty -> file_empty
|
|
22
22
|
|
|
23
23
|
Where non-empty files are filled with their filename (without the extension).
|
|
24
24
|
dir_empty will not exist in the repository (since it is an empty directory),
|
|
@@ -27,12 +27,12 @@ but it will be created by _prep_temp_dir().
|
|
|
27
27
|
|
|
28
28
|
DIRENT_TYPE_DIR = 'dir'
|
|
29
29
|
DIRENT_TYPE_FILE = 'file'
|
|
30
|
+
DIRENT_TYPE_BROKEN_SYMLINK = 'broken_symlink'
|
|
30
31
|
|
|
31
|
-
class
|
|
32
|
+
class TestDirent(edq.testing.unittest.BaseTest):
|
|
32
33
|
""" Test basic operations on dirents. """
|
|
33
34
|
|
|
34
|
-
|
|
35
|
-
def test_dirent_base(self):
|
|
35
|
+
def test_setup(self):
|
|
36
36
|
""" Test that the base temp directory is properly setup. """
|
|
37
37
|
|
|
38
38
|
temp_dir = self._prep_temp_dir()
|
|
@@ -45,14 +45,792 @@ class TestDirentOperations(unittest.TestCase):
|
|
|
45
45
|
(os.path.join('dir_1', 'dir_2', 'c.txt'), DIRENT_TYPE_FILE),
|
|
46
46
|
('dir_empty', DIRENT_TYPE_DIR),
|
|
47
47
|
('file_empty', DIRENT_TYPE_FILE),
|
|
48
|
-
('
|
|
49
|
-
('
|
|
50
|
-
('
|
|
48
|
+
('symlink_a.txt', DIRENT_TYPE_FILE, True),
|
|
49
|
+
('symlink_dir_1', DIRENT_TYPE_DIR, True),
|
|
50
|
+
('symlink_dir_empty', DIRENT_TYPE_DIR, True),
|
|
51
|
+
('symlink_file_empty', DIRENT_TYPE_FILE, True),
|
|
51
52
|
]
|
|
52
53
|
|
|
53
54
|
self._check_existing_paths(temp_dir, expected_paths)
|
|
54
55
|
|
|
55
|
-
def
|
|
56
|
+
def test_contains_path_base(self):
|
|
57
|
+
""" Test checking path containment. """
|
|
58
|
+
|
|
59
|
+
temp_dir = self._prep_temp_dir()
|
|
60
|
+
|
|
61
|
+
# [(parent, child, contains?), ...]
|
|
62
|
+
test_cases = [
|
|
63
|
+
# Containment
|
|
64
|
+
('a', os.path.join('a', 'b', 'c'), True),
|
|
65
|
+
(os.path.join('a', 'b'), os.path.join('a', 'b', 'c'), True),
|
|
66
|
+
('.', os.path.join('a', 'b', 'c'), True),
|
|
67
|
+
('..', '.', True),
|
|
68
|
+
|
|
69
|
+
# Self No Containment
|
|
70
|
+
('a', 'a', False),
|
|
71
|
+
(os.path.join('a', 'b', 'c'), os.path.join('a', 'b', 'c'), False),
|
|
72
|
+
('.', '.', False),
|
|
73
|
+
|
|
74
|
+
# Trivial No Containment
|
|
75
|
+
('a', 'b', False),
|
|
76
|
+
('z', os.path.join('a', 'b', 'c'), False),
|
|
77
|
+
('aa', os.path.join('a', 'b', 'c'), False),
|
|
78
|
+
('a', os.path.join('aa', 'b', 'c'), False),
|
|
79
|
+
|
|
80
|
+
# Child Contains Parent
|
|
81
|
+
(os.path.join('a', 'b', 'c'), 'a', False),
|
|
82
|
+
(os.path.join('a', 'b', 'c'), os.path.join('a', 'b'), False),
|
|
83
|
+
]
|
|
84
|
+
|
|
85
|
+
for (i, test_case) in enumerate(test_cases):
|
|
86
|
+
(parent, child, expected) = test_case
|
|
87
|
+
|
|
88
|
+
with self.subTest(msg = f"Case {i} ('{parent}' ⊂ '{child}'):"):
|
|
89
|
+
parent = os.path.join(temp_dir, parent)
|
|
90
|
+
child = os.path.join(temp_dir, child)
|
|
91
|
+
|
|
92
|
+
actual = edq.util.dirent.contains_path(parent, child)
|
|
93
|
+
self.assertEqual(expected, actual)
|
|
94
|
+
|
|
95
|
+
def test_read_write_file_bytes_base(self):
|
|
96
|
+
""" Test reading and writing a file as bytes. """
|
|
97
|
+
|
|
98
|
+
# [(path, write kwargs, read kwargs, write contents, expected contents, error substring), ...]
|
|
99
|
+
# All conent should be strings that will be encoded.
|
|
100
|
+
test_cases = [
|
|
101
|
+
# Base
|
|
102
|
+
(
|
|
103
|
+
"test.txt",
|
|
104
|
+
{},
|
|
105
|
+
{},
|
|
106
|
+
"test",
|
|
107
|
+
"test",
|
|
108
|
+
None,
|
|
109
|
+
),
|
|
110
|
+
|
|
111
|
+
# Empty Write
|
|
112
|
+
(
|
|
113
|
+
"test.txt",
|
|
114
|
+
{},
|
|
115
|
+
{},
|
|
116
|
+
"",
|
|
117
|
+
"",
|
|
118
|
+
None,
|
|
119
|
+
),
|
|
120
|
+
|
|
121
|
+
# None Write
|
|
122
|
+
(
|
|
123
|
+
"test.txt",
|
|
124
|
+
{},
|
|
125
|
+
{},
|
|
126
|
+
None,
|
|
127
|
+
"",
|
|
128
|
+
None,
|
|
129
|
+
),
|
|
130
|
+
|
|
131
|
+
# Clobber
|
|
132
|
+
(
|
|
133
|
+
"a.txt",
|
|
134
|
+
{},
|
|
135
|
+
{},
|
|
136
|
+
"test",
|
|
137
|
+
"test",
|
|
138
|
+
None,
|
|
139
|
+
),
|
|
140
|
+
(
|
|
141
|
+
"dir_1",
|
|
142
|
+
{},
|
|
143
|
+
{},
|
|
144
|
+
"test",
|
|
145
|
+
"test",
|
|
146
|
+
None,
|
|
147
|
+
),
|
|
148
|
+
(
|
|
149
|
+
"symlink_a.txt",
|
|
150
|
+
{},
|
|
151
|
+
{},
|
|
152
|
+
"test",
|
|
153
|
+
"test",
|
|
154
|
+
None,
|
|
155
|
+
),
|
|
156
|
+
|
|
157
|
+
# No Clobber
|
|
158
|
+
(
|
|
159
|
+
"a.txt",
|
|
160
|
+
{'no_clobber': True},
|
|
161
|
+
{},
|
|
162
|
+
"test",
|
|
163
|
+
"test",
|
|
164
|
+
'already exists',
|
|
165
|
+
),
|
|
166
|
+
(
|
|
167
|
+
"dir_1",
|
|
168
|
+
{'no_clobber': True},
|
|
169
|
+
{},
|
|
170
|
+
"test",
|
|
171
|
+
"test",
|
|
172
|
+
'already exists',
|
|
173
|
+
),
|
|
174
|
+
(
|
|
175
|
+
"symlink_a.txt",
|
|
176
|
+
{'no_clobber': True},
|
|
177
|
+
{},
|
|
178
|
+
"test",
|
|
179
|
+
"test",
|
|
180
|
+
'already exists',
|
|
181
|
+
),
|
|
182
|
+
]
|
|
183
|
+
|
|
184
|
+
for (i, test_case) in enumerate(test_cases):
|
|
185
|
+
(path, write_options, read_options, write_contents, expected_contents, error_substring) = test_case
|
|
186
|
+
|
|
187
|
+
with self.subTest(msg = f"Case {i} ('{path}'):"):
|
|
188
|
+
temp_dir = self._prep_temp_dir()
|
|
189
|
+
path = os.path.join(temp_dir, path)
|
|
190
|
+
|
|
191
|
+
if (write_contents is not None):
|
|
192
|
+
write_contents = bytes(write_contents, edq.util.dirent.DEFAULT_ENCODING)
|
|
193
|
+
|
|
194
|
+
expected_contents = bytes(expected_contents, edq.util.dirent.DEFAULT_ENCODING)
|
|
195
|
+
|
|
196
|
+
try:
|
|
197
|
+
edq.util.dirent.write_file_bytes(path, write_contents, **write_options)
|
|
198
|
+
actual_contents = edq.util.dirent.read_file_bytes(path, **read_options)
|
|
199
|
+
except Exception as ex:
|
|
200
|
+
error_string = self.format_error_string(ex)
|
|
201
|
+
if (error_substring is None):
|
|
202
|
+
self.fail(f"Unexpected error: '{error_string}'.")
|
|
203
|
+
|
|
204
|
+
self.assertIn(error_substring, error_string, 'Error is not as expected.')
|
|
205
|
+
|
|
206
|
+
continue
|
|
207
|
+
|
|
208
|
+
if (error_substring is not None):
|
|
209
|
+
self.fail(f"Did not get expected error: '{error_substring}'.")
|
|
210
|
+
|
|
211
|
+
self.assertEqual(expected_contents, actual_contents)
|
|
212
|
+
|
|
213
|
+
def test_read_write_file_base(self):
|
|
214
|
+
""" Test reading and writing a file. """
|
|
215
|
+
|
|
216
|
+
# [(path, write kwargs, read kwargs, write contents, expected contents, error substring), ...]
|
|
217
|
+
test_cases = [
|
|
218
|
+
# Base
|
|
219
|
+
(
|
|
220
|
+
"test.txt",
|
|
221
|
+
{},
|
|
222
|
+
{},
|
|
223
|
+
"test",
|
|
224
|
+
"test",
|
|
225
|
+
None,
|
|
226
|
+
),
|
|
227
|
+
|
|
228
|
+
# Defaults
|
|
229
|
+
(
|
|
230
|
+
"test.txt",
|
|
231
|
+
{},
|
|
232
|
+
{},
|
|
233
|
+
" test ",
|
|
234
|
+
"test",
|
|
235
|
+
None,
|
|
236
|
+
),
|
|
237
|
+
|
|
238
|
+
# No Modifications
|
|
239
|
+
(
|
|
240
|
+
"test.txt",
|
|
241
|
+
{'strip': False, 'newline': False},
|
|
242
|
+
{'strip': False},
|
|
243
|
+
" test ",
|
|
244
|
+
" test ",
|
|
245
|
+
None,
|
|
246
|
+
),
|
|
247
|
+
|
|
248
|
+
# No Strip
|
|
249
|
+
(
|
|
250
|
+
"test.txt",
|
|
251
|
+
{'strip': False, 'newline': True},
|
|
252
|
+
{'strip': False},
|
|
253
|
+
" test ",
|
|
254
|
+
" test \n",
|
|
255
|
+
None,
|
|
256
|
+
),
|
|
257
|
+
|
|
258
|
+
# No Read Strip
|
|
259
|
+
(
|
|
260
|
+
"test.txt",
|
|
261
|
+
{},
|
|
262
|
+
{'strip': False},
|
|
263
|
+
"test",
|
|
264
|
+
"test\n",
|
|
265
|
+
None,
|
|
266
|
+
),
|
|
267
|
+
|
|
268
|
+
# Empty Write
|
|
269
|
+
(
|
|
270
|
+
"test.txt",
|
|
271
|
+
{'newline': False},
|
|
272
|
+
{},
|
|
273
|
+
"",
|
|
274
|
+
"",
|
|
275
|
+
None,
|
|
276
|
+
),
|
|
277
|
+
|
|
278
|
+
# None Write
|
|
279
|
+
(
|
|
280
|
+
"test.txt",
|
|
281
|
+
{'newline': False},
|
|
282
|
+
{},
|
|
283
|
+
None,
|
|
284
|
+
"",
|
|
285
|
+
None,
|
|
286
|
+
),
|
|
287
|
+
|
|
288
|
+
# Clobber
|
|
289
|
+
(
|
|
290
|
+
"a.txt",
|
|
291
|
+
{},
|
|
292
|
+
{},
|
|
293
|
+
"test",
|
|
294
|
+
"test",
|
|
295
|
+
None,
|
|
296
|
+
),
|
|
297
|
+
(
|
|
298
|
+
"dir_1",
|
|
299
|
+
{},
|
|
300
|
+
{},
|
|
301
|
+
"test",
|
|
302
|
+
"test",
|
|
303
|
+
None,
|
|
304
|
+
),
|
|
305
|
+
(
|
|
306
|
+
"symlink_a.txt",
|
|
307
|
+
{},
|
|
308
|
+
{},
|
|
309
|
+
"test",
|
|
310
|
+
"test",
|
|
311
|
+
None,
|
|
312
|
+
),
|
|
313
|
+
|
|
314
|
+
# No Clobber
|
|
315
|
+
(
|
|
316
|
+
"a.txt",
|
|
317
|
+
{'no_clobber': True},
|
|
318
|
+
{},
|
|
319
|
+
"test",
|
|
320
|
+
"test",
|
|
321
|
+
'Destination of write already exists',
|
|
322
|
+
),
|
|
323
|
+
(
|
|
324
|
+
"dir_1",
|
|
325
|
+
{'no_clobber': True},
|
|
326
|
+
{},
|
|
327
|
+
"test",
|
|
328
|
+
"test",
|
|
329
|
+
'Destination of write already exists',
|
|
330
|
+
),
|
|
331
|
+
(
|
|
332
|
+
"symlink_a.txt",
|
|
333
|
+
{'no_clobber': True},
|
|
334
|
+
{},
|
|
335
|
+
"test",
|
|
336
|
+
"test",
|
|
337
|
+
'Destination of write already exists',
|
|
338
|
+
),
|
|
339
|
+
]
|
|
340
|
+
|
|
341
|
+
for (i, test_case) in enumerate(test_cases):
|
|
342
|
+
(path, write_options, read_options, write_contents, expected_contents, error_substring) = test_case
|
|
343
|
+
|
|
344
|
+
with self.subTest(msg = f"Case {i} ('{path}'):"):
|
|
345
|
+
temp_dir = self._prep_temp_dir()
|
|
346
|
+
path = os.path.join(temp_dir, path)
|
|
347
|
+
|
|
348
|
+
try:
|
|
349
|
+
edq.util.dirent.write_file(path, write_contents, **write_options)
|
|
350
|
+
actual_contents = edq.util.dirent.read_file(path, **read_options)
|
|
351
|
+
except Exception as ex:
|
|
352
|
+
error_string = self.format_error_string(ex)
|
|
353
|
+
if (error_substring is None):
|
|
354
|
+
self.fail(f"Unexpected error: '{error_string}'.")
|
|
355
|
+
|
|
356
|
+
self.assertIn(error_substring, error_string, 'Error is not as expected.')
|
|
357
|
+
|
|
358
|
+
continue
|
|
359
|
+
|
|
360
|
+
if (error_substring is not None):
|
|
361
|
+
self.fail(f"Did not get expected error: '{error_substring}'.")
|
|
362
|
+
|
|
363
|
+
self.assertEqual(expected_contents, actual_contents)
|
|
364
|
+
|
|
365
|
+
def test_copy_contents_base(self):
|
|
366
|
+
"""
|
|
367
|
+
Test copying the contents of a dirent.
|
|
368
|
+
Note that the base functionality of copy_contents() is tested by test_setup().
|
|
369
|
+
"""
|
|
370
|
+
|
|
371
|
+
# [(source, dest, no clobber?, error substring), ...]
|
|
372
|
+
test_cases = [
|
|
373
|
+
('a.txt', 'dir_1', False, None),
|
|
374
|
+
('a.txt', 'ZZZ', False, None),
|
|
375
|
+
('dir_empty', 'dir_1', False, None),
|
|
376
|
+
|
|
377
|
+
('dir_1', 'dir_1', False, 'Source and destination of contents copy cannot be the same'),
|
|
378
|
+
('dir_empty', 'symlink_dir_empty', False, 'Source and destination of contents copy cannot be the same'),
|
|
379
|
+
|
|
380
|
+
('a.txt', 'file_empty', False, 'Destination of contents copy exists and is not a dir'),
|
|
381
|
+
]
|
|
382
|
+
|
|
383
|
+
for (i, test_case) in enumerate(test_cases):
|
|
384
|
+
(source, dest, no_clobber, error_substring) = test_case
|
|
385
|
+
|
|
386
|
+
with self.subTest(msg = f"Case {i} ('{source}' -> '{dest}'):"):
|
|
387
|
+
temp_dir = self._prep_temp_dir()
|
|
388
|
+
|
|
389
|
+
source = os.path.join(temp_dir, source)
|
|
390
|
+
dest = os.path.join(temp_dir, dest)
|
|
391
|
+
|
|
392
|
+
try:
|
|
393
|
+
edq.util.dirent.copy_contents(source, dest, no_clobber = no_clobber)
|
|
394
|
+
except Exception as ex:
|
|
395
|
+
error_string = self.format_error_string(ex)
|
|
396
|
+
if (error_substring is None):
|
|
397
|
+
self.fail(f"Unexpected error: '{error_string}'.")
|
|
398
|
+
|
|
399
|
+
self.assertIn(error_substring, error_string, 'Error is not as expected.')
|
|
400
|
+
|
|
401
|
+
continue
|
|
402
|
+
|
|
403
|
+
if (error_substring is not None):
|
|
404
|
+
self.fail(f"Did not get expected error: '{error_substring}'.")
|
|
405
|
+
|
|
406
|
+
def test_copy_base(self):
|
|
407
|
+
""" Test copying dirents. """
|
|
408
|
+
|
|
409
|
+
# [(source, dest, no_clobber?, error substring), ...]
|
|
410
|
+
test_cases = [
|
|
411
|
+
# File
|
|
412
|
+
('a.txt', 'test.txt', False, None),
|
|
413
|
+
('a.txt', 'test.txt', True, None),
|
|
414
|
+
('a.txt', os.path.join('dir_1', 'test.txt'), False, None),
|
|
415
|
+
('a.txt', os.path.join('dir_1', 'test.txt'), True, None),
|
|
416
|
+
|
|
417
|
+
# File - Clobber
|
|
418
|
+
('a.txt', 'file_empty', False, None),
|
|
419
|
+
('a.txt', os.path.join('dir_1', 'b.txt'), False, None),
|
|
420
|
+
('a.txt', 'dir_1', False, None),
|
|
421
|
+
('a.txt', os.path.join('dir_1', 'dir_2'), False, None),
|
|
422
|
+
|
|
423
|
+
# File - No Clobber
|
|
424
|
+
('a.txt', 'file_empty', True, 'Destination of copy already exists'),
|
|
425
|
+
('a.txt', os.path.join('dir_1', 'b.txt'), True, 'Destination of copy already exists'),
|
|
426
|
+
('a.txt', 'dir_1', True, 'Destination of copy already exists'),
|
|
427
|
+
('a.txt', os.path.join('dir_1', 'dir_2'), True, 'Destination of copy already exists'),
|
|
428
|
+
|
|
429
|
+
# Dir
|
|
430
|
+
('dir_empty', 'test', False, None),
|
|
431
|
+
('dir_empty', 'test', True, None),
|
|
432
|
+
('dir_empty', os.path.join('dir_1', 'test'), False, None),
|
|
433
|
+
('dir_empty', os.path.join('dir_1', 'test'), True, None),
|
|
434
|
+
|
|
435
|
+
# Dir - Clobber
|
|
436
|
+
('dir_empty', 'file_empty', False, None),
|
|
437
|
+
('dir_empty', os.path.join('dir_1', 'b.txt'), False, None),
|
|
438
|
+
('dir_empty', 'dir_1', False, None),
|
|
439
|
+
('dir_empty', os.path.join('dir_1', 'dir_2'), False, None),
|
|
440
|
+
|
|
441
|
+
# Dir - No Clobber
|
|
442
|
+
('dir_empty', 'file_empty', True, 'Destination of copy already exists'),
|
|
443
|
+
('dir_empty', os.path.join('dir_1', 'b.txt'), True, 'Destination of copy already exists'),
|
|
444
|
+
('dir_empty', 'dir_1', True, 'Destination of copy already exists'),
|
|
445
|
+
('dir_empty', os.path.join('dir_1', 'dir_2'), True, 'Destination of copy already exists'),
|
|
446
|
+
|
|
447
|
+
# Link
|
|
448
|
+
('symlink_a.txt', 'test.txt', False, None),
|
|
449
|
+
('symlink_dir_1', 'test', False, None),
|
|
450
|
+
('symlink_dir_empty', 'test', False, None),
|
|
451
|
+
('symlink_file_empty', 'test.txt', False, None),
|
|
452
|
+
|
|
453
|
+
# Link - Clobber
|
|
454
|
+
('symlink_a.txt', 'file_empty', False, None),
|
|
455
|
+
('symlink_a.txt', 'symlink_dir_1', False, None),
|
|
456
|
+
|
|
457
|
+
# Link - No Clobber
|
|
458
|
+
('symlink_a.txt', 'file_empty', True, 'Destination of copy already exists'),
|
|
459
|
+
('symlink_a.txt', 'symlink_dir_1', True, 'Destination of copy already exists'),
|
|
460
|
+
|
|
461
|
+
# Clobber Parent
|
|
462
|
+
(os.path.join('dir_1', 'b.txt'), 'dir_1', False, 'Destination of copy cannot contain the source.'),
|
|
463
|
+
|
|
464
|
+
# Same
|
|
465
|
+
('a.txt', 'a.txt', False, None),
|
|
466
|
+
('symlink_a.txt', 'a.txt', False, None),
|
|
467
|
+
('a.txt', 'a.txt', True, None),
|
|
468
|
+
('symlink_a.txt', 'a.txt', True, None),
|
|
469
|
+
|
|
470
|
+
# Missing Source
|
|
471
|
+
('ZZZ', 'test.txt', False, 'Source of copy does not exist'),
|
|
472
|
+
('ZZZ', 'test.txt', True, 'Source of copy does not exist'),
|
|
473
|
+
]
|
|
474
|
+
|
|
475
|
+
for (i, test_case) in enumerate(test_cases):
|
|
476
|
+
(source, dest, no_clobber, error_substring) = test_case
|
|
477
|
+
|
|
478
|
+
with self.subTest(msg = f"Case {i} ('{source}' -> '{dest}'):"):
|
|
479
|
+
temp_dir = self._prep_temp_dir()
|
|
480
|
+
|
|
481
|
+
source = os.path.join(temp_dir, source)
|
|
482
|
+
dest = os.path.join(temp_dir, dest)
|
|
483
|
+
|
|
484
|
+
try:
|
|
485
|
+
edq.util.dirent.copy(source, dest, no_clobber = no_clobber)
|
|
486
|
+
except Exception as ex:
|
|
487
|
+
error_string = self.format_error_string(ex)
|
|
488
|
+
if (error_substring is None):
|
|
489
|
+
self.fail(f"Unexpected error: '{error_string}'.")
|
|
490
|
+
|
|
491
|
+
self.assertIn(error_substring, error_string, 'Error is not as expected.')
|
|
492
|
+
|
|
493
|
+
continue
|
|
494
|
+
|
|
495
|
+
if (error_substring is not None):
|
|
496
|
+
self.fail(f"Did not get expected error: '{error_substring}'.")
|
|
497
|
+
|
|
498
|
+
dirent_type, is_link = self._get_dirent_type(source)
|
|
499
|
+
|
|
500
|
+
checks = [
|
|
501
|
+
(source, dirent_type, is_link),
|
|
502
|
+
]
|
|
503
|
+
|
|
504
|
+
if (not edq.util.dirent.same(source, dest)):
|
|
505
|
+
checks += [
|
|
506
|
+
(dest, dirent_type, is_link),
|
|
507
|
+
]
|
|
508
|
+
|
|
509
|
+
self._check_existing_paths(temp_dir, checks)
|
|
510
|
+
|
|
511
|
+
def test_same_base(self):
|
|
512
|
+
""" Test checking for two paths pointing to the same dirent. """
|
|
513
|
+
|
|
514
|
+
temp_dir = self._prep_temp_dir()
|
|
515
|
+
|
|
516
|
+
# [(path, path, same?), ...]
|
|
517
|
+
test_cases = [
|
|
518
|
+
# Same
|
|
519
|
+
('a.txt', 'a.txt', True),
|
|
520
|
+
('dir_1', 'dir_1', True),
|
|
521
|
+
(os.path.join('dir_1', 'b.txt'), os.path.join('dir_1', 'b.txt'), True),
|
|
522
|
+
(os.path.join('dir_1', 'b.txt'), os.path.join('dir_1', '..', 'dir_1', 'b.txt'), True),
|
|
523
|
+
|
|
524
|
+
# Not Same
|
|
525
|
+
('a.txt', 'dir_1', False),
|
|
526
|
+
('a.txt', os.path.join('dir_1', 'b.txt'), False),
|
|
527
|
+
('a.txt', 'file_empty', False),
|
|
528
|
+
('a.txt', 'dir_empty', False),
|
|
529
|
+
|
|
530
|
+
# Not Exists
|
|
531
|
+
('a.txt', 'ZZZ', False),
|
|
532
|
+
(os.path.join('dir_1', 'b.txt'), os.path.join('dir_1', 'ZZZ'), False),
|
|
533
|
+
(os.path.join('dir_1', 'b.txt'), os.path.join('ZZZ', 'b.txt'), False),
|
|
534
|
+
|
|
535
|
+
# Links
|
|
536
|
+
('a.txt', 'symlink_a.txt', True),
|
|
537
|
+
('a.txt', 'symlink_file_empty', False),
|
|
538
|
+
('dir_1', 'symlink_dir_1', True),
|
|
539
|
+
('dir_1', 'symlink_dir_empty', False),
|
|
540
|
+
]
|
|
541
|
+
|
|
542
|
+
for (i, test_case) in enumerate(test_cases):
|
|
543
|
+
(a, b, expected) = test_case
|
|
544
|
+
|
|
545
|
+
with self.subTest(msg = f"Case {i} ('{a}' vs '{b}'):"):
|
|
546
|
+
a = os.path.join(temp_dir, a)
|
|
547
|
+
b = os.path.join(temp_dir, b)
|
|
548
|
+
|
|
549
|
+
actual = edq.util.dirent.same(a, b)
|
|
550
|
+
self.assertEqual(expected, actual)
|
|
551
|
+
|
|
552
|
+
def test_mkdir_base(self):
|
|
553
|
+
""" Test creating directories. """
|
|
554
|
+
|
|
555
|
+
temp_dir = self._prep_temp_dir()
|
|
556
|
+
|
|
557
|
+
# [(path, error substring), ...]
|
|
558
|
+
test_cases = [
|
|
559
|
+
# Base
|
|
560
|
+
('new_dir_1', None),
|
|
561
|
+
(os.path.join('dir_1', 'new_dir_2'), None),
|
|
562
|
+
|
|
563
|
+
# Missing Parents
|
|
564
|
+
(os.path.join('ZZZ', 'new_dir_ZZZ'), None),
|
|
565
|
+
(os.path.join('ZZZ', 'YYY', 'XXX', 'new_dir_XXX'), None),
|
|
566
|
+
|
|
567
|
+
# Existing Dir
|
|
568
|
+
('dir_1', None),
|
|
569
|
+
('dir_empty', None),
|
|
570
|
+
('symlink_dir_1', None),
|
|
571
|
+
|
|
572
|
+
# Existing Non-Dir
|
|
573
|
+
('a.txt', 'Target of mkdir already exists'),
|
|
574
|
+
('symlink_a.txt', 'Target of mkdir already exists'),
|
|
575
|
+
|
|
576
|
+
# Existing Non-Dir Parent
|
|
577
|
+
(os.path.join('dir_1', 'b.txt', 'BBB'), 'Target of mkdir contains parent'),
|
|
578
|
+
]
|
|
579
|
+
|
|
580
|
+
for (i, test_case) in enumerate(test_cases):
|
|
581
|
+
(path, error_substring) = test_case
|
|
582
|
+
|
|
583
|
+
with self.subTest(msg = f"Case {i} ('{path}'):"):
|
|
584
|
+
path = os.path.join(temp_dir, path)
|
|
585
|
+
|
|
586
|
+
try:
|
|
587
|
+
edq.util.dirent.mkdir(path)
|
|
588
|
+
except Exception as ex:
|
|
589
|
+
error_string = self.format_error_string(ex)
|
|
590
|
+
if (error_substring is None):
|
|
591
|
+
self.fail(f"Unexpected error: '{error_string}'.")
|
|
592
|
+
|
|
593
|
+
self.assertIn(error_substring, error_string, 'Error is not as expected.')
|
|
594
|
+
|
|
595
|
+
continue
|
|
596
|
+
|
|
597
|
+
if (error_substring is not None):
|
|
598
|
+
self.fail(f"Did not get expected error: '{error_substring}'.")
|
|
599
|
+
|
|
600
|
+
self.assertTrue(edq.util.dirent.exists(path), 'Dir does not exist post mkdir.')
|
|
601
|
+
|
|
602
|
+
def test_get_temp_path_base(self):
|
|
603
|
+
""" Ensure that temp paths are not the same. """
|
|
604
|
+
|
|
605
|
+
a = edq.util.dirent.get_temp_path()
|
|
606
|
+
b = edq.util.dirent.get_temp_path()
|
|
607
|
+
|
|
608
|
+
self.assertNotEqual(a, b)
|
|
609
|
+
|
|
610
|
+
def test_get_temp_dir_base(self):
|
|
611
|
+
""" Ensure that the temp dir exists. """
|
|
612
|
+
|
|
613
|
+
path = edq.util.dirent.get_temp_dir()
|
|
614
|
+
self.assertTrue(edq.util.dirent.exists(path))
|
|
615
|
+
|
|
616
|
+
def test_exists_base(self):
|
|
617
|
+
"""
|
|
618
|
+
Test checking for existence.
|
|
619
|
+
|
|
620
|
+
./dir_empty and ./file_empty will be removed to check for broken links.
|
|
621
|
+
"""
|
|
622
|
+
|
|
623
|
+
temp_dir = self._prep_temp_dir()
|
|
624
|
+
|
|
625
|
+
# Remove some dirents to break links.
|
|
626
|
+
edq.util.dirent.remove(os.path.join(temp_dir, 'dir_empty'))
|
|
627
|
+
edq.util.dirent.remove(os.path.join(temp_dir, 'file_empty'))
|
|
628
|
+
|
|
629
|
+
# [(path, exists?), ...]
|
|
630
|
+
test_cases = [
|
|
631
|
+
# File
|
|
632
|
+
('a.txt', True),
|
|
633
|
+
(os.path.join('dir_1', 'b.txt'), True),
|
|
634
|
+
|
|
635
|
+
# Dir
|
|
636
|
+
('dir_1', True),
|
|
637
|
+
(os.path.join('dir_1', 'dir_2'), True),
|
|
638
|
+
|
|
639
|
+
# Links
|
|
640
|
+
('symlink_a.txt', True),
|
|
641
|
+
('symlink_dir_1', True),
|
|
642
|
+
('symlink_dir_empty', True), # Broken Link
|
|
643
|
+
('symlink_file_empty', True), # Broken Link
|
|
644
|
+
|
|
645
|
+
# Not Exists
|
|
646
|
+
('dir_empty', False),
|
|
647
|
+
('file_empty', False),
|
|
648
|
+
(os.path.join('dir_1', 'ZZZ'), False),
|
|
649
|
+
]
|
|
650
|
+
|
|
651
|
+
for (i, test_case) in enumerate(test_cases):
|
|
652
|
+
(path, expected) = test_case
|
|
653
|
+
|
|
654
|
+
with self.subTest(msg = f"Case {i} ('{path}'):"):
|
|
655
|
+
path = os.path.join(temp_dir, path)
|
|
656
|
+
actual = edq.util.dirent.exists(path)
|
|
657
|
+
self.assertEqual(expected, actual)
|
|
658
|
+
|
|
659
|
+
def test_move_base(self):
|
|
660
|
+
"""
|
|
661
|
+
Test moving dirents.
|
|
662
|
+
|
|
663
|
+
This test will create some additional dirents:
|
|
664
|
+
├── dir_1
|
|
665
|
+
│ └── dir_2
|
|
666
|
+
│ ├── a.txt
|
|
667
|
+
│ └── dir_empty
|
|
668
|
+
"""
|
|
669
|
+
|
|
670
|
+
# [(source, dest, no_clobber?, error substring), ...]
|
|
671
|
+
# The dest can be a single string, or a tuple of (operation input, expected output).
|
|
672
|
+
test_cases = [
|
|
673
|
+
# File
|
|
674
|
+
('a.txt', 'test.txt', False, None),
|
|
675
|
+
|
|
676
|
+
# Move into Dir - Explicit
|
|
677
|
+
('a.txt', os.path.join('dir_1', 'a.txt'), False, None),
|
|
678
|
+
|
|
679
|
+
# Move into Dir - Implicit
|
|
680
|
+
('a.txt', ('dir_1', os.path.join('dir_1', 'a.txt')), False, None),
|
|
681
|
+
|
|
682
|
+
# Move out of Dir
|
|
683
|
+
(os.path.join('dir_1', 'b.txt'), 'b.txt', False, None),
|
|
684
|
+
|
|
685
|
+
# Missing Parents
|
|
686
|
+
('a.txt', os.path.join('dir_1', 'a', 'b', 'a.txt'), False, None),
|
|
687
|
+
|
|
688
|
+
# Same File
|
|
689
|
+
('a.txt', 'a.txt', False, None),
|
|
690
|
+
|
|
691
|
+
# Clobber File with File
|
|
692
|
+
('a.txt', os.path.join('dir_1', 'b.txt'), False, None),
|
|
693
|
+
|
|
694
|
+
# No Clobber File with File
|
|
695
|
+
('a.txt', os.path.join('dir_1', 'b.txt'), True, 'Destination of move already exists'),
|
|
696
|
+
|
|
697
|
+
# Clobber File with File - Implicit
|
|
698
|
+
('a.txt', (os.path.join('dir_1', 'dir_2'), os.path.join('dir_1', 'dir_2', 'a.txt')), False, None),
|
|
699
|
+
|
|
700
|
+
# No Clobber File with File - Implicit
|
|
701
|
+
('a.txt', os.path.join('dir_1', 'dir_2'), True, 'Destination of move already exists'),
|
|
702
|
+
|
|
703
|
+
# Clobber Dir with Dir
|
|
704
|
+
('dir_empty', 'dir_1', False, None),
|
|
705
|
+
|
|
706
|
+
# Clobber Dir with Dir - Implicit
|
|
707
|
+
('dir_empty', (os.path.join('dir_1', 'dir_2'), os.path.join('dir_1', 'dir_2', 'dir_empty')), False, None),
|
|
708
|
+
|
|
709
|
+
# No Clobber Dir with Dir - Implicit
|
|
710
|
+
('dir_empty', os.path.join('dir_1', 'dir_2'), True, 'Destination of move already exists'),
|
|
711
|
+
]
|
|
712
|
+
|
|
713
|
+
for (i, test_case) in enumerate(test_cases):
|
|
714
|
+
(source, raw_dest, no_clobber, error_substring) = test_case
|
|
715
|
+
|
|
716
|
+
with self.subTest(msg = f"Case {i} ('{source}' -> '{raw_dest}'):"):
|
|
717
|
+
temp_dir = self._prep_temp_dir()
|
|
718
|
+
|
|
719
|
+
# Create the additional dirents for this test.
|
|
720
|
+
edq.util.dirent.copy(os.path.join(temp_dir, 'a.txt'), os.path.join(temp_dir, 'dir_1', 'dir_2', 'a.txt'))
|
|
721
|
+
edq.util.dirent.copy(os.path.join(temp_dir, 'dir_empty'), os.path.join(temp_dir, 'dir_1', 'dir_2', 'dir_empty'))
|
|
722
|
+
|
|
723
|
+
if (isinstance(raw_dest, tuple)):
|
|
724
|
+
(input_dest, expected_dest) = raw_dest
|
|
725
|
+
else:
|
|
726
|
+
input_dest = raw_dest
|
|
727
|
+
expected_dest = raw_dest
|
|
728
|
+
|
|
729
|
+
source = os.path.join(temp_dir, source)
|
|
730
|
+
input_dest = os.path.join(temp_dir, input_dest)
|
|
731
|
+
expected_dest = os.path.join(temp_dir, expected_dest)
|
|
732
|
+
|
|
733
|
+
try:
|
|
734
|
+
edq.util.dirent.move(source, input_dest, no_clobber = no_clobber)
|
|
735
|
+
except Exception as ex:
|
|
736
|
+
error_string = self.format_error_string(ex)
|
|
737
|
+
if (error_substring is None):
|
|
738
|
+
self.fail(f"Unexpected error: '{error_string}'.")
|
|
739
|
+
|
|
740
|
+
self.assertIn(error_substring, error_string, 'Error is not as expected.')
|
|
741
|
+
|
|
742
|
+
continue
|
|
743
|
+
|
|
744
|
+
if (error_substring is not None):
|
|
745
|
+
self.fail(f"Did not get expected error: '{error_substring}'.")
|
|
746
|
+
|
|
747
|
+
self._check_existing_paths(temp_dir, [expected_dest])
|
|
748
|
+
|
|
749
|
+
if (not edq.util.dirent.same(os.path.join(temp_dir, source), os.path.join(temp_dir, expected_dest))):
|
|
750
|
+
self._check_nonexisting_paths(temp_dir, [source])
|
|
751
|
+
|
|
752
|
+
def test_move_rename(self):
|
|
753
|
+
""" Test renaming dirents (via move()). """
|
|
754
|
+
|
|
755
|
+
temp_dir = self._prep_temp_dir()
|
|
756
|
+
|
|
757
|
+
# [(source, dest, expected error), ...]
|
|
758
|
+
rename_relpaths = [
|
|
759
|
+
# Symlink - File
|
|
760
|
+
('symlink_a.txt', 'rename_symlink_a.txt', None),
|
|
761
|
+
|
|
762
|
+
# Symlink - Dir
|
|
763
|
+
('symlink_dir_1', 'rename_symlink_dir_1', None),
|
|
764
|
+
|
|
765
|
+
# File in Directory
|
|
766
|
+
(os.path.join('dir_1', 'dir_2', 'c.txt'), os.path.join('dir_1', 'dir_2', 'rename_c.txt'), None),
|
|
767
|
+
|
|
768
|
+
# File
|
|
769
|
+
('a.txt', 'rename_a.txt', None),
|
|
770
|
+
|
|
771
|
+
# Empty File
|
|
772
|
+
('file_empty', 'rename_file_empty', None),
|
|
773
|
+
|
|
774
|
+
# Directory
|
|
775
|
+
('dir_1', 'rename_dir_1', None),
|
|
776
|
+
|
|
777
|
+
# Empty Directory
|
|
778
|
+
('dir_empty', 'rename_dir_empty', None),
|
|
779
|
+
|
|
780
|
+
# Non-Existent
|
|
781
|
+
('ZZZ', 'rename_ZZZ', 'Source of move does not exist'),
|
|
782
|
+
]
|
|
783
|
+
|
|
784
|
+
expected_paths = [
|
|
785
|
+
('rename_a.txt', DIRENT_TYPE_FILE),
|
|
786
|
+
('rename_dir_1', DIRENT_TYPE_DIR),
|
|
787
|
+
(os.path.join('rename_dir_1', 'b.txt'), DIRENT_TYPE_FILE),
|
|
788
|
+
(os.path.join('rename_dir_1', 'dir_2'), DIRENT_TYPE_DIR),
|
|
789
|
+
(os.path.join('rename_dir_1', 'dir_2', 'rename_c.txt'), DIRENT_TYPE_FILE),
|
|
790
|
+
('rename_dir_empty', DIRENT_TYPE_DIR),
|
|
791
|
+
('rename_file_empty', DIRENT_TYPE_FILE),
|
|
792
|
+
('rename_symlink_a.txt', DIRENT_TYPE_BROKEN_SYMLINK, True),
|
|
793
|
+
('rename_symlink_dir_1', DIRENT_TYPE_BROKEN_SYMLINK, True),
|
|
794
|
+
('symlink_dir_empty', DIRENT_TYPE_BROKEN_SYMLINK, True),
|
|
795
|
+
('symlink_file_empty', DIRENT_TYPE_BROKEN_SYMLINK, True),
|
|
796
|
+
]
|
|
797
|
+
|
|
798
|
+
unexpected_paths = [
|
|
799
|
+
'symlink_a.txt',
|
|
800
|
+
'symlink_dir_1',
|
|
801
|
+
os.path.join('dir_1', 'dir_2', 'c.txt'),
|
|
802
|
+
'a.txt',
|
|
803
|
+
'file_empty',
|
|
804
|
+
'dir_1',
|
|
805
|
+
'dir_empty',
|
|
806
|
+
'ZZZ',
|
|
807
|
+
'rename_ZZZ',
|
|
808
|
+
]
|
|
809
|
+
|
|
810
|
+
for (i, test_case) in enumerate(rename_relpaths):
|
|
811
|
+
(source, dest, error_substring) = test_case
|
|
812
|
+
|
|
813
|
+
source = os.path.join(temp_dir, source)
|
|
814
|
+
dest = os.path.join(temp_dir, dest)
|
|
815
|
+
|
|
816
|
+
try:
|
|
817
|
+
edq.util.dirent.move(source, dest)
|
|
818
|
+
except Exception as ex:
|
|
819
|
+
error_string = self.format_error_string(ex)
|
|
820
|
+
if (error_substring is None):
|
|
821
|
+
self.fail(f"Case {i}: Unexpected error: '{error_string}'.")
|
|
822
|
+
|
|
823
|
+
self.assertIn(error_substring, error_string, 'Error is not as expected.')
|
|
824
|
+
|
|
825
|
+
continue
|
|
826
|
+
|
|
827
|
+
if (error_substring is not None):
|
|
828
|
+
self.fail(f"Case {i}: Did not get expected error: '{error_substring}'.")
|
|
829
|
+
|
|
830
|
+
self._check_nonexisting_paths(temp_dir, unexpected_paths)
|
|
831
|
+
self._check_existing_paths(temp_dir, expected_paths)
|
|
832
|
+
|
|
833
|
+
def test_remove_base(self):
|
|
56
834
|
""" Test removing dirents. """
|
|
57
835
|
|
|
58
836
|
temp_dir = self._prep_temp_dir()
|
|
@@ -60,10 +838,10 @@ class TestDirentOperations(unittest.TestCase):
|
|
|
60
838
|
# Remove these paths in this order.
|
|
61
839
|
remove_relpaths = [
|
|
62
840
|
# Symlink - File
|
|
63
|
-
'
|
|
841
|
+
'symlink_a.txt',
|
|
64
842
|
|
|
65
843
|
# Symlink - Dir
|
|
66
|
-
'
|
|
844
|
+
'symlink_dir_1',
|
|
67
845
|
|
|
68
846
|
# File in Directory
|
|
69
847
|
os.path.join('dir_1', 'dir_2', 'c.txt'),
|
|
@@ -78,17 +856,17 @@ class TestDirentOperations(unittest.TestCase):
|
|
|
78
856
|
'dir_1',
|
|
79
857
|
|
|
80
858
|
# Empty Directory
|
|
81
|
-
'dir_empty'
|
|
859
|
+
'dir_empty',
|
|
82
860
|
|
|
83
861
|
# Non-Existent
|
|
84
|
-
'ZZZ'
|
|
862
|
+
'ZZZ',
|
|
85
863
|
]
|
|
86
864
|
|
|
87
865
|
expected_paths = [
|
|
88
866
|
(os.path.join('dir_1', 'dir_2'), DIRENT_TYPE_DIR),
|
|
89
867
|
('file_empty', DIRENT_TYPE_FILE),
|
|
90
868
|
# Windows has some symlink issues, so we will not check for this file.
|
|
91
|
-
# ('
|
|
869
|
+
# ('symlink_dir_empty', DIRENT_TYPE_DIR, True),
|
|
92
870
|
]
|
|
93
871
|
|
|
94
872
|
for relpath in remove_relpaths:
|
|
@@ -100,8 +878,10 @@ class TestDirentOperations(unittest.TestCase):
|
|
|
100
878
|
|
|
101
879
|
def _prep_temp_dir(self):
|
|
102
880
|
temp_dir = edq.util.dirent.get_temp_dir(prefix = 'edq_test_dirent_')
|
|
881
|
+
|
|
103
882
|
edq.util.dirent.mkdir(os.path.join(temp_dir, 'dir_empty'))
|
|
104
883
|
edq.util.dirent.copy_contents(TEST_BASE_DIR, temp_dir)
|
|
884
|
+
|
|
105
885
|
return temp_dir
|
|
106
886
|
|
|
107
887
|
def _check_existing_paths(self, base_dir, raw_paths):
|
|
@@ -118,7 +898,7 @@ class TestDirentOperations(unittest.TestCase):
|
|
|
118
898
|
for raw_path in raw_paths:
|
|
119
899
|
relpath = ''
|
|
120
900
|
dirent_type = None
|
|
121
|
-
is_link =
|
|
901
|
+
is_link = False
|
|
122
902
|
|
|
123
903
|
if (isinstance(raw_path, str)):
|
|
124
904
|
relpath = raw_path
|
|
@@ -137,9 +917,14 @@ class TestDirentOperations(unittest.TestCase):
|
|
|
137
917
|
path = os.path.join(base_dir, relpath)
|
|
138
918
|
|
|
139
919
|
# Check the path exists.
|
|
140
|
-
if (not
|
|
920
|
+
if (not edq.util.dirent.exists(path)):
|
|
141
921
|
self.fail(f"Expected path does not exist: '{relpath}'.")
|
|
142
922
|
|
|
923
|
+
# Check the link status.
|
|
924
|
+
if (is_link is not None):
|
|
925
|
+
if (is_link != os.path.islink(path)):
|
|
926
|
+
self.fail(f"Expected path does not have a matching link status. Expected {is_link}, but is {not is_link}: '{relpath}'.")
|
|
927
|
+
|
|
143
928
|
# Check the type of the dirent.
|
|
144
929
|
if (dirent_type is not None):
|
|
145
930
|
if (dirent_type == DIRENT_TYPE_DIR):
|
|
@@ -148,14 +933,12 @@ class TestDirentOperations(unittest.TestCase):
|
|
|
148
933
|
elif (dirent_type == DIRENT_TYPE_FILE):
|
|
149
934
|
if (not os.path.isfile(path)):
|
|
150
935
|
self.fail(f"Expected path to be a file, but it is not: '{relpath}'.")
|
|
936
|
+
elif (dirent_type == DIRENT_TYPE_BROKEN_SYMLINK):
|
|
937
|
+
if ((not os.path.islink(path)) or os.path.isfile(path) or os.path.isdir(path)):
|
|
938
|
+
self.fail(f"Expected path to be a broken link, but it is not: '{relpath}'.")
|
|
151
939
|
else:
|
|
152
940
|
raise ValueError(f"Unknown dirent type '{dirent_type}' for path: '{relpath}'.")
|
|
153
941
|
|
|
154
|
-
# Check the link status.
|
|
155
|
-
if (is_link is not None):
|
|
156
|
-
if (is_link != os.path.islink(path)):
|
|
157
|
-
self.fail(f"Expected path does not have a matching link status. Expected {is_link}, but is {not is_link}: '{relpath}'.")
|
|
158
|
-
|
|
159
942
|
def _check_nonexisting_paths(self, base_dir, raw_paths):
|
|
160
943
|
"""
|
|
161
944
|
Ensure that specific paths do not exists, and fail the test if they do exist.
|
|
@@ -166,5 +949,20 @@ class TestDirentOperations(unittest.TestCase):
|
|
|
166
949
|
for relpath in raw_paths:
|
|
167
950
|
path = os.path.join(base_dir, relpath)
|
|
168
951
|
|
|
169
|
-
if (
|
|
952
|
+
if (edq.util.dirent.exists(path)):
|
|
170
953
|
self.fail(f"Path exists when it should not: '{relpath}'.")
|
|
954
|
+
|
|
955
|
+
def _get_dirent_type(self, path):
|
|
956
|
+
is_link = os.path.islink(path)
|
|
957
|
+
dirent_type = None
|
|
958
|
+
|
|
959
|
+
if (os.path.isdir(path)):
|
|
960
|
+
dirent_type = DIRENT_TYPE_DIR
|
|
961
|
+
elif (os.path.isfile(path)):
|
|
962
|
+
dirent_type = DIRENT_TYPE_FILE
|
|
963
|
+
elif (os.path.islink(path)):
|
|
964
|
+
dirent_type = DIRENT_TYPE_BROKEN_SYMLINK
|
|
965
|
+
else:
|
|
966
|
+
raise ValueError(f"Unknown dirent type: '{path}'.")
|
|
967
|
+
|
|
968
|
+
return dirent_type, is_link
|