diff --git a/CHANGELOG.md b/CHANGELOG.md index 2fc6d826..decdd6cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ +## v3.1.0 (2021-12-06) +### Feature +* Implement session/client handling for search API #258 ([`46a1539`](https://github.com/ral-facilities/datagateway-api/commit/46a1539398f63e9c8a6539d703a164dd7c8749e7)) + ## v3.0.1 (2021-11-24) ### Fix * Allow blank extensions and slash extension to be valid ([`70ddb7a`](https://github.com/ral-facilities/datagateway-api/commit/70ddb7a4fd89ba10b06cd71c3ab2a98648cfb773)) diff --git a/datagateway_api/config.json.example b/datagateway_api/config.json.example index a82f1c4c..3cce6d58 100644 --- a/datagateway_api/config.json.example +++ b/datagateway_api/config.json.example @@ -12,9 +12,7 @@ "search_api": { "extension": "/search-api", "icat_url": "https://localhost:8181", - "icat_check_cert": false, - "client_pool_init_size": 2, - "client_pool_max_size": 5 + "icat_check_cert": false }, "flask_reloader": false, "log_level": "WARN", diff --git a/datagateway_api/src/api_start_utils.py b/datagateway_api/src/api_start_utils.py index 2991bd25..ebcd7cca 100644 --- a/datagateway_api/src/api_start_utils.py +++ b/datagateway_api/src/api_start_utils.py @@ -7,12 +7,12 @@ from flask_restful import Api from flask_swagger_ui import get_swaggerui_blueprint -from datagateway_api.src.common.config import config +from datagateway_api.src.common.config import Config # Only attempt to create a DataGateway API backend if the datagateway_api object # is present in the config. This ensures that the API does not error on startup # due to an AttributeError exception being thrown if the object is missing. -if config.datagateway_api is not None: +if Config.config.datagateway_api is not None: from datagateway_api.src.datagateway_api.backends import create_backend from datagateway_api.src.datagateway_api.database.helpers import db # noqa: I202 from datagateway_api.src.datagateway_api.icat.icat_client_pool import create_client_pool @@ -73,15 +73,17 @@ def create_app_infrastructure(flask_app): flask_app.url_map.strict_slashes = False api = CustomErrorHandledApi(flask_app) - if config.datagateway_api is not None: + if Config.config.datagateway_api is not None: try: backend_type = flask_app.config["TEST_BACKEND"] - config.datagateway_api.set_backend_type(backend_type) + Config.config.datagateway_api.set_backend_type(backend_type) except KeyError: - backend_type = config.datagateway_api.backend + backend_type = Config.config.datagateway_api.backend if backend_type == "db": - flask_app.config["SQLALCHEMY_DATABASE_URI"] = config.datagateway_api.db_url + flask_app.config[ + "SQLALCHEMY_DATABASE_URI" + ] = Config.config.datagateway_api.db_url flask_app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False db.init_app(flask_app) @@ -92,12 +94,12 @@ def create_app_infrastructure(flask_app): def create_api_endpoints(flask_app, api, spec): # DataGateway API endpoints - if config.datagateway_api is not None: + if Config.config.datagateway_api is not None: try: backend_type = flask_app.config["TEST_BACKEND"] - config.datagateway_api.set_backend_type(backend_type) + Config.config.datagateway_api.set_backend_type(backend_type) except KeyError: - backend_type = config.datagateway_api.backend + backend_type = Config.config.datagateway_api.backend backend = create_backend(backend_type) @@ -106,7 +108,7 @@ def create_api_endpoints(flask_app, api, spec): # Create client pool icat_client_pool = create_client_pool() - datagateway_api_extension = config.datagateway_api.extension + datagateway_api_extension = Config.config.datagateway_api.extension for entity_name in endpoints: get_endpoint_resource = get_endpoint( entity_name, @@ -220,8 +222,8 @@ def create_api_endpoints(flask_app, api, spec): spec.path(resource=ping_resource, api=api) # Search API endpoints - if config.search_api is not None: - search_api_extension = config.search_api.extension + if Config.config.search_api is not None: + search_api_extension = Config.config.search_api.extension search_api_entity_endpoints = ["datasets", "documents", "instruments"] for entity_name in search_api_entity_endpoints: @@ -271,7 +273,7 @@ def create_api_endpoints(flask_app, api, spec): 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 - if config.generate_swagger: + if Config.config.generate_swagger: log.debug("Reordering OpenAPI docs to alphabetical order") for entity_data in spec._paths.values(): for endpoint_name in sorted(entity_data.keys()): diff --git a/datagateway_api/src/common/config.py b/datagateway_api/src/common/config.py index 40cfe6ea..e4835cd3 100644 --- a/datagateway_api/src/common/config.py +++ b/datagateway_api/src/common/config.py @@ -127,8 +127,6 @@ class SearchAPI(BaseModel): validation of the SearchAPI config data using Python type annotations. """ - client_pool_init_size: StrictInt - client_pool_max_size: StrictInt extension: StrictStr icat_check_cert: StrictBool icat_url: StrictStr @@ -216,4 +214,7 @@ def validate_api_extensions(cls, value, values): # noqa: B902, N805 return value -config = APIConfig.load() +class Config: + """Class containing config as a class variable so it can mocked during testing""" + + config = APIConfig.load() diff --git a/datagateway_api/src/common/logger_setup.py b/datagateway_api/src/common/logger_setup.py index ffafc03c..e53811cf 100644 --- a/datagateway_api/src/common/logger_setup.py +++ b/datagateway_api/src/common/logger_setup.py @@ -1,9 +1,9 @@ import logging.config from pathlib import Path -from datagateway_api.src.common.config import config +from datagateway_api.src.common.config import Config -LOG_FILE_NAME = Path(config.log_location) +LOG_FILE_NAME = Path(Config.config.log_location) logger_config = { "version": 1, "formatters": { @@ -14,7 +14,7 @@ }, "handlers": { "default": { - "level": config.log_level, + "level": Config.config.log_level, "formatter": "default", "class": "logging.handlers.RotatingFileHandler", "filename": LOG_FILE_NAME, @@ -22,7 +22,7 @@ "backupCount": 10, }, }, - "root": {"level": config.log_level, "handlers": ["default"]}, + "root": {"level": Config.config.log_level, "handlers": ["default"]}, } diff --git a/datagateway_api/src/datagateway_api/icat/filters.py b/datagateway_api/src/datagateway_api/icat/filters.py index 6a74a559..bf69f3f0 100644 --- a/datagateway_api/src/datagateway_api/icat/filters.py +++ b/datagateway_api/src/datagateway_api/icat/filters.py @@ -1,6 +1,6 @@ import logging -from datagateway_api.src.common.config import config +from datagateway_api.src.common.config import Config from datagateway_api.src.common.exceptions import FilterError from datagateway_api.src.common.filters import ( DistinctFieldFilter, @@ -217,13 +217,14 @@ def __init__(self, skip_value, filter_use="datagateway_api"): def apply_filter(self, query): if self.filter_use == "datagateway_api": icat_properties = get_icat_properties( - config.datagateway_api.icat_url, config.datagateway_api.icat_check_cert, + Config.config.datagateway_api.icat_url, + Config.config.datagateway_api.icat_check_cert, ) else: icat_properties = get_icat_properties( - config.search_api.icat_url, config.search_api.icat_check_cert, + Config.config.search_api.icat_url, + Config.config.search_api.icat_check_cert, ) - icat_set_limit(query, self.skip_value, icat_properties["maxEntities"]) diff --git a/datagateway_api/src/datagateway_api/icat/icat_client_pool.py b/datagateway_api/src/datagateway_api/icat/icat_client_pool.py index 9d81a86b..4801c04e 100644 --- a/datagateway_api/src/datagateway_api/icat/icat_client_pool.py +++ b/datagateway_api/src/datagateway_api/icat/icat_client_pool.py @@ -3,7 +3,7 @@ from icat.client import Client from object_pool import ObjectPool -from datagateway_api.src.common.config import config +from datagateway_api.src.common.config import Config log = logging.getLogger() @@ -11,11 +11,16 @@ class ICATClient(Client): """Wrapper class to allow an object pool of client objects to be created""" - def __init__(self): - super().__init__( - config.datagateway_api.icat_url, - checkCert=config.datagateway_api.icat_check_cert, - ) + def __init__(self, client_use="datagateway_api"): + if client_use == "datagateway_api": + icat_url = Config.config.datagateway_api.icat_url + icat_check_cert = Config.config.datagateway_api.icat_check_cert + else: + # Search API use cases + icat_url = Config.config.search_api.icat_url + icat_check_cert = Config.config.search_api.icat_check_cert + + super().__init__(icat_url, checkCert=icat_check_cert) # When clients are cleaned up, sessions won't be logged out self.autoLogout = False @@ -36,8 +41,8 @@ def create_client_pool(): return ObjectPool( ICATClient, - min_init=config.datagateway_api.client_pool_init_size, - max_capacity=config.datagateway_api.client_pool_max_size, + min_init=Config.config.datagateway_api.client_pool_init_size, + max_capacity=Config.config.datagateway_api.client_pool_max_size, max_reusable=0, expires=0, ) diff --git a/datagateway_api/src/datagateway_api/icat/lru_cache.py b/datagateway_api/src/datagateway_api/icat/lru_cache.py index 272d9019..d3c37431 100644 --- a/datagateway_api/src/datagateway_api/icat/lru_cache.py +++ b/datagateway_api/src/datagateway_api/icat/lru_cache.py @@ -2,7 +2,7 @@ from cachetools.lru import LRUCache -from datagateway_api.src.common.config import config +from datagateway_api.src.common.config import Config log = logging.getLogger() @@ -19,7 +19,7 @@ class ExtendedLRUCache(LRUCache): """ def __init__(self): - super().__init__(maxsize=config.datagateway_api.client_cache_size) + super().__init__(maxsize=Config.config.datagateway_api.client_cache_size) def popitem(self): key, client = super().popitem() diff --git a/datagateway_api/src/datagateway_api/query_filter_factory.py b/datagateway_api/src/datagateway_api/query_filter_factory.py index 7245f378..65e744a5 100644 --- a/datagateway_api/src/datagateway_api/query_filter_factory.py +++ b/datagateway_api/src/datagateway_api/query_filter_factory.py @@ -1,6 +1,6 @@ import logging -from datagateway_api.src.common.config import config +from datagateway_api.src.common.config import Config from datagateway_api.src.common.exceptions import ( ApiError, FilterError, @@ -27,7 +27,7 @@ def get_query_filter(request_filter): :raises FilterError: If the filter name is not recognised """ - backend_type = config.datagateway_api.backend + backend_type = Config.config.datagateway_api.backend if backend_type == "db": from datagateway_api.src.datagateway_api.database.filters import ( DatabaseDistinctFieldFilter as DistinctFieldFilter, diff --git a/datagateway_api/src/main.py b/datagateway_api/src/main.py index d5b98c00..b90ea9c2 100644 --- a/datagateway_api/src/main.py +++ b/datagateway_api/src/main.py @@ -8,7 +8,7 @@ create_openapi_endpoint, openapi_config, ) -from datagateway_api.src.common.config import config +from datagateway_api.src.common.config import Config from datagateway_api.src.common.logger_setup import setup_logger setup_logger() @@ -23,8 +23,8 @@ if __name__ == "__main__": app.run( - host=config.host, - port=config.port, - debug=config.debug_mode, - use_reloader=config.flask_reloader, + host=Config.config.host, + port=Config.config.port, + debug=Config.config.debug_mode, + use_reloader=Config.config.flask_reloader, ) diff --git a/datagateway_api/src/resources/search_api_endpoints.py b/datagateway_api/src/resources/search_api_endpoints.py index 07c2aa85..282e99e7 100644 --- a/datagateway_api/src/resources/search_api_endpoints.py +++ b/datagateway_api/src/resources/search_api_endpoints.py @@ -1,9 +1,14 @@ from flask_restful import Resource +from datagateway_api.src.search_api.helpers import ( + get_count, + get_files, + get_files_count, + get_search, + get_with_id, +) + -# TODO - Might need kwargs on get_search_endpoint(), get_single_endpoint(), -# get_number_count_endpoint(), get_files_endpoint(), get_number_count_files_endpoint() -# for client handling? def get_search_endpoint(name): """ TODO - Add docstring @@ -11,19 +16,7 @@ def get_search_endpoint(name): class Endpoint(Resource): def get(self): - """ - TODO - Need to return similar to - return ( - backend.get_with_filters( - get_session_id_from_auth_header(), - entity_type, - get_filters_from_query_string(), - **kwargs, - ), - 200, - ) - """ - pass + return get_search(name), 200 # TODO - Add `get.__doc__` @@ -38,8 +31,7 @@ def get_single_endpoint(name): class EndpointWithID(Resource): def get(self, pid): - # TODO - Add return - pass + return get_with_id(name, pid), 200 # TODO - Add `get.__doc__` @@ -54,8 +46,7 @@ def get_number_count_endpoint(name): class CountEndpoint(Resource): def get(self): - # TODO - Add return - pass + return get_count(name), 200 # TODO - Add `get.__doc__` @@ -70,8 +61,7 @@ def get_files_endpoint(name): class FilesEndpoint(Resource): def get(self, pid): - # TODO - Add return - pass + return get_files(name), 200 # TODO - Add `get.__doc__` @@ -86,8 +76,7 @@ def get_number_count_files_endpoint(name): class CountFilesEndpoint(Resource): def get(self, pid): - # TODO - Add return - pass + return get_files_count(name, pid) # TODO - Add `get.__doc__` diff --git a/datagateway_api/src/search_api/helpers.py b/datagateway_api/src/search_api/helpers.py index ca6a72a5..1a607a2c 100644 --- a/datagateway_api/src/search_api/helpers.py +++ b/datagateway_api/src/search_api/helpers.py @@ -1,3 +1,38 @@ -""" -Code to store helper functions to deal with the endpoints, like for DataGateway API -""" +import logging + +from datagateway_api.src.search_api.session_handler import ( + client_manager, + SessionHandler, +) + + +log = logging.getLogger() + + +# TODO - Make filters mandatory, if no filters are in a request an empty list will be +# given to these functions +@client_manager +def get_search(entity_name, filters=None): + # TODO - `getApiVersion()` used as a placeholder for testing client handling + # Replace with endpoint functionality when implementing the endpoints + return SessionHandler.client.getApiVersion() + + +@client_manager +def get_with_id(entity_name, id_, filters=None): + pass + + +@client_manager +def get_count(entity_name, filters=None): + pass + + +@client_manager +def get_files(entity_name, filters=None): + pass + + +@client_manager +def get_files_count(entity_name, id_, filters=None): + pass diff --git a/datagateway_api/src/search_api/session_handler.py b/datagateway_api/src/search_api/session_handler.py index 5666e40a..8367a480 100644 --- a/datagateway_api/src/search_api/session_handler.py +++ b/datagateway_api/src/search_api/session_handler.py @@ -1,20 +1,40 @@ -# TODO - can we enforce a singleton pattern on the class? -class SessionHandler: - def __init__(self): - self.client = None - self.session_id = None +from functools import wraps +import logging + +from icat.exception import ICATSessionError + +from datagateway_api.src.datagateway_api.icat.icat_client_pool import ICATClient +log = logging.getLogger() -def requires_session_id(method): + +class SessionHandler: + """ + Class to store Python ICAT client to be used within the search API. As the API + requires no authentication, the same client object can be used which logs in as the + anon user """ - TODO + + client = ICATClient(client_use="search_api") + + +def client_manager(method): """ - pass + Decorator to manage the client object at the beginning of each request. This + decorator checks if the client has a valid session, and if not, logs in as the anon + user + :param method: The function used to process an incoming request """ + @wraps(method) - def wrapper_requires_session(*args, **kwargs): - pass + def wrapper_client_manager(*args, **kwargs): + try: + SessionHandler.client.getRemainingMinutes() + except ICATSessionError as e: + log.debug("Current client session expired: %s", e.args) + SessionHandler.client.login("anon", {}) - return wrapper_requires_session - """ + return method(*args, **kwargs) + + return wrapper_client_manager diff --git a/pyproject.toml b/pyproject.toml index bce6fa47..b2c3b46e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "datagateway-api" -version = "3.0.1" +version = "3.1.0" description = "ICAT API to interface with the DataGateway" license = "Apache-2.0" readme = "README.md" diff --git a/test/conftest.py b/test/conftest.py index 9bf0fc90..83b2ab1a 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -1,4 +1,6 @@ from datetime import datetime, timedelta +import json +from unittest.mock import mock_open, patch from flask import Flask import pytest @@ -7,6 +9,7 @@ create_api_endpoints, create_app_infrastructure, ) +from datagateway_api.src.common.config import APIConfig from datagateway_api.src.datagateway_api.database.helpers import ( delete_row_by_id, insert_row_into_table, @@ -63,3 +66,39 @@ def valid_db_credentials_header(): yield {"Authorization": f"Bearer {session.id}"} delete_row_by_id(SESSION, "Test") + + +@pytest.fixture() +def test_config_data(): + return { + "datagateway_api": { + "extension": "/datagateway-api", + "backend": "db", + "client_cache_size": 5, + "client_pool_init_size": 2, + "client_pool_max_size": 5, + "db_url": "mysql+pymysql://icatdbuser:icatdbuserpw@localhost:3306/icatdb", + "icat_url": "https://localhost:8181", + "icat_check_cert": False, + }, + "search_api": { + "extension": "/search-api", + "icat_url": "https://localhost.testdomain:8181", + "icat_check_cert": True, + }, + "flask_reloader": False, + "log_level": "WARN", + "log_location": "/home/runner/work/datagateway-api/datagateway-api/logs.log", + "debug_mode": False, + "generate_swagger": False, + "host": "127.0.0.1", + "port": "5000", + "test_user_credentials": {"username": "root", "password": "pw"}, + "test_mechanism": "simple", + } + + +@pytest.fixture() +def test_config(test_config_data): + with patch("builtins.open", mock_open(read_data=json.dumps(test_config_data))): + return APIConfig.load("test/path") diff --git a/test/datagateway_api/db/conftest.py b/test/datagateway_api/db/conftest.py index e8ca4047..6bb0fffb 100644 --- a/test/datagateway_api/db/conftest.py +++ b/test/datagateway_api/db/conftest.py @@ -3,7 +3,7 @@ import pytest -from datagateway_api.src.common.config import config +from datagateway_api.src.common.config import Config from datagateway_api.src.common.constants import Constants from datagateway_api.src.datagateway_api.database.helpers import ( delete_row_by_id, @@ -117,7 +117,8 @@ def isis_specific_endpoint_data_db(): @pytest.fixture() def final_instrument_id(flask_test_app_db, valid_db_credentials_header): final_instrument_result = flask_test_app_db.get( - f'{config.datagateway_api.extension}/instruments/findone?order="id DESC"', + f"{Config.config.datagateway_api.extension}/instruments/findone" + '?order="id DESC"', headers=valid_db_credentials_header, ) return final_instrument_result.json["id"] @@ -126,7 +127,8 @@ def final_instrument_id(flask_test_app_db, valid_db_credentials_header): @pytest.fixture() def final_facilitycycle_id(flask_test_app_db, valid_db_credentials_header): final_facilitycycle_result = flask_test_app_db.get( - f'{config.datagateway_api.extension}/facilitycycles/findone?order="id DESC"', + f"{Config.config.datagateway_api.extension}/facilitycycles/findone" + '?order="id DESC"', headers=valid_db_credentials_header, ) return final_facilitycycle_result.json["id"] diff --git a/test/datagateway_api/db/endpoints/test_count_with_filters_db.py b/test/datagateway_api/db/endpoints/test_count_with_filters_db.py index 7b97dc58..6005a360 100644 --- a/test/datagateway_api/db/endpoints/test_count_with_filters_db.py +++ b/test/datagateway_api/db/endpoints/test_count_with_filters_db.py @@ -1,6 +1,6 @@ import pytest -from datagateway_api.src.common.config import config +from datagateway_api.src.common.config import Config class TestDBCountWithFilters: @@ -9,7 +9,7 @@ def test_valid_count_with_filters( self, flask_test_app_db, valid_db_credentials_header, ): test_response = flask_test_app_db.get( - f"{config.datagateway_api.extension}/investigations/count?where=" + f"{Config.config.datagateway_api.extension}/investigations/count?where=" '{"title": {"like": "Title for DataGateway API Testing (DB)"}}', headers=valid_db_credentials_header, ) @@ -20,7 +20,7 @@ def test_valid_no_results_count_with_filters( self, flask_test_app_db, valid_db_credentials_header, ): test_response = flask_test_app_db.get( - f"{config.datagateway_api.extension}/investigations/count?where=" + f"{Config.config.datagateway_api.extension}/investigations/count?where=" '{"title": {"like": "This filter should cause a404 for testing ' 'purposes..."}}', headers=valid_db_credentials_header, diff --git a/test/datagateway_api/db/endpoints/test_findone_db.py b/test/datagateway_api/db/endpoints/test_findone_db.py index bd1f6b8a..167b2a63 100644 --- a/test/datagateway_api/db/endpoints/test_findone_db.py +++ b/test/datagateway_api/db/endpoints/test_findone_db.py @@ -1,4 +1,4 @@ -from datagateway_api.src.common.config import config +from datagateway_api.src.common.config import Config class TestDBFindone: @@ -9,7 +9,7 @@ def test_valid_findone_with_filters( single_investigation_test_data_db, ): test_response = flask_test_app_db.get( - f"{config.datagateway_api.extension}/investigations/findone?where=" + f"{Config.config.datagateway_api.extension}/investigations/findone?where=" '{"title": {"like": "Title for DataGateway API Testing (DB)"}}', headers=valid_db_credentials_header, ) @@ -20,7 +20,7 @@ def test_valid_no_results_findone_with_filters( self, flask_test_app_db, valid_db_credentials_header, ): test_response = flask_test_app_db.get( - f"{config.datagateway_api.extension}/investigations/findone?where=" + f"{Config.config.datagateway_api.extension}/investigations/findone?where=" '{"title": {"eq": "This filter should cause a404 for testing ' 'purposes..."}}', headers=valid_db_credentials_header, diff --git a/test/datagateway_api/db/endpoints/test_get_by_id_db.py b/test/datagateway_api/db/endpoints/test_get_by_id_db.py index eb3819c8..edd12244 100644 --- a/test/datagateway_api/db/endpoints/test_get_by_id_db.py +++ b/test/datagateway_api/db/endpoints/test_get_by_id_db.py @@ -1,4 +1,4 @@ -from datagateway_api.src.common.config import config +from datagateway_api.src.common.config import Config class TestDBGetByID: @@ -10,14 +10,14 @@ def test_valid_get_with_id( ): # Need to identify the ID given to the test data investigation_data = flask_test_app_db.get( - f"{config.datagateway_api.extension}/investigations?where=" + f"{Config.config.datagateway_api.extension}/investigations?where=" '{"title": {"like": "Title for DataGateway API Testing (DB)"}}', headers=valid_db_credentials_header, ) test_data_id = investigation_data.json[0]["id"] test_response = flask_test_app_db.get( - f"{config.datagateway_api.extension}/investigations/{test_data_id}", + f"{Config.config.datagateway_api.extension}/investigations/{test_data_id}", headers=valid_db_credentials_header, ) @@ -27,7 +27,7 @@ def test_invalid_get_with_id( self, flask_test_app_db, valid_db_credentials_header, ): final_investigation_result = flask_test_app_db.get( - f"{config.datagateway_api.extension}/investigations/findone?order=" + f"{Config.config.datagateway_api.extension}/investigations/findone?order=" '"id DESC"', headers=valid_db_credentials_header, ) @@ -35,7 +35,8 @@ def test_invalid_get_with_id( # Adding 100 onto the ID to the most recent result should ensure a 404 test_response = flask_test_app_db.get( - f"{config.datagateway_api.extension}/investigations/{test_data_id + 100}", + f"{Config.config.datagateway_api.extension}/investigations" + f"/{test_data_id + 100}", headers=valid_db_credentials_header, ) diff --git a/test/datagateway_api/db/endpoints/test_get_with_filters.py b/test/datagateway_api/db/endpoints/test_get_with_filters.py index 40cb3015..98d2910f 100644 --- a/test/datagateway_api/db/endpoints/test_get_with_filters.py +++ b/test/datagateway_api/db/endpoints/test_get_with_filters.py @@ -1,6 +1,6 @@ import pytest -from datagateway_api.src.common.config import config +from datagateway_api.src.common.config import Config from datagateway_api.src.common.constants import Constants from datagateway_api.src.common.date_handler import DateHandler @@ -13,7 +13,7 @@ def test_valid_get_with_filters( single_investigation_test_data_db, ): test_response = flask_test_app_db.get( - f"{config.datagateway_api.extension}/investigations?where=" + f"{Config.config.datagateway_api.extension}/investigations?where=" '{"title": {"like": "Title for DataGateway API Testing (DB)"}}', headers=valid_db_credentials_header, ) @@ -24,7 +24,7 @@ def test_valid_no_results_get_with_filters( self, flask_test_app_db, valid_db_credentials_header, ): test_response = flask_test_app_db.get( - f"{config.datagateway_api.extension}/investigations?where=" + f"{Config.config.datagateway_api.extension}/investigations?where=" '{"title": {"eq": "This filter should cause a 404 fortesting ' 'purposes..."}}', headers=valid_db_credentials_header, @@ -37,7 +37,7 @@ def test_valid_get_with_filters_multiple_distinct( self, flask_test_app_db, valid_db_credentials_header, ): test_response = flask_test_app_db.get( - f"{config.datagateway_api.extension}/investigations?where=" + f"{Config.config.datagateway_api.extension}/investigations?where=" '{"title": {"like": "Title for DataGateway API Testing (DB)"}}' '&distinct="title"', headers=valid_db_credentials_header, @@ -128,7 +128,7 @@ def test_valid_get_with_filters_related_distinct( expected_response, ): test_response = flask_test_app_db.get( - f"{config.datagateway_api.extension}/investigations?where=" + f"{Config.config.datagateway_api.extension}/investigations?where=" '{"title": {"like": "Title for DataGateway API Testing (DB)"}}' f"&distinct={distinct_param}", headers=valid_db_credentials_header, @@ -148,7 +148,7 @@ def test_limit_skip_merge_get_with_filters( limit_value = 2 test_response = flask_test_app_db.get( - f"{config.datagateway_api.extension}/investigations?where=" + f"{Config.config.datagateway_api.extension}/investigations?where=" '{"title": {"like": "Title for DataGateway API Testing (DB)"}}' f'&skip={skip_value}&limit={limit_value}&order="id ASC"', headers=valid_db_credentials_header, diff --git a/test/datagateway_api/db/endpoints/test_ping_db.py b/test/datagateway_api/db/endpoints/test_ping_db.py index 376297e4..aa8dfa30 100644 --- a/test/datagateway_api/db/endpoints/test_ping_db.py +++ b/test/datagateway_api/db/endpoints/test_ping_db.py @@ -3,7 +3,7 @@ import pytest from sqlalchemy.exc import SQLAlchemyError -from datagateway_api.src.common.config import config +from datagateway_api.src.common.config import Config from datagateway_api.src.common.constants import Constants from datagateway_api.src.common.exceptions import DatabaseError from datagateway_api.src.datagateway_api.backends import create_backend @@ -12,7 +12,7 @@ class TestICATPing: def test_valid_ping(self, flask_test_app_db): test_response = flask_test_app_db.get( - f"{config.datagateway_api.extension}/ping", + f"{Config.config.datagateway_api.extension}/ping", ) assert test_response.json == Constants.PING_OK_RESPONSE diff --git a/test/datagateway_api/db/endpoints/test_table_endpoints_db.py b/test/datagateway_api/db/endpoints/test_table_endpoints_db.py index adf32245..92f78621 100644 --- a/test/datagateway_api/db/endpoints/test_table_endpoints_db.py +++ b/test/datagateway_api/db/endpoints/test_table_endpoints_db.py @@ -1,4 +1,4 @@ -from datagateway_api.src.common.config import config +from datagateway_api.src.common.config import Config class TestDBTableEndpoints: @@ -14,7 +14,7 @@ def test_valid_get_facility_cycles_with_filters( isis_specific_endpoint_data_db, ): test_response = flask_test_app_db.get( - f"{config.datagateway_api.extension}/instruments" + f"{Config.config.datagateway_api.extension}/instruments" f"/{int(isis_specific_endpoint_data_db[0])}/facilitycycles", headers=valid_db_credentials_header, ) @@ -25,7 +25,7 @@ def test_invalid_get_facility_cycles_with_filters( self, flask_test_app_db, valid_db_credentials_header, final_instrument_id, ): test_response = flask_test_app_db.get( - f"{config.datagateway_api.extension}/instruments" + f"{Config.config.datagateway_api.extension}/instruments" f"/{final_instrument_id + 100}/facilitycycles", headers=valid_db_credentials_header, ) @@ -39,7 +39,7 @@ def test_valid_get_facility_cycles_count_with_filters( isis_specific_endpoint_data_db, ): test_response = flask_test_app_db.get( - f"{config.datagateway_api.extension}/instruments" + f"{Config.config.datagateway_api.extension}/instruments" f"/{isis_specific_endpoint_data_db[0]}/facilitycycles/count", headers=valid_db_credentials_header, ) @@ -50,7 +50,7 @@ def test_invalid_get_facility_cycles_count_with_filters( self, flask_test_app_db, valid_db_credentials_header, final_instrument_id, ): test_response = flask_test_app_db.get( - f"{config.datagateway_api.extension}/instruments" + f"{Config.config.datagateway_api.extension}/instruments" f"/{final_instrument_id + 100}/facilitycycles/count", headers=valid_db_credentials_header, ) @@ -64,7 +64,7 @@ def test_valid_get_investigations_with_filters( isis_specific_endpoint_data_db, ): test_response = flask_test_app_db.get( - f"{config.datagateway_api.extension}/instruments" + f"{Config.config.datagateway_api.extension}/instruments" f"/{isis_specific_endpoint_data_db[0]}/facilitycycles" f"/{isis_specific_endpoint_data_db[1].to_dict()['id']}/investigations", headers=valid_db_credentials_header, @@ -80,7 +80,7 @@ def test_invalid_get_investigations_with_filters( final_facilitycycle_id, ): test_response = flask_test_app_db.get( - f"{config.datagateway_api.extension}/instruments" + f"{Config.config.datagateway_api.extension}/instruments" f"/{final_instrument_id + 100}/facilitycycles" f"/{final_facilitycycle_id + 100}/investigations", headers=valid_db_credentials_header, @@ -95,7 +95,7 @@ def test_valid_get_investigations_count_with_filters( isis_specific_endpoint_data_db, ): test_response = flask_test_app_db.get( - f"{config.datagateway_api.extension}/instruments" + f"{Config.config.datagateway_api.extension}/instruments" f"/{isis_specific_endpoint_data_db[0]}/facilitycycles" f"/{isis_specific_endpoint_data_db[1].to_dict()['id']}" "/investigations/count", @@ -112,7 +112,7 @@ def test_invalid_get_investigations_count_with_filters( final_facilitycycle_id, ): test_response = flask_test_app_db.get( - f"{config.datagateway_api.extension}/instruments" + f"{Config.config.datagateway_api.extension}/instruments" f"/{final_instrument_id + 100}/facilitycycles" f"/{final_facilitycycle_id + 100}/investigations/count", headers=valid_db_credentials_header, diff --git a/test/datagateway_api/db/test_requires_session_id.py b/test/datagateway_api/db/test_requires_session_id.py index 5cca1b1b..d18f5baa 100644 --- a/test/datagateway_api/db/test_requires_session_id.py +++ b/test/datagateway_api/db/test_requires_session_id.py @@ -1,4 +1,4 @@ -from datagateway_api.src.common.config import config +from datagateway_api.src.common.config import Config class TestRequiresSessionID: @@ -9,14 +9,14 @@ class TestRequiresSessionID: def test_invalid_missing_credentials(self, flask_test_app_db): test_response = flask_test_app_db.get( - f"{config.datagateway_api.extension}/datafiles", + f"{Config.config.datagateway_api.extension}/datafiles", ) assert test_response.status_code == 401 def test_invalid_credentials(self, flask_test_app_db, invalid_credentials_header): test_response = flask_test_app_db.get( - f"{config.datagateway_api.extension}/datafiles", + f"{Config.config.datagateway_api.extension}/datafiles", headers=invalid_credentials_header, ) @@ -24,7 +24,7 @@ def test_invalid_credentials(self, flask_test_app_db, invalid_credentials_header def test_bad_credentials(self, flask_test_app_db, bad_credentials_header): test_response = flask_test_app_db.get( - f"{config.datagateway_api.extension}/datafiles", + f"{Config.config.datagateway_api.extension}/datafiles", headers=bad_credentials_header, ) @@ -32,7 +32,7 @@ def test_bad_credentials(self, flask_test_app_db, bad_credentials_header): def test_valid_credentials(self, flask_test_app_db, valid_db_credentials_header): test_response = flask_test_app_db.get( - f"{config.datagateway_api.extension}/datafiles?limit=0", + f"{Config.config.datagateway_api.extension}/datafiles?limit=0", headers=valid_db_credentials_header, ) diff --git a/test/datagateway_api/icat/conftest.py b/test/datagateway_api/icat/conftest.py index a89b4bb8..c7ca8020 100644 --- a/test/datagateway_api/icat/conftest.py +++ b/test/datagateway_api/icat/conftest.py @@ -12,7 +12,7 @@ create_api_endpoints, create_app_infrastructure, ) -from datagateway_api.src.common.config import config +from datagateway_api.src.common.config import Config from test.datagateway_api.icat.endpoints.test_create_icat import TestICATCreateData from test.datagateway_api.icat.test_query import prepare_icat_data_for_assertion @@ -20,11 +20,11 @@ @pytest.fixture(scope="package") def icat_client(): client = Client( - config.datagateway_api.icat_url, - checkCert=config.datagateway_api.icat_check_cert, + Config.config.datagateway_api.icat_url, + checkCert=Config.config.datagateway_api.icat_check_cert, ) client.login( - config.test_mechanism, config.test_user_credentials.dict(), + Config.config.test_mechanism, Config.config.test_user_credentials.dict(), ) return client @@ -149,7 +149,8 @@ def isis_specific_endpoint_data(icat_client): @pytest.fixture() def final_instrument_id(flask_test_app_icat, valid_icat_credentials_header): final_instrument_result = flask_test_app_icat.get( - f'{config.datagateway_api.extension}/instruments/findone?order="id DESC"', + f"{Config.config.datagateway_api.extension}/instruments/findone" + '?order="id DESC"', headers=valid_icat_credentials_header, ) return final_instrument_result.json["id"] @@ -158,7 +159,8 @@ def final_instrument_id(flask_test_app_icat, valid_icat_credentials_header): @pytest.fixture() def final_facilitycycle_id(flask_test_app_icat, valid_icat_credentials_header): final_facilitycycle_result = flask_test_app_icat.get( - f'{config.datagateway_api.extension}/facilitycycles/findone?order="id DESC"', + f"{Config.config.datagateway_api.extension}/facilitycycles/findone" + '?order="id DESC"', headers=valid_icat_credentials_header, ) return final_facilitycycle_result.json["id"] @@ -181,7 +183,7 @@ def remove_test_created_investigation_data( yield created_test_data = flask_test_app_icat.get( - f"{config.datagateway_api.extension}/investigations?where=" + f"{Config.config.datagateway_api.extension}/investigations?where=" '{"name":{"like":' f'"{TestICATCreateData.investigation_name_prefix}"' "}}", @@ -194,6 +196,7 @@ def remove_test_created_investigation_data( for investigation_id in investigation_ids: flask_test_app_icat.delete( - f"{config.datagateway_api.extension}/investigations/{investigation_id}", + f"{Config.config.datagateway_api.extension}/investigations" + f"/{investigation_id}", headers=valid_icat_credentials_header, ) diff --git a/test/datagateway_api/icat/endpoints/test_count_with_filters_icat.py b/test/datagateway_api/icat/endpoints/test_count_with_filters_icat.py index e37b81a7..1fb23509 100644 --- a/test/datagateway_api/icat/endpoints/test_count_with_filters_icat.py +++ b/test/datagateway_api/icat/endpoints/test_count_with_filters_icat.py @@ -1,6 +1,6 @@ import pytest -from datagateway_api.src.common.config import config +from datagateway_api.src.common.config import Config class TestICATCountWithFilters: @@ -30,7 +30,8 @@ def test_valid_count_with_filters( expected_result, ): test_response = flask_test_app_icat.get( - f"{config.datagateway_api.extension}/investigations/count{query_params}", + f"{Config.config.datagateway_api.extension}/investigations" + f"/count{query_params}", headers=valid_icat_credentials_header, ) @@ -40,7 +41,7 @@ def test_valid_no_results_count_with_filters( self, flask_test_app_icat, valid_icat_credentials_header, ): test_response = flask_test_app_icat.get( - f"{config.datagateway_api.extension}/investigations/count?where=" + f"{Config.config.datagateway_api.extension}/investigations/count?where=" '{"title": {"like": "This filter should cause 0results to be found ' 'for testing purposes..."}}', headers=valid_icat_credentials_header, diff --git a/test/datagateway_api/icat/endpoints/test_create_icat.py b/test/datagateway_api/icat/endpoints/test_create_icat.py index 57b3622f..6d055ae4 100644 --- a/test/datagateway_api/icat/endpoints/test_create_icat.py +++ b/test/datagateway_api/icat/endpoints/test_create_icat.py @@ -1,6 +1,6 @@ import pytest -from datagateway_api.src.common.config import config +from datagateway_api.src.common.config import Config from test.datagateway_api.icat.test_query import prepare_icat_data_for_assertion @@ -28,7 +28,7 @@ def test_valid_create_data( ] test_response = flask_test_app_icat.post( - f"{config.datagateway_api.extension}/investigations", + f"{Config.config.datagateway_api.extension}/investigations", headers=valid_icat_credentials_header, json=create_investigations_json, ) @@ -63,7 +63,7 @@ def test_valid_boundary_create_data( } test_response = flask_test_app_icat.post( - f"{config.datagateway_api.extension}/investigations", + f"{Config.config.datagateway_api.extension}/investigations", headers=valid_icat_credentials_header, json=create_investigation_json, ) @@ -87,7 +87,7 @@ def test_invalid_create_data( } test_response = flask_test_app_icat.post( - f"{config.datagateway_api.extension}/investigations", + f"{Config.config.datagateway_api.extension}/investigations", headers=valid_icat_credentials_header, json=invalid_request_body, ) @@ -113,7 +113,7 @@ def test_invalid_existing_data_create( } test_response = flask_test_app_icat.post( - f"{config.datagateway_api.extension}/investigations", + f"{Config.config.datagateway_api.extension}/investigations", headers=valid_icat_credentials_header, json=existing_object_json, ) @@ -142,13 +142,13 @@ def test_valid_rollback_behaviour( ] create_response = flask_test_app_icat.post( - f"{config.datagateway_api.extension}/investigations", + f"{Config.config.datagateway_api.extension}/investigations", headers=valid_icat_credentials_header, json=request_body, ) get_response = flask_test_app_icat.get( - f"{config.datagateway_api.extension}/investigations?where=" + f"{Config.config.datagateway_api.extension}/investigations?where=" '{"title": {"eq": "' f'{request_body[0]["title"]}' '"}}', diff --git a/test/datagateway_api/icat/endpoints/test_delete_by_id_icat.py b/test/datagateway_api/icat/endpoints/test_delete_by_id_icat.py index e7dcb345..8a4a24cc 100644 --- a/test/datagateway_api/icat/endpoints/test_delete_by_id_icat.py +++ b/test/datagateway_api/icat/endpoints/test_delete_by_id_icat.py @@ -1,4 +1,4 @@ -from datagateway_api.src.common.config import config +from datagateway_api.src.common.config import Config class TestDeleteByID: @@ -9,7 +9,7 @@ def test_valid_delete_with_id( single_investigation_test_data, ): test_response = flask_test_app_icat.delete( - f"{config.datagateway_api.extension}/investigations" + f"{Config.config.datagateway_api.extension}/investigations" f'/{single_investigation_test_data[0]["id"]}', headers=valid_icat_credentials_header, ) @@ -22,7 +22,7 @@ def test_invalid_delete_with_id( """Request with a non-existent ID""" final_investigation_result = flask_test_app_icat.get( - f"{config.datagateway_api.extension}/investigations" + f"{Config.config.datagateway_api.extension}/investigations" '/findone?order="id DESC"', headers=valid_icat_credentials_header, ) @@ -30,7 +30,8 @@ def test_invalid_delete_with_id( # Adding 100 onto the ID to the most recent result should ensure a 404 test_response = flask_test_app_icat.delete( - f"{config.datagateway_api.extension}/investigations/{test_data_id + 100}", + f"{Config.config.datagateway_api.extension}/investigations" + f"/{test_data_id + 100}", headers=valid_icat_credentials_header, ) diff --git a/test/datagateway_api/icat/endpoints/test_findone_icat.py b/test/datagateway_api/icat/endpoints/test_findone_icat.py index 02190d87..fd57253b 100644 --- a/test/datagateway_api/icat/endpoints/test_findone_icat.py +++ b/test/datagateway_api/icat/endpoints/test_findone_icat.py @@ -1,4 +1,4 @@ -from datagateway_api.src.common.config import config +from datagateway_api.src.common.config import Config from test.datagateway_api.icat.test_query import prepare_icat_data_for_assertion @@ -10,7 +10,7 @@ def test_valid_findone_with_filters( single_investigation_test_data, ): test_response = flask_test_app_icat.get( - f"{config.datagateway_api.extension}/investigations/findone?where=" + f"{Config.config.datagateway_api.extension}/investigations/findone?where=" '{"title": {"like": "Test data for the Python ICAT Backend on ' 'DataGateway API"}}', headers=valid_icat_credentials_header, @@ -23,7 +23,7 @@ def test_valid_no_results_findone_with_filters( self, flask_test_app_icat, valid_icat_credentials_header, ): test_response = flask_test_app_icat.get( - f"{config.datagateway_api.extension}/investigations/findone?where=" + f"{Config.config.datagateway_api.extension}/investigations/findone?where=" '{"title": {"eq": "This filter should cause a404 for testing ' 'purposes..."}}', headers=valid_icat_credentials_header, diff --git a/test/datagateway_api/icat/endpoints/test_get_by_id_icat.py b/test/datagateway_api/icat/endpoints/test_get_by_id_icat.py index 56babbaa..44cc79d8 100644 --- a/test/datagateway_api/icat/endpoints/test_get_by_id_icat.py +++ b/test/datagateway_api/icat/endpoints/test_get_by_id_icat.py @@ -1,4 +1,4 @@ -from datagateway_api.src.common.config import config +from datagateway_api.src.common.config import Config from test.datagateway_api.icat.test_query import prepare_icat_data_for_assertion @@ -11,7 +11,7 @@ def test_valid_get_with_id( ): # Need to identify the ID given to the test data investigation_data = flask_test_app_icat.get( - f"{config.datagateway_api.extension}/investigations?where=" + f"{Config.config.datagateway_api.extension}/investigations?where=" '{"title": {"like": "Test data for the Python ICAT Backend on ' 'DataGateway API"}}', headers=valid_icat_credentials_header, @@ -19,7 +19,7 @@ def test_valid_get_with_id( test_data_id = investigation_data.json[0]["id"] test_response = flask_test_app_icat.get( - f"{config.datagateway_api.extension}/investigations/{test_data_id}", + f"{Config.config.datagateway_api.extension}/investigations/{test_data_id}", headers=valid_icat_credentials_header, ) # Get with ID gives a dictionary response (only ever one result from that kind @@ -34,7 +34,7 @@ def test_invalid_get_with_id( """Request with a non-existent ID""" final_investigation_result = flask_test_app_icat.get( - f"{config.datagateway_api.extension}/investigations/findone?order=" + f"{Config.config.datagateway_api.extension}/investigations/findone?order=" '"id DESC"', headers=valid_icat_credentials_header, ) @@ -42,7 +42,8 @@ def test_invalid_get_with_id( # Adding 100 onto the ID to the most recent result should ensure a 404 test_response = flask_test_app_icat.get( - f"{config.datagateway_api.extension}/investigations/{test_data_id + 100}", + f"{Config.config.datagateway_api.extension}/investigations" + f"/{test_data_id + 100}", headers=valid_icat_credentials_header, ) diff --git a/test/datagateway_api/icat/endpoints/test_get_with_filters_icat.py b/test/datagateway_api/icat/endpoints/test_get_with_filters_icat.py index 16be90c3..9d3a9a2d 100644 --- a/test/datagateway_api/icat/endpoints/test_get_with_filters_icat.py +++ b/test/datagateway_api/icat/endpoints/test_get_with_filters_icat.py @@ -1,6 +1,6 @@ import pytest -from datagateway_api.src.common.config import config +from datagateway_api.src.common.config import Config from test.datagateway_api.icat.test_query import prepare_icat_data_for_assertion @@ -12,7 +12,7 @@ def test_valid_get_with_filters( single_investigation_test_data, ): test_response = flask_test_app_icat.get( - f"{config.datagateway_api.extension}/investigations?where=" + f"{Config.config.datagateway_api.extension}/investigations?where=" '{"title": {"like": "Test data for the Python ICAT Backend on ' 'DataGateway API"}}', headers=valid_icat_credentials_header, @@ -25,7 +25,7 @@ def test_valid_no_results_get_with_filters( self, flask_test_app_icat, valid_icat_credentials_header, ): test_response = flask_test_app_icat.get( - f"{config.datagateway_api.extension}/investigations?where=" + f"{Config.config.datagateway_api.extension}/investigations?where=" '{"title": {"eq": "This filter should cause a 404 fortesting ' 'purposes..."}}', headers=valid_icat_credentials_header, @@ -38,7 +38,7 @@ def test_valid_get_with_filters_distinct( self, flask_test_app_icat, valid_icat_credentials_header, ): test_response = flask_test_app_icat.get( - f"{config.datagateway_api.extension}/investigations?where=" + f"{Config.config.datagateway_api.extension}/investigations?where=" '{"title": {"like": "Test data for the Python ICAT Backend on ' 'DataGateway API"}}&distinct="title"', headers=valid_icat_credentials_header, @@ -62,7 +62,7 @@ def test_limit_skip_merge_get_with_filters( limit_value = 2 test_response = flask_test_app_icat.get( - f"{config.datagateway_api.extension}/investigations?where=" + f"{Config.config.datagateway_api.extension}/investigations?where=" '{"title": {"like": "Test data for the Python ICAT Backend on ' 'DataGateway API"}}' f'&skip={skip_value}&limit={limit_value}&order="id ASC"', diff --git a/test/datagateway_api/icat/endpoints/test_ping_icat.py b/test/datagateway_api/icat/endpoints/test_ping_icat.py index 950342f7..faf0b42a 100644 --- a/test/datagateway_api/icat/endpoints/test_ping_icat.py +++ b/test/datagateway_api/icat/endpoints/test_ping_icat.py @@ -3,7 +3,7 @@ from icat.exception import ICATError import pytest -from datagateway_api.src.common.config import config +from datagateway_api.src.common.config import Config from datagateway_api.src.common.constants import Constants from datagateway_api.src.common.exceptions import PythonICATError from datagateway_api.src.datagateway_api.backends import create_backend @@ -13,7 +13,7 @@ class TestICATPing: def test_valid_ping(self, flask_test_app_icat): test_response = flask_test_app_icat.get( - f"{config.datagateway_api.extension}/ping", + f"{Config.config.datagateway_api.extension}/ping", ) assert test_response.json == Constants.PING_OK_RESPONSE diff --git a/test/datagateway_api/icat/endpoints/test_table_endpoints_icat.py b/test/datagateway_api/icat/endpoints/test_table_endpoints_icat.py index 66b04da7..58a1345b 100644 --- a/test/datagateway_api/icat/endpoints/test_table_endpoints_icat.py +++ b/test/datagateway_api/icat/endpoints/test_table_endpoints_icat.py @@ -1,4 +1,4 @@ -from datagateway_api.src.common.config import config +from datagateway_api.src.common.config import Config from test.datagateway_api.icat.test_query import prepare_icat_data_for_assertion @@ -15,7 +15,7 @@ def test_valid_get_facility_cycles_with_filters( isis_specific_endpoint_data, ): test_response = flask_test_app_icat.get( - f"{config.datagateway_api.extension}/instruments" + f"{Config.config.datagateway_api.extension}/instruments" f"/{isis_specific_endpoint_data[0]}/facilitycycles", headers=valid_icat_credentials_header, ) @@ -28,7 +28,7 @@ def test_invalid_get_facility_cycles_with_filters( self, flask_test_app_icat, valid_icat_credentials_header, final_instrument_id, ): test_response = flask_test_app_icat.get( - f"{config.datagateway_api.extension}/instruments" + f"{Config.config.datagateway_api.extension}/instruments" f"/{final_instrument_id + 100}/facilitycycles", headers=valid_icat_credentials_header, ) @@ -42,7 +42,7 @@ def test_valid_get_facility_cycles_count_with_filters( isis_specific_endpoint_data, ): test_response = flask_test_app_icat.get( - f"{config.datagateway_api.extension}/instruments" + f"{Config.config.datagateway_api.extension}/instruments" f"/{isis_specific_endpoint_data[0]}/facilitycycles/count", headers=valid_icat_credentials_header, ) @@ -53,7 +53,7 @@ def test_invalid_get_facility_cycles_count_with_filters( self, flask_test_app_icat, valid_icat_credentials_header, final_instrument_id, ): test_response = flask_test_app_icat.get( - f"{config.datagateway_api.extension}/instruments" + f"{Config.config.datagateway_api.extension}/instruments" f"/{final_instrument_id + 100}/facilitycycles/count", headers=valid_icat_credentials_header, ) @@ -67,7 +67,7 @@ def test_valid_get_investigations_with_filters( isis_specific_endpoint_data, ): test_response = flask_test_app_icat.get( - f"{config.datagateway_api.extension}/instruments" + f"{Config.config.datagateway_api.extension}/instruments" f"/{isis_specific_endpoint_data[0]}/facilitycycles" f"/{isis_specific_endpoint_data[2]}/investigations", headers=valid_icat_credentials_header, @@ -85,7 +85,7 @@ def test_invalid_get_investigations_with_filters( final_facilitycycle_id, ): test_response = flask_test_app_icat.get( - f"{config.datagateway_api.extension}/instruments" + f"{Config.config.datagateway_api.extension}/instruments" f"/{final_instrument_id + 100}/facilitycycles" f"/{final_facilitycycle_id + 100}/investigations", headers=valid_icat_credentials_header, @@ -100,7 +100,7 @@ def test_valid_get_investigations_count_with_filters( isis_specific_endpoint_data, ): test_response = flask_test_app_icat.get( - f"{config.datagateway_api.extension}/instruments" + f"{Config.config.datagateway_api.extension}/instruments" f"/{isis_specific_endpoint_data[0]}/facilitycycles" f"/{isis_specific_endpoint_data[2]}/investigations/count", headers=valid_icat_credentials_header, @@ -116,7 +116,7 @@ def test_invalid_get_investigations_count_with_filters( final_facilitycycle_id, ): test_response = flask_test_app_icat.get( - f"{config.datagateway_api.extension}/instruments" + f"{Config.config.datagateway_api.extension}/instruments" f"/{final_instrument_id + 100}/facilitycycles" f"/{final_facilitycycle_id + 100}/investigations/count", headers=valid_icat_credentials_header, diff --git a/test/datagateway_api/icat/endpoints/test_update_by_id_icat.py b/test/datagateway_api/icat/endpoints/test_update_by_id_icat.py index 6e498936..a9e52b8f 100644 --- a/test/datagateway_api/icat/endpoints/test_update_by_id_icat.py +++ b/test/datagateway_api/icat/endpoints/test_update_by_id_icat.py @@ -1,4 +1,4 @@ -from datagateway_api.src.common.config import config +from datagateway_api.src.common.config import Config from test.datagateway_api.icat.test_query import prepare_icat_data_for_assertion @@ -17,7 +17,7 @@ def test_valid_update_with_id( single_investigation_test_data[0].update(update_data_json) test_response = flask_test_app_icat.patch( - f"{config.datagateway_api.extension}/investigations" + f"{Config.config.datagateway_api.extension}/investigations" f"/{single_investigation_test_data[0]['id']}", headers=valid_icat_credentials_header, json=update_data_json, @@ -40,7 +40,7 @@ def test_invalid_update_with_id( } test_response = flask_test_app_icat.patch( - f"{config.datagateway_api.extension}/investigations" + f"{Config.config.datagateway_api.extension}/investigations" f"/{single_investigation_test_data[0]['id']}", headers=valid_icat_credentials_header, json=invalid_update_json, diff --git a/test/datagateway_api/icat/endpoints/test_update_multiple_icat.py b/test/datagateway_api/icat/endpoints/test_update_multiple_icat.py index 2ea0c958..6c7de86b 100644 --- a/test/datagateway_api/icat/endpoints/test_update_multiple_icat.py +++ b/test/datagateway_api/icat/endpoints/test_update_multiple_icat.py @@ -1,6 +1,6 @@ import pytest -from datagateway_api.src.common.config import config +from datagateway_api.src.common.config import Config from test.datagateway_api.icat.test_query import prepare_icat_data_for_assertion @@ -28,7 +28,7 @@ def test_valid_multiple_update_data( update_data_list.append(update_entity) test_response = flask_test_app_icat.patch( - f"{config.datagateway_api.extension}/investigations", + f"{Config.config.datagateway_api.extension}/investigations", headers=valid_icat_credentials_header, json=update_data_list, ) @@ -56,7 +56,7 @@ def test_valid_boundary_update_data( single_investigation_test_data[0]["summary"] = expected_summary test_response = flask_test_app_icat.patch( - f"{config.datagateway_api.extension}/investigations", + f"{Config.config.datagateway_api.extension}/investigations", headers=valid_icat_credentials_header, json=update_data_json, ) @@ -78,7 +78,7 @@ def test_invalid_missing_update_data( } test_response = flask_test_app_icat.patch( - f"{config.datagateway_api.extension}/investigations", + f"{Config.config.datagateway_api.extension}/investigations", headers=valid_icat_credentials_header, json=update_data_json, ) @@ -106,7 +106,7 @@ def test_invalid_attribute_update( } test_response = flask_test_app_icat.patch( - f"{config.datagateway_api.extension}/investigations", + f"{Config.config.datagateway_api.extension}/investigations", headers=valid_icat_credentials_header, json=invalid_update_data_json, ) @@ -138,7 +138,7 @@ def test_valid_rollback_behaviour( ] update_response = flask_test_app_icat.patch( - f"{config.datagateway_api.extension}/investigations", + f"{Config.config.datagateway_api.extension}/investigations", headers=valid_icat_credentials_header, json=request_body, ) @@ -147,7 +147,7 @@ def test_valid_rollback_behaviour( # were rolled back when the ICATValidationError occurred for the second entity # in the request body get_response = flask_test_app_icat.get( - f"{config.datagateway_api.extension}/investigations" + f"{Config.config.datagateway_api.extension}/investigations" f"/{multiple_investigation_test_data[0]['id']}", headers=valid_icat_credentials_header, ) diff --git a/test/datagateway_api/icat/filters/test_skip_filter.py b/test/datagateway_api/icat/filters/test_skip_filter.py index 327d2037..f20aaee5 100644 --- a/test/datagateway_api/icat/filters/test_skip_filter.py +++ b/test/datagateway_api/icat/filters/test_skip_filter.py @@ -1,6 +1,6 @@ import pytest -from datagateway_api.src.common.config import config +from datagateway_api.src.common.config import Config from datagateway_api.src.common.exceptions import FilterError from datagateway_api.src.common.helpers import get_icat_properties from datagateway_api.src.datagateway_api.icat.filters import PythonICATSkipFilter @@ -17,7 +17,8 @@ def test_valid_skip_value(self, icat_query, skip_value): assert icat_query.limit == ( skip_value, get_icat_properties( - config.datagateway_api.icat_url, config.datagateway_api.icat_check_cert, + Config.config.datagateway_api.icat_url, + Config.config.datagateway_api.icat_check_cert, )["maxEntities"], ) diff --git a/test/datagateway_api/icat/test_icat_client.py b/test/datagateway_api/icat/test_icat_client.py index e722f083..850dfc1b 100644 --- a/test/datagateway_api/icat/test_icat_client.py +++ b/test/datagateway_api/icat/test_icat_client.py @@ -1,4 +1,7 @@ +from unittest.mock import patch + from icat.client import Client +import pytest from datagateway_api.src.datagateway_api.icat.icat_client_pool import ICATClient @@ -10,6 +13,43 @@ def test_init(self): assert not test_icat_client.autoLogout + @pytest.mark.parametrize( + "client_use, expected_url, expected_check_cert", + [ + pytest.param( + "datagateway_api", + "https://localhost:8181/ICATService/ICAT?wsdl", + False, + id="DataGateway API Usage", + ), + pytest.param( + "search_api", + "https://localhost.testdomain:8181/ICATService/ICAT?wsdl", + True, + id="Search API Usage", + ), + ], + ) + def test_client_use( + self, test_config, client_use, expected_url, expected_check_cert, + ): + class MockClient: + def __init__(url, checkCert=True): # noqa + # Would've preferred to assign these values to self but this didn't + # seem to be possible + Client.url = f"{url}/ICATService/ICAT?wsdl" + Client.checkCert = checkCert + + with patch( + "datagateway_api.src.common.config.Config.config", test_config, + ): + with patch( + "icat.client.Client.__init__", side_effect=MockClient.__init__, + ): + test_icat_client = ICATClient(client_use) + assert test_icat_client.url == expected_url + assert test_icat_client.checkCert == expected_check_cert + def test_clean_up(self): test_icat_client = ICATClient() assert id(test_icat_client) in Client.Register diff --git a/test/datagateway_api/icat/test_lru_cache.py b/test/datagateway_api/icat/test_lru_cache.py index 82ad4554..e5c87396 100644 --- a/test/datagateway_api/icat/test_lru_cache.py +++ b/test/datagateway_api/icat/test_lru_cache.py @@ -3,7 +3,7 @@ from cachetools import cached from icat.client import Client -from datagateway_api.src.common.config import config +from datagateway_api.src.common.config import Config from datagateway_api.src.datagateway_api.icat.icat_client_pool import create_client_pool from datagateway_api.src.datagateway_api.icat.lru_cache import ExtendedLRUCache @@ -11,14 +11,14 @@ class TestLRUCache: def test_valid_cache_creation(self): test_cache = ExtendedLRUCache() - assert test_cache.maxsize == config.datagateway_api.client_cache_size + assert test_cache.maxsize == Config.config.datagateway_api.client_cache_size def test_valid_popitem(self): test_cache = ExtendedLRUCache() test_pool = create_client_pool() test_client = Client( - config.datagateway_api.icat_url, - checkCert=config.datagateway_api.icat_check_cert, + Config.config.datagateway_api.icat_url, + checkCert=Config.config.datagateway_api.icat_check_cert, ) test_cache.popitem = MagicMock(side_effect=test_cache.popitem) @@ -27,7 +27,7 @@ def test_valid_popitem(self): def get_cached_client(cache_number, client_pool): return test_client - for cache_number in range(config.datagateway_api.client_cache_size + 1): + for cache_number in range(Config.config.datagateway_api.client_cache_size + 1): get_cached_client(cache_number, test_pool) assert test_cache.popitem.called diff --git a/test/datagateway_api/icat/test_session_handling.py b/test/datagateway_api/icat/test_session_handling.py index f5f771dc..20155faf 100644 --- a/test/datagateway_api/icat/test_session_handling.py +++ b/test/datagateway_api/icat/test_session_handling.py @@ -5,7 +5,7 @@ from icat.client import Client import pytest -from datagateway_api.src.common.config import config +from datagateway_api.src.common.config import Config from datagateway_api.src.common.date_handler import DateHandler from datagateway_api.src.common.exceptions import AuthenticationError from datagateway_api.src.datagateway_api.backends import create_backend @@ -18,7 +18,7 @@ def test_get_valid_session_details( self, flask_test_app_icat, valid_icat_credentials_header, ): session_details = flask_test_app_icat.get( - f"{config.datagateway_api.extension}/sessions", + f"{Config.config.datagateway_api.extension}/sessions", headers=valid_icat_credentials_header, ) @@ -34,8 +34,8 @@ def test_get_valid_session_details( assert time_diff_minutes < 120 and time_diff_minutes >= 118 # Check username is correct - test_mechanism = config.test_mechanism - test_username = config.test_user_credentials.username + test_mechanism = Config.config.test_mechanism + test_username = Config.config.test_user_credentials.username assert session_details.json["username"] == f"{test_mechanism}/{test_username}" # Check session ID matches the header from the request @@ -48,7 +48,7 @@ def test_get_invalid_session_details( self, bad_credentials_header, flask_test_app_icat, ): session_details = flask_test_app_icat.get( - f"{config.datagateway_api.extension}/sessions", + f"{Config.config.datagateway_api.extension}/sessions", headers=bad_credentials_header, ) @@ -56,17 +56,17 @@ def test_get_invalid_session_details( def test_refresh_session(self, valid_icat_credentials_header, flask_test_app_icat): pre_refresh_session_details = flask_test_app_icat.get( - f"{config.datagateway_api.extension}/sessions", + f"{Config.config.datagateway_api.extension}/sessions", headers=valid_icat_credentials_header, ) refresh_session = flask_test_app_icat.put( - f"{config.datagateway_api.extension}/sessions", + f"{Config.config.datagateway_api.extension}/sessions", headers=valid_icat_credentials_header, ) post_refresh_session_details = flask_test_app_icat.get( - f"{config.datagateway_api.extension}/sessions", + f"{Config.config.datagateway_api.extension}/sessions", headers=valid_icat_credentials_header, ) @@ -83,16 +83,16 @@ def test_refresh_session(self, valid_icat_credentials_header, flask_test_app_ica [ pytest.param( { - "username": config.test_user_credentials.username, - "password": config.test_user_credentials.password, - "mechanism": config.test_mechanism, + "username": Config.config.test_user_credentials.username, + "password": Config.config.test_user_credentials.password, + "mechanism": Config.config.test_mechanism, }, id="Normal request body", ), pytest.param( { - "username": config.test_user_credentials.username, - "password": config.test_user_credentials.password, + "username": Config.config.test_user_credentials.username, + "password": Config.config.test_user_credentials.password, }, id="Missing mechanism in request body", ), @@ -102,7 +102,7 @@ def test_valid_login( self, flask_test_app_icat, icat_client, icat_query, request_body, ): login_response = flask_test_app_icat.post( - f"{config.datagateway_api.extension}/sessions", json=request_body, + f"{Config.config.datagateway_api.extension}/sessions", json=request_body, ) icat_client.sessionId = login_response.json["sessionID"] @@ -123,7 +123,7 @@ def test_valid_login( { "username": "Invalid Username", "password": "InvalidPassword", - "mechanism": config.test_mechanism, + "mechanism": Config.config.test_mechanism, }, 403, id="Invalid credentials", @@ -135,7 +135,7 @@ def test_invalid_login( self, flask_test_app_icat, request_body, expected_response_code, ): login_response = flask_test_app_icat.post( - f"{config.datagateway_api.extension}/sessions", json=request_body, + f"{Config.config.datagateway_api.extension}/sessions", json=request_body, ) assert login_response.status_code == expected_response_code @@ -149,23 +149,23 @@ def test_expired_session(self): def test_valid_logout(self, flask_test_app_icat): client = Client( - config.datagateway_api.icat_url, - checkCert=config.datagateway_api.icat_check_cert, + Config.config.datagateway_api.icat_url, + checkCert=Config.config.datagateway_api.icat_check_cert, ) client.login( - config.test_mechanism, config.test_user_credentials.dict(), + Config.config.test_mechanism, Config.config.test_user_credentials.dict(), ) creds_header = {"Authorization": f"Bearer {client.sessionId}"} logout_response = flask_test_app_icat.delete( - f"{config.datagateway_api.extension}/sessions", headers=creds_header, + f"{Config.config.datagateway_api.extension}/sessions", headers=creds_header, ) assert logout_response.status_code == 200 def test_invalid_logout(self, bad_credentials_header, flask_test_app_icat): logout_response = flask_test_app_icat.delete( - f"{config.datagateway_api.extension}/sessions", + f"{Config.config.datagateway_api.extension}/sessions", headers=bad_credentials_header, ) diff --git a/test/search_api/test_session_handler.py b/test/search_api/test_session_handler.py new file mode 100644 index 00000000..f2693559 --- /dev/null +++ b/test/search_api/test_session_handler.py @@ -0,0 +1,21 @@ +from datagateway_api.src.datagateway_api.icat.icat_client_pool import ICATClient +from datagateway_api.src.search_api.session_handler import ( + client_manager, + SessionHandler, +) + + +class TestSessionHandler: + def test_session_handler_class(self): + assert isinstance(SessionHandler.client, ICATClient) + + def test_client_manager_decorator(self): + @client_manager + def manage_client(): + pass + + # Checks that the decorator assigns a session ID, checking one is not present + # before the decorator runs + assert not SessionHandler.client.sessionId + manage_client() + assert SessionHandler.client.sessionId diff --git a/test/test_config.py b/test/test_config.py index 8b01bbbc..c22e07b8 100644 --- a/test/test_config.py +++ b/test/test_config.py @@ -6,44 +6,6 @@ from datagateway_api.src.common.config import APIConfig, validate_extension -@pytest.fixture() -def test_config_data(): - return { - "datagateway_api": { - "extension": "/datagateway-api", - "backend": "db", - "client_cache_size": 5, - "client_pool_init_size": 2, - "client_pool_max_size": 5, - "db_url": "mysql+pymysql://icatdbuser:icatdbuserpw@localhost:3306/icatdb", - "icat_url": "https://localhost:8181", - "icat_check_cert": False, - }, - "search_api": { - "extension": "/search-api", - "icat_url": "https://localhost:8181", - "icat_check_cert": False, - "client_pool_init_size": 2, - "client_pool_max_size": 5, - }, - "flask_reloader": False, - "log_level": "WARN", - "log_location": "/home/runner/work/datagateway-api/datagateway-api/logs.log", - "debug_mode": False, - "generate_swagger": False, - "host": "127.0.0.1", - "port": "5000", - "test_user_credentials": {"username": "root", "password": "pw"}, - "test_mechanism": "simple", - } - - -@pytest.fixture() -def test_config(test_config_data): - with patch("builtins.open", mock_open(read_data=json.dumps(test_config_data))): - return APIConfig.load("test/path") - - class TestAPIConfig: def test_load_with_valid_config_data(self, test_config): backend_type = test_config.datagateway_api.backend diff --git a/test/test_endpoint_rules.py b/test/test_endpoint_rules.py index 54e141c4..f09fa004 100644 --- a/test/test_endpoint_rules.py +++ b/test/test_endpoint_rules.py @@ -1,6 +1,6 @@ import pytest -from datagateway_api.src.common.config import config +from datagateway_api.src.common.config import Config from datagateway_api.src.resources.entities.entity_endpoint_dict import endpoints @@ -24,7 +24,7 @@ def test_entity_endpoints(self, flask_test_app, endpoint_ending, expected_method for rule in flask_test_app.url_map.iter_rules(): if ( - f"{config.datagateway_api.extension}" + f"{Config.config.datagateway_api.extension}" f"/{endpoint_entity.lower()}{endpoint_ending}" == rule.rule ): endpoint_found = True @@ -40,86 +40,87 @@ def test_entity_endpoints(self, flask_test_app, endpoint_ending, expected_method "endpoint_name, expected_methods", [ pytest.param( - f"{config.datagateway_api.extension}/sessions", + f"{Config.config.datagateway_api.extension}/sessions", ["DELETE", "GET", "POST", "PUT"], id="sessions", ), pytest.param( - f"{config.datagateway_api.extension}/instruments/" + f"{Config.config.datagateway_api.extension}/instruments/" f"/facilitycycles", ["GET"], id="ISIS instrument's facility cycles", ), pytest.param( - f"{config.datagateway_api.extension}/instruments/" + f"{Config.config.datagateway_api.extension}/instruments/" f"/facilitycycles/count", ["GET"], id="count ISIS instrument's facility cycles", ), pytest.param( - f"{config.datagateway_api.extension}/instruments/" - "/facilitycycles//investigations", + f"{Config.config.datagateway_api.extension}/instruments" + "//facilitycycles//investigations", ["GET"], id="ISIS investigations", ), pytest.param( - f"{config.datagateway_api.extension}/instruments/" - f"/facilitycycles//investigations/count", + f"{Config.config.datagateway_api.extension}/instruments" + "//facilitycycles//investigations" + "/count", ["GET"], id="count ISIS investigations", ), pytest.param( - f"{config.search_api.extension}/datasets", + f"{Config.config.search_api.extension}/datasets", ["GET"], id="Search API search datasets", ), pytest.param( - f"{config.search_api.extension}/documents", + f"{Config.config.search_api.extension}/documents", ["GET"], id="Search API search documents", ), pytest.param( - f"{config.search_api.extension}/instruments", + f"{Config.config.search_api.extension}/instruments", ["GET"], id="Search API search instruments", ), pytest.param( - f"{config.search_api.extension}/datasets/", + f"{Config.config.search_api.extension}/datasets/", ["GET"], id="Search API get single dataset", ), pytest.param( - f"{config.search_api.extension}/documents/", + f"{Config.config.search_api.extension}/documents/", ["GET"], id="Search API get single document", ), pytest.param( - f"{config.search_api.extension}/instruments/", + f"{Config.config.search_api.extension}/instruments/", ["GET"], id="Search API get single instrument", ), pytest.param( - f"{config.search_api.extension}/datasets/count", + f"{Config.config.search_api.extension}/datasets/count", ["GET"], id="Search API dataset count", ), pytest.param( - f"{config.search_api.extension}/documents/count", + f"{Config.config.search_api.extension}/documents/count", ["GET"], id="Search API document count", ), pytest.param( - f"{config.search_api.extension}/instruments/count", + f"{Config.config.search_api.extension}/instruments/count", ["GET"], id="Search API instrument count", ), pytest.param( - f"{config.search_api.extension}/datasets//files", + f"{Config.config.search_api.extension}/datasets//files", ["GET"], id="Search API get dataset files", ), pytest.param( - f"{config.search_api.extension}/datasets//files/count", + f"{Config.config.search_api.extension}/datasets//files/count", ["GET"], id="Search API dataset files count", ), diff --git a/test/test_query_filter.py b/test/test_query_filter.py index 0024ad63..0148d6cd 100644 --- a/test/test_query_filter.py +++ b/test/test_query_filter.py @@ -1,6 +1,6 @@ import pytest -import datagateway_api.src.common.config as config +from datagateway_api.src.common.config import Config from datagateway_api.src.common.exceptions import ApiError from datagateway_api.src.common.filters import QueryFilter from datagateway_api.src.datagateway_api.query_filter_factory import QueryFilterFactory @@ -23,6 +23,6 @@ class DummyQueryFilter(QueryFilter): assert qf.apply_filter(apply_filter) is None def test_invalid_query_filter_getter(self): - config.config.datagateway_api.backend = "invalid_backend" + Config.config.datagateway_api.backend = "invalid_backend" with pytest.raises(ApiError): QueryFilterFactory.get_query_filter({"order": "id DESC"}) diff --git a/util/icat_db_generator.py b/util/icat_db_generator.py index dc759a1c..3c295c35 100644 --- a/util/icat_db_generator.py +++ b/util/icat_db_generator.py @@ -8,7 +8,7 @@ from sqlalchemy.orm import scoped_session, sessionmaker from sqlalchemy.pool import QueuePool -from datagateway_api.src.common.config import config +from datagateway_api.src.common.config import Config from datagateway_api.src.datagateway_api.database import models parser = argparse.ArgumentParser() @@ -36,7 +36,10 @@ engine = create_engine( - config.datagateway_api.db_url, poolclass=QueuePool, pool_size=100, max_overflow=0, + Config.config.datagateway_api.db_url, + poolclass=QueuePool, + pool_size=100, + max_overflow=0, ) session_factory = sessionmaker(engine) session = scoped_session(session_factory)()