Skip to content

Commit 74b3c62

Browse files
committed
-
1 parent 0d3d35e commit 74b3c62

File tree

1 file changed

+29
-13
lines changed

1 file changed

+29
-13
lines changed

source_py3/python_toolbox/file_tools.py

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import pathlib
77
import re
88

9+
from python_toolbox import cute_iter_tools
910
from python_toolbox import context_management
1011

1112

@@ -15,7 +16,15 @@
1516
r'''(?P<raw_name>.*) \((?P<number>[0-9]+)\)'''
1617
)
1718

18-
def _get_next_name(path):
19+
def _get_next_path(path):
20+
'''
21+
Get the name that `path` should be renamed to if taken.
22+
23+
For example, "c:\example.ogg" would become "c:\example (1).ogg", while
24+
"c:\example (1).ogg" would become "c:\example (2).ogg".
25+
26+
(Uses `Path` objects rather than strings.)
27+
'''
1928
assert isinstance(path, pathlib.Path)
2029
suffix = path.suffix
2130
suffixless_name = path.name[:-len(suffix)]
@@ -33,28 +42,35 @@ def _get_next_name(path):
3342
return pathlib.Path(
3443
'{}{}{}'.format(parent_with_separator, fixed_suffixless_name, suffix)
3544
)
45+
46+
47+
def iterate_file_paths(path):
48+
'''
49+
Iterate over file paths, hoping to find one that's available.
50+
51+
For example, when given "c:\example.ogg", would first yield
52+
"c:\example.ogg", then "c:\example (1).ogg", then "c:\example (2).ogg", and
53+
so on.
54+
55+
(Uses `Path` objects rather than strings.)
56+
'''
57+
while True:
58+
yield path
59+
path = _get_next_path(path)
3660

3761

38-
class FileContainer(context_management.ContextManager):
39-
def __init__(self, file):
40-
self.file = file
41-
42-
def __exit__(self, exc_type, exc_value, exc_traceback):
43-
return self.file.__exit__(exc_type, exc_value, exc_traceback)
44-
45-
4662
def create_file_renaming_if_taken(path, mode='x',
4763
buffering=-1, encoding=None,
4864
errors=None, newline=None):
4965
assert 'x' in mode
50-
current_path = pathlib.Path(path)
51-
for i in range(N_MAX_ATTEMPTS):
66+
for path in cute_iter_tools.shorten(iterate_file_paths(pathlib.Path(path)),
67+
N_MAX_ATTEMPTS):
5268
try:
53-
return current_path.open(mode, buffering=buffering,
69+
return path.open(mode, buffering=buffering,
5470
encoding=encoding, errors=errors,
5571
newline=newline)
5672
except FileExistsError:
57-
current_path = _get_next_name(current_path)
73+
pass
5874
else:
5975
raise Exception("Exceeded {} tries, can't create file {}".format(
6076
N_MAX_ATTEMPTS,

0 commit comments

Comments
 (0)