Source code for NekUpload.metadata.user

from __future__ import annotations
from abc import ABC,abstractmethod
from typing import Any
from .identifier import Identifier,IdentifierType

[docs] class InvenioUserInfoFactory: def __init__(self): pass
[docs] @classmethod def create_from_json(cls,json_data: dict[str,Any]) -> InvenioUserInfo: """Create suitable object from json. Note that to figure out which object to create, "type" is used as unique identifier Args: json_data (dict[str,Any]): JSON serialised data Raises: ValueError: _description_ Returns: InvenioUserInfo: An object of this class or subclass """ #"type" in the JSON is used to identify what class to create type_map: dict[str,InvenioUserInfo] = { "personal": InvenioPersonInfo, "organizational": InvenioOrgInfo } user_type = json_data.get("type") if user_type not in type_map: raise ValueError(f"Unknown user info type: {user_type}") return type_map[user_type].from_json(json_data)
[docs] class InvenioUserInfo(ABC): """Base abstract class describing information about a user """ @abstractmethod def __init__(self): """Class initiliaser """ self.id_schemes: set[IdentifierType] = set() self.identifiers: list[Identifier] = []
[docs] def add_identifier(self,identifier: Identifier) -> None: """Add a persistent identifier related to the user Args: identifier (Identifier): Object describing a unique identifier Raises: ValueError: _description_ """ id_type: IdentifierType = identifier.get_id_type() if id_type in self.id_schemes: raise ValueError(f"Cannot have duplicate identifiers of same type for one organisation {id_type}") self.id_schemes.add(id_type) self.identifiers.append(identifier)
[docs] @abstractmethod def get_info(self) -> dict[str,Any]: """Return the json payload package Returns: Dict[str,Any]: JSON representation of the information, formatted for an API call """ identifier_payload = [] for identifier in self.identifiers: payload = { "scheme": identifier.get_id_type().value.lower(), "identifier": identifier.get_id() } identifier_payload.append(payload) data = {} if identifier_payload: data["identifiers"] = identifier_payload return data
[docs] @abstractmethod def to_json_serialisable(self) -> dict[str,Any]: """Return a json serialisable object representing this class Returns: Dict[str,Any]: JSON serialisable object """ data = {} identifiers = [id.to_json_serialisable() for id in self.identifiers] if identifiers: data["identifiers"] = identifiers return data
[docs] @classmethod @abstractmethod def from_json(cls,data: dict[str,Any]) -> InvenioUserInfo: """Deserialise json serialisable object to reconstruct an object of this class. Factory method. Args: data (Dict[str,Any]): JSON serialisable object Returns: InvenioUserInfo: Object """ pass
@abstractmethod def __eq__(self,other: object) -> bool: pass @abstractmethod def __repr__(self) -> bool: return ( f"Identifiers: {self.identifiers}" f"Identifier Types: {sorted(self.id_schemes)}" )
[docs] class InvenioPersonInfo(InvenioUserInfo): """Holds information about a person in the format expected from InvenioRDM. Effectively a model for the InvenioRDM Author as a Person field. """ def __init__(self, given_name: str, family_name: str) -> None: """Class initialiser Args: given_name (str): First name family_name (str): Last name """ super().__init__() self.type: str = "personal" self.given_name: str = given_name self.family_name: str = family_name
[docs] def get_info(self) -> dict[str,Any]: """Return the json payload package, formatted in a way InvenioRDM API expects Returns: Dict[str,Any]: json payload package, formatted in a way InvenioRDM API expects """ data = { "type": self.type, "given_name": self.given_name, "family_name": self.family_name, } return super().get_info() | data
def __str__(self): return f"Person: {self.given_name} {self.family_name}" def __repr__(self) -> str: return ( f"InvenioPersonInfo(given_name={self.given_name!r}, " f"family_name={self.family_name!r})" ) + super().__repr__()
[docs] def to_json_serialisable(self) -> dict[str,Any]: """Return a json serialisable object representing this class Returns: Dict[str,Any]: JSON serialisable object """ data = { "type": self.type, "given_name": self.given_name, "family_name": self.family_name, } return super().to_json_serialisable() | data
[docs] @classmethod def from_json(cls,data: dict[str,Any]) -> 'InvenioPersonInfo': """Deserialise json serialisable object to reconstruct an object of this class. Args: data (Dict[str,Any]): JSON serialisable object Returns: InvenioPersonInfo: Reconstructed object """ given_name = data["given_name"] family_name = data["family_name"] data_identifiers = data.get("identifiers",[])#in case not present in dict identifiers: list[Identifier] = [Identifier.from_json(id) for id in data_identifiers] person = InvenioPersonInfo(given_name,family_name) for identifier in identifiers: person.add_identifier(identifier) return person
def __eq__(self,other: object) -> bool: if not isinstance(other, InvenioPersonInfo): return False return ( self.type == other.type and self.given_name == other.given_name and self.family_name == other.family_name and self.identifiers == other.identifiers )
[docs] class InvenioOrgInfo(InvenioUserInfo): """Holds information about an organisation in the format expected from InvenioRDM. Effectively a model for the InvenioRDM Author as an Organisation field. """ def __init__(self, name: str) -> None: """Class initialiser Args: name (str): Organisation name """ super().__init__() self.type: str = "organizational" self.name: str = name
[docs] def get_info(self) -> dict[str,Any]: """Return the json payload package, formatted in a way InvenioRDM API expects Returns: Dict[str,Any]: json payload package, formatted in a way InvenioRDM API expects """ data = { "type": self.type, "name": self.name, } return super().get_info() | data
def __str__(self): return f"Organisation: {self.name}"
[docs] def to_json_serialisable(self): """Return a json serialisable object representing this class Returns: Dict[str,Any]: JSON serialisable object """ data = { "type": self.type, "name": self.name, } return super().to_json_serialisable() | data
[docs] @classmethod def from_json(cls,data: dict[str,Any]) -> 'InvenioOrgInfo': """Deserialise json serialisable object to reconstruct an object of this class. Args: data (Dict[str,Any]): JSON serialisable object Returns: InvenioOrgInfo: Reconstructed object """ name = data["name"] data_identifiers = data.get("identifiers",[])#in case not present in dict identifiers: list[Identifier] = [Identifier.from_json(id) for id in data_identifiers] org = InvenioOrgInfo(name) for identifier in identifiers: org.add_identifier(identifier) return org
def __eq__(self,other: object) -> bool: if not isinstance(other, InvenioOrgInfo): return False return ( self.type == other.type and self.name == other.name and self.identifiers == other.identifiers ) def __repr__(self) -> str: return ( f"InvenioOrgInfo(name={self.name!r})" ) + super().__repr__()