Skip to content

Commit

Permalink
Update hexit and small improvements (#30)
Browse files Browse the repository at this point in the history
  • Loading branch information
Cito authored Jul 25, 2023
1 parent 1d0a324 commit 25e1d2a
Show file tree
Hide file tree
Showing 14 changed files with 162 additions and 45 deletions.
1 change: 1 addition & 0 deletions .static_files
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ scripts/script_utils/__init__.py
scripts/script_utils/cli.py

scripts/__init__.py
scripts/update_all.py
scripts/license_checker.py
scripts/get_package_name.py
scripts/update_config_docs.py
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,21 +62,21 @@ We recommend using the provided Docker container.

A pre-build version is available at [docker hub](https://hub.docker.com/repository/docker/ghga/metldata):
```bash
docker pull ghga/metldata:0.3.6
docker pull ghga/metldata:0.3.7
```

Or you can build the container yourself from the [`./Dockerfile`](./Dockerfile):
```bash
# Execute in the repo's root dir:
docker build -t ghga/metldata:0.3.6 .
docker build -t ghga/metldata:0.3.7 .
```

For production-ready deployment, we recommend using Kubernetes, however,
for simple use cases, you could execute the service using docker
on a single server:
```bash
# The entrypoint is preconfigured:
docker run -p 8080:8080 ghga/metldata:0.3.6 --help
docker run -p 8080:8080 ghga/metldata:0.3.7 --help
```

If you prefer not to use containers, you may install the service from source:
Expand Down
2 changes: 1 addition & 1 deletion metldata/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@

"""Short description of package""" # Please adapt to package

__version__ = "0.3.6"
__version__ = "0.3.7"
33 changes: 14 additions & 19 deletions metldata/model_utils/essentials.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import json
from contextlib import contextmanager
from copy import copy, deepcopy
from functools import lru_cache
from pathlib import Path
from tempfile import NamedTemporaryFile
from typing import Any, Generator
Expand All @@ -36,16 +35,11 @@
ROOT_CLASS = "Submission"


@lru_cache
def schema_view_from_model(model: MetadataModel) -> SchemaView:
"""Get a schema view instance from the metadata model."""

return ExportableSchemaView(model)


class MetadataModel(SchemaDefinition):
"""A dataclass for describing metadata models."""

_schema_view = None

@classmethod
def init_from_path(cls, model_path: Path) -> MetadataModel:
"""Initialize from a model file in yaml format."""
Expand All @@ -58,13 +52,19 @@ def init_from_path(cls, model_path: Path) -> MetadataModel:
@property
def schema_view(self) -> ExportableSchemaView:
"""Get a schema view instance from the metadata model."""
schema_view = self._schema_view
if schema_view is None:
schema_view = ExportableSchemaView(self)
self._schema_view = schema_view
return schema_view

return schema_view_from_model(self)

def copy(self) -> MetadataModel:
"""Copy the model."""

return deepcopy(self)
def __deepcopy__(self, memo: Any):
"""Return a deep copy of the model."""
schema_view = self._schema_view
self._schema_view = None
copied_model = deepcopy(super())
self._schema_view = schema_view
return copied_model

def __eq__(self, other: object):
"""For comparisons."""
Expand Down Expand Up @@ -141,11 +141,6 @@ def temporary_yaml_path(self) -> Generator[Path, None, None]:
file.flush()
yield Path(file.name)

def __hash__(self):
"""Return a hash of the model."""

return hash(self.as_json())


class ExportableSchemaView(SchemaView):
"""Extend the SchemaView by adding a method for exporting a MetadataModel."""
Expand Down
6 changes: 3 additions & 3 deletions metldata/transform/handling.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
)


class WorkflowConfigMissmatchError(RuntimeError):
class WorkflowConfigMismatchError(RuntimeError):
"""Raised when the provided workflow config does not match the config class of the
workflow definition.
"""
Expand Down Expand Up @@ -140,11 +140,11 @@ def check_workflow_config(
definition.
Raises:
WorkflowConfigMissmatchError:
WorkflowConfigMismatchError:
"""

if workflow_config.schema_json() == workflow_definition.schema_json():
raise WorkflowConfigMissmatchError(
raise WorkflowConfigMismatchError(
workflow_definition=workflow_definition, workflow_config=workflow_config
)

Expand Down
51 changes: 51 additions & 0 deletions scripts/update_all.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/usr/bin/env python3

# Copyright 2021 - 2023 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
# for the German Human Genome-Phenome Archive (GHGA)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

"""Run all update scripts that are present in the repository in the correct order"""

try:
from scripts.update_template_files import main as update_template
except ImportError:
pass
else:
print("Pulling in updates from template repository")
update_template()

try:
from scripts.update_config_docs import main as update_config
except ImportError:
pass
else:
print("Updating config docs")
update_config()

try:
from scripts.update_openapi_docs import main as update_openapi
except ImportError:
pass
else:
print("Updating OpenAPI docs")
update_openapi()

try:
from scripts.update_readme import main as update_readme
except ImportError:
pass
else:
print("Updating README")
update_readme()
7 changes: 4 additions & 3 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,11 @@ zip_safe = False
include_package_data = True
packages = find:
install_requires =
hexkit[mongodb]==0.10.0
ghga-service-commons[api,auth]==0.4.2
hexkit[mongodb]==0.10.2
ghga-service-commons[api,auth]==0.4.3
typer==0.7.0
linkml-runtime==1.4.2
linkml==1.5.6
linkml-runtime==1.5.5
linkml-validator==0.4.5

python_requires = >= 3.9
Expand Down
13 changes: 9 additions & 4 deletions tests/artifact_rest/test_api_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@
from fastapi import FastAPI
from ghga_service_commons.api.testing import AsyncTestClient
from hexkit.protocols.dao import DaoFactoryProtocol
from hexkit.providers.mongodb.testutils import mongodb_fixture # noqa: F401
from hexkit.providers.mongodb.testutils import MongoDbFixture

from metldata.artifacts_rest.api_factory import rest_api_factory
from metldata.artifacts_rest.artifact_info import ArtifactInfo
from tests.artifact_rest.test_load_artifacts import load_example_artifact_resources
from tests.fixtures.artifact_info import EXAMPLE_ARTIFACT_INFOS, MINIMAL_ARTIFACT_INFO
from tests.fixtures.mongodb import ( # noqa: F401; pylint: disable=unused-import
MongoDbFixture,
mongodb_fixture,
)


@pytest.mark.asyncio
Expand All @@ -48,7 +50,9 @@ async def get_example_app_client(


@pytest.mark.asyncio
async def test_artifacts_info_endpoint(mongodb_fixture: MongoDbFixture): # noqa: F811
async def test_artifacts_info_endpoint(
mongodb_fixture: MongoDbFixture, # noqa: F811
):
"""Test happy path of using the artifacts info endpoint."""

expected_infos = EXAMPLE_ARTIFACT_INFOS
Expand Down Expand Up @@ -99,7 +103,8 @@ async def test_get_artifact_resource_endpoint(
class_name = "File"
resource_id = "test_sample_01_R1"
async with await get_example_app_client(
dao_factory=mongodb_fixture.dao_factory, artifact_infos=[MINIMAL_ARTIFACT_INFO]
dao_factory=mongodb_fixture.dao_factory,
artifact_infos=[MINIMAL_ARTIFACT_INFO],
) as client:
response = await client.get(
f"/artifacts/{artifact_name}/classes/{class_name}/resources/{resource_id}"
Expand Down
10 changes: 7 additions & 3 deletions tests/artifact_rest/test_load_artifacts.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,16 @@

import pytest
from hexkit.protocols.dao import DaoFactoryProtocol
from hexkit.providers.mongodb.testutils import mongodb_fixture # noqa: F401
from hexkit.providers.mongodb.testutils import MongoDbFixture

from metldata.artifacts_rest.artifact_dao import ArtifactDaoCollection
from metldata.artifacts_rest.load_resources import load_artifact_resources
from metldata.artifacts_rest.models import ArtifactResource
from tests.fixtures.artifact_info import MINIMAL_ARTIFACT_INFO
from tests.fixtures.metadata import VALID_MINIMAL_METADATA_EXAMPLE
from tests.fixtures.mongodb import ( # noqa: F401; pylint: disable=unused-import
MongoDbFixture,
mongodb_fixture,
)


async def load_example_artifact_resources(
Expand All @@ -51,7 +53,9 @@ async def load_example_artifact_resources(


@pytest.mark.asyncio
async def test_load_artifact_resources(mongodb_fixture: MongoDbFixture): # noqa: F811
async def test_load_artifact_resources(
mongodb_fixture: MongoDbFixture, # noqa: F811
):
"""Test happy path of using load_artifact_resources function."""

dao_collection = await load_example_artifact_resources(
Expand Down
10 changes: 7 additions & 3 deletions tests/artifact_rest/test_query_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,20 @@
"""Test the query_resource module."""

import pytest
from hexkit.providers.mongodb.testutils import mongodb_fixture # noqa: F401
from hexkit.providers.mongodb.testutils import MongoDbFixture

from metldata.artifacts_rest.query_resources import query_artifact_resource
from tests.artifact_rest.test_load_artifacts import load_example_artifact_resources
from tests.fixtures.artifact_info import MINIMAL_ARTIFACT_INFO
from tests.fixtures.mongodb import ( # noqa: F401; pylint: disable=unused-import
MongoDbFixture,
mongodb_fixture,
)


@pytest.mark.asyncio
async def test_query_artifact_resource(mongodb_fixture: MongoDbFixture): # noqa: F811
async def test_query_artifact_resource(
mongodb_fixture: MongoDbFixture, # noqa: F811
):
"""Test happy path of using the query_artifact_resource function."""

# load example resources and prepare client:
Expand Down
24 changes: 24 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Copyright 2021 - 2023 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
# for the German Human Genome-Phenome Archive (GHGA)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

""""Shared fixtures"""

from hexkit.providers.mongodb.testutils import get_mongodb_fixture
from hexkit.providers.testing.utils import get_event_loop

event_loop = get_event_loop(scope="session")

mongodb_session = get_mongodb_fixture(scope="session")
6 changes: 3 additions & 3 deletions tests/fixtures/event_handling.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
)


class EventExpectationMissmatch(RuntimeError):
class EventExpectationMismatch(RuntimeError):
"""Raised when expected events where not found."""

def __init__(self, expected_events: set[str], consumed_events: set[str]):
Expand All @@ -49,7 +49,7 @@ def expect_events(self, expected_events: list[Event]) -> None:
"""Check if the events expected to be published can be consumed.
Raises:
EventExpectationMissmatch: If the expected events are not consumed.
EventExpectationMismatch: If the expected events are not consumed.
"""

topics = sorted({event.topic for event in expected_events})
Expand All @@ -66,7 +66,7 @@ def expect_events(self, expected_events: list[Event]) -> None:
expected_event_jsons = {event.json() for event in expected_events}

if expected_event_jsons != observed_event_jsons:
raise EventExpectationMissmatch(
raise EventExpectationMismatch(
expected_events=observed_event_jsons,
consumed_events=expected_event_jsons,
)
Expand Down
29 changes: 29 additions & 0 deletions tests/fixtures/mongodb.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Copyright 2021 - 2023 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
# for the German Human Genome-Phenome Archive (GHGA)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

"""Fixture for using the MongoDB."""

from hexkit.providers.mongodb.testutils import MongoDbFixture
from pytest import fixture


@fixture
def mongodb_fixture( # pylint: disable=redefined-outer-name
mongodb_session: MongoDbFixture,
) -> MongoDbFixture:
"""Fixture that gets an empty MongoDB."""
mongodb_session.empty_collections()
return mongodb_session
9 changes: 6 additions & 3 deletions tests/load/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,17 @@
import pytest
from ghga_service_commons.api.testing import AsyncTestClient
from hexkit.protocols.dao import ResourceNotFoundError
from hexkit.providers.mongodb.testutils import mongodb_fixture # noqa: F401
from hexkit.providers.mongodb.testutils import MongoDbFixture

from metldata.artifacts_rest.artifact_dao import ArtifactDaoCollection
from metldata.artifacts_rest.models import ArtifactInfo
from metldata.load.auth import generate_token, generate_token_and_hash
from metldata.load.config import ArtifactLoaderAPIConfig
from metldata.load.main import get_app
from tests.fixtures.artifact_info import EXAMPLE_ARTIFACT_INFOS
from tests.fixtures.mongodb import ( # noqa: F401; pylint: disable=unused-import
MongoDbFixture,
mongodb_fixture,
)
from tests.fixtures.workflows import EXAMPLE_ARTIFACTS


Expand Down Expand Up @@ -81,7 +83,8 @@ async def test_load_artifacts_endpoint_happy(
}

dao_collection = await ArtifactDaoCollection.construct(
dao_factory=mongodb_fixture.dao_factory, artifact_infos=EXAMPLE_ARTIFACT_INFOS
dao_factory=mongodb_fixture.dao_factory,
artifact_infos=EXAMPLE_ARTIFACT_INFOS,
)
dao = await dao_collection.get_dao(
artifact_name=expected_artifact_name, class_name=expected_resource_class
Expand Down

0 comments on commit 25e1d2a

Please sign in to comment.