Skip to content

Commit

Permalink
Merge branch 'master' into respect-config-for-search-api-endpoints-#283
Browse files Browse the repository at this point in the history
  • Loading branch information
MRichards99 committed Nov 22, 2021
2 parents 6aac97b + 44c48e8 commit a5ce9fa
Show file tree
Hide file tree
Showing 10 changed files with 102 additions and 17 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/ci-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: '3.9'
python-version: '3.9.7'
architecture: x64
- name: Checkout DataGateway API
uses: actions/checkout@v2
Expand All @@ -117,7 +117,7 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: '3.9'
python-version: '3.9.7'
architecture: x64
- name: Checkout DataGateway API
uses: actions/checkout@v2
Expand All @@ -137,7 +137,7 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: '3.9'
python-version: '3.9.7'
architecture: x64
- name: Checkout DataGateway API
uses: actions/checkout@v2
Expand Down Expand Up @@ -167,7 +167,7 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: '3.9'
python-version: '3.9.7'
architecture: x64

# ICAT Ansible clone and install dependencies
Expand Down
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,21 @@

<!--next-version-placeholder-->

## v1.1.0 (2021-11-19)
### Feature
* Add unimplemented endpoint definitions for search API #257 ([`d0e52d9`](https://github.com/ral-facilities/datagateway-api/commit/d0e52d96dd3b94ce54dcc9b81969e777a196922a))

### Documentation
* Rebuild openapi docs #257 ([`de15357`](https://github.com/ral-facilities/datagateway-api/commit/de1535772db64916f75e16d79be3f3fdf10fc47c))

## v1.0.1 (2021-11-15)
### Fix
* Add PID field for study in DB backend #287 ([`18379be`](https://github.com/ral-facilities/datagateway-api/commit/18379becafd23ff2957e556de2bd3fc210a71f5b))
* Add generation of study.pid #287 ([`f6a8ebc`](https://github.com/ral-facilities/datagateway-api/commit/f6a8ebc6c775ba3f5252d5af5cedc4e1e0e79a40))

### Documentation
* Add study PID to swagger docs #287 ([`89a9e27`](https://github.com/ral-facilities/datagateway-api/commit/89a9e27b72dfe1d474d49a721f128a643ef2ae36))

## v1.0.0 (2021-11-03)
### Breaking
* As the API will be approaching production use soon, this seems like a good opportunity to bump the version to 1.0.0. This also serves as a good test that the introduction of automatic versioning actually works ([`ccf6d29`](https://github.com/ral-facilities/datagateway-api/commit/ccf6d2974216f8979a03e3e223f7c9e84ced05cb))
Expand Down
5 changes: 1 addition & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -314,10 +314,7 @@ fix: fix bug found with count endpoints #issue-number
feat: add endpoints for search API #issue-number
# Commit which introduces a breaking change for users
BREAKING CHANGE: change format of `config.json`, the previous version is no longer supported #issue-number
# You can also use `BREAKING CHANGE:` in the additional information if the commit also adds a new feature, like so:
feat: my new feature #issue-number
<commit-type>: change format of `config.json`, the previous version is no longer supported #issue-number
BREAKING CHANGE: this feature means X functionality has been removed
```
Expand Down
60 changes: 53 additions & 7 deletions datagateway_api/src/common/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,24 @@
log = logging.getLogger()


def validate_extension(extension):
"""
Checks that the API extension starts and does not end with a '/'. An error is
raised, at which point the application exits, if the extension does not meet
these validation rules.
:param extension: The extension for the API
"""
extension = extension.strip()

if not extension.startswith("/"):
raise ValueError("must start with '/'")
if extension.endswith("/"):
raise ValueError("must not end with '/'")

return extension


class DataGatewayAPI(BaseModel):
"""
Configuration model class that implements pydantic's BaseModel class to allow for
Expand All @@ -34,16 +52,18 @@ class DataGatewayAPI(BaseModel):
icat_check_cert: Optional[StrictBool]
icat_url: Optional[StrictStr]

_validate_extension = validator("extension", allow_reuse=True)(validate_extension)

@validator("db_url", always=True)
def require_db_config_value(cls, value, values): # noqa: B902, N805
"""
By default the `db_url` config field is optional so that it does not have to be
present in the config file if `backend` is set to `python_icat`. However, if the
`backend` is set to `db`, this validator esentially makes the `db_url` config
field mandatory. This means that if the an error is raised, at which point the
field mandatory. This means that an error is raised, at which point the
application exits, if a `db_url` config value is not present in the config file.
:param cls: :class:`APIConfig` pointer
:param cls: :class:`DataGatewayAPI` pointer
:param value: The value of the given config field
:param values: The config field values loaded before the given config field
"""
Expand All @@ -62,13 +82,13 @@ def require_db_config_value(cls, value, values): # noqa: B902, N805
def require_icat_config_value(cls, value, values): # noqa: B902, N805
"""
By default the above config fields that are passed to the `@validator` decorator
are optional so that they not have to be present in the config file if `backend`
is set to `db`. However, if the `backend` is set to `python_icat`, this
validator esentially makes these config fields mandatory. This means that an
error is raised, at which point the application exits, if any of these config
are optional so that they do not have to be present in the config file if
`backend` is set to `db`. However, if the `backend` is set to `python_icat`,
this validator esentially makes these config fields mandatory. This means that
an error is raised, at which point the application exits, if any of these config
values are not present in the config file.
:param cls: :class:`APIConfig` pointer
:param cls: :class:`DataGatewayAPI` pointer
:param value: The value of the given config field
:param values: The config field values loaded before the given config field
"""
Expand Down Expand Up @@ -112,6 +132,8 @@ class SearchAPI(BaseModel):
icat_check_cert: StrictBool
icat_url: StrictStr

_validate_extension = validator("extension", allow_reuse=True)(validate_extension)


class TestUserCredentials(BaseModel):
username: StrictStr
Expand Down Expand Up @@ -158,6 +180,7 @@ def load(cls, path=Path(__file__).parent.parent.parent / "config.json"):
model. Exits the application if it fails to locate the JSON config file or
the APIConfig model validation fails.
:param cls: :class:`APIConfig` pointer
:param path: path to the configuration file
:return: APIConfig model object that contains the config data
"""
Expand All @@ -168,5 +191,28 @@ def load(cls, path=Path(__file__).parent.parent.parent / "config.json"):
except (IOError, ValidationError) as error:
sys.exit(f"An error occurred while trying to load the config data: {error}")

@validator("search_api")
def validate_api_extensions(cls, value, values): # noqa: B902, N805
"""
Checks that the DataGateway API and Search API extensions are not the same. An
error is raised, at which point the application exits, if the extensions are the
same.
:param cls: :class:`APIConfig` pointer
:param value: The value of the given config field
:param values: The config field values loaded before the given config field
"""
if (
"datagateway_api" in values
and values["datagateway_api"] is not None
and value is not None
and values["datagateway_api"].extension == value.extension
):
raise ValueError(
"extension cannot be the same as datagateway_api extension",
)

return value


config = APIConfig.load()
1 change: 1 addition & 0 deletions datagateway_api/src/datagateway_api/database/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1229,6 +1229,7 @@ class STUDY(Base, EntityHelper, metaclass=EntityMeta):
modId = Column("MOD_ID", String(255), nullable=False)
modTime = Column("MOD_TIME", DateTime, nullable=False)
name = Column("NAME", String(255), nullable=False)
pid = Column("PID", String(255))
startDate = Column("STARTDATE", DateTime)
status = Column("STATUS", Integer)
userID = Column("USER_ID", ForeignKey("USER_.ID"), index=True)
Expand Down
2 changes: 2 additions & 0 deletions datagateway_api/src/swagger/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1659,6 +1659,8 @@ components:
type: string
name:
type: string
pid:
type: string
startDate:
format: datetime
type: string
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "datagateway-api"
version = "1.0.0"
version = "1.1.0"
description = "ICAT API to interface with the DataGateway"
license = "Apache-2.0"
readme = "README.md"
Expand Down
22 changes: 22 additions & 0 deletions test/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,28 @@ def test_load_with_datagateway_api_icat_backend_and_missing_icat_config_data(
with pytest.raises(SystemExit):
APIConfig.load("test/path")

def test_load_with_invalid_api_extension_does_not_start_with_slash(
self, test_config_data,
):
test_config_data["datagateway_api"]["extension"] = "datagateway-api"
with patch("builtins.open", mock_open(read_data=json.dumps(test_config_data))):
with pytest.raises(SystemExit):
APIConfig.load("test/path")

def test_load_with_invalid_api_extension_ends_with_slash(
self, test_config_data,
):
test_config_data["search_api"]["extension"] = "/search-api/"
with patch("builtins.open", mock_open(read_data=json.dumps(test_config_data))):
with pytest.raises(SystemExit):
APIConfig.load("test/path")

def test_load_with_same_api_extensions(self, test_config_data):
test_config_data["search_api"]["extension"] = "/datagateway-api"
with patch("builtins.open", mock_open(read_data=json.dumps(test_config_data))):
with pytest.raises(SystemExit):
APIConfig.load("test/path")

def test_set_backend_type(self, test_config):
test_config.datagateway_api.set_backend_type("backend_name_changed")

Expand Down
1 change: 0 additions & 1 deletion test/test_query_filter.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import pytest


import datagateway_api.src.common.config as config
from datagateway_api.src.common.exceptions import ApiError
from datagateway_api.src.common.filters import QueryFilter
Expand Down
3 changes: 3 additions & 0 deletions util/icat_db_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,8 @@ def generate_user_groups(i):
class StudyGenerator(Generator):
tier = 3
amount = UserGenerator.amount
pid_faker = Faker()
pid_faker.seed_instance(SEED)

def generate(self):
for i in range(1, self.amount):
Expand All @@ -431,6 +433,7 @@ def generate_studies(i):
apply_common_attributes(study, i)
study.startDate = get_start_date(i)
study.status = faker.random_int(0, 1)
study.pid = StudyGenerator.pid_faker.isbn10(separator="-")
study.userID = i
post_entity(study)

Expand Down

0 comments on commit a5ce9fa

Please sign in to comment.