【Python】よく作るio系ライブラリ | ツール・シミュレータ

ツール・シミュレータ

ツール・シミュレータ等のプログラミングをネタとしてブログ。

色々言語を勉強して、ツールを作るときに毎度毎度作成する自分のライブラリ

 

 

io.ioutil.py 

 

# -*- coding:utf-8 -*-

from typing import List,Callable,Tuple
import os
import os.path
from ..excollections.elist import Enumerable as Elist
import re
import shutil
from pathlib import Path


class DirectoryNotFoundError(Exception):
    pass


class DirectoryExistsError(Exception):
    pass


def file_exists(file:str) -> bool:
    return os.path.isfile(file)


def dir_exists(dirpath:str) -> bool:
    return os.path.isdir(dirpath)


def file_exists_with_exp(file:str) -> None:
    if not file_exists(file):
        raise FileNotFoundError("ファイルがありません:" + file)
    

def dir_exists_with_exp(dirpath:str) -> None:
    if not dir_exists(dirpath):
        raise DirectoryNotFoundError("ディレクトリがありません:" + dirpath)


def _curry_path_join(dirpath:str) -> Callable[[str],str]:
    dir_exists_with_exp(dirpath)
    def f(file:str):
        return os.path.join(dirpath,file)
    return f


def file_dir_divide(dirpath:str) -> Tuple[List[str],List[str]]:
    dir_exists_with_exp(dirpath)
    et,ef = Elist(os.listdir(dirpath)).select(_curry_path_join(dirpath)).divide(os.path.isfile)
    return (et.tolist(),ef.tolist())


def find_file(dirpath:str,filterfunc:Callable[[str],bool]) -> List[str]:
    fs,_ = file_dir_divide(dirpath)
    return Elist(fs).where(filterfunc).tolist()


def find_dir(dirpath:str,filterfunc:Callable[[str],bool]) -> List[str]:
    _,ds = file_dir_divide(dirpath)
    return Elist(ds).where(filterfunc).tolist()


def find_file_recur(dirpath:str,filterfunc:Callable[[str],bool]) -> List[str]:
    ds = find_dir_recur(dirpath,PathFilter.all())
    ds.append(dirpath)
    def f(acc:List[str],d:str) -> List[str]:
        acc.extend(find_file(d,filterfunc))
        return acc
    return Elist(ds).aggregate([],f)


def find_dir_recur(dirpath:str,filterfunc:Callable[[str],bool]) -> List[str]:
    dir_exists_with_exp(dirpath)
    return Elist(_find_dir_recur(dirpath)).where(filterfunc).tolist()


def _find_dir_recur(dirpath:str) -> List[str]:
    ds = find_dir(dirpath,PathFilter.all())
    r:List[str] = []
    for d in ds:
        r.extend(_find_dir_recur(d))
    r.extend(ds)
    return r


class PathFilter:
    @staticmethod
    def all() -> Callable[[str],bool]:
        def f(path:str):
            return True
        return f
    
    @staticmethod
    def extension(ext:str) -> Callable[[str],bool]:
        def f(path:str):
            return path.endswith("." + ext)
        return f
    
    @staticmethod
    def regex(r:str) -> Callable[[str],bool]:
        def f(path:str):
            return re.search(r,os.path.basename(path)) != None
        return f


def file_copy_file_specify(ff:str,tf:str,force:bool=True) -> bool:
    file_exists_with_exp(ff)
    if os.path.isdir(tf):
        raise DirectoryExistsError(tf)
    parent = Path(tf).parent
    if os.path.isdir(parent):
        if force:
            shutil.copy(ff,tf)
            return True
        else:
            if not os.path.exists(tf):
                shutil.copy(ff,tf)
                return True
            else:
                return False
    else:
        raise DirectoryNotFoundError(parent)


def file_copy_file_specify_reg(fd:str,ffreg:str,tf:str,selectFunc:Callable[[List[str]],str|None],force:bool=True) -> bool:
    DirectoryExistsError(fd)
    parent = Path(tf).parent
    if os.path.isdir(parent):
        raise DirectoryNotFoundError(parent)
    if os.path.isdir(tf):
        raise DirectoryExistsError(tf)
    if (not force) and os.path.isfile(tf):
        return False
    ffs = find_file(fd,PathFilter.regex(ffreg))
    ff = selectFunc(ffs)
    if ff == None:
        return False
    shutil.copy(os.path.join(fd,ff),tf)
    return True