Skip to content

Commit b5dbae1

Browse files
committed
-
1 parent 11b87d4 commit b5dbae1

File tree

1 file changed

+43
-3
lines changed

1 file changed

+43
-3
lines changed

source_py3/python_toolbox/file_tools.py

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@
55

66
import pathlib
77
import re
8+
import contextlib
89

10+
from python_toolbox import context_management
11+
12+
13+
N_MAX_ATTEMPTS = 100
914

1015
numbered_name_pattern = re.compile(
1116
r'''(?P<raw_name>.*) \((?P<number>[0-9]+)\)'''
@@ -16,7 +21,7 @@ def _get_next_name(path):
1621
parent = path.parent
1722
suffix = path.suffix
1823
suffixless_name = path.name[:-len(suffix)]
19-
assert parent + suffix + suffixless_name == path
24+
assert '{}{}{}'.format(parent, suffixless_name, suffix) == path
2025
match = numbered_name_pattern.match(suffixless_name)
2126
if match:
2227
fixed_suffixless_name = '{} ({})'.format(
@@ -31,8 +36,43 @@ def _get_next_name(path):
3136
)
3237

3338

39+
class FileContainer(context_management.ContextManager):
40+
def __init__(self, file):
41+
self.file = file
42+
43+
def __exit__(self, exc_type, exc_value, exc_traceback):
44+
return self.file.__exit__(exc_type, exc_value, exc_traceback)
45+
3446

35-
def create_file_renaming_if_taken(path, binary=False):
36-
path = pathlib.Path(path)
47+
def create_file_renaming_if_taken(path, mode='x',
48+
buffering=-1, encoding=None,
49+
errors=None, newline=None):
50+
assert 'x' in mode
51+
current_path = pathlib.Path(path)
52+
with contextlib.ExitStack() as exit_stack:
53+
for i in range(N_MAX_ATTEMPTS):
54+
try:
55+
file = exit_stack.enter_context(
56+
current_path.open(mode, buffering=buffering,
57+
encoding=encoding, errors=errors,
58+
newline=newline)
59+
)
60+
except FileExistsError:
61+
current_path = _get_next_name(current_path)
62+
else:
63+
return FileContainer(file)
64+
else:
65+
raise Exception("Exceeded {} tries, can't create file {}".format(
66+
N_MAX_ATTEMPTS,
67+
path
68+
))
3769

3870

71+
def write_to_file_renaming_if_taken(path, data, mode='x',
72+
buffering=-1, encoding=None,
73+
errors=None, newline=None):
74+
with create_file_renaming_if_taken(
75+
path, mode=mode, buffering=buffering, encoding=encoding, errors=errors,
76+
newline=newline) as file:
77+
file.write(data)
78+

0 commit comments

Comments
 (0)