Skip to content

Commit

Permalink
Specify identifiers and remove public-api module
Browse files Browse the repository at this point in the history
  • Loading branch information
cutoffthetop committed Feb 20, 2024
1 parent c308312 commit d3bd12a
Show file tree
Hide file tree
Showing 45 changed files with 395 additions and 1,656 deletions.
6 changes: 3 additions & 3 deletions mex/common/backend_api/connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from mex.common.backend_api.models import BulkInsertResponse
from mex.common.connector import HTTPConnector
from mex.common.models import MExModel
from mex.common.models import ExtractedData
from mex.common.settings import BaseSettings
from mex.common.types import Identifier

Expand All @@ -27,7 +27,7 @@ def _set_url(self) -> None:
settings = BaseSettings.get()
self.url = urljoin(str(settings.backend_api_url), self.API_VERSION)

def post_models(self, models: list[MExModel]) -> list[Identifier]:
def post_models(self, models: list[ExtractedData]) -> list[Identifier]:
"""Post models to Backend API in a bulk insertion request.
Args:
Expand All @@ -37,7 +37,7 @@ def post_models(self, models: list[MExModel]) -> list[Identifier]:
HTTPError: If insert was not accepted, crashes or times out
Returns:
Identifiers of posted models
Identifiers of posted extracted models
"""
response = self.request(
method="POST",
Expand Down
8 changes: 4 additions & 4 deletions mex/common/identity/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from mex.common.connector import BaseConnector
from mex.common.identity.models import Identity
from mex.common.types import Identifier, PrimarySourceID
from mex.common.types import AnyMergedIdentifier, MergedPrimarySourceIdentifier


class BaseProvider(BaseConnector):
Expand All @@ -11,7 +11,7 @@ class BaseProvider(BaseConnector):
@abstractmethod
def assign(
self,
had_primary_source: PrimarySourceID,
had_primary_source: MergedPrimarySourceIdentifier,
identifier_in_primary_source: str,
) -> Identity: # pragma: no cover
"""Find an Identity in a database or assign a new one."""
Expand All @@ -21,9 +21,9 @@ def assign(
def fetch(
self,
*,
had_primary_source: Identifier | None = None,
had_primary_source: MergedPrimarySourceIdentifier | None = None,
identifier_in_primary_source: str | None = None,
stable_target_id: Identifier | None = None,
stable_target_id: AnyMergedIdentifier | None = None,
) -> list[Identity]: # pragma: no cover
"""Find Identity instances matching the given filters."""
...
14 changes: 10 additions & 4 deletions mex/common/identity/memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
MEX_PRIMARY_SOURCE_IDENTIFIER_IN_PRIMARY_SOURCE,
MEX_PRIMARY_SOURCE_STABLE_TARGET_ID,
)
from mex.common.types import Identifier, PrimarySourceID
from mex.common.types import (
AnyMergedIdentifier,
Identifier,
MergedPrimarySourceIdentifier,
)


class MemoryIdentityProvider(BaseProvider):
Expand All @@ -22,7 +26,9 @@ def __init__(self) -> None:
]

def assign(
self, had_primary_source: PrimarySourceID, identifier_in_primary_source: str
self,
had_primary_source: MergedPrimarySourceIdentifier,
identifier_in_primary_source: str,
) -> Identity:
"""Find an Identity in the in-memory database or assign a new one.
Expand Down Expand Up @@ -52,9 +58,9 @@ def assign(
def fetch(
self,
*,
had_primary_source: Identifier | None = None,
had_primary_source: MergedPrimarySourceIdentifier | None = None,
identifier_in_primary_source: str | None = None,
stable_target_id: Identifier | None = None,
stable_target_id: AnyMergedIdentifier | None = None,
) -> list[Identity]:
"""Find Identity instances in the in-memory database.
Expand Down
4 changes: 2 additions & 2 deletions mex/common/identity/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
from pydantic import Field

from mex.common.models import BaseModel
from mex.common.types import Identifier, PrimarySourceID
from mex.common.types import Identifier, MergedPrimarySourceIdentifier


class Identity(BaseModel):
"""Model for identifier lookup."""

identifier: Annotated[Identifier, Field(frozen=True)]
hadPrimarySource: Annotated[PrimarySourceID, Field(frozen=True)]
hadPrimarySource: Annotated[MergedPrimarySourceIdentifier, Field(frozen=True)]
identifierInPrimarySource: Annotated[str, Field(frozen=True)]
stableTargetId: Annotated[Identifier, Field(frozen=True)]
2 changes: 1 addition & 1 deletion mex/common/ldap/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ The module `ldap.transform` contains functions for transforming LDAP data into M
models.

The `mex_person.stableTargetId` attribute can be used in any entity that requires a
`PersonID`.
`MergedPersonIdentifier`.

# Convenience Functions

Expand Down
40 changes: 21 additions & 19 deletions mex/common/ldap/extract.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@
from mex.common.identity import get_provider
from mex.common.ldap.models.person import LDAPPerson, LDAPPersonWithQuery
from mex.common.models import ExtractedPrimarySource
from mex.common.types import PersonID
from mex.common.types import MergedPersonIdentifier


def _get_merged_ids_by_attribute(
attribute: str,
persons: Iterable[LDAPPerson],
primary_source: ExtractedPrimarySource,
) -> dict[str, list[PersonID]]:
"""Return a mapping from a dynamic Person attribute to corresponding PersonIDs.
) -> dict[str, list[MergedPersonIdentifier]]:
"""Return mapping from dynamic Person attribute to corresponding merged person ids.
PersonIDs are looked up in the identity provider and will be omitted
MergedPersonIdentifiers are looked up in the identity provider and will be omitted
for any person that has not yet been assigned an `Identity` there.
Args:
Expand All @@ -23,7 +23,8 @@ def _get_merged_ids_by_attribute(
primary_source: Primary source for LDAP
Returns:
Mapping from a stringified `LDAPPerson[attribute]` to corresponding PersonIDs
Mapping from a stringified `LDAPPerson[attribute]` to corresponding
MergedPersonIdentifiers
"""
if attribute not in LDAPPerson.model_fields:
raise RuntimeError(f"Not a valid LDAPPerson field: {attribute}")
Expand All @@ -35,62 +36,63 @@ def _get_merged_ids_by_attribute(
identifier_in_primary_source=str(person.objectGUID),
):
merged_ids_by_attribute[str(getattr(person, attribute))].append(
PersonID(identities[0].stableTargetId)
MergedPersonIdentifier(identities[0].stableTargetId)
)
return merged_ids_by_attribute


def get_merged_ids_by_employee_ids(
persons: Iterable[LDAPPerson], primary_source: ExtractedPrimarySource
) -> dict[str, list[PersonID]]:
"""Return a mapping from a person's employeeID to their PersonIDs.
) -> dict[str, list[MergedPersonIdentifier]]:
"""Return a mapping from a person's employeeID to their merged person ids.
PersonIDs are looked up in the identity provider and will be omitted
MergedPersonIdentifiers are looked up in the identity provider and will be omitted
for any person that has not yet been assigned an `Identity` there.
Args:
persons: Iterable of LDAP persons
primary_source: Primary source for LDAP
Returns:
Mapping from `LDAPPerson.employeeID` to corresponding PersonIDs
Mapping from `LDAPPerson.employeeID` to corresponding MergedPersonIdentifiers
"""
return _get_merged_ids_by_attribute("employeeID", persons, primary_source)


def get_merged_ids_by_email(
persons: Iterable[LDAPPerson], primary_source: ExtractedPrimarySource
) -> dict[str, list[PersonID]]:
"""Return a mapping from a person's e-mail to their PersonIDs.
) -> dict[str, list[MergedPersonIdentifier]]:
"""Return a mapping from a person's e-mail to their merged person ids.
PersonIDs are looked up in the identity provider and will be omitted
MergedPersonIdentifiers are looked up in the identity provider and will be omitted
for any person that has not yet been assigned an `Identity` there.
Args:
persons: Iterable of LDP persons
primary_source: Primary source for LDAP
Returns:
Mapping from `LDAPPerson.mail` to corresponding PersonIDs
Mapping from `LDAPPerson.mail` to corresponding MergedPersonIdentifiers
"""
return _get_merged_ids_by_attribute("mail", persons, primary_source)


def get_merged_ids_by_query_string(
persons_with_query: Iterable[LDAPPersonWithQuery],
primary_source: ExtractedPrimarySource,
) -> dict[str, list[PersonID]]:
"""Return a mapping from a person query string to their PersonIDs.
) -> dict[str, list[MergedPersonIdentifier]]:
"""Return a mapping from a person query string to their merged person ids.
PersonIDs are looked up in the identity provider and will be omitted
MergedPersonIdentifiers are looked up in the identity provider and will be omitted
for any person that has not yet been assigned an `Identity` there.
Args:
persons_with_query: Iterable of LDP persons with query
primary_source: Primary source for LDAP
Returns:
Mapping from `LDAPPersonWithQuery.query` to corresponding PersonIDs
Mapping from `LDAPPersonWithQuery.query` to corresponding
MergedPersonIdentifiers
"""
merged_ids_by_attribute = defaultdict(list)
provider = get_provider()
Expand All @@ -100,6 +102,6 @@ def get_merged_ids_by_query_string(
identifier_in_primary_source=str(person_with_query.person.objectGUID),
):
merged_ids_by_attribute[str(person_with_query.query)].append(
PersonID(identities[0].stableTargetId)
MergedPersonIdentifier(identities[0].stableTargetId)
)
return merged_ids_by_attribute
21 changes: 14 additions & 7 deletions mex/common/models/access_platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@
from mex.common.models.extracted_data import ExtractedData
from mex.common.models.merged_item import MergedItem
from mex.common.types import (
AccessPlatformID,
APIType,
ContactPointID,
ExtractedAccessPlatformIdentifier,
Link,
OrganizationalUnitID,
PersonID,
MergedAccessPlatformIdentifier,
MergedContactPointIdentifier,
MergedOrganizationalUnitIdentifier,
MergedPersonIdentifier,
TechnicalAccessibility,
Text,
)
Expand All @@ -21,7 +22,11 @@ class BaseAccessPlatform(BaseModel):
"""A way of physically accessing the Resource for re-use."""

alternativeTitle: list[Text] = []
contact: list[OrganizationalUnitID | PersonID | ContactPointID] = []
contact: list[
MergedOrganizationalUnitIdentifier
| MergedPersonIdentifier
| MergedContactPointIdentifier
] = []
description: list[Text] = []
endpointDescription: Link | None = None
endpointType: (
Expand All @@ -35,7 +40,7 @@ class BaseAccessPlatform(BaseModel):
Field(examples=["https://mex.rki.de/item/technical-accessibility-1"]),
]
title: list[Text] = []
unitInCharge: list[OrganizationalUnitID] = []
unitInCharge: list[MergedOrganizationalUnitIdentifier] = []


class ExtractedAccessPlatform(BaseAccessPlatform, ExtractedData):
Expand All @@ -44,7 +49,8 @@ class ExtractedAccessPlatform(BaseAccessPlatform, ExtractedData):
entityType: Literal["ExtractedAccessPlatform"] = Field(
"ExtractedAccessPlatform", alias="$type", frozen=True
)
stableTargetId: AccessPlatformID
identifier: Annotated[ExtractedAccessPlatformIdentifier, Field(frozen=True)]
stableTargetId: MergedAccessPlatformIdentifier


class MergedAccessPlatform(BaseAccessPlatform, MergedItem):
Expand All @@ -53,3 +59,4 @@ class MergedAccessPlatform(BaseAccessPlatform, MergedItem):
entityType: Literal["MergedAccessPlatform"] = Field(
"MergedAccessPlatform", alias="$type", frozen=True
)
identifier: Annotated[MergedAccessPlatformIdentifier, Field(frozen=True)]
38 changes: 24 additions & 14 deletions mex/common/models/activity.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
from mex.common.models.extracted_data import ExtractedData
from mex.common.models.merged_item import MergedItem
from mex.common.types import (
ActivityID,
ActivityType,
ContactPointID,
ExtractedActivityIdentifier,
Link,
OrganizationalUnitID,
OrganizationID,
PersonID,
MergedActivityIdentifier,
MergedContactPointIdentifier,
MergedOrganizationalUnitIdentifier,
MergedOrganizationIdentifier,
MergedPersonIdentifier,
Text,
Theme,
Timestamp,
Expand All @@ -33,25 +34,32 @@ class BaseActivity(BaseModel):
] = []
alternativeTitle: list[Text] = []
contact: Annotated[
list[OrganizationalUnitID | PersonID | ContactPointID,], Field(min_length=1)
list[
MergedOrganizationalUnitIdentifier
| MergedPersonIdentifier
| MergedContactPointIdentifier,
],
Field(min_length=1),
]
documentation: list[Link] = []
end: list[
Annotated[Timestamp, Field(examples=["2024-01-17", "2024", "2024-01"])]
] = []
externalAssociate: list[OrganizationID | PersonID] = []
funderOrCommissioner: list[OrganizationID] = []
externalAssociate: list[MergedOrganizationIdentifier | MergedPersonIdentifier] = []
funderOrCommissioner: list[MergedOrganizationIdentifier] = []
fundingProgram: list[str] = []
involvedPerson: list[PersonID] = []
involvedUnit: list[OrganizationalUnitID] = []
isPartOfActivity: list[ActivityID] = []
involvedPerson: list[MergedPersonIdentifier] = []
involvedUnit: list[MergedOrganizationalUnitIdentifier] = []
isPartOfActivity: list[MergedActivityIdentifier] = []
publication: list[Link] = []
responsibleUnit: Annotated[list[OrganizationalUnitID], Field(min_length=1)]
responsibleUnit: Annotated[
list[MergedOrganizationalUnitIdentifier], Field(min_length=1)
]
shortName: list[Text] = []
start: list[
Annotated[Timestamp, Field(examples=["2023-01-16", "2023", "2023-02"])]
] = []
succeeds: list[ActivityID] = []
succeeds: list[MergedActivityIdentifier] = []
theme: list[
Annotated[Theme, Field(examples=["https://mex.rki.de/item/theme-1"])]
] = []
Expand All @@ -65,7 +73,8 @@ class ExtractedActivity(BaseActivity, ExtractedData):
entityType: Literal["ExtractedActivity"] = Field(
"ExtractedActivity", alias="$type", frozen=True
)
stableTargetId: ActivityID
identifier: Annotated[ExtractedActivityIdentifier, Field(frozen=True)]
stableTargetId: MergedActivityIdentifier


class MergedActivity(BaseActivity, MergedItem):
Expand All @@ -74,3 +83,4 @@ class MergedActivity(BaseActivity, MergedItem):
entityType: Literal["MergedActivity"] = Field(
"MergedActivity", alias="$type", frozen=True
)
identifier: Annotated[MergedActivityIdentifier, Field(frozen=True)]
Loading

0 comments on commit d3bd12a

Please sign in to comment.