diff --git a/README.md b/README.md index 99205f3..e2312b7 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,12 @@ cd src && uvicorn main:app --reload You may need to run the following additional installation `pip install git+https://github.com/SheffieldSolar/PV_Live-API#pvlive_api` for `pvlive-api`, as in the Dockerfile. -## Docker +> If you don't have a local database set up, you can leave the `DB_URL` string empty (default not set) and the API will still run and return routes such as `http://localhost:8000/` for API info and any other non-DB routes with DB dependencies e.g. session/caching commented out. +> +> You will not be able to access any routes using the DB client / database, but for local development of new routes this should work for now, until we reinstate dynamic fake data as a dependable dev tool. + +## [ Docker ] +### 🛑 Currently non-functional, needs updating to migrate database to match datamodel 1. Make sure docker is installed on your system. 2. Use `docker-compose up` @@ -62,7 +67,7 @@ as Actions when code is pushed to GitHub. You can run the formatters and linters locally. To do that: 1. [Install pre-commit](https://pre-commit.com/#install) -2. Check the install worked via `pre-commit --version` +2. Check the install worked via `pre-commit --v` 3. Install the git hooks script via `pre-commit install` # Deployment diff --git a/src/database.py b/src/database.py index a02cb1c..472810b 100644 --- a/src/database.py +++ b/src/database.py @@ -1,5 +1,6 @@ """ Functions to read from the database and format """ +import abc import os from datetime import datetime, timedelta, timezone from typing import List, Optional, Union @@ -44,7 +45,64 @@ ) from utils import filter_forecast_values, floor_30_minutes_dt, get_start_datetime -db_conn = DatabaseConnection(url=os.getenv("DB_URL", "not_set")) + +class BaseDBConnection(abc.ABC): + """This is a base class for database connections with one static method get_connection(). + + Methods + ------- + get_connection : static method + It gets the database connection. If a valid Postgresql database URL is set in + the "DB_URL" environment variable, get_connection returns an instance + of DatabaseConnection(). If not, it returns an instance of the DummyDBConnection. + """ + + @staticmethod + def get_connection(): + """ + Get the database connection. + """ + db_url = os.getenv("DB_URL") + if db_url and db_url.find("postgresql") != -1: + return DatabaseConnection(url=db_url) + else: + return DummyDBConnection() + + +class DummyDBConnection(BaseDBConnection): + """The DummyDBConnection serves as a placeholder database connection + + This might be useful when a valid Postgresql + database connection is not available. in testing or development environments. + Feel free to improve on this implementation and submit a pull request! + A better example can be found in the [india-api]( + https://github.com/openclimatefix/india-api/blob/f4e3b776194290d78e1c9702b792cbb88edf4b90/src/india_api/cmd/main.py#L12 + ) repository. + + It inherits from the BaseDBConnection class and implements the methods accordingly. + + Methods + ---------- + get_session: + Returns None for now, but should mock the session if possible, + if we keep the current DB/datamodel implementation. + """ + + def __init__(self): + """Initializes the DummyDBConnection""" + pass + + def get_session(self): + """Returns None for now, but mock the session if we keep the current implementation.""" + return None + + +def get_db_connection() -> BaseDBConnection: + """Return either the datamodel connection or a dummy connection""" + return BaseDBConnection.get_connection() + + +db_conn = get_db_connection() logger = structlog.stdlib.get_logger() diff --git a/src/national.py b/src/national.py index 09457c6..b73da1f 100644 --- a/src/national.py +++ b/src/national.py @@ -189,3 +189,28 @@ def get_national_pvlive( return get_truth_values_for_a_specific_gsp_from_database( session=session, gsp_id=0, regime=regime ) + + +@router.get( + "/bmrs", + response_model=dict, + # dependencies=[Depends(get_auth_implicit_scheme())], + summary="Get BMRS Forecast", +) +# @cache_response +@limiter.limit(f"{N_CALLS_PER_HOUR}/hour") +def get_bmrs_forecast( + request: Request, + # session: Session = Depends(get_session), + # user: Auth0User = Security(get_user()), +) -> dict: + """ + + This route returns the most recent BMRS forecast for each _target_time_. + + #### Parameters + + """ + logger.debug("Get bmrs forecast") + + return {"message": "This route is not yet implemented. Please check back later."}