From a99b81b0c7b009aa21ee5b33757e8e04999554f6 Mon Sep 17 00:00:00 2001 From: Firq Date: Fri, 5 Jul 2024 16:05:35 +0200 Subject: [PATCH] Pylint settings --- dockge_cli/__main__.py | 2 + dockge_cli/client/commandprovider/bindings.py | 40 +++++++++++++++++++ dockge_cli/client/parser.py | 4 ++ dockge_cli/client/run.py | 9 ++++- dockge_cli/client/utils.py | 12 ++++++ dockge_cli/dockge_cli.py | 3 ++ dockge_cli/models/codes.py | 3 ++ dockge_cli/models/commands.py | 3 ++ dockge_cli/models/parser.py | 6 +++ dockge_cli/service/communicate.py | 39 +++++++++++++++++- dockge_cli/service/storage.py | 17 ++++++++ pyproject.toml | 5 ++- 12 files changed, 140 insertions(+), 3 deletions(-) create mode 100644 dockge_cli/__main__.py diff --git a/dockge_cli/__main__.py b/dockge_cli/__main__.py new file mode 100644 index 0000000..660e368 --- /dev/null +++ b/dockge_cli/__main__.py @@ -0,0 +1,2 @@ +from .dockge_cli import cli +cli() diff --git a/dockge_cli/client/commandprovider/bindings.py b/dockge_cli/client/commandprovider/bindings.py index d6c7685..c29c3ab 100644 --- a/dockge_cli/client/commandprovider/bindings.py +++ b/dockge_cli/client/commandprovider/bindings.py @@ -7,6 +7,10 @@ from ...service.communicate import DockgeConnection from ..utils import stack_formatter, status_formatter, generic_formatter, get_credential_parser class ExecutionCommands(): + """ + Helper class that provides all the static methods in an organized way + This is an abstraction layer of the CLI, as those functions only do little preprocessing before calling the actural DockgeConnection + """ @staticmethod def __setup(): con = DockgeConnection() @@ -15,6 +19,9 @@ class ExecutionCommands(): @staticmethod def host(extra_args): + """ + host command binding + """ if len(extra_args) > 0: res = urlparse(extra_args[0]) if all([res.scheme, res.netloc]): @@ -26,6 +33,9 @@ class ExecutionCommands(): @staticmethod def login(extra_args): + """ + login command binding + """ if len(extra_args) > 0: credentials = get_credential_parser().parse_args(extra_args, namespace=Credentials) storage.put("username", credentials.username, encoded=True) @@ -36,21 +46,33 @@ class ExecutionCommands(): @staticmethod def logout(_): + """ + logout command binding + """ storage.remove("username") storage.remove("password") @staticmethod def exit(_): + """ + exit command binding + """ storage.clear() @staticmethod def list(_): + """ + list command binding + """ con = ExecutionCommands.__setup() stack_formatter(con.list_stacks()) con.disconnect() @staticmethod def status(extra_args): + """ + status command binding + """ if extra_args is None: raise ValueError con = ExecutionCommands.__setup() @@ -59,6 +81,9 @@ class ExecutionCommands(): @staticmethod def restart(extra_args): + """ + restart command binding + """ if extra_args is None: raise ValueError con = ExecutionCommands.__setup() @@ -67,6 +92,9 @@ class ExecutionCommands(): @staticmethod def update(extra_args): + """ + update command binding + """ if extra_args is None: raise ValueError con = ExecutionCommands.__setup() @@ -75,6 +103,9 @@ class ExecutionCommands(): @staticmethod def stop(extra_args): + """ + stop command binding + """ if extra_args is None: raise ValueError con = ExecutionCommands.__setup() @@ -83,6 +114,9 @@ class ExecutionCommands(): @staticmethod def start(extra_args): + """ + start command binding + """ if extra_args is None: raise ValueError con = ExecutionCommands.__setup() @@ -91,6 +125,9 @@ class ExecutionCommands(): @staticmethod def down(extra_args): + """ + down command binding + """ if extra_args is None: raise ValueError con = ExecutionCommands.__setup() @@ -99,4 +136,7 @@ class ExecutionCommands(): @staticmethod def help(): + """ + exit command binding - This should never be invoked + """ print("WTF") diff --git a/dockge_cli/client/parser.py b/dockge_cli/client/parser.py index f76bc36..9e68f3e 100644 --- a/dockge_cli/client/parser.py +++ b/dockge_cli/client/parser.py @@ -6,6 +6,10 @@ from ..models import Arguments from .commandprovider.factory import commands def parse_arguments(): + """ + Create a parser and parse the arguments of sys.argv based on the Arguments Namespace + Returns arguments and extra arguments separately + """ parser = argparse.ArgumentParser( prog="dockge_cli", description="CLI interface for interacting with Dockge",) diff --git a/dockge_cli/client/run.py b/dockge_cli/client/run.py index 105f380..bd5e7d8 100644 --- a/dockge_cli/client/run.py +++ b/dockge_cli/client/run.py @@ -1,6 +1,9 @@ from .commandprovider.factory import commands def display_help(extra_args): + """ + Display help dialogues for each command + """ if not extra_args: print(f"{commands['help'].description}") return @@ -11,6 +14,10 @@ def display_help(extra_args): print(f"{commands[extra_args[0]].description}") def run(command, args): + """ + Runs a given command with the provided args + Alsso automatically maps the given command string to the correct Command class + """ if command not in commands: raise ValueError("Invalid Command") @@ -25,4 +32,4 @@ def run(command, args): display_help(args) return - c.binding(args) + c.bind(args) diff --git a/dockge_cli/client/utils.py b/dockge_cli/client/utils.py index 6e9fa87..9ac97bc 100644 --- a/dockge_cli/client/utils.py +++ b/dockge_cli/client/utils.py @@ -3,6 +3,9 @@ from tabulate import tabulate from ..models import StackStatus def get_credential_parser(): + """ + Creates a new parser for login credentials + """ credentialparser = argparse.ArgumentParser( prog="login", description="Subparser for login credentials provided by CI" @@ -12,6 +15,9 @@ def get_credential_parser(): return credentialparser def stack_formatter(stacks): + """ + Prints a given stack list formatted as a table + """ if not stacks["ok"]: raise RuntimeError("Stack GET didn't work") @@ -22,11 +28,17 @@ def stack_formatter(stacks): print(tabulate(table, headers=headers, tablefmt="github"), "\n") def status_formatter(status): + """ + Prints the status for a given stack + """ print(f"Is Stack Ok? {'Yes' if status['ok'] else 'No'}") headers = ["Container", "Status"] table = [[k, v] for k, v in status["serviceStatusList"].items()] print(tabulate(table, headers=headers, tablefmt="github"), "\n") def generic_formatter(status): + """ + Prints a generic dockge message + """ print(f"Is Ok? {'Yes' if status['ok'] else 'No'}") print(f"Stack status: {status['msg']}") diff --git a/dockge_cli/dockge_cli.py b/dockge_cli/dockge_cli.py index 25c437f..af77054 100644 --- a/dockge_cli/dockge_cli.py +++ b/dockge_cli/dockge_cli.py @@ -2,5 +2,8 @@ from .client.parser import parse_arguments from .client.run import run def cli(): + """ + main function for cli invocation + """ command, args= parse_arguments() run(command.command, args) diff --git a/dockge_cli/models/codes.py b/dockge_cli/models/codes.py index b8f9a07..4c3799b 100644 --- a/dockge_cli/models/codes.py +++ b/dockge_cli/models/codes.py @@ -1,6 +1,9 @@ from enum import Enum class StackStatus(Enum): + """ + mapping codes for status vs text + """ # pylint: disable=invalid-name inactive = 1 running = 3 diff --git a/dockge_cli/models/commands.py b/dockge_cli/models/commands.py index 5bc7fb6..d7a8123 100644 --- a/dockge_cli/models/commands.py +++ b/dockge_cli/models/commands.py @@ -2,6 +2,9 @@ from typing import Callable from pydantic import BaseModel class Command(BaseModel): + """ + Basic command structure for the CLI to automatically generate valid commands + """ cmd: str bind: Callable args: int diff --git a/dockge_cli/models/parser.py b/dockge_cli/models/parser.py index c836e62..e590ce9 100644 --- a/dockge_cli/models/parser.py +++ b/dockge_cli/models/parser.py @@ -2,9 +2,15 @@ import argparse # pylint: disable=too-few-public-methods class Arguments(argparse.Namespace): + """ + Default Arguments when calling the CLI + """ command: str # pylint: disable=too-few-public-methods class Credentials(argparse.Namespace): + """ + Special Argument Namespace for login credentials of the login commands + """ username: str password: str diff --git a/dockge_cli/service/communicate.py b/dockge_cli/service/communicate.py index 4eb645d..b534174 100644 --- a/dockge_cli/service/communicate.py +++ b/dockge_cli/service/communicate.py @@ -5,8 +5,14 @@ import socketio.exceptions from . import storage class DockgeConnection: + """ + Provider class for Dockge + Provides all the functionality for connecting, logging in and executing commands + """ class LoginException(BaseException): - pass + """ + Special exception when login fails too often + """ _sio: socketio.Client _host: str @@ -61,10 +67,17 @@ class DockgeConnection: # Functions def connect_and_login(self): + """ + Connect to the websocket + """ self._sio.connect(f"https://{self._host}/socket.io/", transports=['websocket']) self.connect() def connect(self): + """ + Log into dockge using basicauth + Retries 5 times when timeouts occur + """ if self._logged_in: return @@ -92,6 +105,9 @@ class DockgeConnection: self._logged_in = True def list_stacks(self): + """ + Requests stack list from dockge, returns list when event was sent + """ self._sio.emit("agent", ("", "requestStackList")) while self._stacklist is None: time.sleep(0.5) @@ -100,29 +116,50 @@ class DockgeConnection: return retval def list_stack(self, name: str): + """ + Lists status for a stack + """ ret = self._sio.call("agent", ("", "serviceStatusList", name), timeout=5) return ret def restart(self, name): + """ + Restarts a given stack + """ ret = self._sio.call("agent", ("", "restartStack", name), timeout=10) return ret def update(self, name): + """ + Updates a given stack + """ ret = self._sio.call("agent", ("", "updateStack", name), timeout=10) return ret def stop(self, name): + """ + Stops a given stack + """ ret = self._sio.call("agent", ("", "stopStack", name), timeout=10) return ret def start(self, name): + """ + Starts a given stack + """ ret = self._sio.call("agent", ("", "startStack", name), timeout=10) return ret def down(self, name): + """ + Stops and downs a given stack + """ ret = self._sio.call("agent", ("", "downStack", name), timeout=10) return ret def disconnect(self): + """ + Logs out of dockge + """ self._sio.emit("logout") self._sio.disconnect() diff --git a/dockge_cli/service/storage.py b/dockge_cli/service/storage.py index 0a3a0f8..e4276a2 100644 --- a/dockge_cli/service/storage.py +++ b/dockge_cli/service/storage.py @@ -9,11 +9,18 @@ _file = _storagepath / "storage.yaml" _storagepath.mkdir(exist_ok=True, parents=True) def fileexists(): + """ + Checks if storage file does exist, creates it when necessary + """ if not _file.exists(): with open(_file, 'a', encoding="utf-8"): os.utime(_file, None) def put(key: str, value: str, encoded=False): + """ + Puts a given value with a given key into the storage file + Encodes the data as base64 when encoded is set to true + """ fileexists() with open(_file, "r+", encoding="utf-8") as file: content: dict[str, str] = yaml.load(file, Loader=yaml.SafeLoader) or {} @@ -22,6 +29,9 @@ def put(key: str, value: str, encoded=False): yaml.dump(content, file, Dumper=yaml.SafeDumper) def remove(key: str): + """ + Removed a given key from the storage file + """ fileexists() with open(_file, "r", encoding="utf-8") as file: content: dict[str, str] = yaml.load(file, Loader=yaml.SafeLoader) or {} @@ -30,6 +40,10 @@ def remove(key: str): yaml.dump(content, file, Dumper=yaml.SafeDumper) def get(key: str, encoded=False): + """ + Retrieves a value for a given key from the storage file + If the value was encoded, encoded needs to be set True to decode it again + """ value: str | None = None if not _file.exists(): return None @@ -41,4 +55,7 @@ def get(key: str, encoded=False): return base64.b64decode(value).decode() if encoded else value def clear(): + """ + Deletes the storage file + """ _file.unlink() diff --git a/pyproject.toml b/pyproject.toml index 830b0f4..7b15966 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,7 +42,10 @@ typing = [ ] [tool.pylint."MAIN"] -disable = [ "line-too-long", "missing-module-docstring", "missing-function-docstring", "missing-class-docstring" ] +disable = [ + "line-too-long", + "missing-module-docstring", +] [tool.mypy] python_version = "3.11"