def test_logging(self): string_test = "Basic string" with LogCapture() as log: log.install() logger.debug("Debug-level test") logger.error("Error-level test") logger.warning("Warning-level test") logger.info("Info-level test") logger.info(f"f-string test for {string_test}") log.check_present(("backend.global_logger", "DEBUG", "Debug-level test")) log.check_present(("backend.global_logger", "ERROR", "Error-level test")) log.check_present(("backend.global_logger", "WARNING", "Warning-level test")) log.check_present(("backend.global_logger", "INFO", "Info-level test")) log.check_present(("backend.global_logger", "INFO", "f-string test for Basic string"))
class Config(object): logger.debug("Start of the Config() class.") # Apply the environment variables when running locally # When running in GCP, these are loaded from the env_variables.yaml file when the app loads if local: from env_tools import apply_env apply_env() logger.info("Local .env variables applied.") DEBUG = True else: DEBUG = False # Load AWS credentials AWS_ACCOUNT_ID = environ.get('AWS_ACCOUNT_ID') AWS_ACCESS_KEY = environ.get('AWS_ACCESS_KEY_ID') AWS_SECRET_ACCESS_KEY = environ.get('AWS_SECRET_ACCESS_KEY') AWS_USER = environ.get('AWS_USER') AWS_REGION = environ.get('AWS_REGION') # Load app-related credentials BOUND_PORT = 5000 DOMAIN_URL = environ.get('DOMAIN_URL') WHITELISTED_ORIGIN = environ.get('WHITELISTED_ORIGIN') WHITELISTED_ORIGINS = environ.get('WHITELISTED_ORIGINS') SECRET_KEY = environ.get( 'SECRET_KEY') or '0y4TJIyEjH8ZVkXPMGBiFEcHk8tdfe57kE1IJhvR1yb1cmWY' if SECRET_KEY != environ.get('SECRET_KEY'): logger.warning( "Error loading SECRET_KEY! Temporarily using a hard-coded key.") logger.debug("End of the Config() class.")
def put(self) -> json: """Add/update the list of picklist values.""" logger.debug(f"Request: {request}") # Ensure there's a body to accompany this request if not request.data: return {'message': 'Error', 'data': 'PUT request must contain a body.'}, 400 # Load & decode the provided JSON try: data = json.loads(request.data.decode()) logger.debug(f"Data submitted: {data}") except json.JSONDecodeError as e: error_msg = f"Error attempting to decode the provided JSON." logger.debug(f"{error_msg},\n{request.data.__str__()},\n{e}") return {'message': 'Error', 'data': error_msg + f"\n{request.data.__str__()}"}, 400 except BaseException as e: error_msg = f"Unknown error attempting to parse the provided JSON.\n{e}" logger.debug(error_msg) return {'message': 'Error', 'data': error_msg}, 400 # Create a Picklist instance from the provided data try: picklist = Picklist(**data) picklist.last_modified = datetime.utcnow() logger.debug(f"Picklist instance created: {picklist}") except PynamoDBException as e: error_msg = f"Error parsing data into the Picklist model." logger.debug(f"{error_msg}\n{e}") return {'message': 'Error', 'data': f'{error_msg}\n{e}'}, 500 # Save to the database try: logger.debug(f"Saving {picklist} to the db...") picklist.save() logger.info(f"Picklist updated: {picklist.list_name})") logger.debug(f"End of PicklistApi.PUT") return {'message': 'Success', 'data': picklist.to_dict()}, 200 except Picklist.DoesNotExist: logger.debug(f"Picklist {picklist} not found.") return {'message': 'Not Found', 'data': f'Picklist {picklist} not found.'}, 404 except PynamoDBException as e: error_msg = f"Error attempting to save picklist {picklist}." logger.debug(f"{error_msg}\n{e}") return {'message': 'Error', 'data': error_msg}, 500
def delete(self, beverage_id, location) -> json: """Delete the specified beverage.""" logger.debug( f"Request: {request}, for id: {beverage_id}, loc: {location}.") # Retrieve this beverage from the database try: beverage = Beverage.get(beverage_id, location) logger.debug(f"Retrieved beverage: {beverage}") except Beverage.DoesNotExist: logger.debug(f"Beverage {beverage_id} not found.") return { 'message': 'Not Found', 'data': f'Beverage {beverage_id} not found.' }, 404 except PynamoDBException as e: error_msg = f"Error attempting to retrieve beverage {beverage_id}." logger.debug(f"{error_msg}\n{e}") return {'message': 'Error', 'data': error_msg}, 500 # Delete the specified beverage try: footprint = f"{beverage}" beverage.delete() logger.info(f"Beverage {footprint} deleted successfully.") logger.debug("End of BeverageApi.DELETE") return { 'message': 'Success', 'data': f'{footprint} deleted successfully.' }, 200 except PynamoDBException as e: error_msg = f"Error attempting to delete beverage: {beverage}." logger.debug(f"{error_msg}\n{e}") return {'message': 'Error', 'data': error_msg}, 500
from backend.global_logger import logger, local from backend.models import Beverage from data.example_data import example_data import time skipped = 0 count = 0 success = 0 errors = [] beerlist = [] # Create table if necessary if not Beverage.exists(): logger.info(f"Creating a new table: {Beverage.Meta.table_name}.") Beverage.create_table(wait=True, read_capacity_units=5, write_capacity_units=5) logger.info(f"Table created.") for item in example_data: logger.debug(f"Initializing a new Beverage for: {item}") beer = Beverage(**item) beerlist.append(beer) # logger.debug("Beverage initialized.") logger.info(f"Starting batch save for {len(beerlist)} beers.") print(f"Starting batch save for {len(beerlist)} beers.") for beer in beerlist: logger.debug(f"Saving beer #{count+1}: {beer}.") print(f"Saving beer #{count+1}: {beer.to_dict()}") beer.save()
# Logging & config from backend.global_logger import logger from backend.config import Config # External packages from flask import Flask from flask_cors import CORS from flask_restful import Api # App components from backend.cellar_routes import CellarCollectionApi, BeverageApi from backend.picklist_routes import PicklistApi app = Flask("cellarsync") logger.info(f"Flask app {app.name} created!") app.config.from_object(Config) logger.info("Applied config parameters to the app.") # Enable CORS for the app to ensure our UI can call the backend API import logging logging.getLogger('flask_cors').level = logging.DEBUG CORS(app, resources={r"/api/*": {"origins": Config.WHITELISTED_ORIGINS}}) logger.info("CORS initialized.") api = Api(app) logger.info("Flask-RESTful API initialized.") # Define the functional endpoints api.add_resource(CellarCollectionApi, '/api/v1/cellar')
def post(self) -> json: """Add a new beverage to the database based on the provided JSON.""" logger.debug(f"Request: {request}") # Ensure there's a body to accompany this request if not request.data: return { 'message': 'Error', 'data': 'POST request must contain a body.' }, 400 # Load the provided JSON try: data = json.loads(request.data.decode()) logger.debug(f"Data submitted: {type(data)}, {data}") # Replace empty strings with None for key in data.keys(): if data[key] == "": data[key] = None logger.debug(f"Data post-cleaning: {type(data)}, {data}") except json.JSONDecodeError as e: error_msg = f"Error attempting to decode the provided JSON." logger.debug(f"{error_msg},\n{request.data.__str__()},\n{e}") return { 'message': 'Error', 'data': error_msg + f"\n{request.data.__str__()}" }, 400 except BaseException as e: error_msg = f"Unknown error attempting to parse the provided JSON.\n{e}" logger.debug(error_msg) return {'message': 'Error', 'data': error_msg}, 400 # Create a new Beverage from the provided data try: new_beverage = Beverage(**data) logger.debug(f"New Beverage created: {new_beverage}") except PynamoDBException as e: error_msg = f"Error attempting to create new Beverage from: {data}." logger.debug(f"{error_msg}\nError: {e}.") return {'message': 'Error', 'data': error_msg}, 500 except BaseException as e: error_msg = f"Unknown error creating a new Beverage from: {data}." logger.debug(f"{error_msg}\n{e}.") return {'message': 'Error', 'data': error_msg}, 500 # Write this Beverage to the database try: logger.debug( f"Attempting to save Beverage {new_beverage} to the database.") new_beverage.save() logger.info(f"Successfully saved {new_beverage}.") logger.debug(f"End of CellarCollectionApi.POST") return { 'message': 'Created', 'data': new_beverage.to_dict(dates_as_epoch=True) }, 201 except PynamoDBException as e: error_msg = f"Error attempting to save new beverage." logger.debug(f"{error_msg}\n{new_beverage}: {e}.") return {'message': 'Error', 'data': error_msg}, 500
def put(self, beverage_id, location) -> json: """Update the specified beverage.""" logger.debug( f"Request: {request}, for id: {beverage_id}, loc: {location}.") # Ensure there's a body to accompany this request if not request.data: return { 'message': 'Error', 'data': 'PUT request must contain a body.' }, 400 # Load & decode the provided JSON try: data = json.loads(request.data.decode()) logger.debug(f"Data submitted: {data}") except json.JSONDecodeError as e: error_msg = f"Error attempting to decode the provided JSON." logger.debug(f"{error_msg},\n{request.data.__str__()},\n{e}") return { 'message': 'Error', 'data': error_msg + f"\n{request.data.__str__()}" }, 400 except BaseException as e: error_msg = f"Unknown error attempting to parse the provided JSON.\n{e}" logger.debug(error_msg) return {'message': 'Error', 'data': error_msg}, 400 # Ensure the variables provided to the endpoint match the body details. if str(beverage_id) != str(data['beverage_id']): error_msg = f"/beverage_id provided to the endpoint ({beverage_id}) " \ f"doesn't match the beverage_id from the body ({data['beverage_id']})." logger.debug(f"{error_msg}") return {'message': 'Error', 'data': error_msg}, 400 elif str(location) != str(data['location']): error_msg = f"/location provided to the endpoint ({location}) " \ f"doesn't match the location from the body ({data['location']})." logger.debug(f"{error_msg}") return {'message': 'Error', 'data': error_msg}, 400 # Create a Beverage instance from the provided data try: beverage = Beverage(**data) beverage.last_modified = datetime.utcnow() logger.debug(f"Beverage instance created: {beverage}") except PynamoDBException as e: error_msg = f"Error parsing data into the Beverage model." logger.debug(f"{error_msg}\n{e}") return {'message': 'Error', 'data': f'{error_msg}\n{e}'}, 500 # Save to the database try: logger.debug(f"Saving {beverage} to the db...") beverage.save() logger.info(f"Beverage updated: {beverage})") logger.debug(f"End of BeverageApi.PUT") return { 'message': 'Success', 'data': beverage.to_dict(dates_as_epoch=True) }, 200 except Beverage.DoesNotExist: logger.debug(f"Beverage {beverage_id} not found.") return { 'message': 'Not Found', 'data': f'Beverage {beverage_id} not found.' }, 404 except PynamoDBException as e: error_msg = f"Error attempting to save beverage {beverage_id}." logger.debug(f"{error_msg}\n{e}") return {'message': 'Error', 'data': error_msg}, 500