Skip to content

Commit

Permalink
#150: Move Flask/API setup into functions
Browse files Browse the repository at this point in the history
- This will help to specify whether a unit test should use the db or python_icat backend, to be fully implemented in future commits
  • Loading branch information
MRichards99 committed Nov 30, 2020
1 parent 2c37baa commit 64f9981
Showing 1 changed file with 88 additions and 71 deletions.
159 changes: 88 additions & 71 deletions datagateway_api/src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from flask_restful import Api
from flask_swagger_ui import get_swaggerui_blueprint

from datagateway_api.common.backends import create_backend
from datagateway_api.common.config import config
from datagateway_api.common.exceptions import ApiError
from datagateway_api.common.logger_setup import setup_logger
Expand All @@ -28,95 +29,108 @@
from datagateway_api.src.swagger.apispec_flask_restful import RestfulPlugin
from datagateway_api.src.swagger.initialise_spec import initialise_spec


spec = APISpec(
title="DataGateway API",
version="1.0",
openapi_version="3.0.3",
plugins=[RestfulPlugin()],
security=[{"session_id": []}],
)
setup_logger()
log = logging.getLogger()
log.info("Logging now setup")

app = Flask(__name__)
cors = CORS(app)
app.url_map.strict_slashes = False
api = Api(app)


def handle_error(e):
return str(e), e.status_code


app.register_error_handler(ApiError, handle_error)


swaggerui_blueprint = get_swaggerui_blueprint(
"", "/openapi.json", config={"app_name": "DataGateway API OpenAPI Spec"},
)

app.register_blueprint(swaggerui_blueprint, url_prefix="/")

setup_logger()
log = logging.getLogger()
log.info("Logging now setup")

initialise_spec(spec)
def create_app_infrastructure(app):
spec = APISpec(
title="DataGateway API",
version="1.0",
openapi_version="3.0.3",
plugins=[RestfulPlugin()],
security=[{"session_id": []}],
)

for entity_name in endpoints:
get_endpoint_resource = get_endpoint(entity_name, endpoints[entity_name])
api.add_resource(get_endpoint_resource, f"/{entity_name.lower()}")
spec.path(resource=get_endpoint_resource, api=api)
cors = CORS(app)
app.url_map.strict_slashes = False
api = Api(app)

get_id_endpoint_resource = get_id_endpoint(entity_name, endpoints[entity_name])
api.add_resource(get_id_endpoint_resource, f"/{entity_name.lower()}/<int:id_>")
spec.path(resource=get_id_endpoint_resource, api=api)
app.register_error_handler(ApiError, handle_error)

get_count_endpoint_resource = get_count_endpoint(
entity_name, endpoints[entity_name],
)
api.add_resource(get_count_endpoint_resource, f"/{entity_name.lower()}/count")
spec.path(resource=get_count_endpoint_resource, api=api)
initialise_spec(spec)

get_find_one_endpoint_resource = get_find_one_endpoint(
entity_name, endpoints[entity_name],
)
api.add_resource(get_find_one_endpoint_resource, f"/{entity_name.lower()}/findone")
spec.path(resource=get_find_one_endpoint_resource, api=api)
return (api, spec)


# Session endpoint
api.add_resource(Sessions, "/sessions")
spec.path(resource=Sessions, api=api)
def handle_error(e):
return str(e), e.status_code


def create_api_endpoints(app, api, spec):
try:
backend_type = app.config["TEST_BACKEND"]
except KeyError:
backend_type = config.get_backend_type()

backend = create_backend(backend_type)

for entity_name in endpoints:
get_endpoint_resource = get_endpoint(entity_name, endpoints[entity_name])
api.add_resource(get_endpoint_resource, f"/{entity_name.lower()}")
spec.path(resource=get_endpoint_resource, api=api)

get_id_endpoint_resource = get_id_endpoint(entity_name, endpoints[entity_name])
api.add_resource(get_id_endpoint_resource, f"/{entity_name.lower()}/<int:id_>")
spec.path(resource=get_id_endpoint_resource, api=api)

get_count_endpoint_resource = get_count_endpoint(
entity_name, endpoints[entity_name],
)
api.add_resource(get_count_endpoint_resource, f"/{entity_name.lower()}/count")
spec.path(resource=get_count_endpoint_resource, api=api)

get_find_one_endpoint_resource = get_find_one_endpoint(
entity_name, endpoints[entity_name],
)
api.add_resource(
get_find_one_endpoint_resource, f"/{entity_name.lower()}/findone"
)
spec.path(resource=get_find_one_endpoint_resource, api=api)

# Session endpoint
api.add_resource(Sessions, "/sessions")
spec.path(resource=Sessions, api=api)

# Table specific endpoints
api.add_resource(InstrumentsFacilityCycles, "/instruments/<int:id_>/facilitycycles")
spec.path(resource=InstrumentsFacilityCycles, api=api)
api.add_resource(
InstrumentsFacilityCyclesCount, "/instruments/<int:id_>/facilitycycles/count",
)
spec.path(resource=InstrumentsFacilityCyclesCount, api=api)
api.add_resource(
InstrumentsFacilityCyclesInvestigations,
"/instruments/<int:instrument_id>/facilitycycles/<int:cycle_id>/investigations",
)
spec.path(resource=InstrumentsFacilityCyclesInvestigations, api=api)
api.add_resource(
InstrumentsFacilityCyclesInvestigationsCount,
"/instruments/<int:instrument_id>/facilitycycles/<int:cycle_id>/investigations"
"/count",
)
spec.path(resource=InstrumentsFacilityCyclesInvestigationsCount, api=api)

# Table specific endpoints
api.add_resource(InstrumentsFacilityCycles, "/instruments/<int:id_>/facilitycycles")
spec.path(resource=InstrumentsFacilityCycles, api=api)
api.add_resource(
InstrumentsFacilityCyclesCount, "/instruments/<int:id_>/facilitycycles/count",
)
spec.path(resource=InstrumentsFacilityCyclesCount, api=api)
api.add_resource(
InstrumentsFacilityCyclesInvestigations,
"/instruments/<int:instrument_id>/facilitycycles/<int:cycle_id>/investigations",
)
spec.path(resource=InstrumentsFacilityCyclesInvestigations, api=api)
api.add_resource(
InstrumentsFacilityCyclesInvestigationsCount,
"/instruments/<int:instrument_id>/facilitycycles/<int:cycle_id>/investigations"
"/count",
)
spec.path(resource=InstrumentsFacilityCyclesInvestigationsCount, api=api)

# Reorder paths (e.g. get, patch, post) so openapi.yaml only changes when there's a
# change to the Swagger docs, rather than changing on each startup
log.debug("Reordering OpenAPI docs to alphabetical order")
for entity_data in spec._paths.values():
for endpoint_name in sorted(entity_data.keys()):
entity_data.move_to_end(endpoint_name)
def openapi_config(spec):
# Reorder paths (e.g. get, patch, post) so openapi.yaml only changes when there's a
# change to the Swagger docs, rather than changing on each startup
log.debug("Reordering OpenAPI docs to alphabetical order")
for entity_data in spec._paths.values():
for endpoint_name in sorted(entity_data.keys()):
entity_data.move_to_end(endpoint_name)

openapi_spec_path = Path(__file__).parent / "swagger/openapi.yaml"
with open(openapi_spec_path, "w") as f:
f.write(spec.to_yaml())
openapi_spec_path = Path(__file__).parent / "swagger/openapi.yaml"
with open(openapi_spec_path, "w") as f:
f.write(spec.to_yaml())


@app.route("/openapi.json")
Expand All @@ -127,6 +141,9 @@ def specs():


if __name__ == "__main__":
api, spec = create_app_infrastructure()
create_api_endpoints(app, api, spec)
openapi_config(spec)
app.run(
host=config.get_host(), port=config.get_port(), debug=config.is_debug_mode(),
)

0 comments on commit 64f9981

Please sign in to comment.