Source code for cmdbox.app.client

from pathlib import Path
from cmdbox.app import filer
from cmdbox.app.commons import convert, redis_client
import base64
import logging


[docs] class Client(object): def __init__(self, logger:logging.Logger, redis_host:str = "localhost", redis_port:int = 6379, redis_password:str = None, svname:str = 'server'): """ Redisサーバーとの通信を行うクラス Args: logger (logging): ロガー redis_host (str, optional): Redisサーバーのホスト名. Defaults to "localhost". redis_port (int, optional): Redisサーバーのポート番号. Defaults to 6379. redis_password (str, optional): Redisサーバーのパスワード. Defaults to None. svname (str, optional): サーバーのサービス名. Defaults to 'server'. """ self.logger = logger if svname is None or svname == "": raise Exception("svname is empty.") if svname.find('-') >= 0: raise ValueError(f"Server name is invalid. '-' is not allowed. svname={svname}") self.redis_cli = redis_client.RedisClient(logger, host=redis_host, port=redis_port, password=redis_password, svname=svname) self.is_running = False def __exit__(self, a, b, c): pass
[docs] def stop_server(self, retry_count:int=3, retry_interval:int=5, timeout:int=60): """ Redisサーバーを停止する Args: retry_count (int, optional): リトライ回数. Defaults to 3. retry_interval (int, optional): リトライ間隔. Defaults to 5. timeout (int, optional): タイムアウト時間. Defaults to 60. Returns: dict: Redisサーバーからの応答 """ res_json = self.redis_cli.send_cmd('stop_server', [], retry_count=retry_count, retry_interval=retry_interval, timeout=timeout) return res_json
[docs] def file_list(self, svpath:str, recursive:bool, scope:str="client", client_data:Path = None, retry_count:int=3, retry_interval:int=5, timeout:int=60): """ サーバー上のファイルリストを取得する Args: svpath (Path): サーバー上のファイルパス recursive (bool): 再帰的に取得するかどうか scope (str, optional): 参照先のスコープ. Defaults to "client". client_data (Path, optional): ローカルを参照させる場合のデータフォルダ. Defaults to None. retry_count (int, optional): リトライ回数. Defaults to 3. retry_interval (int, optional): リトライ間隔. Defaults to 5. timeout (int, optional): タイムアウト時間. Defaults to 60. Returns: dict: Redisサーバーからの応答 """ if scope == "client": if client_data is not None: f = filer.Filer(client_data, self.logger) _, res_json = f.file_list(svpath, recursive) return res_json else: self.logger.warning(f"client_data is empty.") return dict(warn=f"client_data is empty.") elif scope == "current": f = filer.Filer(Path.cwd(), self.logger) _, res_json = f.file_list(svpath, recursive) return res_json elif scope == "server": res_json = self.redis_cli.send_cmd('file_list', [convert.str2b64str(str(svpath)), str(recursive)], retry_count=retry_count, retry_interval=retry_interval, timeout=timeout) return res_json else: self.logger.warning(f"scope is invalid. {scope}") return dict(warn=f"scope is invalid. {scope}")
[docs] def file_mkdir(self, svpath:str, scope:str="client", client_data:Path = None, retry_count:int=3, retry_interval:int=5, timeout:int=60): """ サーバー上にディレクトリを作成する Args: svpath (Path): サーバー上のディレクトリパス scope (str, optional): 参照先のスコープ. Defaults to "client". client_data (Path, optional): ローカルを参照させる場合のデータフォルダ. Defaults to None. retry_count (int, optional): リトライ回数. Defaults to 3. retry_interval (int, optional): リトライ間隔. Defaults to 5. timeout (int, optional): タイムアウト時間. Defaults to 60. Returns: dict: Redisサーバーからの応答 """ if scope == "client": if client_data is not None: f = filer.Filer(client_data, self.logger) _, res_json = f.file_mkdir(svpath) return res_json else: self.logger.warning(f"client_data is empty.") return dict(warn=f"client_data is empty.") elif scope == "current": f = filer.Filer(Path.cwd(), self.logger) _, res_json = f.file_mkdir(svpath) return res_json elif scope == "server": res_json = self.redis_cli.send_cmd('file_mkdir', [convert.str2b64str(str(svpath))], retry_count=retry_count, retry_interval=retry_interval, timeout=timeout) return res_json else: self.logger.warning(f"scope is invalid. {scope}") return dict(warn=f"scope is invalid. {scope}")
[docs] def file_rmdir(self, svpath:str, scope:str="client", client_data:Path = None, retry_count:int=3, retry_interval:int=5, timeout:int=60): """ サーバー上のディレクトリを削除する Args: svpath (Path): サーバー上のディレクトリパス scope (str, optional): 参照先のスコープ. Defaults to "client". client_data (Path, optional): ローカルを参照させる場合のデータフォルダ. Defaults to None. retry_count (int, optional): リトライ回数. Defaults to 3. retry_interval (int, optional): リトライ間隔. Defaults to 5. timeout (int, optional): タイムアウト時間. Defaults to 60. Returns: dict: Redisサーバーからの応答 """ if scope == "client": if client_data is not None: f = filer.Filer(client_data, self.logger) _, res_json = f.file_rmdir(svpath) return res_json else: self.logger.warning(f"client_data is empty.") return dict(warn=f"client_data is empty.") elif scope == "current": f = filer.Filer(Path.cwd(), self.logger) _, res_json = f.file_rmdir(svpath) return res_json elif scope == "server": res_json = self.redis_cli.send_cmd('file_rmdir', [convert.str2b64str(str(svpath))], retry_count=retry_count, retry_interval=retry_interval, timeout=timeout) return res_json else: self.logger.warning(f"scope is invalid. {scope}") return dict(warn=f"scope is invalid. {scope}")
[docs] def file_download(self, svpath:str, download_file:Path, scope:str="client", client_data:Path = None, rpath:str="", img_thumbnail:float=0.0, retry_count:int=3, retry_interval:int=5, timeout:int=60): """ サーバー上のファイルをダウンロードする Args: svpath (Path): サーバー上のファイルパス download_file (Path): ローカルのファイルパス scope (str, optional): 参照先のスコープ. Defaults to "client". client_data (Path, optional): ローカルを参照させる場合のデータフォルダ. Defaults to None. rpath (str, optional): リクエストパス. Defaults to "". img_thumbnail (float, optional): サムネイル画像のサイズ. Defaults to 0.0. retry_count (int, optional): リトライ回数. Defaults to 3. retry_interval (int, optional): リトライ間隔. Defaults to 5. timeout (int, optional): タイムアウト時間. Defaults to 60. Returns: bytes: ダウンロードファイルの内容 """ if scope == "client": if client_data is not None: f = filer.Filer(client_data, self.logger) _, res_json = f.file_download(svpath, img_thumbnail) else: self.logger.warning(f"client_data is empty.") return dict(warn=f"client_data is empty.") elif scope == "current": f = filer.Filer(Path.cwd(), self.logger) _, res_json = f.file_download(svpath, img_thumbnail) elif scope == "server": res_json = self.redis_cli.send_cmd('file_download', [convert.str2b64str(str(svpath)), str(img_thumbnail)], retry_count=retry_count, retry_interval=retry_interval, timeout=timeout) else: self.logger.warning(f"scope is invalid. {scope}") return dict(warn=f"scope is invalid. {scope}") if "success" in res_json: res_json["success"]["rpath"] = rpath res_json["success"]["svpath"] = svpath if download_file is not None: if download_file.is_dir(): download_file = download_file / res_json["success"]["name"] if download_file.exists(): self.logger.warning(f"download_file {download_file} already exists.") return dict(warn=f"download_file {download_file} already exists.") with open(download_file, "wb") as f: f.write(base64.b64decode(res_json["success"]["data"])) del res_json["success"]["data"] res_json["success"]["download_file"] = str(download_file.absolute()) return res_json
[docs] def file_upload(self, svpath:str, upload_file:Path, scope:str="client", client_data:Path=None, mkdir:bool=False, orverwrite:bool=False, retry_count:int=3, retry_interval:int=5, timeout:int=60): """ サーバー上にファイルをアップロードする Args: svpath (Path): サーバー上のファイルパス upload_file (Path): ローカルのファイルパス scope (str, optional): 参照先のスコープ. Defaults to "client". mkdir (bool, optional): ディレクトリを作成するかどうか. Defaults to False. orverwrite (bool, optional): 上書きするかどうか. Defaults to False. client_data (Path, optional): ローカルを参照させる場合のデータフォルダ. Defaults to None. retry_count (int, optional): リトライ回数. Defaults to 3. retry_interval (int, optional): リトライ間隔. Defaults to 5. timeout (int, optional): タイムアウト時間. Defaults to 60. Returns: dict: Redisサーバーからの応答 """ if upload_file is None: self.logger.warning(f"upload_file is empty.") return dict(warn=f"upload_file is empty.") if not upload_file.exists(): self.logger.warning(f"input_file {upload_file} does not exist.") return dict(warn=f"input_file {upload_file} does not exist.") if upload_file.is_dir(): self.logger.warning(f"input_file {upload_file} is directory.") return dict(warn=f"input_file {upload_file} is directory.") with open(upload_file, "rb") as f: if scope == "client": if client_data is not None: fi = filer.Filer(client_data, self.logger) _, res_json = fi.file_upload(svpath, upload_file.name, f.read(), mkdir, orverwrite) return res_json else: self.logger.warning(f"client_data is empty.") return dict(warn=f"client_data is empty.") elif scope == "current": fi = filer.Filer(Path.cwd(), self.logger) _, res_json = fi.file_upload(svpath, upload_file.name, f.read(), mkdir, orverwrite) return res_json elif scope == "server": res_json = self.redis_cli.send_cmd('file_upload', [convert.str2b64str(str(svpath)), convert.str2b64str(upload_file.name), convert.bytes2b64str(f.read()), str(mkdir), str(orverwrite)], retry_count=retry_count, retry_interval=retry_interval, timeout=timeout) return res_json else: self.logger.warning(f"scope is invalid. {scope}") return dict(warn=f"scope is invalid. {scope}")
[docs] def file_remove(self, svpath:str, scope:str="client", client_data:Path = None, retry_count:int=3, retry_interval:int=5, timeout:int=60): """ サーバー上のファイルを削除する Args: svpath (Path): サーバー上のファイルパス scope (str, optional): 参照先のスコープ. Defaults to "client". client_data (Path, optional): ローカルを参照させる場合のデータフォルダ. Defaults to None. retry_count (int, optional): リトライ回数. Defaults to 3. retry_interval (int, optional): リトライ間隔. Defaults to 5. timeout (int, optional): タイムアウト時間. Defaults to 60. Returns: dict: Redisサーバーからの応答 """ if scope == "client": if client_data is not None: f = filer.Filer(client_data, self.logger) _, res_json = f.file_remove(svpath) return res_json else: self.logger.warning(f"client_data is empty.") return dict(warn=f"client_data is empty.") elif scope == "current": f = filer.Filer(Path.cwd(), self.logger) _, res_json = f.file_remove(svpath) return res_json elif scope == "server": res_json = self.redis_cli.send_cmd('file_remove', [convert.str2b64str(str(svpath))], retry_count=retry_count, retry_interval=retry_interval, timeout=timeout) return res_json else: self.logger.warning(f"scope is invalid. {scope}") return dict(warn=f"scope is invalid. {scope}")
[docs] def file_copy(self, from_path:str, to_path:str, orverwrite:bool=False, scope:str="client", client_data:Path = None, retry_count:int=3, retry_interval:int=5, timeout:int=60): """ サーバー上のファイルをコピーする Args: from_path (Path): コピー元のファイルパス to_path (Path): コピー先のファイルパス orverwrite (bool, optional): 上書きするかどうか. Defaults to False. scope (str, optional): 参照先のスコープ. Defaults to "client". client_data (Path, optional): ローカルを参照させる場合のデータフォルダ. Defaults to None. retry_count (int, optional): リトライ回数. Defaults to 3. retry_interval (int, optional): リトライ間隔. Defaults to 5. timeout (int, optional): タイムアウト時間. Defaults to 60. Returns: dict: Redisサーバーからの応答 """ if scope == "client": if client_data is not None: f = filer.Filer(client_data, self.logger) _, res_json = f.file_copy(from_path, to_path, orverwrite) return res_json else: self.logger.warning(f"client_data is empty.") return dict(warn=f"client_data is empty.") elif scope == "current": f = filer.Filer(Path.cwd(), self.logger) _, res_json = f.file_copy(from_path, to_path, orverwrite) return res_json elif scope == "server": res_json = self.redis_cli.send_cmd('file_copy', [convert.str2b64str(str(from_path)), convert.str2b64str(str(to_path)), str(orverwrite)], retry_count=retry_count, retry_interval=retry_interval, timeout=timeout) return res_json else: self.logger.warning(f"scope is invalid. {scope}") return dict(warn=f"scope is invalid. {scope}")
[docs] def file_move(self, from_path:str, to_path:str, scope:str="client", client_data:Path = None, retry_count:int=3, retry_interval:int=5, timeout:int=60): """ サーバー上のファイルを移動する Args: from_path (Path): 移動元のファイルパス to_path (Path): 移動先のファイルパス scope (str, optional): 参照先のスコープ. Defaults to "client". client_data (Path, optional): ローカルを参照させる場合のデータフォルダ. Defaults to None. retry_count (int, optional): リトライ回数. Defaults to 3. retry_interval (int, optional): リトライ間隔. Defaults to 5. timeout (int, optional): タイムアウト時間. Defaults to 60. Returns: dict: Redisサーバーからの応答 """ if scope == "client": if client_data is not None: f = filer.Filer(client_data, self.logger) _, res_json = f.file_move(from_path, to_path) return res_json else: self.logger.warning(f"client_data is empty.") return dict(warn=f"client_data is empty.") elif scope == "current": f = filer.Filer(Path.cwd(), self.logger) _, res_json = f.file_move(from_path, to_path) return res_json elif scope == "server": res_json = self.redis_cli.send_cmd('file_move', [convert.str2b64str(str(from_path)), convert.str2b64str(str(to_path))], retry_count=retry_count, retry_interval=retry_interval, timeout=timeout) return res_json else: self.logger.warning(f"scope is invalid. {scope}") return dict(warn=f"scope is invalid. {scope}")
[docs] def server_info(self, retry_count:int=3, retry_interval:int=5, timeout:int=60): """ サーバーの情報を取得する Args: retry_count (int, optional): リトライ回数. Defaults to 3. retry_interval (int, optional): リトライ間隔. Defaults to 5. timeout (int, optional): タイムアウト時間. Defaults to 60. Returns: dict: Redisサーバーからの応答 """ res_json = self.redis_cli.send_cmd('server_info', [], retry_count=retry_count, retry_interval=retry_interval, timeout=timeout) return res_json