1+ """
2+ A module that provides a class IO to process the input and output files.
3+ Classes:
4+ IO: IO tool class. It will process the input and output files.
5+ """
16from __future__ import absolute_import
2- from .utils import *
3- from . import log
4- from io import open , IOBase
5- import subprocess
6- import tempfile
77import os
88import re
9+ import subprocess
10+ import tempfile
11+ from typing import Union , overload
12+ from io import IOBase
13+ from . import log
14+ from .utils import list_like , make_unicode
915
1016
11- class IO ( object ) :
17+ class IO :
1218 """Class IO: IO tool class. It will process the input and output files."""
13- def __init__ (self , input_file = None , output_file = None , data_id = None , file_prefix = None , input_suffix = '.in' , output_suffix = '.out' , disable_output = False ):
14- """__init__(self, input_file=None, output_file=None, data_id=None, file_prefix=None, input_suffix='.in', output_suffix='.out', disable_output=False) -> None
15- input_file, output_file overload:
16- None -> make a temp file (if file_prefix is None)
17- file object -> treat the file-like object as in/output file
18- int -> open file by file descriptor
19- str -> a filename or filename template like 'awd{}.in'. ``{}`` will be replaced by ``data_id``
20- int data_id -> the id of the data. if it's None, the file names will not contain the id.
21- legacy argumants:
22- str file_prefix -> the prefix for the input and output files
23- str input_suffix = ".in" -> the suffix of the input file
24- str output_suffix = ".out" -> the suffix of the output file
25- disable_output -> bool, set to True to disable output
26- Examples:
27- IO("a","b") -> create input file "a" and output file "b"
28- IO("a.in","b.out") -> create input file "a.in" and output file "b.out"
29- IO(file_prefix="data") -> create input file "data.in" and output file "data.out"
30- IO(file_prefix="data",data_id=1) -> create input file "data1.in" and output file "data1.out"
31- IO(file_prefix="data",input_suffix=".input") -> create input file "data.input" and output file "data.out"
32- IO(file_prefix="data",output_suffix=".output") -> create input file "data.in" and output file "data.output"
33- IO(file_prefix="data",data_id=2,input_suffix=".input") -> create input file "data2.input" and output file "data2.out"
34- IO("data{}.in","data{}.out",data_id=2) -> create input file "data2.in" and output file "data2.out"
35- IO(open('data.in', 'w+'), open('data.out', 'w+')) -> input file "data.in" and output file "data.out"
19+
20+ @overload
21+ def __init__ (self ,
22+ input_file : Union [IOBase , str , int , None ] = None ,
23+ output_file : Union [IOBase , str , int , None ] = None ,
24+ data_id : Union [str , None ] = None ,
25+ disable_output : bool = False ):
26+ ...
27+
28+ @overload
29+ def __init__ (self ,
30+ data_id : Union [str , None ] = None ,
31+ file_prefix : Union [str , None ] = None ,
32+ input_suffix : Union [str , None ] = '.in' ,
33+ output_suffix : Union [str , None ] = '.out' ,
34+ disable_output : bool = False ):
35+ ...
36+
37+ def __init__ (self ,
38+ input_file : Union [IOBase , str , int , None ] = None ,
39+ output_file : Union [IOBase , str , int , None ] = None ,
40+ data_id : Union [str , None ] = None ,
41+ file_prefix : Union [str , None ] = None ,
42+ input_suffix : Union [str , None ] = '.in' ,
43+ output_suffix : Union [str , None ] = '.out' ,
44+ disable_output : bool = False ):
45+ """
46+ Args:
47+ input_file (optional): input file object or filename or file descriptor.
48+ If it's None, make a temp file. Defaults to None.
49+ output_file (optional): input file object or filename or file descriptor.
50+ If it's None, make a temp file. Defaults to None.
51+ data_id (optional): the id of the data. It will be add after
52+ `input_file` and `output_file` when they are str.
53+ If it's None, the file names will not contain the id. Defaults to None.
54+ file_prefix (optional): the prefix for the input and output files. Defaults to None.
55+ input_suffix (optional): the suffix of the input file. Defaults to '.in'.
56+ output_suffix (optional): the suffix of the output file. Defaults to '.out'.
57+ disable_output (optional): set to True to disable output file. Defaults to False.
58+ Examples:
59+ >>> IO("a","b")
60+ # create input file "a" and output file "b"
61+ >>> IO("a.in","b.out")
62+ # create input file "a.in" and output file "b.out"
63+ >>> IO(file_prefix="data")
64+ # create input file "data.in" and output file "data.out"
65+ >>> IO(file_prefix="data",data_id=1)
66+ # create input file "data1.in" and output file "data1.out"
67+ >>> IO(file_prefix="data",input_suffix=".input")
68+ # create input file "data.input" and output file "data.out"
69+ >>> IO(file_prefix="data",output_suffix=".output")
70+ # create input file "data.in" and output file "data.output"
71+ >>> IO(file_prefix="data",data_id=2,input_suffix=".input")
72+ # create input file "data2.input" and output file "data2.out"
73+ >>> IO("data{}.in","data{}.out",data_id=2)
74+ # create input file "data2.in" and output file "data2.out"
75+ >>> IO(open('data.in', 'w+'), open('data.out', 'w+'))
76+ # input file "data.in" and output file "data.out"
3677 """
3778 if file_prefix is not None :
3879 # legacy mode
39- input_file = '{}{{}}{}' .format (self .__escape_format (file_prefix ), self .__escape_format (input_suffix ))
40- output_file = '{}{{}}{}' .format (self .__escape_format (file_prefix ), self .__escape_format (output_suffix ))
80+ input_file = '{}{{}}{}' .format (self .__escape_format (file_prefix ),
81+ self .__escape_format (input_suffix ))
82+ output_file = '{}{{}}{}' .format (
83+ self .__escape_format (file_prefix ),
84+ self .__escape_format (output_suffix ))
4185 self .input_filename , self .output_filename = None , None
4286 self .__input_temp , self .__output_temp = False , False
4387 self .__init_file (input_file , data_id , 'i' )
@@ -48,20 +92,18 @@ def __init__(self, input_file=None, output_file=None, data_id=None, file_prefix=
4892 self .__closed = False
4993 self .is_first_char = {}
5094
51- def __init_file (self , f , data_id , file_type ):
52- try :
53- is_file = isinstance (f , file )
54- except NameError :
55- is_file = False
56- if isinstance (f , IOBase ) or is_file :
95+ def __init_file (self , f : Union [IOBase , str , int , None ],
96+ data_id : Union [int , None ], file_type : str ):
97+ if isinstance (f , IOBase ):
5798 # consider ``f`` as a file object
5899 if file_type == 'i' :
59100 self .input_file = f
60101 else :
61102 self .output_file = f
62103 elif isinstance (f , int ):
63104 # consider ``f`` as a file descor
64- self .__init_file (open (f , 'w+' , newline = '\n ' ), data_id , file_type )
105+ self .__init_file (open (f , 'w+' , encoding = "utf-8" , newline = '\n ' ),
106+ data_id , file_type )
65107 elif f is None :
66108 # consider wanna temp file
67109 fd , self .input_filename = tempfile .mkstemp ()
@@ -75,12 +117,13 @@ def __init_file(self, f, data_id, file_type):
75117 filename = f .format (data_id or '' )
76118 if file_type == 'i' :
77119 self .input_filename = filename
78- log .debug ("Processing %s" % self .input_filename )
79120 else :
80121 self .output_filename = filename
81- self .__init_file (open (filename , 'w+' , newline = '\n ' ), data_id , file_type )
122+ self .__init_file (
123+ open (filename , 'w+' , newline = '\n ' , encoding = 'utf-8' ), data_id ,
124+ file_type )
82125
83- def __escape_format (self , st ):
126+ def __escape_format (self , st : str ):
84127 """replace "{}" to "{{}}" """
85128 return re .sub (r'\{' , '{{' , re .sub (r'\}' , '}}' , st ))
86129
@@ -99,7 +142,8 @@ def close(self):
99142 deleted = False
100143 try :
101144 # on posix, one can remove a file while it's opend by a process
102- # the file then will be not visable to others, but process still have the file descriptor
145+ # the file then will be not visable to others,
146+ # but process still have the file descriptor
103147 # it is recommand to remove temp file before close it on posix to avoid race
104148 # on nt, it will just fail and raise OSError so that after closing remove it again
105149 self .__del_files ()
@@ -123,12 +167,10 @@ def __enter__(self):
123167 def __exit__ (self , exc_type , exc_val , exc_tb ):
124168 self .close ()
125169
126- def __write (self , file , * args , ** kwargs ):
127- """__write(self, file, *args, **kwargs) -> None
128- Write every element in *args into file. If the element isn't "\n ", insert a space. It will convert every element into str
129- file file -> the file object to write
130- **kwargs:
131- str separator = " " -> a string used to separate every element
170+ def __write (self , file : IOBase , * args , ** kwargs ):
171+ """
172+ Write every element in *args into file. If the element isn't "\n ", insert `separator`.
173+ It will convert every element into str.
132174 """
133175 separator = kwargs .get ("separator" , " " )
134176 for arg in args :
@@ -143,53 +185,70 @@ def __write(self, file, *args, **kwargs):
143185 self .is_first_char [file ] = True
144186
145187 def input_write (self , * args , ** kwargs ):
146- """input_write(self, *args, **kwargs) -> None
147- Write every element in *args into the input file. Splits with spaces. It will convert every element into string
148- **kwargs:
149- str separator = " " -> a string used to separate every element
188+ """
189+ Write every element in *args into the input file. Splits with `separator`.
190+ It will convert every element into str.
191+ Args:
192+ *args: the elements to write
193+ separator: a string used to separate every element. Defaults to " ".
150194 """
151195 self .__write (self .input_file , * args , ** kwargs )
152196
153197 def input_writeln (self , * args , ** kwargs ):
154- """input_writeln(self, *args, **kwargs) -> None
155- Write every element in *args into the input file and turn to a new line. Splits with spaces. It will convert every element into string
156- **kwargs:
157- str separator = " " -> a string used to separate every element
198+ """
199+ Write every element in *args into the input file and turn to a new line
200+ Splits with `separator`.
201+ It will convert every element into str.
202+ Args:
203+ *args: the elements to write
204+ separator: a string used to separate every element. Defaults to " ".
158205 """
159206 args = list (args )
160207 args .append ("\n " )
161208 self .input_write (* args , ** kwargs )
162209
163210 def output_gen (self , shell_cmd ):
164- """output_gen(self, shell_cmd) -> None
165- Run the command shell_cmd(usually the std programme) and send it the input file as stdin. Write its output to the output file.
166- str shell_cmd -> the command to run, usually the std programme
211+ """
212+ Run the command `shell_cmd` (usually the std program) and send it the input file as stdin.
213+ Write its output to the output file.
214+ Args:
215+ shell_cmd: the command to run, usually the std program.
167216 """
168217 self .flush_buffer ()
169218 origin_pos = self .input_file .tell ()
170219 self .input_file .seek (0 )
171- subprocess .check_call (shell_cmd , shell = True , stdin = self .input_file , stdout = self .output_file , universal_newlines = True )
220+ subprocess .check_call (shell_cmd ,
221+ shell = True ,
222+ stdin = self .input_file ,
223+ stdout = self .output_file ,
224+ universal_newlines = True )
172225 self .input_file .seek (origin_pos )
173226
174227 log .debug (self .output_filename , " done" )
175228
176229 def output_write (self , * args , ** kwargs ):
177- """output_write(self, *args, **kwargs) -> None
178- Write every element in *args into the output file. Splits with spaces. It will convert every element into string
179- **kwargs:
180- str separator = " " -> a string used to separate every element
230+ """
231+ Write every element in *args into the output file. Splits with `separator`.
232+ It will convert every element into str.
233+ Args:
234+ *args: the elements to write
235+ separator: a string used to separate every element. Defaults to " ".
181236 """
182237 self .__write (self .output_file , * args , ** kwargs )
183238
184239 def output_writeln (self , * args , ** kwargs ):
185- """output_writeln(self, *args, **kwargs) -> None
186- Write every element in *args into the output file and turn to a new line. Splits with spaces. It will convert every element into string
187- **kwargs:
188- str separator = " " -> a string used to separate every element
240+ """
241+ Write every element in *args into the output file and turn to a new line.
242+ Splits with `separator`.
243+ It will convert every element into str.
244+ Args:
245+ *args: the elements to write
246+ separator: a string used to separate every element. Defaults to " ".
189247 """
190248 args = list (args )
191249 args .append ("\n " )
192250 self .output_write (* args , ** kwargs )
193251
194252 def flush_buffer (self ):
253+ """Flush the input file"""
195254 self .input_file .flush ()
0 commit comments