@@ -22,7 +22,8 @@ def __init__(self,
2222 input_file : Optional [Union [IOBase , str , int ]] = None ,
2323 output_file : Optional [Union [IOBase , str , int ]] = None ,
2424 data_id : Optional [int ] = None ,
25- disable_output : bool = False ):
25+ disable_output : bool = False ,
26+ make_dirs : bool = False ):
2627 ...
2728
2829 @overload
@@ -31,7 +32,8 @@ def __init__(self,
3132 file_prefix : Optional [str ] = None ,
3233 input_suffix : str = '.in' ,
3334 output_suffix : str = '.out' ,
34- disable_output : bool = False ):
35+ disable_output : bool = False ,
36+ make_dirs : bool = False ):
3537 ...
3638
3739 def __init__ ( # type: ignore
@@ -42,20 +44,22 @@ def __init__( # type: ignore
4244 file_prefix : Optional [str ] = None ,
4345 input_suffix : str = '.in' ,
4446 output_suffix : str = '.out' ,
45- disable_output : bool = False ):
47+ disable_output : bool = False ,
48+ make_dirs : bool = False ):
4649 """
4750 Args:
48- input_file (optional): input file object or filename or file descriptor.
51+ input_file (optional): input file object or filename or file descriptor.
4952 If it's None, make a temp file. Defaults to None.
50- output_file (optional): input file object or filename or file descriptor.
53+ output_file (optional): input file object or filename or file descriptor.
5154 If it's None, make a temp file. Defaults to None.
52- data_id (optional): the id of the data. It will be add after
55+ data_id (optional): the id of the data. It will be add after
5356 `input_file` and `output_file` when they are str.
5457 If it's None, the file names will not contain the id. Defaults to None.
5558 file_prefix (optional): the prefix for the input and output files. Defaults to None.
5659 input_suffix (optional): the suffix of the input file. Defaults to '.in'.
5760 output_suffix (optional): the suffix of the output file. Defaults to '.out'.
5861 disable_output (optional): set to True to disable output file. Defaults to False.
62+ make_dirs (optional): set to True to create dir if path is not found. Defaults to False.
5963 Examples:
6064 >>> IO("a","b")
6165 # create input file "a" and output file "b"
@@ -75,7 +79,12 @@ def __init__( # type: ignore
7579 # create input file "data2.in" and output file "data2.out"
7680 >>> IO(open('data.in', 'w+'), open('data.out', 'w+'))
7781 # input file "data.in" and output file "data.out"
82+ >>> IO("./io/data.in", "./io/data.out", disable_output = True)
83+ # input file "./io/data.in" and output file "./io/data.out"
84+ # if the dir "./io" not found it will be created
7885 """
86+ self .__closed = False
87+ self .input_file , self .output_file = None , None
7988 if file_prefix is not None :
8089 # legacy mode
8190 input_file = '{}{{}}{}' .format (self .__escape_format (file_prefix ),
@@ -85,16 +94,16 @@ def __init__( # type: ignore
8594 self .__escape_format (output_suffix ))
8695 self .input_filename , self .output_filename = None , None
8796 self .__input_temp , self .__output_temp = False , False
88- self .__init_file (input_file , data_id , "i" )
97+ self .__init_file (input_file , data_id , "i" , make_dirs )
8998 if not disable_output :
90- self .__init_file (output_file , data_id , "o" )
99+ self .__init_file (output_file , data_id , "o" , make_dirs )
91100 else :
92101 self .output_file = None
93- self .__closed = False
94102 self .is_first_char = {}
95103
96- def __init_file (self , f : Union [IOBase , str , int , None ],
97- data_id : Union [int , None ], file_type : str ):
104+ def __init_file (self , f : Union [IOBase , str , int ,
105+ None ], data_id : Union [int , None ],
106+ file_type : str , make_dirs : bool ):
98107 if isinstance (f , IOBase ):
99108 # consider ``f`` as a file object
100109 if file_type == "i" :
@@ -104,30 +113,36 @@ def __init_file(self, f: Union[IOBase, str, int, None],
104113 elif isinstance (f , int ):
105114 # consider ``f`` as a file descor
106115 self .__init_file (open (f , 'w+' , encoding = "utf-8" , newline = '\n ' ),
107- data_id , file_type )
116+ data_id , file_type , make_dirs )
108117 elif f is None :
109118 # consider wanna temp file
110119 fd , self .input_filename = tempfile .mkstemp ()
111- self .__init_file (fd , data_id , file_type )
120+ self .__init_file (fd , data_id , file_type , make_dirs )
112121 if file_type == "i" :
113122 self .__input_temp = True
114123 else :
115124 self .__output_temp = True
116125 else :
117126 # consider ``f`` as filename template
118127 filename = f .format (data_id or "" )
128+ # be sure dir is existed
129+ if make_dirs :
130+ self .__make_dirs (filename )
119131 if file_type == "i" :
120132 self .input_filename = filename
121133 else :
122134 self .output_filename = filename
123135 self .__init_file (
124136 open (filename , 'w+' , newline = '\n ' , encoding = 'utf-8' ), data_id ,
125- file_type )
137+ file_type , make_dirs )
126138
127139 def __escape_format (self , st : str ):
128140 """replace "{}" to "{{}}" """
129141 return re .sub (r"\{" , "{{" , re .sub (r"\}" , "}}" , st ))
130142
143+ def __make_dirs (self , pth : str ):
144+ os .makedirs (os .path .dirname (pth ), exist_ok = True )
145+
131146 def __del_files (self ):
132147 """delete files"""
133148 if self .__input_temp and self .input_filename is not None :
@@ -170,7 +185,7 @@ def __exit__(self, exc_type, exc_val, exc_tb):
170185
171186 def __write (self , file : IOBase , * args , ** kwargs ):
172187 """
173- Write every element in *args into file. If the element isn't "\n ", insert `separator`.
188+ Write every element in *args into file. If the element isn't "\n ", insert `separator`.
174189 It will convert every element into str.
175190 """
176191 separator = kwargs .get ("separator" , " " )
@@ -185,6 +200,17 @@ def __write(self, file: IOBase, *args, **kwargs):
185200 if arg == "\n " :
186201 self .is_first_char [file ] = True
187202
203+ def __clear (self , file : IOBase , pos : int = 0 ):
204+ """
205+ Clear the content use truncate()
206+ Args:
207+ file: Which file to clear
208+ pos: Where file will truncate.
209+ """
210+ file .truncate (pos )
211+ self .is_first_char [file ] = True
212+ file .seek (pos )
213+
188214 def input_write (self , * args , ** kwargs ):
189215 """
190216 Write every element in *args into the input file. Splits with `separator`.
@@ -208,6 +234,15 @@ def input_writeln(self, *args, **kwargs):
208234 args .append ("\n " )
209235 self .input_write (* args , ** kwargs )
210236
237+ def input_clear_content (self , pos : int = 0 ):
238+ """
239+ Clear the content of input
240+ Args:
241+ pos: Where file will truncate.
242+ """
243+
244+ self .__clear (self .input_file , pos )
245+
211246 def output_gen (self , shell_cmd , time_limit = None ):
212247 """
213248 Run the command `shell_cmd` (usually the std program) and send it the input file as stdin.
@@ -268,6 +303,14 @@ def output_writeln(self, *args, **kwargs):
268303 args .append ("\n " )
269304 self .output_write (* args , ** kwargs )
270305
306+ def output_clear_content (self , pos : int = 0 ):
307+ """
308+ Clear the content of output
309+ Args:
310+ pos: Where file will truncate
311+ """
312+ self .__clear (self .output_file , pos )
313+
271314 def flush_buffer (self ):
272315 """Flush the input file"""
273316 self .input_file .flush ()
0 commit comments