From 7ea8bd796278a52676bc1bf15c3aa773515d8571 Mon Sep 17 00:00:00 2001 From: OrangePie <125730489+OranPie@users.noreply.github.com> Date: Fri, 4 Oct 2024 11:44:06 +0800 Subject: [PATCH 01/14] Update io.py Add originzation. Add a Enum class to speified use Output & Input. Add a clear_content to clear Output & Input file. --- cyaron/io.py | 81 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 31 deletions(-) diff --git a/cyaron/io.py b/cyaron/io.py index 126ce90..ce4d034 100644 --- a/cyaron/io.py +++ b/cyaron/io.py @@ -8,11 +8,16 @@ import re import subprocess import tempfile +from enum import IntEnum from typing import Union, overload from io import IOBase from . import log from .utils import list_like, make_unicode +class File(IntEnum): + INPUT = 0 + OUTPUT = 1 + class IO: """Class IO: IO tool class. It will process the input and output files.""" @@ -84,19 +89,19 @@ def __init__(self, self.__escape_format(output_suffix)) self.input_filename, self.output_filename = None, None self.__input_temp, self.__output_temp = False, False - self.__init_file(input_file, data_id, "i") + self.__init_file(input_file, data_id, File.INPUT) if not disable_output: - self.__init_file(output_file, data_id, "o") + self.__init_file(output_file, data_id, File.OUTPUT) else: self.output_file = None self.__closed = False self.is_first_char = {} def __init_file(self, f: Union[IOBase, str, int, None], - data_id: Union[int, None], file_type: str): + data_id: Union[int, None], file_type: File): if isinstance(f, IOBase): # consider ``f`` as a file object - if file_type == "i": + if file_type == File.INPUT: self.input_file = f else: self.output_file = f @@ -108,7 +113,7 @@ def __init_file(self, f: Union[IOBase, str, int, None], # consider wanna temp file fd, self.input_filename = tempfile.mkstemp() self.__init_file(fd, data_id, file_type) - if file_type == "i": + if file_type == File.INPUT: self.__input_temp = True else: self.__output_temp = True @@ -184,28 +189,65 @@ def __write(self, file: IOBase, *args, **kwargs): if arg == "\n": self.is_first_char[file] = True - def input_write(self, *args, **kwargs): + def __clear(self, file: IOBase, *args, **kwargs): + """ + Clear the content use truncate() + Args: + file: Which file (File.INPUT/File.OUTPUT) to clear + pos: Where file will truncate. + """ + pos = kwargs.get("pos", 0) + file.truncate(pos) + + + def write(self, file: File = File.INPUT, *args, **kwargs): """ Write every element in *args into the input file. Splits with `separator`. It will convert every element into str. Args: + file: Which file (File.INPUT/File.OUTPUT) to write *args: the elements to write separator: a string used to separate every element. Defaults to " ". """ + if file == File.INPUT: + file = self.input_file + elif file == File.OUTPUT: + file = self.output_file + else: + raise ValueError("file type is not in File.INPUT or File.OUTPUT") + self.__write(self.input_file, *args, **kwargs) - def input_writeln(self, *args, **kwargs): + def writeln(self, file: File = File.INPUT, *args, **kwargs): """ Write every element in *args into the input file and turn to a new line Splits with `separator`. It will convert every element into str. Args: + file: Which file (File.INPUT/File.OUTPUT) to write *args: the elements to write separator: a string used to separate every element. Defaults to " ". """ args = list(args) args.append("\n") - self.input_write(*args, **kwargs) + self.write(file, *args, **kwargs) + + + def clear_content(self, file: File = File.INPUT, *args, **kwargs): + """ + Clear the content of input/output + Args: + file: Which file (File.INPUT/File.OUTPUT) to clear + pos: Where file will truncate. + """ + if file == File.INPUT: + file = self.input_file + elif file == File.OUTPUT: + file = self.output_file + else: + raise ValueError("file type is not in File.INPUT or File.OUTPUT") + + self.__clear(file, *args, **kwargs) def output_gen(self, shell_cmd, time_limit=None): """ @@ -240,29 +282,6 @@ def output_gen(self, shell_cmd, time_limit=None): log.debug(self.output_filename, " done") - def output_write(self, *args, **kwargs): - """ - Write every element in *args into the output file. Splits with `separator`. - It will convert every element into str. - Args: - *args: the elements to write - separator: a string used to separate every element. Defaults to " ". - """ - self.__write(self.output_file, *args, **kwargs) - - def output_writeln(self, *args, **kwargs): - """ - Write every element in *args into the output file and turn to a new line. - Splits with `separator`. - It will convert every element into str. - Args: - *args: the elements to write - separator: a string used to separate every element. Defaults to " ". - """ - args = list(args) - args.append("\n") - self.output_write(*args, **kwargs) - def flush_buffer(self): """Flush the input file""" self.input_file.flush() From 1fe6da54807876b8f5cd858038a186b2f0530f45 Mon Sep 17 00:00:00 2001 From: OrangePie <125730489+OranPie@users.noreply.github.com> Date: Fri, 4 Oct 2024 11:44:26 +0800 Subject: [PATCH 02/14] Update __init__.py including IO.File Enum class --- cyaron/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cyaron/__init__.py b/cyaron/__init__.py index ec5f271..66eff0e 100644 --- a/cyaron/__init__.py +++ b/cyaron/__init__.py @@ -13,7 +13,7 @@ from .compare import Compare from .consts import * from .graph import Edge, Graph -from .io import IO +from .io import IO, File from .math import * from .merger import Merger from .polygon import Polygon From 051a789378035dfc880ec4ea8c225519ef09dd77 Mon Sep 17 00:00:00 2001 From: OrangePie <125730489+OranPie@users.noreply.github.com> Date: Fri, 4 Oct 2024 11:57:53 +0800 Subject: [PATCH 03/14] Update io.py Add some notes Add a flag make_dirs to ensure the dir has created/ Fix some bug. --- cyaron/io.py | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/cyaron/io.py b/cyaron/io.py index ce4d034..f6da2b6 100644 --- a/cyaron/io.py +++ b/cyaron/io.py @@ -9,6 +9,7 @@ import subprocess import tempfile from enum import IntEnum +from pathlib import Path from typing import Union, overload from io import IOBase from . import log @@ -27,7 +28,8 @@ def __init__(self, input_file: Union[IOBase, str, int, None] = None, output_file: Union[IOBase, str, int, None] = None, data_id: Union[str, None] = None, - disable_output: bool = False): + disable_output: bool = False, + make_dirs: bool = True): ... @overload @@ -36,7 +38,8 @@ def __init__(self, file_prefix: Union[str, None] = None, input_suffix: Union[str, None] = '.in', output_suffix: Union[str, None] = '.out', - disable_output: bool = False): + disable_output: bool = False, + make_dirs: bool = True): ... def __init__(self, @@ -46,20 +49,22 @@ def __init__(self, file_prefix: Union[str, None] = None, input_suffix: Union[str, None] = '.in', output_suffix: Union[str, None] = '.out', - disable_output: bool = False): + disable_output: bool = False, + make_dirs: bool = True): """ Args: - input_file (optional): input file object or filename or file descriptor. + input_file (optional): input file object or filename or file descriptor. If it's None, make a temp file. Defaults to None. - output_file (optional): input file object or filename or file descriptor. + output_file (optional): input file object or filename or file descriptor. If it's None, make a temp file. Defaults to None. - data_id (optional): the id of the data. It will be add after + data_id (optional): the id of the data. It will be add after `input_file` and `output_file` when they are str. If it's None, the file names will not contain the id. Defaults to None. file_prefix (optional): the prefix for the input and output files. Defaults to None. input_suffix (optional): the suffix of the input file. Defaults to '.in'. output_suffix (optional): the suffix of the output file. Defaults to '.out'. disable_output (optional): set to True to disable output file. Defaults to False. + make_dirs (optional): set to True to create dir if path is not found. Defaults to True. Examples: >>> IO("a","b") # create input file "a" and output file "b" @@ -79,6 +84,8 @@ def __init__(self, # create input file "data2.in" and output file "data2.out" >>> IO(open('data.in', 'w+'), open('data.out', 'w+')) # input file "data.in" and output file "data.out" + >>> IO("./io/data.in", "./io/data.out") + # input file "./io/data.in" and output file "./io/data.out" if the dir "./io" not found it will be created """ if file_prefix is not None: # legacy mode @@ -120,7 +127,9 @@ def __init_file(self, f: Union[IOBase, str, int, None], else: # consider ``f`` as filename template filename = f.format(data_id or "") - if file_type == "i": + # be sure dir is existed + self.__make_dirs(filename) + if file_type == File.INPUT: self.input_filename = filename else: self.output_filename = filename @@ -132,6 +141,10 @@ def __escape_format(self, st: str): """replace "{}" to "{{}}" """ return re.sub(r"\{", "{{", re.sub(r"\}", "}}", st)) + def __make_dirs(self, pth: Union[IOBase, str, int, None]): + if isinstance(pth, str): + os.makedirs(os.path.dirname(pth), exist_ok=True) + def __del_files(self): """delete files""" if self.__input_temp and self.input_filename is not None: @@ -174,7 +187,7 @@ def __exit__(self, exc_type, exc_val, exc_tb): def __write(self, file: IOBase, *args, **kwargs): """ - Write every element in *args into file. If the element isn't "\n", insert `separator`. + Write every element in *args into file. If the element isn't "\n", insert `separator`. It will convert every element into str. """ separator = kwargs.get("separator", " ") @@ -198,7 +211,7 @@ def __clear(self, file: IOBase, *args, **kwargs): """ pos = kwargs.get("pos", 0) file.truncate(pos) - + def write(self, file: File = File.INPUT, *args, **kwargs): """ @@ -231,7 +244,7 @@ def writeln(self, file: File = File.INPUT, *args, **kwargs): args = list(args) args.append("\n") self.write(file, *args, **kwargs) - + def clear_content(self, file: File = File.INPUT, *args, **kwargs): """ From edadd844ec61e15bad81cf0a5575ca965f54ae25 Mon Sep 17 00:00:00 2001 From: OrangePie <125730489+OranPie@users.noreply.github.com> Date: Fri, 4 Oct 2024 15:57:23 +0800 Subject: [PATCH 04/14] Update io.py Set make_dirs default value to False --- cyaron/io.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cyaron/io.py b/cyaron/io.py index f6da2b6..2680685 100644 --- a/cyaron/io.py +++ b/cyaron/io.py @@ -29,7 +29,7 @@ def __init__(self, output_file: Union[IOBase, str, int, None] = None, data_id: Union[str, None] = None, disable_output: bool = False, - make_dirs: bool = True): + make_dirs: bool = False): ... @overload @@ -39,7 +39,7 @@ def __init__(self, input_suffix: Union[str, None] = '.in', output_suffix: Union[str, None] = '.out', disable_output: bool = False, - make_dirs: bool = True): + make_dirs: bool = False): ... def __init__(self, @@ -50,7 +50,7 @@ def __init__(self, input_suffix: Union[str, None] = '.in', output_suffix: Union[str, None] = '.out', disable_output: bool = False, - make_dirs: bool = True): + make_dirs: bool = False): """ Args: input_file (optional): input file object or filename or file descriptor. From b4bbfff2bc4bf577a691d9c2c00cd6a8507ddecd Mon Sep 17 00:00:00 2001 From: OrangePie <125730489+OranPie@users.noreply.github.com> Date: Fri, 4 Oct 2024 16:02:25 +0800 Subject: [PATCH 05/14] Update io.py Add logic to check make_dirs flag --- cyaron/io.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/cyaron/io.py b/cyaron/io.py index 2680685..9aa8bba 100644 --- a/cyaron/io.py +++ b/cyaron/io.py @@ -96,16 +96,16 @@ def __init__(self, self.__escape_format(output_suffix)) self.input_filename, self.output_filename = None, None self.__input_temp, self.__output_temp = False, False - self.__init_file(input_file, data_id, File.INPUT) + self.__init_file(input_file, data_id, File.INPUT, make_dirs) if not disable_output: - self.__init_file(output_file, data_id, File.OUTPUT) + self.__init_file(output_file, data_id, File.OUTPUT, make_dirs) else: self.output_file = None self.__closed = False self.is_first_char = {} def __init_file(self, f: Union[IOBase, str, int, None], - data_id: Union[int, None], file_type: File): + data_id: Union[int, None], file_type: File, make_dirs: bool): if isinstance(f, IOBase): # consider ``f`` as a file object if file_type == File.INPUT: @@ -128,7 +128,8 @@ def __init_file(self, f: Union[IOBase, str, int, None], # consider ``f`` as filename template filename = f.format(data_id or "") # be sure dir is existed - self.__make_dirs(filename) + if make_dirs: + self.__make_dirs(filename) if file_type == File.INPUT: self.input_filename = filename else: From 1567080ebbbca21a9a844fa25444ffbd02bcb2a0 Mon Sep 17 00:00:00 2001 From: OrangePie <125730489+OranPie@users.noreply.github.com> Date: Fri, 4 Oct 2024 16:04:37 +0800 Subject: [PATCH 06/14] Update io.py Add forget flag make_dirs in __init_file --- cyaron/io.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cyaron/io.py b/cyaron/io.py index 9aa8bba..818bf0f 100644 --- a/cyaron/io.py +++ b/cyaron/io.py @@ -115,11 +115,11 @@ def __init_file(self, f: Union[IOBase, str, int, None], elif isinstance(f, int): # consider ``f`` as a file descor self.__init_file(open(f, 'w+', encoding="utf-8", newline='\n'), - data_id, file_type) + data_id, file_type, make_dirs) elif f is None: # consider wanna temp file fd, self.input_filename = tempfile.mkstemp() - self.__init_file(fd, data_id, file_type) + self.__init_file(fd, data_id, file_type, make_dirs) if file_type == File.INPUT: self.__input_temp = True else: @@ -136,7 +136,7 @@ def __init_file(self, f: Union[IOBase, str, int, None], self.output_filename = filename self.__init_file( open(filename, 'w+', newline='\n', encoding='utf-8'), data_id, - file_type) + file_type, make_dirs) def __escape_format(self, st: str): """replace "{}" to "{{}}" """ From 10a22de795928d1777519a70bcde894999bd0a4a Mon Sep 17 00:00:00 2001 From: OrangePie <125730489+OranPie@users.noreply.github.com> Date: Fri, 4 Oct 2024 16:23:22 +0800 Subject: [PATCH 07/14] Update io.py Fix: file cannot specified --- cyaron/io.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cyaron/io.py b/cyaron/io.py index 818bf0f..5b6823e 100644 --- a/cyaron/io.py +++ b/cyaron/io.py @@ -230,7 +230,7 @@ def write(self, file: File = File.INPUT, *args, **kwargs): else: raise ValueError("file type is not in File.INPUT or File.OUTPUT") - self.__write(self.input_file, *args, **kwargs) + self.__write(file, *args, **kwargs) def writeln(self, file: File = File.INPUT, *args, **kwargs): """ From 7487c691abd3115c3030d8033079482b8941862b Mon Sep 17 00:00:00 2001 From: OrangePie <125730489+OranPie@users.noreply.github.com> Date: Fri, 4 Oct 2024 16:33:02 +0800 Subject: [PATCH 08/14] Update io.py Restore the origin api. --- cyaron/io.py | 78 +++++++++++++++++++++++++++++----------------------- 1 file changed, 44 insertions(+), 34 deletions(-) diff --git a/cyaron/io.py b/cyaron/io.py index 5b6823e..1dcfc5a 100644 --- a/cyaron/io.py +++ b/cyaron/io.py @@ -15,11 +15,6 @@ from . import log from .utils import list_like, make_unicode -class File(IntEnum): - INPUT = 0 - OUTPUT = 1 - - class IO: """Class IO: IO tool class. It will process the input and output files.""" @@ -96,19 +91,19 @@ def __init__(self, self.__escape_format(output_suffix)) self.input_filename, self.output_filename = None, None self.__input_temp, self.__output_temp = False, False - self.__init_file(input_file, data_id, File.INPUT, make_dirs) + self.__init_file(input_file, data_id, "i", make_dirs) if not disable_output: - self.__init_file(output_file, data_id, File.OUTPUT, make_dirs) + self.__init_file(output_file, data_id, "o", make_dirs) else: self.output_file = None self.__closed = False self.is_first_char = {} def __init_file(self, f: Union[IOBase, str, int, None], - data_id: Union[int, None], file_type: File, make_dirs: bool): + data_id: Union[int, None], file_type: str, make_dirs: bool): if isinstance(f, IOBase): # consider ``f`` as a file object - if file_type == File.INPUT: + if file_type == "i": self.input_file = f else: self.output_file = f @@ -130,7 +125,7 @@ def __init_file(self, f: Union[IOBase, str, int, None], # be sure dir is existed if make_dirs: self.__make_dirs(filename) - if file_type == File.INPUT: + if file_type == "i": self.input_filename = filename else: self.output_filename = filename @@ -214,54 +209,37 @@ def __clear(self, file: IOBase, *args, **kwargs): file.truncate(pos) - def write(self, file: File = File.INPUT, *args, **kwargs): + def input_write(self, *args, **kwargs): """ Write every element in *args into the input file. Splits with `separator`. It will convert every element into str. Args: - file: Which file (File.INPUT/File.OUTPUT) to write *args: the elements to write separator: a string used to separate every element. Defaults to " ". """ - if file == File.INPUT: - file = self.input_file - elif file == File.OUTPUT: - file = self.output_file - else: - raise ValueError("file type is not in File.INPUT or File.OUTPUT") - - self.__write(file, *args, **kwargs) + self.__write(self.input_file, *args, **kwargs) - def writeln(self, file: File = File.INPUT, *args, **kwargs): + def input_writeln(self, *args, **kwargs): """ Write every element in *args into the input file and turn to a new line Splits with `separator`. It will convert every element into str. Args: - file: Which file (File.INPUT/File.OUTPUT) to write *args: the elements to write separator: a string used to separate every element. Defaults to " ". """ args = list(args) args.append("\n") - self.write(file, *args, **kwargs) + self.input_write(*args, **kwargs) - - def clear_content(self, file: File = File.INPUT, *args, **kwargs): + def input_clear_content(self, *args, **kwargs): """ - Clear the content of input/output + Clear the content of input Args: - file: Which file (File.INPUT/File.OUTPUT) to clear pos: Where file will truncate. """ - if file == File.INPUT: - file = self.input_file - elif file == File.OUTPUT: - file = self.output_file - else: - raise ValueError("file type is not in File.INPUT or File.OUTPUT") - self.__clear(file, *args, **kwargs) + self.__clear(self.input_file, *args, **kwargs) def output_gen(self, shell_cmd, time_limit=None): """ @@ -296,6 +274,38 @@ def output_gen(self, shell_cmd, time_limit=None): log.debug(self.output_filename, " done") + def output_write(self, *args, **kwargs): + """ + Write every element in *args into the output file. Splits with `separator`. + It will convert every element into str. + Args: + *args: the elements to write + separator: a string used to separate every element. Defaults to " ". + """ + self.__write(self.output_file, *args, **kwargs) + + def output_writeln(self, *args, **kwargs): + """ + Write every element in *args into the output file and turn to a new line. + Splits with `separator`. + It will convert every element into str. + Args: + *args: the elements to write + separator: a string used to separate every element. Defaults to " ". + """ + args = list(args) + args.append("\n") + self.output_write(*args, **kwargs) + + + def output_clear_content(self, *args, **kwargs): + """ + Clear the content of output + Args: + pos: Where file will truncate + """ + self.__clear(self.output_file, *args, **kwargs) + def flush_buffer(self): """Flush the input file""" self.input_file.flush() From 90edbdd51417f960f08418342ac422b8474f83ea Mon Sep 17 00:00:00 2001 From: OrangePie <125730489+OranPie@users.noreply.github.com> Date: Fri, 4 Oct 2024 16:33:21 +0800 Subject: [PATCH 09/14] Update __init__.py Disimport old part --- cyaron/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cyaron/__init__.py b/cyaron/__init__.py index 66eff0e..ec5f271 100644 --- a/cyaron/__init__.py +++ b/cyaron/__init__.py @@ -13,7 +13,7 @@ from .compare import Compare from .consts import * from .graph import Edge, Graph -from .io import IO, File +from .io import IO from .math import * from .merger import Merger from .polygon import Polygon From 786822a187220c95365e7397860ecc6b94e9e402 Mon Sep 17 00:00:00 2001 From: "Mr. Python" <2789762371@qq.com> Date: Fri, 4 Oct 2024 20:47:55 +0800 Subject: [PATCH 10/14] Write test for make_dir and clear_content --- cyaron/io.py | 40 ++++++++++++++--------------- cyaron/tests/io_test.py | 56 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 73 insertions(+), 23 deletions(-) diff --git a/cyaron/io.py b/cyaron/io.py index 1dcfc5a..669af30 100644 --- a/cyaron/io.py +++ b/cyaron/io.py @@ -8,13 +8,12 @@ import re import subprocess import tempfile -from enum import IntEnum -from pathlib import Path from typing import Union, overload from io import IOBase from . import log from .utils import list_like, make_unicode + class IO: """Class IO: IO tool class. It will process the input and output files.""" @@ -59,7 +58,7 @@ def __init__(self, input_suffix (optional): the suffix of the input file. Defaults to '.in'. output_suffix (optional): the suffix of the output file. Defaults to '.out'. disable_output (optional): set to True to disable output file. Defaults to False. - make_dirs (optional): set to True to create dir if path is not found. Defaults to True. + make_dirs (optional): set to True to create dir if path is not found. Defaults to False. Examples: >>> IO("a","b") # create input file "a" and output file "b" @@ -79,9 +78,12 @@ def __init__(self, # create input file "data2.in" and output file "data2.out" >>> IO(open('data.in', 'w+'), open('data.out', 'w+')) # input file "data.in" and output file "data.out" - >>> IO("./io/data.in", "./io/data.out") - # input file "./io/data.in" and output file "./io/data.out" if the dir "./io" not found it will be created + >>> IO("./io/data.in", "./io/data.out", disable_output = True) + # input file "./io/data.in" and output file "./io/data.out" + # if the dir "./io" not found it will be created """ + self.__closed = False + self.input_file, self.output_file = None, None if file_prefix is not None: # legacy mode input_file = '{}{{}}{}'.format(self.__escape_format(file_prefix), @@ -96,11 +98,11 @@ def __init__(self, self.__init_file(output_file, data_id, "o", make_dirs) else: self.output_file = None - self.__closed = False self.is_first_char = {} - def __init_file(self, f: Union[IOBase, str, int, None], - data_id: Union[int, None], file_type: str, make_dirs: bool): + def __init_file(self, f: Union[IOBase, str, int, + None], data_id: Union[int, None], + file_type: str, make_dirs: bool): if isinstance(f, IOBase): # consider ``f`` as a file object if file_type == "i": @@ -115,7 +117,7 @@ def __init_file(self, f: Union[IOBase, str, int, None], # consider wanna temp file fd, self.input_filename = tempfile.mkstemp() self.__init_file(fd, data_id, file_type, make_dirs) - if file_type == File.INPUT: + if file_type == "i": self.__input_temp = True else: self.__output_temp = True @@ -137,9 +139,8 @@ def __escape_format(self, st: str): """replace "{}" to "{{}}" """ return re.sub(r"\{", "{{", re.sub(r"\}", "}}", st)) - def __make_dirs(self, pth: Union[IOBase, str, int, None]): - if isinstance(pth, str): - os.makedirs(os.path.dirname(pth), exist_ok=True) + def __make_dirs(self, pth: str): + os.makedirs(os.path.dirname(pth), exist_ok=True) def __del_files(self): """delete files""" @@ -198,17 +199,15 @@ def __write(self, file: IOBase, *args, **kwargs): if arg == "\n": self.is_first_char[file] = True - def __clear(self, file: IOBase, *args, **kwargs): + def __clear(self, file: IOBase, pos: int = 0): """ Clear the content use truncate() Args: - file: Which file (File.INPUT/File.OUTPUT) to clear + file: Which file to clear pos: Where file will truncate. """ - pos = kwargs.get("pos", 0) file.truncate(pos) - def input_write(self, *args, **kwargs): """ Write every element in *args into the input file. Splits with `separator`. @@ -232,14 +231,14 @@ def input_writeln(self, *args, **kwargs): args.append("\n") self.input_write(*args, **kwargs) - def input_clear_content(self, *args, **kwargs): + def input_clear_content(self, pos: int = 0): """ Clear the content of input Args: pos: Where file will truncate. """ - self.__clear(self.input_file, *args, **kwargs) + self.__clear(self.input_file, pos) def output_gen(self, shell_cmd, time_limit=None): """ @@ -297,14 +296,13 @@ def output_writeln(self, *args, **kwargs): args.append("\n") self.output_write(*args, **kwargs) - - def output_clear_content(self, *args, **kwargs): + def output_clear_content(self, pos: int = 0): """ Clear the content of output Args: pos: Where file will truncate """ - self.__clear(self.output_file, *args, **kwargs) + self.__clear(self.output_file, pos) def flush_buffer(self): """Flush the input file""" diff --git a/cyaron/tests/io_test.py b/cyaron/tests/io_test.py index b83dc03..42cb996 100644 --- a/cyaron/tests/io_test.py +++ b/cyaron/tests/io_test.py @@ -56,8 +56,10 @@ def test_write_stuff(self): input = f.read() with open("test_write.out") as f: output = f.read() - self.assertEqual(input.split(), ["1", "2", "3", "4", "5", "6", "7", "8", "9"]) - self.assertEqual(output.split(), ["9", "8", "7", "6", "5", "4", "3", "2", "1"]) + self.assertEqual(input.split(), + ["1", "2", "3", "4", "5", "6", "7", "8", "9"]) + self.assertEqual(output.split(), + ["9", "8", "7", "6", "5", "4", "3", "2", "1"]) self.assertEqual(input.count("\n"), 2) self.assertEqual(output.count("\n"), 2) @@ -111,3 +113,53 @@ def test_init_overload(self): with IO(fin, fout) as test: self.assertEqual(test.input_file, fin) self.assertEqual(test.output_file, fout) + + def test_make_dirs(self): + mkdir_true = False + with IO("./automkdir_true/data.in", + "./automkdir_true/data.out", + make_dirs=True): + mkdir_true = os.path.exists("./automkdir_true") + self.assertEqual(mkdir_true, True) + + mkdir_false = False + try: + with IO( + "./automkdir_false/data.in", + "./automkdir_false/data.out", + ): + pass + except FileNotFoundError: + mkdir_false = True + mkdir_false &= not os.path.exists("./automkdir_false") + self.assertEqual(mkdir_false, True) + + def test_output_clear_content(self): + with IO("test_clear.in", "test_clear.out") as test: + test.input_write("This is a test.") + test.input_clear_content() + test.input_write("Cleared content.") + test.output_write("This is a test.") + test.output_clear_content() + test.output_write("Cleared content.") + with open("test_clear.in", encoding="utf-8") as f: + input_text = f.read() + with open("test_clear.out", encoding="utf-8") as f: + output_text = f.read() + self.assertEqual(input_text, "Cleared content.") + self.assertEqual(output_text, "Cleared content.") + + def test_output_clear_content_with_position(self): + with IO("test_clear_pos.in", "test_clear_pos.out") as test: + test.input_write("This is a test.") + test.input_clear_content(5) + test.input_write("Cleared content.") + test.output_write("This is a test.") + test.output_clear_content(5) + test.output_write("Cleared content.") + with open("test_clear_pos.in", encoding="utf-8") as f: + input_text = f.read() + with open("test_clear_pos.out", encoding="utf-8") as f: + output_text = f.read() + self.assertEqual(input_text, "This Cleared content.") + self.assertEqual(output_text, "This Cleared content.") From a0073e2581780515ba95b8c883e1323d21f0d6cf Mon Sep 17 00:00:00 2001 From: OrangePie <125730489+OranPie@users.noreply.github.com> Date: Fri, 4 Oct 2024 21:31:29 +0800 Subject: [PATCH 11/14] Update io.py Add forget seek() for clear --- cyaron/io.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cyaron/io.py b/cyaron/io.py index 669af30..931c03d 100644 --- a/cyaron/io.py +++ b/cyaron/io.py @@ -207,6 +207,7 @@ def __clear(self, file: IOBase, pos: int = 0): pos: Where file will truncate. """ file.truncate(pos) + file.seek(pos) def input_write(self, *args, **kwargs): """ From c71ff6720b02acfc4db025523bbc810a2ae38fc3 Mon Sep 17 00:00:00 2001 From: OrangePie <125730489+OranPie@users.noreply.github.com> Date: Fri, 4 Oct 2024 21:51:07 +0800 Subject: [PATCH 12/14] Update io.py Fix: truncated file will more a space --- cyaron/io.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cyaron/io.py b/cyaron/io.py index 931c03d..2edf9ef 100644 --- a/cyaron/io.py +++ b/cyaron/io.py @@ -207,6 +207,15 @@ def __clear(self, file: IOBase, pos: int = 0): pos: Where file will truncate. """ file.truncate(pos) + if pos == 0: # 重置self.is_first_char + self.is_first_char[file] = True + else: + file.seek(pos - 1) + if file.read(1) != " ": # 若不是空格 重置self.is_first_char + self.is_first_char[file] = False + else: + self.is_first_char[file] = True + file.seek(pos) def input_write(self, *args, **kwargs): From 8b0cc65bf6c9c653140ed27aeb5182a5e66fe217 Mon Sep 17 00:00:00 2001 From: OrangePie <125730489+OranPie@users.noreply.github.com> Date: Fri, 4 Oct 2024 21:59:51 +0800 Subject: [PATCH 13/14] Update io.py Always set is_first_char[file] to True, igrone space problem (Review from PR) --- cyaron/io.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/cyaron/io.py b/cyaron/io.py index 2edf9ef..2d49fe5 100644 --- a/cyaron/io.py +++ b/cyaron/io.py @@ -199,6 +199,15 @@ def __write(self, file: IOBase, *args, **kwargs): if arg == "\n": self.is_first_char[file] = True + def __clear_last_space(self, file: IOBase): + """ + Clear the last space(s) use truncate() + Args: + file:Which file to clear + """ + while True: + + def __clear(self, file: IOBase, pos: int = 0): """ Clear the content use truncate() @@ -207,15 +216,7 @@ def __clear(self, file: IOBase, pos: int = 0): pos: Where file will truncate. """ file.truncate(pos) - if pos == 0: # 重置self.is_first_char - self.is_first_char[file] = True - else: - file.seek(pos - 1) - if file.read(1) != " ": # 若不是空格 重置self.is_first_char - self.is_first_char[file] = False - else: - self.is_first_char[file] = True - + self.is_first_char[file] = True file.seek(pos) def input_write(self, *args, **kwargs): From a0700ecb8ab3666ec782b54ad3a342139f19151d Mon Sep 17 00:00:00 2001 From: yanyige Date: Sun, 6 Oct 2024 09:14:04 +0800 Subject: [PATCH 14/14] Delete useless functions and variables to make the code cleaner and easier to read. --- cyaron/io.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/cyaron/io.py b/cyaron/io.py index 2d49fe5..0a6ea0c 100644 --- a/cyaron/io.py +++ b/cyaron/io.py @@ -198,14 +198,6 @@ def __write(self, file: IOBase, *args, **kwargs): file.write(make_unicode(arg)) if arg == "\n": self.is_first_char[file] = True - - def __clear_last_space(self, file: IOBase): - """ - Clear the last space(s) use truncate() - Args: - file:Which file to clear - """ - while True: def __clear(self, file: IOBase, pos: int = 0):