py3toolset 1.2.18__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.
- py3toolset/LICENSE.md +11 -0
- py3toolset/__init__.py +1 -0
- py3toolset/bash_autocomp.py +70 -0
- py3toolset/cmd_interact.py +153 -0
- py3toolset/dep.py +144 -0
- py3toolset/file_backup.py +113 -0
- py3toolset/fs.py +543 -0
- py3toolset/nmath.py +419 -0
- py3toolset/setup.py +32 -0
- py3toolset/tuple_file.py +104 -0
- py3toolset/txt_color.py +168 -0
- py3toolset-1.2.18.dist-info/METADATA +24 -0
- py3toolset-1.2.18.dist-info/RECORD +16 -0
- py3toolset-1.2.18.dist-info/WHEEL +5 -0
- py3toolset-1.2.18.dist-info/licenses/LICENSE.md +11 -0
- py3toolset-1.2.18.dist-info/top_level.txt +1 -0
py3toolset/fs.py
ADDED
@@ -0,0 +1,543 @@
|
|
1
|
+
"""
|
2
|
+
A module for file system operations.
|
3
|
+
|
4
|
+
File removal, copying, checking, path operations, etc.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from glob import glob
|
8
|
+
from os.path import (isabs, exists, os, dirname, basename, isfile, isdir, join,
|
9
|
+
sep)
|
10
|
+
from os import environ, pathsep, mkdir
|
11
|
+
import re
|
12
|
+
import sys
|
13
|
+
from posix import remove, getcwd, rmdir
|
14
|
+
from shutil import which, copyfile
|
15
|
+
|
16
|
+
|
17
|
+
def remove_files(*files):
|
18
|
+
"""
|
19
|
+
Removes all ``files`` from the file system.
|
20
|
+
|
21
|
+
.. note::
|
22
|
+
Item which is not a file is ignored.
|
23
|
+
|
24
|
+
.. seealso::
|
25
|
+
:func:`.remove_dirs`
|
26
|
+
|
27
|
+
Example:
|
28
|
+
>>> from random import randint
|
29
|
+
>>> rand_suffix = str(randint(1, 2**10))
|
30
|
+
>>> # create a folder and dummy files
|
31
|
+
>>> parent_dir = "test_remove_files" + rand_suffix
|
32
|
+
>>> os.mkdir(parent_dir)
|
33
|
+
>>> f1 = os.path.join(parent_dir, "f1")
|
34
|
+
>>> f_out = open(f1, 'w')
|
35
|
+
>>> f_out.writelines(["Test test test"])
|
36
|
+
>>> f_out.close()
|
37
|
+
>>> f2 = os.path.join(parent_dir, "f2")
|
38
|
+
>>> f2_out = open(f2, 'w')
|
39
|
+
>>> f2_out.writelines(["Test2 test2 test2"])
|
40
|
+
>>> f2_out.close()
|
41
|
+
>>> os.path.exists(f1)
|
42
|
+
True
|
43
|
+
>>> os.path.exists(f2)
|
44
|
+
True
|
45
|
+
>>> # remove files f1 and f2
|
46
|
+
>>> remove_files(f1, f2)
|
47
|
+
>>> os.path.exists(f1)
|
48
|
+
False
|
49
|
+
>>> os.path.exists(f2)
|
50
|
+
False
|
51
|
+
>>> remove_dirs(parent_dir)
|
52
|
+
|
53
|
+
"""
|
54
|
+
for f in files:
|
55
|
+
if isfile(f):
|
56
|
+
remove(f)
|
57
|
+
|
58
|
+
|
59
|
+
def remove_dirs(*dirs):
|
60
|
+
"""
|
61
|
+
Removes recursively directories/folders.
|
62
|
+
|
63
|
+
Args:
|
64
|
+
dirs: ``list``
|
65
|
+
List of directories to remove.
|
66
|
+
|
67
|
+
.. note::
|
68
|
+
If an element in dirs isn't a folder, it is ignored.
|
69
|
+
|
70
|
+
.. seealso::
|
71
|
+
:func:`.remove_files`
|
72
|
+
|
73
|
+
|
74
|
+
Example:
|
75
|
+
>>> from random import randint
|
76
|
+
>>> rand_suffix = str(randint(1, 2**10))
|
77
|
+
>>> # create a folder and dummy files
|
78
|
+
>>> parent_dir = "test_remove_dirs" + rand_suffix
|
79
|
+
>>> parent_dir2 = "test_remove_dirs" + rand_suffix + '2'
|
80
|
+
>>> os.mkdir(parent_dir)
|
81
|
+
>>> os.mkdir(parent_dir2)
|
82
|
+
>>> f1 = os.path.join(parent_dir, "f1")
|
83
|
+
>>> f_out = open(f1, 'w')
|
84
|
+
>>> f_out.close()
|
85
|
+
>>> f2 = os.path.join(parent_dir, "f2")
|
86
|
+
>>> f2_out = open(f2, 'w')
|
87
|
+
>>> f2_out.close()
|
88
|
+
>>> os.path.exists(f1)
|
89
|
+
True
|
90
|
+
>>> os.path.exists(f2)
|
91
|
+
True
|
92
|
+
>>> os.path.exists(parent_dir2)
|
93
|
+
True
|
94
|
+
>>> # remove directories
|
95
|
+
>>> remove_dirs(parent_dir, parent_dir2)
|
96
|
+
>>> os.path.exists(parent_dir)
|
97
|
+
False
|
98
|
+
>>> os.path.exists(parent_dir2)
|
99
|
+
False
|
100
|
+
|
101
|
+
"""
|
102
|
+
for d in dirs:
|
103
|
+
if isdir(d):
|
104
|
+
for e in glob(d+os.sep+"*"):
|
105
|
+
if isdir(e):
|
106
|
+
remove_dirs(e)
|
107
|
+
else:
|
108
|
+
remove_files(e)
|
109
|
+
# d empty
|
110
|
+
rmdir(d)
|
111
|
+
|
112
|
+
|
113
|
+
def get_prog_parent_dir():
|
114
|
+
"""
|
115
|
+
Returns absolute path of parent folder of the currently running script.
|
116
|
+
|
117
|
+
Example:
|
118
|
+
|
119
|
+
Script ``./nop.py``:
|
120
|
+
|
121
|
+
.. code-block:: python
|
122
|
+
|
123
|
+
#!/usr/bin/env python3
|
124
|
+
from py3toolset.fs import get_prog_parent_dir
|
125
|
+
|
126
|
+
if __name__ == '__main__':
|
127
|
+
print(get_prog_parent_dir())
|
128
|
+
|
129
|
+
Use of script and function:
|
130
|
+
|
131
|
+
.. code-block:: bash
|
132
|
+
|
133
|
+
$ echo $PWD
|
134
|
+
/my/current/working/dir/.
|
135
|
+
$ ./nop.py
|
136
|
+
/my/current/working/dir
|
137
|
+
$ export PATH=$PATH:.
|
138
|
+
$ nop.py
|
139
|
+
/my/current/working/dir/.
|
140
|
+
$ cd ..
|
141
|
+
$ ./dir/nop.py
|
142
|
+
/my/current/working/dir
|
143
|
+
|
144
|
+
|
145
|
+
"""
|
146
|
+
pdir = dirname(sys.argv[0])
|
147
|
+
if pdir.startswith(os.sep):
|
148
|
+
# absolute path of prog was given
|
149
|
+
return pdir
|
150
|
+
elif not pdir:
|
151
|
+
# no parent dir given in script cmd
|
152
|
+
# prog probably located through PATH
|
153
|
+
return which(sys.argv[0]) or "."
|
154
|
+
# TODO: or "." should be removed
|
155
|
+
# it was just a tmp test trick
|
156
|
+
# anyway it shouldn't be reached
|
157
|
+
else:
|
158
|
+
# relative dir given to script
|
159
|
+
# return absolute dir
|
160
|
+
return getcwd() + os.sep + pdir
|
161
|
+
|
162
|
+
|
163
|
+
def set_abs_or_relative_path(parent_dir, _file):
|
164
|
+
"""
|
165
|
+
Sets a full path for ``_file`` (can be relative or absolute).
|
166
|
+
|
167
|
+
If ``_file`` is an absolute path returns ``_file`` as is.
|
168
|
+
Otherwise if ``parent_dir`` is set, returns the path ``parent_dir/_file``.
|
169
|
+
Raises an exception if ``parent_dir`` is ``None`` while ``_file`` is not
|
170
|
+
absolute.
|
171
|
+
The function never verifies the file exists, it only builds a full path.
|
172
|
+
|
173
|
+
Args:
|
174
|
+
parent_dir: ``str``
|
175
|
+
a candidate parent directory (relative or absolute path)
|
176
|
+
for _file. It is only used if _file is not an absolute path.
|
177
|
+
_file: ``str``
|
178
|
+
any filename or filepath (relative to ``parent_dir`` or
|
179
|
+
``absolute``).
|
180
|
+
|
181
|
+
Return:
|
182
|
+
the full (absolute or relative path) of ``_file``; that is
|
183
|
+
``parent_dir + os.sep + _file`` or ``_file``.
|
184
|
+
|
185
|
+
Example:
|
186
|
+
>>> set_abs_or_relative_path(None, '/my/absolute/file/path')
|
187
|
+
'/my/absolute/file/path'
|
188
|
+
>>> set_abs_or_relative_path('/my/absolute/file', 'path')
|
189
|
+
'/my/absolute/file/path'
|
190
|
+
>>> set_abs_or_relative_path(None, 'path')
|
191
|
+
Traceback (most recent call last):
|
192
|
+
...
|
193
|
+
ValueError: parent_dir must be defined
|
194
|
+
|
195
|
+
"""
|
196
|
+
if isabs(_file):
|
197
|
+
# _file is absolute path
|
198
|
+
# or not absolute path, but exists
|
199
|
+
return _file
|
200
|
+
elif parent_dir is None:
|
201
|
+
raise ValueError('parent_dir must be defined')
|
202
|
+
else: # parent_dir is not None: # not abs path, prefix with parent dir
|
203
|
+
return parent_dir + os.sep + _file
|
204
|
+
|
205
|
+
|
206
|
+
def all_files_in_same_dir(*files):
|
207
|
+
"""
|
208
|
+
Returns ``True`` all ``files`` are in the same folder, ``False`` otherwise.
|
209
|
+
|
210
|
+
Example:
|
211
|
+
>>> all_files_in_same_dir('/etc/hosts', '/etc/passwd')
|
212
|
+
True
|
213
|
+
>>> all_files_in_same_dir('/etc/hosts', '/etc/passwd', '/usr/share')
|
214
|
+
False
|
215
|
+
|
216
|
+
"""
|
217
|
+
pdir = None
|
218
|
+
for f in files:
|
219
|
+
if pdir is None:
|
220
|
+
pdir = dirname(f) or "."
|
221
|
+
elif not exists(pdir + os.sep + basename(f)):
|
222
|
+
return False
|
223
|
+
return True
|
224
|
+
|
225
|
+
|
226
|
+
def glob_files(*files, only_first=True):
|
227
|
+
"""
|
228
|
+
Helper to do a :func:`glob` on each file pattern in ``files``.
|
229
|
+
|
230
|
+
Args:
|
231
|
+
only_first: ``bool``
|
232
|
+
If ``True`` (default) returns only the first file matching pattern
|
233
|
+
``files[i]`` for all ``i`` otherwise (``False``) returns all of
|
234
|
+
them.
|
235
|
+
Return:
|
236
|
+
the list of "globbed" files.
|
237
|
+
|
238
|
+
Example:
|
239
|
+
>>> from random import randint
|
240
|
+
>>> rand_suffix = str(randint(1, 2**10))
|
241
|
+
>>> # create a folder and dummy files
|
242
|
+
>>> dir = "test_remove_dirs" + rand_suffix
|
243
|
+
>>> dir2 = "test_remove_dirs" + rand_suffix + '2'
|
244
|
+
>>> os.mkdir(dir)
|
245
|
+
>>> os.mkdir(dir2)
|
246
|
+
>>> f1 = os.path.join(dir, "f1")
|
247
|
+
>>> f_out = open(f1, 'w')
|
248
|
+
>>> f_out.close()
|
249
|
+
>>> f2 = os.path.join(dir, "f2")
|
250
|
+
>>> f2_out = open(f2, 'w')
|
251
|
+
>>> f2_out.close()
|
252
|
+
>>> f3 = os.path.join(dir2, "f3")
|
253
|
+
>>> f3_out = open(f3, 'w')
|
254
|
+
>>> f3_out.close()
|
255
|
+
>>> # globbing onfly first file of each globbing
|
256
|
+
>>> files = glob_files(dir + '/f*', dir2 + '/f*')
|
257
|
+
>>> len(files) == 2
|
258
|
+
True
|
259
|
+
>>> files[0] == f1
|
260
|
+
True
|
261
|
+
>>> files[1] == f3
|
262
|
+
True
|
263
|
+
>>> # globbing all matching files
|
264
|
+
>>> files = glob_files(dir + '/f*', dir2 + '/f*', only_first=False)
|
265
|
+
>>> len(files) == 3
|
266
|
+
True
|
267
|
+
>>> files[0] == f1
|
268
|
+
True
|
269
|
+
>>> files[1] == f2
|
270
|
+
True
|
271
|
+
>>> files[2] == f3
|
272
|
+
True
|
273
|
+
|
274
|
+
"""
|
275
|
+
out_files = []
|
276
|
+
for f in files:
|
277
|
+
gl = glob(f)
|
278
|
+
if len(gl) > 0:
|
279
|
+
if only_first:
|
280
|
+
out_files.append(gl[0])
|
281
|
+
else:
|
282
|
+
for f in gl:
|
283
|
+
out_files.append(f)
|
284
|
+
else:
|
285
|
+
out_files.append(f)
|
286
|
+
return out_files
|
287
|
+
|
288
|
+
|
289
|
+
def force_suffix_folder(dir_path, suffix):
|
290
|
+
"""
|
291
|
+
Enforces path ``dir_path`` to be terminated with folder/file ``suffix``.
|
292
|
+
|
293
|
+
Return:
|
294
|
+
the resulting path (with ``suffix`` appended if not already present).
|
295
|
+
|
296
|
+
Example:
|
297
|
+
>>> dir_path = './my/path'
|
298
|
+
>>> force_suffix_folder(dir_path, 'is_here')
|
299
|
+
'./my/path/is_here'
|
300
|
+
>>> dir_path = './my/path/is_here'
|
301
|
+
>>> force_suffix_folder(dir_path, 'is_here')
|
302
|
+
'./my/path/is_here'
|
303
|
+
"""
|
304
|
+
if not re.match(r".*" + suffix + r"/?", dir_path):
|
305
|
+
dir_path += os.sep + suffix
|
306
|
+
return dir_path
|
307
|
+
|
308
|
+
|
309
|
+
def check_file(file_path, additional_msg=""):
|
310
|
+
"""
|
311
|
+
Checks file ``file_path`` exists.
|
312
|
+
|
313
|
+
Raises an exception if file doesn't exist.
|
314
|
+
Otherwise returns the ``file_path`` passed as argument.
|
315
|
+
|
316
|
+
Args:
|
317
|
+
additional_msg: ``str``
|
318
|
+
Message additionally printed if exception raised.
|
319
|
+
|
320
|
+
.. seealso::
|
321
|
+
:func:`.check_files`
|
322
|
+
|
323
|
+
Example:
|
324
|
+
>>> check_file('/etc/passwd')
|
325
|
+
'/etc/passwd'
|
326
|
+
>>> check_file('nonexistingfileforsureornot')
|
327
|
+
Traceback (most recent call last):
|
328
|
+
...
|
329
|
+
Exception: Error: the file nonexistingfileforsureornot doesn't exist.
|
330
|
+
"""
|
331
|
+
if not exists(file_path):
|
332
|
+
raise Exception("Error: the file " + file_path +
|
333
|
+
" doesn't exist." + additional_msg)
|
334
|
+
return file_path
|
335
|
+
|
336
|
+
|
337
|
+
def check_files(*files):
|
338
|
+
"""
|
339
|
+
Proceeds to a :func:`.check_file` for each file in ``files``.
|
340
|
+
|
341
|
+
Return:
|
342
|
+
``None``
|
343
|
+
|
344
|
+
.. seealso::
|
345
|
+
:func:`.check_file`
|
346
|
+
|
347
|
+
|
348
|
+
Example:
|
349
|
+
>>> check_files('/etc/passwd', '/etc/hosts')
|
350
|
+
>>> check_files('/etc/passwd', '/etc/hosts', 'likelynonexistingfile')
|
351
|
+
Traceback (most recent call last):
|
352
|
+
...
|
353
|
+
Exception: Error: the file likelynonexistingfile doesn't exist.
|
354
|
+
|
355
|
+
"""
|
356
|
+
for f in files:
|
357
|
+
check_file(f)
|
358
|
+
|
359
|
+
|
360
|
+
def count_file_lines(file):
|
361
|
+
r"""
|
362
|
+
Counts the number of lines in ``file``.
|
363
|
+
|
364
|
+
Return:
|
365
|
+
number of lines found.
|
366
|
+
|
367
|
+
Example:
|
368
|
+
>>> from random import randint
|
369
|
+
>>> rand_suffix = str(randint(1, 2**10))
|
370
|
+
>>> f1 = "f1-" + rand_suffix
|
371
|
+
>>> f_out = open(f1, 'w')
|
372
|
+
>>> f_out.writelines(["line 1\n", "line 2\n", "line 3\n"])
|
373
|
+
>>> f_out.close()
|
374
|
+
>>> count_file_lines(f1)
|
375
|
+
3
|
376
|
+
>>> remove_files(f1)
|
377
|
+
|
378
|
+
"""
|
379
|
+
check_file(file)
|
380
|
+
fd = open(file)
|
381
|
+
n = len(fd.readlines())
|
382
|
+
fd.close()
|
383
|
+
return n
|
384
|
+
|
385
|
+
|
386
|
+
def truncate_file(file, nlines):
|
387
|
+
r"""
|
388
|
+
Truncates ``file`` to ``nlines`` number of lines.
|
389
|
+
|
390
|
+
Example:
|
391
|
+
>>> from random import randint
|
392
|
+
>>> rand_suffix = str(randint(1, 2**10))
|
393
|
+
>>> f1 = "f1-" + rand_suffix
|
394
|
+
>>> f_out = open(f1, 'w')
|
395
|
+
>>> f_out.writelines(["line 1\n", "line 2\n", "line 3\n"])
|
396
|
+
>>> f_out.close()
|
397
|
+
>>> count_file_lines(f1)
|
398
|
+
3
|
399
|
+
>>> truncate_file(f1, 1)
|
400
|
+
>>> count_file_lines(f1)
|
401
|
+
1
|
402
|
+
>>> remove_files(f1)
|
403
|
+
|
404
|
+
"""
|
405
|
+
check_file(file)
|
406
|
+
fd = open(file)
|
407
|
+
lines = fd.readlines()
|
408
|
+
fd.close()
|
409
|
+
fd = open(file, 'w')
|
410
|
+
fd.writelines(lines[:nlines])
|
411
|
+
fd.close()
|
412
|
+
|
413
|
+
|
414
|
+
def infer_path_rel_and_abs_cmds(argv):
|
415
|
+
r"""
|
416
|
+
This function is an helper to define which string (filename or filepath) to
|
417
|
+
use to launch a program (``argv[0]``).
|
418
|
+
|
419
|
+
This function can help to write a USAGE message for a script. Precisely, to
|
420
|
+
determine how to print the program (as a filepath or just a name).
|
421
|
+
|
422
|
+
The string is not the same if the current working directory is the parent
|
423
|
+
directory of ``argv[0]`` (a relative path to the program might be used)
|
424
|
+
or another directory (an absolute path to the program might be used).
|
425
|
+
Besides, the program can also be available from a directory set in the PATH
|
426
|
+
environment variable (in this case only the program filename is enough to
|
427
|
+
launch it).
|
428
|
+
|
429
|
+
Args:
|
430
|
+
argv: ``list[str]``
|
431
|
+
the arguments of the program of interest (see ``sys.argv``).
|
432
|
+
|
433
|
+
Return: ``tuple(str, str)``
|
434
|
+
- ``tuple[0]``: the command to use in current working directory to run
|
435
|
+
``argv[0]``,
|
436
|
+
- ``tuple[1]``: the command to use in another directory to run
|
437
|
+
``argv[0]``.
|
438
|
+
``tuple[0]`` can possibly be the same as ``tuple[1]``.
|
439
|
+
|
440
|
+
Example:
|
441
|
+
>>> # for a program in PATH
|
442
|
+
>>> cwd_cmd, other_dir_cmd = infer_path_rel_and_abs_cmds(['ls'])
|
443
|
+
>>> cwd_cmd == 'ls'
|
444
|
+
True
|
445
|
+
>>> other_dir_cmd == os.getcwd() + '/ls'
|
446
|
+
True
|
447
|
+
>>> # for a program in PATH but with absolute path given
|
448
|
+
>>> cwd_cmd, odir_cmd = infer_path_rel_and_abs_cmds(['/usr/bin/ls'])
|
449
|
+
>>> cwd_cmd == 'ls'
|
450
|
+
True
|
451
|
+
>>> odir_cmd == 'ls'
|
452
|
+
True
|
453
|
+
>>> # for a program not in PATH
|
454
|
+
>>> script = 'nop232323.py'
|
455
|
+
>>> exists(script)
|
456
|
+
False
|
457
|
+
>>> s = open(script, 'w')
|
458
|
+
>>> s.writelines(['#!/usr/bin/env python3\n'])
|
459
|
+
>>> s.write('from sys import argv\n')
|
460
|
+
21
|
461
|
+
>>> s.write('from py3toolset.fs import infer_path_rel_and_abs_cmds\n')
|
462
|
+
51
|
463
|
+
>>> s.writelines(["if __name__ == '__main__':\n"])
|
464
|
+
>>> s.writelines([' print(infer_path_rel_and_abs_cmds(argv))\n'])
|
465
|
+
>>> s.close()
|
466
|
+
>>> os.system("chmod +x "+script)
|
467
|
+
0
|
468
|
+
>>> import subprocess
|
469
|
+
>>> ret = subprocess.run("./"+script, capture_output=True)
|
470
|
+
>>> ret.stdout # doctest:+ELLIPSIS
|
471
|
+
b"('./nop232323.py', '/.../nop232323.py')\n"
|
472
|
+
>>> # 1st path is ./ because script is in cwd
|
473
|
+
>>> # 2nd path is absolute path to use the script from any directory
|
474
|
+
>>> remove_files(script)
|
475
|
+
"""
|
476
|
+
prog_name = basename(argv[0])
|
477
|
+
if dirname(argv[0]) in environ['PATH'].split(pathsep):
|
478
|
+
# the script is in path we don't need to print location in usage
|
479
|
+
prog_abs_path = ""
|
480
|
+
prog_rel_path = ""
|
481
|
+
elif argv[0].startswith(os.path.sep):
|
482
|
+
# absolute path
|
483
|
+
prog_abs_path = dirname(argv[0])
|
484
|
+
prog_rel_path = dirname(argv[0])
|
485
|
+
else:
|
486
|
+
# relative path
|
487
|
+
prog_abs_path = join(getcwd(), dirname(argv[0]))
|
488
|
+
prog_abs_path = prog_abs_path.replace(os.path.sep+'.', '')
|
489
|
+
prog_rel_path = dirname(argv[0])
|
490
|
+
cwd_cmd = join(prog_rel_path, prog_name)
|
491
|
+
other_dir_cmd = join(prog_abs_path, prog_name)
|
492
|
+
return cwd_cmd, other_dir_cmd
|
493
|
+
|
494
|
+
|
495
|
+
def copy_file_with_rpath(path, targetdir):
|
496
|
+
"""
|
497
|
+
Copies file ``path`` into ``targetdir`` keeping its relative path.
|
498
|
+
|
499
|
+
For example, ``path = 'dir1/dir2/dir3/file'`` is copied as
|
500
|
+
``targetdir + '/dir1/dir2/dir3/file'
|
501
|
+
|
502
|
+
``targetdir`` and intermediate folders are created recursively if needed.
|
503
|
+
|
504
|
+
Args:
|
505
|
+
path: ``str``
|
506
|
+
relative path of the file.
|
507
|
+
targetdir: ``str``
|
508
|
+
target directory to copy the file into (keeping its relative path).
|
509
|
+
|
510
|
+
Example:
|
511
|
+
>>> from random import randint
|
512
|
+
>>> rand_suffix = str(randint(1, 2**10))
|
513
|
+
>>> # create a folder and dummy files
|
514
|
+
>>> parent_dir = "my_dir" + rand_suffix
|
515
|
+
>>> os.mkdir(parent_dir)
|
516
|
+
>>> f1 = os.path.join(parent_dir, "f1")
|
517
|
+
>>> f_out = open(f1, 'w')
|
518
|
+
>>> f_out.writelines(["Test test test"])
|
519
|
+
>>> f_out.close()
|
520
|
+
>>> f2 = os.path.join(parent_dir, "f2")
|
521
|
+
>>> f2_out = open(f2, 'w')
|
522
|
+
>>> f2_out.writelines(["Test2 test2 test2"])
|
523
|
+
>>> f2_out.close()
|
524
|
+
>>> target_dir = 'new_dir' + rand_suffix
|
525
|
+
>>> copy_file_with_rpath(f2, target_dir)
|
526
|
+
>>> exists(os.path.join(target_dir, f2))
|
527
|
+
True
|
528
|
+
>>> print(os.path.join(target_dir, f2)) # doctest:+ELLIPSIS
|
529
|
+
new_dir.../my_dir.../f2
|
530
|
+
>>> remove_dirs(target_dir, parent_dir)
|
531
|
+
|
532
|
+
"""
|
533
|
+
if path.startswith(sep):
|
534
|
+
raise ValueError('path must be relative')
|
535
|
+
dpath = join(targetdir, dirname(path))
|
536
|
+
folders = dpath.split(sep)
|
537
|
+
bpath = ""
|
538
|
+
for f in folders:
|
539
|
+
bpath += f
|
540
|
+
bpath += sep
|
541
|
+
if not exists(bpath):
|
542
|
+
mkdir(bpath)
|
543
|
+
copyfile(path, join(targetdir, path))
|