Skip to content

Commit

Permalink
Format and write commit for io.py
Browse files Browse the repository at this point in the history
  • Loading branch information
Mr-Python-in-China committed Oct 2, 2024
1 parent cdcf62d commit 8027e5a
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 76 deletions.
2 changes: 1 addition & 1 deletion .pylintrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[MASTER]
py-version=3.5
disable=R0902,R0913
disable=R0902,R0913,R0917
195 changes: 127 additions & 68 deletions cyaron/io.py
Original file line number Diff line number Diff line change
@@ -1,43 +1,87 @@
"""
A module that provides a class IO to process the input and output files.
Classes:
IO: IO tool class. It will process the input and output files.
"""
from __future__ import absolute_import
from .utils import *
from . import log
from io import open, IOBase
import subprocess
import tempfile
import os
import re
import subprocess
import tempfile
from typing import Union, overload
from io import IOBase
from . import log
from .utils import list_like, make_unicode


class IO(object):
class IO:
"""Class IO: IO tool class. It will process the input and output files."""
def __init__(self, input_file=None, output_file=None, data_id=None, file_prefix=None, input_suffix='.in', output_suffix='.out', disable_output=False):
"""__init__(self, input_file=None, output_file=None, data_id=None, file_prefix=None, input_suffix='.in', output_suffix='.out', disable_output=False) -> None
input_file, output_file overload:
None -> make a temp file (if file_prefix is None)
file object -> treat the file-like object as in/output file
int -> open file by file descriptor
str -> a filename or filename template like 'awd{}.in'. ``{}`` will be replaced by ``data_id``
int data_id -> the id of the data. if it's None, the file names will not contain the id.
legacy argumants:
str file_prefix -> the prefix for the input and output files
str input_suffix = ".in" -> the suffix of the input file
str output_suffix = ".out" -> the suffix of the output file
disable_output -> bool, set to True to disable output
Examples:
IO("a","b") -> create input file "a" and output file "b"
IO("a.in","b.out") -> create input file "a.in" and output file "b.out"
IO(file_prefix="data") -> create input file "data.in" and output file "data.out"
IO(file_prefix="data",data_id=1) -> create input file "data1.in" and output file "data1.out"
IO(file_prefix="data",input_suffix=".input") -> create input file "data.input" and output file "data.out"
IO(file_prefix="data",output_suffix=".output") -> create input file "data.in" and output file "data.output"
IO(file_prefix="data",data_id=2,input_suffix=".input") -> create input file "data2.input" and output file "data2.out"
IO("data{}.in","data{}.out",data_id=2) -> 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"

@overload
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):
...

@overload
def __init__(self,
data_id: Union[str, None] = None,
file_prefix: Union[str, None] = None,
input_suffix: Union[str, None] = '.in',
output_suffix: Union[str, None] = '.out',
disable_output: bool = False):
...

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,
file_prefix: Union[str, None] = None,
input_suffix: Union[str, None] = '.in',
output_suffix: Union[str, None] = '.out',
disable_output: bool = False):
"""
Args:
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.
If it's None, make a temp file. Defaults to None.
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.
Examples:
>>> IO("a","b")
# create input file "a" and output file "b"
>>> IO("a.in","b.out")
# create input file "a.in" and output file "b.out"
>>> IO(file_prefix="data")
# create input file "data.in" and output file "data.out"
>>> IO(file_prefix="data",data_id=1)
# create input file "data1.in" and output file "data1.out"
>>> IO(file_prefix="data",input_suffix=".input")
# create input file "data.input" and output file "data.out"
>>> IO(file_prefix="data",output_suffix=".output")
# create input file "data.in" and output file "data.output"
>>> IO(file_prefix="data",data_id=2,input_suffix=".input")
# create input file "data2.input" and output file "data2.out"
>>> IO("data{}.in","data{}.out",data_id=2)
# 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"
"""
if file_prefix is not None:
# legacy mode
input_file = '{}{{}}{}'.format(self.__escape_format(file_prefix), self.__escape_format(input_suffix))
output_file = '{}{{}}{}'.format(self.__escape_format(file_prefix), self.__escape_format(output_suffix))
input_file = '{}{{}}{}'.format(self.__escape_format(file_prefix),
self.__escape_format(input_suffix))
output_file = '{}{{}}{}'.format(
self.__escape_format(file_prefix),
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')
Expand All @@ -48,20 +92,18 @@ def __init__(self, input_file=None, output_file=None, data_id=None, file_prefix=
self.__closed = False
self.is_first_char = {}

def __init_file(self, f, data_id, file_type):
try:
is_file = isinstance(f, file)
except NameError:
is_file = False
if isinstance(f, IOBase) or is_file:
def __init_file(self, f: Union[IOBase, str, int, None],
data_id: Union[int, None], file_type: str):
if isinstance(f, IOBase):
# consider ``f`` as a file object
if file_type == 'i':
self.input_file = f
else:
self.output_file = f
elif isinstance(f, int):
# consider ``f`` as a file descor
self.__init_file(open(f, 'w+', newline='\n'), data_id, file_type)
self.__init_file(open(f, 'w+', encoding="utf-8", newline='\n'),
data_id, file_type)
elif f is None:
# consider wanna temp file
fd, self.input_filename = tempfile.mkstemp()
Expand All @@ -75,12 +117,13 @@ def __init_file(self, f, data_id, file_type):
filename = f.format(data_id or '')
if file_type == 'i':
self.input_filename = filename
log.debug("Processing %s" % self.input_filename)
else:
self.output_filename = filename
self.__init_file(open(filename, 'w+', newline='\n'), data_id, file_type)
self.__init_file(
open(filename, 'w+', newline='\n', encoding='utf-8'), data_id,
file_type)

def __escape_format(self, st):
def __escape_format(self, st: str):
"""replace "{}" to "{{}}" """
return re.sub(r'\{', '{{', re.sub(r'\}', '}}', st))

Expand All @@ -99,7 +142,8 @@ def close(self):
deleted = False
try:
# on posix, one can remove a file while it's opend by a process
# the file then will be not visable to others, but process still have the file descriptor
# the file then will be not visable to others,
# but process still have the file descriptor
# it is recommand to remove temp file before close it on posix to avoid race
# on nt, it will just fail and raise OSError so that after closing remove it again
self.__del_files()
Expand All @@ -123,12 +167,10 @@ def __enter__(self):
def __exit__(self, exc_type, exc_val, exc_tb):
self.close()

def __write(self, file, *args, **kwargs):
"""__write(self, file, *args, **kwargs) -> None
Write every element in *args into file. If the element isn't "\n", insert a space. It will convert every element into str
file file -> the file object to write
**kwargs:
str separator = " " -> a string used to separate every element
def __write(self, file: IOBase, *args, **kwargs):
"""
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", " ")
for arg in args:
Expand All @@ -143,53 +185,70 @@ def __write(self, file, *args, **kwargs):
self.is_first_char[file] = True

def input_write(self, *args, **kwargs):
"""input_write(self, *args, **kwargs) -> None
Write every element in *args into the input file. Splits with spaces. It will convert every element into string
**kwargs:
str separator = " " -> a string used to separate every element
"""
Write every element in *args into the input 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.input_file, *args, **kwargs)

def input_writeln(self, *args, **kwargs):
"""input_writeln(self, *args, **kwargs) -> None
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
**kwargs:
str separator = " " -> a string used to separate every element
"""
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:
*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)

def output_gen(self, shell_cmd):
"""output_gen(self, shell_cmd) -> None
Run the command shell_cmd(usually the std programme) and send it the input file as stdin. Write its output to the output file.
str shell_cmd -> the command to run, usually the std programme
"""
Run the command `shell_cmd` (usually the std program) and send it the input file as stdin.
Write its output to the output file.
Args:
shell_cmd: the command to run, usually the std program.
"""
self.flush_buffer()
origin_pos = self.input_file.tell()
self.input_file.seek(0)
subprocess.check_call(shell_cmd, shell=True, stdin=self.input_file, stdout=self.output_file, universal_newlines=True)
subprocess.check_call(shell_cmd,
shell=True,
stdin=self.input_file,
stdout=self.output_file,
universal_newlines=True)
self.input_file.seek(origin_pos)

log.debug(self.output_filename, " done")

def output_write(self, *args, **kwargs):
"""output_write(self, *args, **kwargs) -> None
Write every element in *args into the output file. Splits with spaces. It will convert every element into string
**kwargs:
str separator = " " -> a string used to separate every element
"""
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):
"""output_writeln(self, *args, **kwargs) -> None
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
**kwargs:
str separator = " " -> a string used to separate every element
"""
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()
6 changes: 3 additions & 3 deletions cyaron/math.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
'''
"""
This is a module that includes some useful math functions.
Functions:
Expand Down Expand Up @@ -27,7 +27,7 @@
n2words(num,join=True): Number to words
forked from https://blog.dreamshire.com/common-functions-routines-project-euler/
'''
"""

from __future__ import absolute_import
from math import sqrt, factorial
Expand Down Expand Up @@ -170,7 +170,7 @@ def fibonacci(n: int):


def _fib(n: int) -> Tuple[int, int]:
'''Returns a tuple of fibonacci (F(n), F(n+1)).'''
"""Returns a tuple of fibonacci (F(n), F(n+1))."""
if n == 0:
return (0, 1)
a, b = _fib(n // 2)
Expand Down
5 changes: 1 addition & 4 deletions cyaron/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,7 @@ def strtolines(str):


def make_unicode(data):
try:
return unicode(data)
except NameError:
return str(data)
return str(data)

def unpack_kwargs(funcname, kwargs, arg_pattern):
rv = {}
Expand Down

0 comments on commit 8027e5a

Please sign in to comment.