diff --git a/.gitignore b/.gitignore index ea7ee7e..1736ee6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ __pycache__ env/ dist/ +venv/ diff --git a/Makefile b/Makefile index 81f2ea8..88e0700 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,5 @@ #!/usr/bin/make -f +LINT_TARGETS=./src debian_changelog: ifndef DAS_CLI_VERSION @@ -20,3 +21,15 @@ endif @bats tests/integration/*.bats --filter-tags '!cluster' +isort: + @isort --settings-path ./src/.isort.cfg $(LINT_TARGETS) + +black: + @black --config ./src/.black.cfg $(LINT_TARGETS) + +flake8: + @flake8 --config ./src/.flake8.cfg $(LINT_TARGETS) + +lint: isort black flake8 + +pre-commit: lint diff --git a/src/.black.cfg b/src/.black.cfg new file mode 100644 index 0000000..477f5c6 --- /dev/null +++ b/src/.black.cfg @@ -0,0 +1,4 @@ +[tool.black] +line-length = 100 +target-version = ['py38'] +skip-string-normalization = true diff --git a/src/.flake8.cfg b/src/.flake8.cfg new file mode 100644 index 0000000..f44afe3 --- /dev/null +++ b/src/.flake8.cfg @@ -0,0 +1,4 @@ +[flake8] +max-line-length = 100 +show-source = true +extend-ignore = E203,E501 diff --git a/src/.isort.cfg b/src/.isort.cfg new file mode 100644 index 0000000..cf6c0a6 --- /dev/null +++ b/src/.isort.cfg @@ -0,0 +1,9 @@ +[isort] +py_version = 38 +multi_line_output = 3 +include_trailing_comma = true +force_grid_wrap = 0 +use_parentheses = true +line_length = 100 +profile = black +skip=src/config/__init__.py diff --git a/src/.pylintrc b/src/.pylintrc new file mode 100644 index 0000000..93e2bb6 --- /dev/null +++ b/src/.pylintrc @@ -0,0 +1,222 @@ +[MASTER] + +py-version=3.10 + + +[MESSAGES CONTROL] + +disable=all +enable= + abstract-method, + anomalous-backslash-in-string, + anomalous-unicode-escape-in-string, + astroid-error, + attribute-defined-outside-init, + bad-classmethod-argument, + bad-except-order, + bad-exception-context, + bad-format-character, + bad-format-string, + bad-format-string-key, + bad-mcs-classmethod-argument, + bad-mcs-method-argument, + bad-open-mode, + bad-option-value, + bad-reversed-sequence, + bad-staticmethod-argument, + bad-str-strip-call, + bad-string-format-type, + bad-super-call, + bare-except, + blacklisted-name, + broad-except, + c-extension-no-member, + cell-var-from-loop, + chained-comparison, + class-variable-slots-conflict, + comparison-with-itself, + consider-iterating-dictionary, + consider-merging-isinstance, + consider-swap-variables, + consider-using-dict-comprehension, + consider-using-enumerate, + consider-using-get, + consider-using-in, + consider-using-join, + consider-using-set-comprehension, + consider-using-sys-exit, + consider-using-ternary, + continue-in-finally, + dangerous-default-value, + deprecated-method, + deprecated-module, + dict-iter-missing-items, + duplicate-except, + duplicate-key, + duplicate-string-formatting-argument, + empty-docstring, + eval-used, + exec-used, + expression-not-assigned, + fatal, + format-combined-specification, + format-needs-mapping, + global-at-module-level, + global-statement, + global-variable-not-assigned, + import-outside-toplevel, + import-self, + inconsistent-return-statements, + init-is-generator, + invalid-all-object, + invalid-characters-in-docstring, + invalid-envvar-default, + invalid-format-index, + invalid-length-returned, + invalid-name, + invalid-slots-object, + literal-comparison, + logging-format-interpolation, + logging-format-truncated, + logging-not-lazy, + logging-too-few-args, + logging-too-many-args, + logging-unsupported-format, + lost-exception, + method-check-failed, + misplaced-bare-raise, + misplaced-future, + missing-format-argument-key, + missing-format-attribute, + missing-format-string-key, + missing-kwoa, + missing-parentheses-for-call-in-test, + mixed-format-string, + multiple-imports, + no-classmethod-decorator, + no-else-continue, + no-self-argument, + non-iterator-returned, + non-parent-init-called, + nonlocal-and-global, + nonlocal-without-binding, + notimplemented-raised, + parse-error, + pointless-statement, + pointless-string-statement, + possibly-unused-variable, + preferred-module, + protected-access, + raising-format-tuple, + redeclared-assigned-name, + redefined-argument-from-local, + redefined-builtin, + redefined-outer-name, + redundant-unittest-assert, + reimported, + relative-beyond-top-level, + return-arg-in-generator, + return-in-init, + self-assigning-variable, + self-cls-assignment, + shallow-copy-environ, + simplifiable-if-expression, + simplifiable-if-statement, + simplify-boolean-expression, + single-string-used-for-slots, + singleton-comparison, + subprocess-popen-preexec-fn, + subprocess-run-check, + super-init-not-called, + too-few-format-args, + too-many-format-args, + too-many-nested-blocks, + too-many-star-expressions, + trailing-comma-tuple, + truncated-format-string, + try-except-raise, + undefined-all-variable, + undefined-loop-variable, + undefined-variable, + unexpected-line-ending-format, + ungrouped-imports, + unidiomatic-typecheck, + unnecessary-comprehension, + unnecessary-pass, + unneeded-not, + unreachable, + unrecognized-inline-option, + unused-format-string-argument, + unused-format-string-key, + unused-import, + unused-variable, + unused-wildcard-import, + used-before-assignment, + used-prior-global-declaration, + useless-else-on-loop, + useless-object-inheritance, + using-constant-test, + wildcard-import, + wrong-exception-operation, + wrong-import-position, + wrong-spelling-in-comment, + wrong-spelling-in-docstring, + + +[REPORTS] + +# Set the output format. Available formats are text, parseable, colorized and json. +output-format=parseable,colorized + +# Tells whether to display a full report or only the messages +reports=no + + +[SCORE] +score=no + + +[CLASSES] +valid-classmethod-first-arg=cls +valid-metaclass-classmethod-first-arg=mcs + + +[EXCEPTIONS] +overgeneral-exceptions=builtins.Exception + + +[BASIC] +good-names=i,j,k,ex,Run,_,logger,T +variable-rgx=(([a-z][a-z0-9_]{0,})|(_[a-z0-9_]*))$ +argument-rgx=(F|([a-z][a-z0-9_]{0,})|(_[a-z0-9_]*))$ +attr-rgx=(([a-z][a-z0-9_]{0,})|(_[a-z0-9_]*))$ +module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ +bad-names=toto,tutu,tata + + +[VARIABLES] + +dummy-variables-rgx=(_+[a-zA-Z0-9_]*?$)|dummy + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid defining new builtins when possible. +additional-builtins= + +# List of strings which can identify a callback function by name. A callback +# name must start or end with one of those strings. +callbacks=cb_,_cb + +# Tells whether unused global variables should be treated as a violation. +allow-global-unused-variables=yes + +# List of names allowed to shadow builtins +allowed-redefined-builtins= + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=FIXME \ No newline at end of file diff --git a/src/commands/config/__init__.py b/src/commands/config/__init__.py index e4dac98..b450425 100644 --- a/src/commands/config/__init__.py +++ b/src/commands/config/__init__.py @@ -1 +1,3 @@ from .config_module import ConfigModule + +__all__ = ["ConfigModule"] diff --git a/src/commands/config/config_cli.py b/src/commands/config/config_cli.py index 0202ce4..03bcac4 100644 --- a/src/commands/config/config_cli.py +++ b/src/commands/config/config_cli.py @@ -1,15 +1,18 @@ +from typing import Dict, List + from injector import inject -from typing import List, Dict -from common import Settings, StdoutSeverity + from common import ( Command, CommandGroup, - ReachableIpAddress, IntRange, + ReachableIpAddress, RemoteContextManager, - get_server_username, + Settings, + StdoutSeverity, get_public_ip, get_rand_token, + get_server_username, ) @@ -75,7 +78,7 @@ class ConfigSet(Command): mongodb.cluster Indicates whether a MongoDB cluster is being used (true/false). - + mongodb.cluster_secret_key This key is uploaded to all nodes within the MongoDB cluster. It is used for mutual authentication between nodes, ensuring that only authorized nodes can communicate with each other. @@ -354,9 +357,7 @@ class ConfigCli(CommandGroup): parameters such as port numbers, usernames and other configuration settings required by various DAS components. """ - short_help = ( - "'das-cli config' allows you to manage configuration settings for the DAS CLI" - ) + short_help = "'das-cli config' allows you to manage configuration settings for the DAS CLI" @inject def __init__( diff --git a/src/commands/config/config_module.py b/src/commands/config/config_module.py index 83d6a43..88f794b 100644 --- a/src/commands/config/config_module.py +++ b/src/commands/config/config_module.py @@ -1,4 +1,5 @@ from common import Module + from .config_cli import ConfigCli diff --git a/src/commands/das/__init__.py b/src/commands/das/__init__.py index fce5b42..78bba5e 100644 --- a/src/commands/das/__init__.py +++ b/src/commands/das/__init__.py @@ -1 +1,3 @@ from .das_module import DasModule + +__all__ = ["DasModule"] diff --git a/src/commands/das/das_cli.py b/src/commands/das/das_cli.py index 2b52637..f4720c8 100644 --- a/src/commands/das/das_cli.py +++ b/src/commands/das/das_cli.py @@ -1,24 +1,21 @@ import os +import sys + import click import distro -import sys -from config import VERSION from injector import inject -from common import ( - Command, - CommandGroup, - CommandOption, - is_executable_bin, - StdoutSeverity, -) + +from common import Command, CommandGroup, CommandOption, StdoutSeverity, is_executable_bin +from config import VERSION + from .das_ubuntu_advanced_packaging_tool import ( - DasUbuntuAdvancedPackagingTool, - DasNotFoundError, DasError, + DasNotFoundError, + DasUbuntuAdvancedPackagingTool, ) -class PermissionError(Exception): ... +class PermissionError(Exception): ... # noqa: E701 class DasCliUpdateVersion(Command): @@ -130,6 +127,4 @@ def __init__( ) def version(self): - self.group = click.version_option(VERSION, message="%(prog)s %(version)s")( - self.group - ) + self.group = click.version_option(VERSION, message="%(prog)s %(version)s")(self.group) diff --git a/src/commands/das/das_module.py b/src/commands/das/das_module.py index ecf13a9..0825bd0 100644 --- a/src/commands/das/das_module.py +++ b/src/commands/das/das_module.py @@ -1,4 +1,5 @@ from common import Module + from .das_cli import DasCli diff --git a/src/commands/das/das_ubuntu_advanced_packaging_tool.py b/src/commands/das/das_ubuntu_advanced_packaging_tool.py index 4de0f74..10485a0 100644 --- a/src/commands/das/das_ubuntu_advanced_packaging_tool.py +++ b/src/commands/das/das_ubuntu_advanced_packaging_tool.py @@ -1,12 +1,12 @@ import re import subprocess -from typing import Union, Tuple +from typing import Tuple, Union -class DasError(Exception): ... +class DasError(Exception): ... # noqa: E701 -class DasNotFoundError(DasError): ... +class DasNotFoundError(DasError): ... # noqa: E701 class DasUbuntuAdvancedPackagingTool: @@ -38,9 +38,7 @@ def get_package_version(self) -> Tuple[Union[None, str]]: stderr=subprocess.DEVNULL, ) - version_pattern = ( - r"Installed:\s*(\d+\.\d+\.\d+)\n\s*Candidate:\s*(\d+\.\d+\.\d+)" - ) + version_pattern = r"Installed:\s*(\d+\.\d+\.\d+)\n\s*Candidate:\s*(\d+\.\d+\.\d+)" matches = re.findall(version_pattern, output.decode("utf-8")) diff --git a/src/commands/db/__init__.py b/src/commands/db/__init__.py index 76500a2..bddbae5 100644 --- a/src/commands/db/__init__.py +++ b/src/commands/db/__init__.py @@ -1 +1,3 @@ from .db_module import DbModule + +__all__ = ["DbModule"] diff --git a/src/commands/db/db_cli.py b/src/commands/db/db_cli.py index 1126ac5..dbb19bf 100644 --- a/src/commands/db/db_cli.py +++ b/src/commands/db/db_cli.py @@ -1,13 +1,16 @@ +from typing import AnyStr, Union + from injector import inject + from common import Command, CommandGroup, Settings, StdoutSeverity from common.docker.exceptions import ( DockerContainerDuplicateError, - DockerError, DockerContainerNotFoundError, + DockerError, ) + from .mongodb_container_manager import MongodbContainerManager from .redis_container_manager import RedisContainerManager -from typing import Union, AnyStr class DbStop(Command): @@ -58,7 +61,7 @@ def _redis_node(self, context, ip, username): ) def _redis(self): - self.stdout(f"Stopping Redis service...") + self.stdout("Stopping Redis service...") redis_nodes = self._settings.get("redis.nodes", []) @@ -67,7 +70,7 @@ def _redis(self): self._redis_node(**redis_node) except DockerError as e: self.stdout( - f"\nError occurred while trying to stop Redis\n", + "\nError occurred while trying to stop Redis\n", severity=StdoutSeverity.ERROR, ) raise e @@ -90,7 +93,7 @@ def _mongodb_node(self, context, ip, username): ) def _mongodb(self): - self.stdout(f"Stopping MongoDB service...") + self.stdout("Stopping MongoDB service...") mongodb_nodes = self._settings.get("mongodb.nodes", []) @@ -100,7 +103,7 @@ def _mongodb(self): except DockerError as e: self.stdout( - f"\nError occurred while trying to stop MongoDB\n", + "\nError occurred while trying to stop MongoDB\n", severity=StdoutSeverity.ERROR, ) raise e @@ -167,14 +170,14 @@ def _redis_node( f"Redis is already running. It is currently listening on port {redis_port} at {node_ip} under the server user {node_username}.", severity=StdoutSeverity.WARNING, ) - except DockerError as e: + except DockerError: self.stdout( f"\nError occurred while trying to start Redis on port {redis_port} at {node_ip} under the server user {node_username}.\n", severity=StdoutSeverity.ERROR, ) def _redis(self) -> None: - self.stdout(f"Starting Redis service...") + self.stdout("Starting Redis service...") redis_port = self._settings.get("redis.port") redis_nodes = self._settings.get("redis.nodes", []) @@ -188,7 +191,7 @@ def _redis(self) -> None: self._redis_container_manager.start_cluster(redis_nodes, redis_port) except Exception as e: self.stdout( - f"\nFailed to start the cluster. Please check the conectivity between the nodes and try again.\n", + "\nFailed to start the cluster. Please check the conectivity between the nodes and try again.\n", severity=StdoutSeverity.ERROR, ) raise e @@ -243,7 +246,7 @@ def _mongodb_node( raise e def _mongodb(self) -> None: - self.stdout(f"Starting MongoDB service...") + self.stdout("Starting MongoDB service...") mongodb_port = self._settings.get("mongodb.port") mongodb_username = self._settings.get("mongodb.username") @@ -272,7 +275,7 @@ def _mongodb(self) -> None: ) except Exception as e: self.stdout( - f"\nFailed to start the cluster. Please check the conectivity between the nodes and try again.\n", + "\nFailed to start the cluster. Please check the conectivity between the nodes and try again.\n", severity=StdoutSeverity.ERROR, ) raise e @@ -290,7 +293,9 @@ class DbRestart(Command): short_help = "Restart all DBMS containers." help = """ -'das-cli db restart' restarts all database containers previously started with 'das-cli start'. If no database have been started, 'das-cli db restart' just start them. +'das-cli db restart' restarts all database containers previously started with +'das-cli start'. If no database have been started, 'das-cli db restart' just +start them. IMPORTANTE NOTE: Restarting the databases will result in all data being lost. Databases are started empty. @@ -317,7 +322,11 @@ class DbCli(CommandGroup): short_help = "Manage db-related operations." - help = "'das-cli db' commands allow you to manage DAS backend DBMSs for use with the DAS CLI. 'das-cli db' provides commands to start, stop, and restart the databases as needed." + help = """ + 'das-cli db' commands allow you to manage DAS backend DBMSs for use + with the DAS CLI. 'das-cli db' provides commands to start, stop, and + restart the databases as needed. + """ @inject def __init__( diff --git a/src/commands/db/db_module.py b/src/commands/db/db_module.py index 39d2353..e384817 100644 --- a/src/commands/db/db_module.py +++ b/src/commands/db/db_module.py @@ -1,5 +1,6 @@ from common import Module -from .db_cli import DbCli, RedisContainerManager, Settings, MongodbContainerManager + +from .db_cli import DbCli, MongodbContainerManager, RedisContainerManager, Settings class DbModule(Module): diff --git a/src/commands/db/mongodb_container_manager.py b/src/commands/db/mongodb_container_manager.py index c59fd46..62fb961 100644 --- a/src/commands/db/mongodb_container_manager.py +++ b/src/commands/db/mongodb_container_manager.py @@ -1,9 +1,10 @@ -import json import io -from common import Container, ContainerManager, ssh, get_rand_token -from config import MONGODB_IMAGE_NAME, MONGODB_IMAGE_VERSION -from typing import List, Dict, Union, AnyStr +import json +from typing import AnyStr, Dict, List, Union + +from common import Container, ContainerManager, get_rand_token, ssh from common.docker.exceptions import DockerError +from config import MONGODB_IMAGE_NAME, MONGODB_IMAGE_VERSION class MongodbContainerManager(ContainerManager): diff --git a/src/commands/db/redis_container_manager.py b/src/commands/db/redis_container_manager.py index b958c46..ce8e050 100644 --- a/src/commands/db/redis_container_manager.py +++ b/src/commands/db/redis_container_manager.py @@ -1,6 +1,7 @@ +from typing import AnyStr, Dict, List, Union + from common import Container, ContainerManager from config import REDIS_IMAGE_NAME, REDIS_IMAGE_VERSION -from typing import AnyStr, Union, List, Dict class RedisContainerManager(ContainerManager): @@ -62,9 +63,7 @@ def start_cluster(self, redis_nodes: List[Dict], redis_port: AnyStr): server_ip = redis_node.get("ip") nodes_str += f"{server_ip}:{redis_port} " - cmd = ( - f"redis-cli --cluster create {nodes_str} --cluster-replicas 0 --cluster-yes" - ) + cmd = f"redis-cli --cluster create {nodes_str} --cluster-replicas 0 --cluster-yes" container_id = self._exec_container(cmd) diff --git a/src/commands/example/__init__.py b/src/commands/example/__init__.py index 02986fc..87e406f 100644 --- a/src/commands/example/__init__.py +++ b/src/commands/example/__init__.py @@ -1 +1,3 @@ from .example_module import ExampleModule + +__all__ = ["ExampleModule"] diff --git a/src/commands/example/example_cli.py b/src/commands/example/example_cli.py index 2fa9c75..1387211 100644 --- a/src/commands/example/example_cli.py +++ b/src/commands/example/example_cli.py @@ -1,4 +1,5 @@ from injector import inject + from common import Command, CommandGroup diff --git a/src/commands/example/example_module.py b/src/commands/example/example_module.py index 0cf7363..9c1e625 100644 --- a/src/commands/example/example_module.py +++ b/src/commands/example/example_module.py @@ -1,6 +1,6 @@ -from common import Module +from common import Module, get_script_name + from .example_cli import ExampleCli, ExampleFaaS, ExampleLocal -from common import get_script_name class ExampleModule(Module): diff --git a/src/commands/faas/__init__.py b/src/commands/faas/__init__.py index b6b1a07..7f5720d 100644 --- a/src/commands/faas/__init__.py +++ b/src/commands/faas/__init__.py @@ -1 +1,3 @@ from .faas_module import FaaSModule + +__all__ = ["FaaSModule"] diff --git a/src/commands/faas/faas_cli.py b/src/commands/faas/faas_cli.py index cf453fa..641ae83 100644 --- a/src/commands/faas/faas_cli.py +++ b/src/commands/faas/faas_cli.py @@ -1,18 +1,20 @@ from injector import inject -from config import OPENFAAS_IMAGE_NAME + from commands.db.mongodb_container_manager import MongodbContainerManager from commands.db.redis_container_manager import RedisContainerManager -from common.docker.exceptions import DockerContainerNotFoundError from common import ( + Choice, Command, CommandGroup, - StdoutSeverity, - ImageManager, - Settings, CommandOption, - Choice, FunctionVersion, + ImageManager, + Settings, + StdoutSeverity, ) +from common.docker.exceptions import DockerContainerNotFoundError +from config import OPENFAAS_IMAGE_NAME + from .openfaas_container_manager import OpenFaaSContainerManager @@ -43,7 +45,10 @@ class FaaSStop(Command): short_help = "Stop the running OpenFaaS service.." help = """ -'das-cli faas stop' allows you to stop the execution of the DAS function in OpenFaaS. This is useful for terminating the function's operation when it's no longer needed. After stopping the faas, the function will no longer be available and cannot be used with the DAS. +'das-cli faas stop' allows you to stop the execution of the DAS function in +OpenFaaS. This is useful for terminating the function's operation when it's no +longer needed. After stopping the faas, the function will no longer be +available and cannot be used with the DAS. .SH EXAMPLES @@ -60,14 +65,12 @@ def __init__(self, settings: Settings) -> None: def run(self): self._settings.raise_on_missing_file() - self.stdout(f"Stopping OpenFaaS service...") + self.stdout("Stopping OpenFaaS service...") openfaas_container_name = self._settings.get("openfaas.container_name") try: - openfaas_container_service = OpenFaaSContainerManager( - openfaas_container_name - ) + openfaas_container_service = OpenFaaSContainerManager(openfaas_container_name) openfaas_container_service.stop() self.stdout("OpenFaaS service stopped", severity=StdoutSeverity.SUCCESS) @@ -80,12 +83,24 @@ class FaaSStart(Command): short_help = "Start OpenFaaS service." - help = """ -OpenFaaS, an open-source serverless computing platform, makes running functions in containers fast and simple. With this command, you can initialize the DAS remotely through a function in OpenFaaS, which can be run on your server or locally. - -If you've just installed the DAS CLI, the function will be executed using the latest version by default. However, if you want to specify a particular version, you can use the faas update-version command. Versions are available at https://github.com/singnet/das-serverless-functions/releases, or you can choose to leave it as latest, which will always use the latest available version. - -Since the function needs to communicate with databases, you need to run db start to establish this communication. Upon the first execution of the function, it might take a little longer as it needs to fetch the specified version and set everything up for you. Subsequent initializations will be faster unless you change the version, which will require the same process again to set everything up. + help = r""" +OpenFaaS, an open-source serverless computing platform, makes running functions +in containers fast and simple. With this command, you can initialize the DAS +remotely through a function in OpenFaaS, which can be run on your server or +locally. + +If you've just installed the DAS CLI, the function will be executed using the +latest version by default. However, if you want to specify a particular +version, you can use the faas update-version command. Versions are available at +https://github.com/singnet/das-serverless-functions/releases, or you can choose +to leave it as latest, which will always use the latest available version. + +Since the function needs to communicate with databases, you need to run db +start to establish this communication. Upon the first execution of the +function, it might take a little longer as it needs to fetch the specified +version and set everything up for you. Subsequent initializations will be +faster unless you change the version, which will require the same process again +to set everything up. .B Ensure that the following ports are open: @@ -99,7 +114,8 @@ class FaaSStart(Command): .IP \[bu] 2 Port 5000: For the watchdog -After starting the function, you will receive a message on the screen with the function version and the port on which the function is being executed. +After starting the function, you will receive a message on the screen with the +function version and the port on which the function is being executed. .SH EXAMPLES @@ -158,9 +174,7 @@ def run(self): [ { "name": "MongoDB", - "container_manager": MongodbContainerManager( - mongodb_container_name - ), + "container_manager": MongodbContainerManager(mongodb_container_name), "port": mongodb_port, }, { @@ -211,7 +225,12 @@ class FaaSRestart(Command): short_help = "Restart OpenFaaS service." help = """ -'das-cli faas restart' restarts OpenFaaS server container. This is useful when you want to restart the function to apply configuration changes. During this process, there is typically a downtime until the function is running again and deemed healthy. This downtime occurs because the existing instance of the function needs to be stopped, and then a new instance needs to be started with the updated configuration or changes. +'das-cli faas restart' restarts OpenFaaS server container. This is useful when +you want to restart the function to apply configuration changes. During this +process, there is typically a downtime until the function is running again and +deemed healthy. This downtime occurs because the existing instance of the +function needs to be stopped, and then a new instance needs to be started with +the updated configuration or changes. .SH EXAMPLES @@ -237,7 +256,10 @@ class FaaSVersion(Command): short_help = "Get OpenFaaS function version." help = """ -'das-cli faas version' is used to display the current version of the DAS function in OpenFaaS. This command is particularly useful for checking the version of the deployed function, which can be helpful troubleshooting issues, or ensuring compatibility. +'das-cli faas version' is used to display the current version of the DAS +function in OpenFaaS. This command is particularly useful for checking the +version of the deployed function, which can be helpful troubleshooting issues, +or ensuring compatibility. .SH EXAMPLES @@ -277,7 +299,14 @@ class FaaSUpdateVersion(Command): short_help = "Update an OpenFaaS service to a newer version." help = """ -'das-cli update-version' allows you to update the version of your function in OpenFaaS. All available versions can be found at https://github.com/singnet/das-serverless-functions/releases. This command has two optional parameters. When executed without parameters, it will fetch the latest version of the 'query-engine' function and update it on your local server if a newer version is found. You can also specify the function you want to update in OpenFaaS (currently only 'query-engine' is available), and define the version of the function you want to use, as mentioned earlier. +'das-cli update-version' allows you to update the version of your function in +OpenFaaS. All available versions can be found at +https://github.com/singnet/das-serverless-functions/releases. This command has +two optional parameters. When executed without parameters, it will fetch the +latest version of the 'query-engine' function and update it on your local +server if a newer version is found. You can also specify the function you want +to update in OpenFaaS (currently only 'query-engine' is available), and define +the version of the function you want to use, as mentioned earlier. .SH EXAMPLES @@ -329,9 +358,7 @@ def run( ) -> None: self._settings.raise_on_missing_file() - current_function_name, current_function_version = get_function_version( - self._settings - ) + current_function_name, current_function_version = get_function_version(self._settings) self.stdout(f"Downloading the {function} function, version {version}...") @@ -344,9 +371,7 @@ def run( self._set_version(function, version) - newer_function_name, newer_function_version = get_function_version( - self._settings - ) + newer_function_name, newer_function_version = get_function_version(self._settings) if ( current_function_name != newer_function_name diff --git a/src/commands/faas/faas_module.py b/src/commands/faas/faas_module.py index d57a94f..a0fdddd 100644 --- a/src/commands/faas/faas_module.py +++ b/src/commands/faas/faas_module.py @@ -1,4 +1,5 @@ from common import Module + from .faas_cli import FaaSCli diff --git a/src/commands/faas/openfaas_container_manager.py b/src/commands/faas/openfaas_container_manager.py index c659fba..c14515e 100644 --- a/src/commands/faas/openfaas_container_manager.py +++ b/src/commands/faas/openfaas_container_manager.py @@ -1,11 +1,10 @@ -import docker import socket + +import docker + from common import Container, ContainerManager +from common.docker.exceptions import DockerContainerNotFoundError, DockerError from config import OPENFAAS_IMAGE_NAME -from common.docker.exceptions import ( - DockerError, - DockerContainerNotFoundError, -) class OpenFaaSContainerManager(ContainerManager): diff --git a/src/commands/jupyter_notebook/__init__.py b/src/commands/jupyter_notebook/__init__.py index 902171f..3caf8f5 100644 --- a/src/commands/jupyter_notebook/__init__.py +++ b/src/commands/jupyter_notebook/__init__.py @@ -1 +1,3 @@ from .jupyter_notebook_module import JupyterNotebookModule + +__all__ = ["JupyterNotebookModule"] diff --git a/src/commands/jupyter_notebook/jupyter_notebook_cli.py b/src/commands/jupyter_notebook/jupyter_notebook_cli.py index dbeada9..31fccdf 100644 --- a/src/commands/jupyter_notebook/jupyter_notebook_cli.py +++ b/src/commands/jupyter_notebook/jupyter_notebook_cli.py @@ -1,10 +1,12 @@ from injector import inject + from common import Command, CommandGroup, Settings, StdoutSeverity from common.docker.exceptions import ( DockerContainerDuplicateError, - DockerError, DockerContainerNotFoundError, + DockerError, ) + from .jupyter_notebook_container_manager import JupyterNotebookContainerManager @@ -37,9 +39,7 @@ def run(self): self.stdout("Starting Jupyter Notebook...") - jupyter_notebook_container_name = self._settings.get( - "jupyter_notebook.container_name" - ) + jupyter_notebook_container_name = self._settings.get("jupyter_notebook.container_name") jupyter_notebook_port = self._settings.get("jupyter_notebook.port") try: @@ -88,11 +88,9 @@ def __init__(self, settings: Settings) -> None: def run(self): self._settings.raise_on_missing_file() - self.stdout(f"Stopping jupyter notebook...") + self.stdout("Stopping jupyter notebook...") - jupyter_notebook_container_name = self._settings.get( - "jupyter_notebook.container_name" - ) + jupyter_notebook_container_name = self._settings.get("jupyter_notebook.container_name") try: JupyterNotebookContainerManager(jupyter_notebook_container_name).stop() diff --git a/src/commands/jupyter_notebook/jupyter_notebook_container_manager.py b/src/commands/jupyter_notebook/jupyter_notebook_container_manager.py index 6353d8d..aa77882 100644 --- a/src/commands/jupyter_notebook/jupyter_notebook_container_manager.py +++ b/src/commands/jupyter_notebook/jupyter_notebook_container_manager.py @@ -1,7 +1,8 @@ import docker + from common import Container, ContainerManager -from config import JUPYTER_NOTEBOOK_IMAGE_NAME, JUPYTER_NOTEBOOK_IMAGE_VERSION from common.docker.exceptions import DockerError +from config import JUPYTER_NOTEBOOK_IMAGE_NAME, JUPYTER_NOTEBOOK_IMAGE_VERSION class JupyterNotebookContainerManager(ContainerManager): diff --git a/src/commands/jupyter_notebook/jupyter_notebook_module.py b/src/commands/jupyter_notebook/jupyter_notebook_module.py index 1fa6e26..56944b8 100644 --- a/src/commands/jupyter_notebook/jupyter_notebook_module.py +++ b/src/commands/jupyter_notebook/jupyter_notebook_module.py @@ -1,4 +1,5 @@ from common import Module + from .jupyter_notebook_cli import JupyterNotebookCli diff --git a/src/commands/logs/__init__.py b/src/commands/logs/__init__.py index 28501b8..ca6e521 100644 --- a/src/commands/logs/__init__.py +++ b/src/commands/logs/__init__.py @@ -1 +1,3 @@ from .logs_module import LogsModule + +__all__ = ["LogsModule"] diff --git a/src/commands/logs/logs_cli.py b/src/commands/logs/logs_cli.py index 254632a..919b948 100644 --- a/src/commands/logs/logs_cli.py +++ b/src/commands/logs/logs_cli.py @@ -1,10 +1,12 @@ +from time import sleep + from injector import inject -from common import Command, CommandGroup, StdoutSeverity, Settings -from common.docker.exceptions import DockerError -from commands.faas.openfaas_container_manager import OpenFaaSContainerManager + from commands.db.mongodb_container_manager import MongodbContainerManager from commands.db.redis_container_manager import RedisContainerManager -from time import sleep +from commands.faas.openfaas_container_manager import OpenFaaSContainerManager +from common import Command, CommandGroup, Settings, StdoutSeverity +from common.docker.exceptions import DockerError from config import LOG_FILE_NAME diff --git a/src/commands/logs/logs_module.py b/src/commands/logs/logs_module.py index 031d4d4..58ee74c 100644 --- a/src/commands/logs/logs_module.py +++ b/src/commands/logs/logs_module.py @@ -1,4 +1,5 @@ from common import Module + from .logs_cli import LogsCli diff --git a/src/commands/metta/__init__.py b/src/commands/metta/__init__.py index 7390746..5ae4f94 100644 --- a/src/commands/metta/__init__.py +++ b/src/commands/metta/__init__.py @@ -1 +1,3 @@ from .metta_module import MettaModule + +__all__ = ["MettaModule"] diff --git a/src/commands/metta/metta_cli.py b/src/commands/metta/metta_cli.py index 8f85a3f..6b05feb 100644 --- a/src/commands/metta/metta_cli.py +++ b/src/commands/metta/metta_cli.py @@ -1,20 +1,16 @@ import glob import os + from injector import inject -from common import ( - Command, - CommandGroup, - CommandArgument, - Path, - Settings, - StdoutSeverity, -) -from .metta_loader_container_manager import MettaLoaderContainerManager -from .metta_syntax_container_manager import MettaSyntaxContainerManager + from commands.db.mongodb_container_manager import MongodbContainerManager from commands.db.redis_container_manager import RedisContainerManager +from common import Command, CommandArgument, CommandGroup, Path, Settings, StdoutSeverity from common.docker.exceptions import DockerContainerNotFoundError, DockerError +from .metta_loader_container_manager import MettaLoaderContainerManager +from .metta_syntax_container_manager import MettaSyntaxContainerManager + class MettaLoad(Command): name = "load" @@ -61,9 +57,7 @@ def run(self, path: str): services_not_running = False - metta_loader_container_manager = MettaLoaderContainerManager( - metta_container_name - ) + metta_loader_container_manager = MettaLoaderContainerManager(metta_container_name) redis_container_manager = RedisContainerManager(redis_container_name) mongodb_container_manager = MongodbContainerManager(mongodb_container_name) @@ -153,9 +147,7 @@ def validate_file(self, file_path): except IsADirectoryError: raise IsADirectoryError(f"The specified path '{file_path}' is a directory.") except FileNotFoundError: - raise FileNotFoundError( - f"The specified file path '{file_path}' does not exist." - ) + raise FileNotFoundError(f"The specified file path '{file_path}' does not exist.") except DockerError: self.stdout("Checking syntax... FAILED", severity=StdoutSeverity.ERROR) diff --git a/src/commands/metta/metta_loader_container_manager.py b/src/commands/metta/metta_loader_container_manager.py index 155d892..c0ef7b7 100644 --- a/src/commands/metta/metta_loader_container_manager.py +++ b/src/commands/metta/metta_loader_container_manager.py @@ -1,11 +1,10 @@ import os + import docker + from common import Container, ContainerManager from common.docker.exceptions import DockerContainerNotFoundError, DockerError -from config import ( - METTA_PARSER_IMAGE_NAME, - METTA_PARSER_IMAGE_VERSION, -) +from config import METTA_PARSER_IMAGE_NAME, METTA_PARSER_IMAGE_VERSION class MettaLoaderContainerManager(ContainerManager): @@ -68,9 +67,7 @@ def start_container( exit_code = self.get_container_exit_status(container) if exit_code != 0: - raise DockerError( - f"File '{os.path.basename(path)}' could not be loaded." - ) + raise DockerError(f"File '{os.path.basename(path)}' could not be loaded.") return None except docker.errors.APIError as e: diff --git a/src/commands/metta/metta_module.py b/src/commands/metta/metta_module.py index 678b4de..7da715f 100644 --- a/src/commands/metta/metta_module.py +++ b/src/commands/metta/metta_module.py @@ -1,4 +1,5 @@ from common import Module + from .metta_cli import MettaCli diff --git a/src/commands/metta/metta_syntax_container_manager.py b/src/commands/metta/metta_syntax_container_manager.py index 95fa7d6..43cf2c0 100644 --- a/src/commands/metta/metta_syntax_container_manager.py +++ b/src/commands/metta/metta_syntax_container_manager.py @@ -1,12 +1,11 @@ import os + import docker import docker.errors + from common import Container, ContainerManager from common.docker.exceptions import DockerContainerNotFoundError, DockerError -from config import ( - METTA_PARSER_IMAGE_NAME, - METTA_PARSER_IMAGE_VERSION, -) +from config import METTA_PARSER_IMAGE_NAME, METTA_PARSER_IMAGE_VERSION class MettaSyntaxContainerManager(ContainerManager): diff --git a/src/commands/python_library/__init__.py b/src/commands/python_library/__init__.py index 522be6c..9d5a390 100644 --- a/src/commands/python_library/__init__.py +++ b/src/commands/python_library/__init__.py @@ -1 +1,3 @@ from .python_library_module import PythonLibraryModule + +__all__ = ["PythonLibraryModule"] diff --git a/src/commands/python_library/python_library_cli.py b/src/commands/python_library/python_library_cli.py index 70cf466..5da5ea7 100644 --- a/src/commands/python_library/python_library_cli.py +++ b/src/commands/python_library/python_library_cli.py @@ -1,14 +1,10 @@ from enum import Enum + from injector import inject -from common import ( - Command, - CommandGroup, - CommandOption, - Choice, - StdoutSeverity, - FunctionVersion, -) -from .python_library_package import PythonLibraryPackage, PackageError + +from common import Choice, Command, CommandGroup, CommandOption, FunctionVersion, StdoutSeverity + +from .python_library_package import PackageError, PythonLibraryPackage class LibraryEnum(Enum): @@ -50,9 +46,7 @@ def get_packages_version(self) -> list: def run(self): for package, current_version, latest_version in self.get_packages_version(): - self.stdout( - f"{package}\n INSTALLED: {current_version}\n LATEST: {latest_version}" - ) + self.stdout(f"{package}\n INSTALLED: {current_version}\n LATEST: {latest_version}") class PythonLibraryList(Command): @@ -124,11 +118,9 @@ def run(self, show_patches, library): if library is not None and package != library: continue - versions = ( - self._python_library_package.get_all_major_minor_versions_from_pypi( - package, - show_patches, - ) + versions = self._python_library_package.get_all_major_minor_versions_from_pypi( + package, + show_patches, ) self.stdout( f"\n{package} available versions:\n", @@ -140,7 +132,9 @@ def run(self, show_patches, library): class PythonLibrarySet(Command): name = "set" - short_help = "Allow setting specific versions for both hyperon-das and hyperon-das-atomdb libraries" + short_help = ( + "Allow setting specific versions for both hyperon-das and hyperon-das-atomdb libraries" + ) help = """ 'das-cli python-library set' sets the versions of Python libraries, such as hyperon-das and hyperon-das-atomdb, to the specified versions. @@ -201,9 +195,7 @@ def run(self, hyperon_das, hyperon_das_atomdb): if package_version is not None: try: self.stdout(f"Updating package {package_name}...") - self._python_library_package.update_version( - package_name, package_version - ) + self._python_library_package.update_version(package_name, package_version) self.stdout( f"Package {package_name} has been successfully updated.", severity=StdoutSeverity.SUCCESS, diff --git a/src/commands/python_library/python_library_module.py b/src/commands/python_library/python_library_module.py index 1991b48..d16fd37 100644 --- a/src/commands/python_library/python_library_module.py +++ b/src/commands/python_library/python_library_module.py @@ -1,4 +1,5 @@ from common import Module + from .python_library_cli import PythonLibraryCli diff --git a/src/commands/python_library/python_library_package.py b/src/commands/python_library/python_library_package.py index b747ee6..78906fe 100644 --- a/src/commands/python_library/python_library_package.py +++ b/src/commands/python_library/python_library_package.py @@ -1,12 +1,13 @@ -import requests import re import subprocess +import requests + -class PackageError(Exception): ... +class PackageError(Exception): ... # noqa: E701 -class PackageNotFoundError(PackageError): ... +class PackageNotFoundError(PackageError): ... # noqa: E701 class PythonLibraryPackage: @@ -58,15 +59,13 @@ def get_version(self, package_name): raise PackageNotFoundError( f"Version information not found for package '{package_name}'." ) - except subprocess.CalledProcessError as e: + except subprocess.CalledProcessError: raise PackageNotFoundError(f"Package '{package_name}' is not installed.") def update_version(self, package_name, version=None): self.get_version(package_name) - pypi_package = ( - f"{package_name}=={version}" if version is not None else package_name - ) + pypi_package = f"{package_name}=={version}" if version is not None else package_name try: subprocess.run( diff --git a/src/commands/release_notes/__init__.py b/src/commands/release_notes/__init__.py index c6599ca..d06b002 100644 --- a/src/commands/release_notes/__init__.py +++ b/src/commands/release_notes/__init__.py @@ -1 +1,3 @@ from .release_notes_module import ReleaseNotesModule + +__all__ = ["ReleaseNotesModule"] diff --git a/src/commands/release_notes/release_notes_cli.py b/src/commands/release_notes/release_notes_cli.py index 29307a7..d23ce22 100644 --- a/src/commands/release_notes/release_notes_cli.py +++ b/src/commands/release_notes/release_notes_cli.py @@ -1,5 +1,7 @@ from injector import inject -from common import CommandOption, CommandGroup, StdoutSeverity + +from common import CommandGroup, CommandOption, StdoutSeverity + from .release_notes_package import ReleaseNotesPackage diff --git a/src/commands/release_notes/release_notes_module.py b/src/commands/release_notes/release_notes_module.py index ed86aa2..91d642f 100644 --- a/src/commands/release_notes/release_notes_module.py +++ b/src/commands/release_notes/release_notes_module.py @@ -1,4 +1,5 @@ from common import Module + from .release_notes_cli import ReleaseNotesCli diff --git a/src/commands/release_notes/release_notes_package.py b/src/commands/release_notes/release_notes_package.py index 3ad8334..4c84f96 100644 --- a/src/commands/release_notes/release_notes_package.py +++ b/src/commands/release_notes/release_notes_package.py @@ -1,14 +1,16 @@ import re -import requests -from config import RELEASE_NOTES_URL from typing import Union + +import requests + from common import remove_special_characters +from config import RELEASE_NOTES_URL -class ReleaseNoteError(Exception): ... +class ReleaseNoteError(Exception): ... # noqa: E701 -class ReleaseNoteNotFound(ReleaseNoteError): ... +class ReleaseNoteNotFound(ReleaseNoteError): ... # noqa: E701 class Library: diff --git a/src/common/__init__.py b/src/common/__init__.py index 18e7f0f..1a218d6 100644 --- a/src/common/__init__.py +++ b/src/common/__init__.py @@ -1,22 +1,53 @@ -from .module import Module -from .settings import Settings, JsonHandler +from click import Choice, IntRange, Path + +from . import ssh from .command import ( Command, + CommandArgument, CommandGroup, CommandOption, StdoutSeverity, StdoutType, - CommandArgument, ) -from .prompt_types import IntRange, ReachableIpAddress, Choice, FunctionVersion, Path -from .docker import RemoteContextManager, ContainerManager, Container, ImageManager +from .docker import Container, ContainerManager, ImageManager, RemoteContextManager +from .logger import logger +from .module import Module from .network import get_public_ip +from .prompt_types import FunctionVersion, ReachableIpAddress +from .settings import JsonHandler, Settings from .utils import ( + get_rand_token, get_script_name, + get_server_username, is_executable_bin, remove_special_characters, - get_server_username, - get_rand_token, ) -from .logger import logger -from . import ssh + +__all__ = [ + "ssh", + "Command", + "CommandArgument", + "CommandGroup", + "CommandOption", + "StdoutSeverity", + "StdoutType", + "Container", + "ContainerManager", + "ImageManager", + "RemoteContextManager", + "logger", + "Module", + "get_public_ip", + "Choice", + "FunctionVersion", + "IntRange", + "Path", + "ReachableIpAddress", + "JsonHandler", + "Settings", + "get_rand_token", + "get_script_name", + "get_server_username", + "is_executable_bin", + "remove_special_characters", +] diff --git a/src/common/command.py b/src/common/command.py index 0004df5..805e3e4 100644 --- a/src/common/command.py +++ b/src/common/command.py @@ -1,6 +1,8 @@ -import click -from typing import Any from enum import Enum +from typing import Any + +import click + from common.logger import logger diff --git a/src/common/docker/__init__.py b/src/common/docker/__init__.py index 7d137dd..c8437a0 100644 --- a/src/common/docker/__init__.py +++ b/src/common/docker/__init__.py @@ -1,3 +1,5 @@ -from .container_manager import ContainerManager, Container -from .remote_context_manager import RemoteContextManager +from .container_manager import Container, ContainerManager from .image_manager import ImageManager +from .remote_context_manager import RemoteContextManager + +__all__ = ["Container", "ContainerManager", "ImageManager", "RemoteContextManager"] diff --git a/src/common/docker/container_manager.py b/src/common/docker/container_manager.py index 47a432f..930c68c 100644 --- a/src/common/docker/container_manager.py +++ b/src/common/docker/container_manager.py @@ -1,14 +1,12 @@ -import docker import curses import time +from typing import Any, AnyStr, Union + +import docker import docker.errors -from typing import Any, Union, AnyStr + from .docker_manager import DockerManager -from .exceptions import ( - DockerContainerDuplicateError, - DockerError, - DockerContainerNotFoundError, -) +from .exceptions import DockerContainerDuplicateError, DockerContainerNotFoundError, DockerError class Container: @@ -86,9 +84,7 @@ def is_running(self): container_name = self._container.get_name() try: - result = self.get_docker_client().containers.list( - filters={"name": container_name} - ) + result = self.get_docker_client().containers.list(filters={"name": container_name}) return len(result) > 0 except docker.errors.APIError: @@ -112,13 +108,9 @@ def get_label(self, label: str) -> Union[dict, None]: def logs(self) -> None: try: - container = self.get_docker_client().containers.get( - self.get_container().get_name() - ) + container = self.get_docker_client().containers.get(self.get_container().get_name()) except docker.errors.NotFound: - raise DockerError( - f"Service {self.get_container().get_name()} is not running" - ) + raise DockerError(f"Service {self.get_container().get_name()} is not running") for log in container.logs(stdout=True, stderr=True, stream=True): print(log.decode("utf-8"), end="") @@ -175,7 +167,8 @@ def stop(self): try: container.kill() - except: + # TODO: better exception handling, for now do not use bare except + except Exception: pass try: @@ -208,9 +201,7 @@ def is_container_healthy(self, container): def wait_for_container(self, container, timeout=60, interval=2): elapsed_time = 0 while elapsed_time < timeout: - if self.is_container_running(container) and self.is_container_healthy( - container - ): + if self.is_container_running(container) and self.is_container_healthy(container): return True time.sleep(interval) diff --git a/src/common/docker/docker_manager.py b/src/common/docker/docker_manager.py index 919cabd..3608279 100644 --- a/src/common/docker/docker_manager.py +++ b/src/common/docker/docker_manager.py @@ -1,9 +1,8 @@ -import docker from typing import AnyStr, Union -from .exceptions import ( - DockerContextError, - DockerDaemonConnectionError, -) + +import docker + +from .exceptions import DockerContextError, DockerDaemonConnectionError class DockerManager: diff --git a/src/common/docker/exceptions.py b/src/common/docker/exceptions.py index cba7aa7..f862211 100644 --- a/src/common/docker/exceptions.py +++ b/src/common/docker/exceptions.py @@ -28,12 +28,6 @@ class DockerContainerNotFoundError(DockerError): pass -class DockerImageNotFoundError(DockerError): - """Exception raised when a specified image cannot be found.""" - - pass - - class DockerImageNotFoundError(DockerError): """Exception raised when a specified Docker image cannot be found.""" diff --git a/src/common/docker/image_manager.py b/src/common/docker/image_manager.py index 68d301e..32e7547 100644 --- a/src/common/docker/image_manager.py +++ b/src/common/docker/image_manager.py @@ -1,10 +1,9 @@ -import docker from typing import Union + +import docker + from .docker_manager import DockerManager -from .exceptions import ( - DockerImageNotFoundError, - DockerError, -) +from .exceptions import DockerError, DockerImageNotFoundError class ImageManager(DockerManager): diff --git a/src/common/docker/remote_context_manager.py b/src/common/docker/remote_context_manager.py index 25d8a83..6073581 100644 --- a/src/common/docker/remote_context_manager.py +++ b/src/common/docker/remote_context_manager.py @@ -1,5 +1,5 @@ import subprocess -from typing import List, Dict, AnyStr +from typing import AnyStr, Dict, List from uuid import uuid4 @@ -49,9 +49,7 @@ def create_context(self) -> List[AnyStr]: server_username = server.get("username") context_name = str(uuid4()) - context_description = ( - f"This context connects to {server_ip} and managed by das-cli" - ) + context_description = f"This context connects to {server_ip} and managed by das-cli" context_host = self._get_host(server_username, server_ip) context_docker = self._get_context( host=context_host, diff --git a/src/common/json_handler.py b/src/common/json_handler.py index e3bc0bc..ed92aa9 100644 --- a/src/common/json_handler.py +++ b/src/common/json_handler.py @@ -1,5 +1,5 @@ -import os import json +import os from typing import Any diff --git a/src/common/logger.py b/src/common/logger.py index 3ddb012..68477bc 100644 --- a/src/common/logger.py +++ b/src/common/logger.py @@ -1,8 +1,9 @@ import logging + from config.config import LOG_FILE_NAME -class LoggerError(Exception): ... +class LoggerError(Exception): ... # noqa: E701 class Logger: diff --git a/src/common/module.py b/src/common/module.py index d3ca059..25481c6 100644 --- a/src/common/module.py +++ b/src/common/module.py @@ -1,4 +1,5 @@ -from injector import Binder, Module as InjectorModule +from injector import Binder +from injector import Module as InjectorModule class Module(InjectorModule): diff --git a/src/common/network.py b/src/common/network.py index e4e5942..4f204c3 100644 --- a/src/common/network.py +++ b/src/common/network.py @@ -1,13 +1,15 @@ +import re import subprocess -import requests from typing import Union -import re + +import requests def get_public_ip(): try: return requests.get("https://api.ipify.org").content.decode("utf8") - except: + # TODO: better exception handler, for now do not use bare except + except Exception: return None diff --git a/src/common/prompt_types.py b/src/common/prompt_types.py index 609b85b..4c92228 100644 --- a/src/common/prompt_types.py +++ b/src/common/prompt_types.py @@ -1,17 +1,17 @@ import re -from click import IntRange, ParamType, Choice, Path -from common.network import is_server_port_available from typing import Union +from click import ParamType + +from common.network import is_server_port_available + class FunctionVersion(ParamType): name = "function version" def convert(self, value, param, ctx): if value != "latest" and not re.match(r"v?\d+\.\d+\.\d+", value): - self.fail( - "The version must follow the format x.x.x (e.g 1.10.9)", param, ctx - ) + self.fail("The version must follow the format x.x.x (e.g 1.10.9)", param, ctx) return value diff --git a/src/common/settings.py b/src/common/settings.py index c14877c..4c681f0 100644 --- a/src/common/settings.py +++ b/src/common/settings.py @@ -1,4 +1,5 @@ import os + from common.json_handler import JsonHandler from config.config import SECRETS_PATH @@ -33,13 +34,9 @@ def calculate_column_widths(current_dict, service=""): else: name = key if service else key service = service.strip(".") - column_widths["Service"] = max( - column_widths["Service"], len(service) - ) + column_widths["Service"] = max(column_widths["Service"], len(service)) column_widths["Name"] = max(column_widths["Name"], len(name)) - column_widths["Value"] = max( - column_widths["Value"], len(str(value)) - ) + column_widths["Value"] = max(column_widths["Value"], len(str(value))) calculate_column_widths(obj) diff --git a/src/common/ssh.py b/src/common/ssh.py index 38095c4..cb23c60 100644 --- a/src/common/ssh.py +++ b/src/common/ssh.py @@ -1,6 +1,7 @@ -import paramiko from typing import Union +import paramiko + class SSHConnection: def __init__(self, ssh_host, ssh_port, ssh_username, ssh_password): diff --git a/src/common/utils.py b/src/common/utils.py index aab600c..f0bbaa9 100644 --- a/src/common/utils.py +++ b/src/common/utils.py @@ -1,9 +1,9 @@ -import os -import sys +import base64 import getpass +import os import secrets -import base64 import string +import sys def is_executable_bin(): diff --git a/src/config/__init__.py b/src/config/__init__.py index 2b46fc9..6bfa362 100644 --- a/src/config/__init__.py +++ b/src/config/__init__.py @@ -1,2 +1,2 @@ -from .secrets import Secret -from .config import * +from .secrets import Secret # noqa: F401 +from .config import * # noqa: F401,F403 diff --git a/src/config/config.py b/src/config/config.py index 92d4f23..5ce7df2 100644 --- a/src/config/config.py +++ b/src/config/config.py @@ -1,10 +1,7 @@ from common.utils import get_server_username - VERSION = '0.4.0' -RELEASE_NOTES_URL = ( - "https://raw.githubusercontent.com/singnet/das/master/docs/release-notes.md" -) +RELEASE_NOTES_URL = "https://raw.githubusercontent.com/singnet/das/master/docs/release-notes.md" # PATHS diff --git a/src/config/secrets.py b/src/config/secrets.py index d454d40..43cee27 100644 --- a/src/config/secrets.py +++ b/src/config/secrets.py @@ -1,4 +1,5 @@ import os + from common.settings import JsonHandler from config.config import SECRETS_PATH diff --git a/src/das_cli.py b/src/das_cli.py index 9214457..39b6c5b 100644 --- a/src/das_cli.py +++ b/src/das_cli.py @@ -1,14 +1,15 @@ from injector import Injector + from commands.config import ConfigModule -from commands.example import ExampleModule +from commands.das import DasModule from commands.db import DbModule +from commands.example import ExampleModule from commands.faas import FaaSModule from commands.jupyter_notebook import JupyterNotebookModule -from commands.python_library import PythonLibraryModule -from commands.release_notes import ReleaseNotesModule from commands.logs import LogsModule from commands.metta import MettaModule -from commands.das import DasModule +from commands.python_library import PythonLibraryModule +from commands.release_notes import ReleaseNotesModule MODULES = [ ConfigModule, diff --git a/src/mypy.ini b/src/mypy.ini new file mode 100644 index 0000000..b907caf --- /dev/null +++ b/src/mypy.ini @@ -0,0 +1,10 @@ +[mypy] +ignore_missing_imports = true +follow_imports = silent +check_untyped_defs = true +warn_redundant_casts = true +warn_unused_ignores = true +implicit_reexport = true +show_error_context = true +namespace_packages = true +pretty = true diff --git a/src/requirements.txt b/src/requirements.txt index 7a37269..e88d3a9 100644 --- a/src/requirements.txt +++ b/src/requirements.txt @@ -6,3 +6,11 @@ fabric==3.2.2 cryptography==36.0.2 paramiko==3.4.0 injector==0.21.0 + +# Dev dependencies +flake8==6.1.0 +pylint==3.2.6 +mypy==1.10.1 +isort==5.12.0 +black==23.7.0 +pre-commit==3.5.0 diff --git a/src/setup.py b/src/setup.py index 2b29083..c6e6e89 100644 --- a/src/setup.py +++ b/src/setup.py @@ -1,4 +1,5 @@ -from setuptools import setup, find_packages +from setuptools import find_packages, setup + from config.config import VERSION setup(