55
66import pathlib
77import re
8+ import contextlib
89
10+ from python_toolbox import context_management
11+
12+
13+ N_MAX_ATTEMPTS = 100
914
1015numbered_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