From 519b2f52c9a0b2c76af225467dbfd6d02b7e2058 Mon Sep 17 00:00:00 2001 From: David Karchmer Date: Sun, 20 Aug 2023 12:45:25 -0700 Subject: [PATCH] Add BaseFacade static class to allow access to API from anywhere (#15) * Add Facade to allow for access to API and options * Set version to 0.8.0 --- CHANGELOG.md | 5 +++ drf_client/helpers/base_facade.py | 25 +++++++++++++ drf_client/helpers/base_main.py | 59 ++++++++++++++++++------------- setup.py | 4 +-- tests/helpers.py | 15 ++++++++ tox.ini | 2 +- 6 files changed, 82 insertions(+), 28 deletions(-) create mode 100644 drf_client/helpers/base_facade.py create mode 100644 tests/helpers.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 5357ca6..e2d8f54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +### v0.9.0 (2023-08-20) + + * Add isort and Black as formatter + * Add static BaseFacade class to allow access to API class and BaseMain options + ### v0.8.0 (2023-07-04) * Remove support for Python 3.8. diff --git a/drf_client/helpers/base_facade.py b/drf_client/helpers/base_facade.py new file mode 100644 index 0000000..c4351b1 --- /dev/null +++ b/drf_client/helpers/base_facade.py @@ -0,0 +1,25 @@ +"""Hold static information that can be accessed by any part of the package. + +A facade is an object that serves as a front-facing interface masking more complex +underlying or structural code. +""" +from argparse import Namespace + +from drf_client.connection import Api as RestApi + + +class BaseFacade: + """Stores key static information used across the package.""" + + api: RestApi or None = None + api_options: dict or None = None + cmd_args: Namespace or None = None + + @staticmethod + def initialize_api(api_options: dict, cmd_args: Namespace = None): + """Initialize API with the given options.""" + if BaseFacade.api is None: + # Only initialize ones + BaseFacade.api_options = api_options.copy() + BaseFacade.api = RestApi(api_options) + BaseFacade.cmd_args = cmd_args diff --git a/drf_client/helpers/base_main.py b/drf_client/helpers/base_main.py index a247306..b588aeb 100644 --- a/drf_client/helpers/base_main.py +++ b/drf_client/helpers/base_main.py @@ -1,12 +1,10 @@ -import sys -import logging import argparse import getpass - +import logging +import sys from urllib.parse import urlparse -from drf_client.connection import Api as RestApi, DEFAULT_HEADERS -from drf_client.exceptions import HttpClientError +from .facade import Facade LOG = logging.getLogger(__name__) @@ -16,14 +14,14 @@ class BaseMain: args = None api = None options = { - 'DOMAIN': None, - 'API_PREFIX': 'api/v1', - 'TOKEN_TYPE': 'jwt', - 'TOKEN_FORMAT': 'JWT {token}', - 'USERNAME_KEY': 'username', - 'LOGIN': 'auth/login/', - 'LOGOUT': 'auth/logout/', - 'USE_DASHES': False, + "DOMAIN": None, + "API_PREFIX": "api/v1", + "TOKEN_TYPE": "jwt", + "TOKEN_FORMAT": "JWT {token}", + "USERNAME_KEY": "username", + "LOGIN": "auth/login/", + "LOGOUT": "auth/logout/", + "USE_DASHES": False, } logging_level = logging.INFO @@ -38,12 +36,19 @@ def __init__(self): """ self.parser = argparse.ArgumentParser(description=__doc__) self.parser.add_argument( - '-u', '--user', dest='username', type=str, required=True, - help='Username used for login' + "-u", + "--user", + dest="username", + type=str, + required=True, + help="Username used for login", ) self.parser.add_argument( - '--server', dest='server', type=str, required=True, - help='Server Domain Name to use' + "--server", + dest="server", + type=str, + required=True, + help="Server Domain Name to use", ) self.add_extra_args() @@ -64,7 +69,9 @@ def main(self): 4. Call after_loging to do actual work with server data """ self.domain = self.get_domain() - self.api = RestApi(self.get_options()) + # Create a static pointer to the API for global access + Facade.initialize_api(options=self.get_options(), args=self.args) + self.api = Facade.api self.before_login() ok = self.login() if ok: @@ -75,7 +82,7 @@ def main(self): def get_options(self): options = self.options - options['DOMAIN'] = self.domain + options["DOMAIN"] = self.domain return options def config_logging(self): @@ -83,9 +90,11 @@ def config_logging(self): Overwrite to change the way the logging package is configured :return: Nothing """ - logging.basicConfig(level=self.logging_level, - format='[%(asctime)-15s] %(levelname)-6s %(message)s', - datefmt='%d/%b/%Y %H:%M:%S') + logging.basicConfig( + level=self.logging_level, + format="[%(asctime)-15s] %(levelname)-6s %(message)s", + datefmt="%d/%b/%Y %H:%M:%S", + ) def add_extra_args(self): """ @@ -99,7 +108,7 @@ def get_domain(self) -> str: Figure out server domain URL based on --server and --customer args """ if not urlparse(self.args.server).scheme: - return f'https://{self.args.server}' + return f"https://{self.args.server}" return self.args.server def login(self) -> bool: @@ -109,7 +118,7 @@ def login(self) -> bool: password = getpass.getpass() ok = self.api.login(username=self.args.username, password=password) if ok: - LOG.info('Welcome {0}'.format(self.args.username)) + LOG.info("Welcome {0}".format(self.args.username)) return ok def before_login(self): @@ -125,4 +134,4 @@ def after_login(self): This function MUST be overwritten to do actual work after logging into the Server :return: Nothing """ - LOG.warning('No actual work done') + LOG.warning("No actual work done") diff --git a/setup.py b/setup.py index bfaf372..344a627 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ import pathlib -from setuptools import find_packages, setup +from setuptools import setup # The directory containing this file HERE = pathlib.Path(__file__).parent @@ -10,7 +10,7 @@ setup( name="django-rest-framework-client", - version="0.8.0", + version="0.9.0", description="Python client for a DjangoRestFramework based web site", long_description=README, long_description_content_type="text/markdown", diff --git a/tests/helpers.py b/tests/helpers.py new file mode 100644 index 0000000..139130e --- /dev/null +++ b/tests/helpers.py @@ -0,0 +1,15 @@ +"""test Resource class.""" +import argparse +import unittest + +from drf_client.helpers.base_facade import BaseFacade + + +class FacadeTestCase(unittest.TestCase): + """Test static facade class.""" + + def test_initialize_facade(self): + """Test Initializer.""" + BaseFacade.initialize_api({"DOMAIN": "https://example.com"}) + assert BaseFacade.api_options["DOMAIN"] == "https://example.com" + assert BaseFacade.api is not None diff --git a/tox.ini b/tox.ini index fc79e29..ede7769 100644 --- a/tox.ini +++ b/tox.ini @@ -4,7 +4,7 @@ # and then run "tox" from this directory. [tox] -envlist = py39, py310 +envlist = py310, py311 [testenv] deps =