fairdm.contrib.contributors.utils.transforms#

Data transformation utilities for contributors.

This module provides bidirectional transformations between Contributor objects and various external metadata formats (DataCite, Schema.org, CSL-JSON, ORCID, ROR, etc.).

Module Contents#

Classes#

BaseTransform

Base class for bidirectional contributor data transformations.

DataCiteTransform

Bidirectional transformation for DataCite Metadata Schema 4.4.

SchemaOrgTransform

Bidirectional transformation for Schema.org JSON-LD format.

CSLJSONTransform

Bidirectional transformation for CSL-JSON (Citation Style Language) format.

ORCIDTransform

Bidirectional transformation for ORCID Public API v3.0 data.

RORTransform

Bidirectional transformation for ROR (Research Organization Registry) API data.

Functions#

contributor_to_datacite

Export contributor as DataCite JSON.

contributor_to_schema_org

Export contributor as Schema.org JSON-LD.

contributor_to_csljson

Export contributor as CSL-JSON.

csljson_to_contributor

Import CSL-JSON data as Contributor.

API#

class BaseTransform#

Base class for bidirectional contributor data transformations.

Provides utilities for converting between external data formats and Contributor model instances. Subclasses should implement:

  • export(): Convert Contributor → external format

  • import_data(): Convert external format → Contributor

dictget(data: dict | list, path: list, default: Any = '') → Any#

Navigate nested data structures using a path list.

Safely retrieves values from deeply nested dictionaries or lists.

Args: data: Nested dictionary or list structure path: List of keys/indices to navigate (e.g., [“person”, “name”, 0]) default: Value to return if path doesn’t exist

Returns: The value at the specified path, or default if not found

Example: >>> data = {“person”: {“names”: [{“given”: “John”}]}} >>> self.dictget(data, [“person”, “names”, 0, “given”]) ‘John’

abstractmethod export(contributor: fairdm.contrib.contributors.models.Contributor) → dict#

Export a Contributor instance to external format.

Args: contributor: The Contributor instance to export

Returns: dict: Data in the external format

Raises: NotImplementedError: Subclasses must implement this method

abstractmethod import_data(data: dict, instance: fairdm.contrib.contributors.models.Contributor | None = None, save: bool = True) → fairdm.contrib.contributors.models.Contributor#

Import external format data into a Contributor instance.

Args: data: External format data dictionary instance: Existing Contributor to update (creates new if None) save: Whether to save the instance to the database

Returns: Contributor: The created or updated Contributor instance

Raises: NotImplementedError: Subclasses must implement this method

validate(data: dict) → bool#

Validate that data conforms to the expected format.

Args: data: Data to validate

Returns: bool: True if valid, False otherwise

class DataCiteTransform#

Bases: fairdm.contrib.contributors.utils.transforms.BaseTransform

Bidirectional transformation for DataCite Metadata Schema 4.4.

Converts between Contributor objects and DataCite creator/contributor format. See: https://schema.datacite.org/meta/kernel-4.4/

export(contributor: fairdm.contrib.contributors.models.Contributor) → dict#

Export Contributor to DataCite creator/contributor format.

Args: contributor: Person or Organization instance

Returns: dict: DataCite-formatted contributor metadata

import_data(data: dict, instance: fairdm.contrib.contributors.models.Contributor | None = None, save: bool = True) → fairdm.contrib.contributors.models.Contributor#

Import DataCite creator/contributor data into a Contributor.

Args: data: DataCite formatted contributor data instance: Existing Contributor to update (creates new if None) save: Whether to save to database

Returns: Contributor: Created or updated instance

class SchemaOrgTransform#

Bases: fairdm.contrib.contributors.utils.transforms.BaseTransform

Bidirectional transformation for Schema.org JSON-LD format.

Converts between Contributor objects and Schema.org Person/Organization types. See: https://schema.org/Person and https://schema.org/Organization

export(contributor: fairdm.contrib.contributors.models.Contributor) → dict#

Export Contributor to Schema.org JSON-LD format.

Args: contributor: Person or Organization instance

Returns: dict: Schema.org formatted data

import_data(data: dict, instance: fairdm.contrib.contributors.models.Contributor | None = None, save: bool = True) → fairdm.contrib.contributors.models.Contributor#

Import Schema.org Person/Organization data into a Contributor.

Args: data: Schema.org formatted data instance: Existing Contributor to update (creates new if None) save: Whether to save to database

Returns: Contributor: Created or updated instance

class CSLJSONTransform#

Bases: fairdm.contrib.contributors.utils.transforms.BaseTransform

Bidirectional transformation for CSL-JSON (Citation Style Language) format.

Converts between Contributor objects and CSL-JSON author/contributor format. See: https://citeproc-js.readthedocs.io/en/latest/csl-json/markup.html

export(contributor: fairdm.contrib.contributors.models.Contributor) → dict#

Export Contributor to CSL-JSON author format.

Args: contributor: Contributor instance

Returns: dict: CSL-JSON formatted author object

import_data(data: dict, instance: fairdm.contrib.contributors.models.Contributor | None = None, save: bool = True) → fairdm.contrib.contributors.models.Contributor#

Import CSL-JSON author data into a Contributor.

Args: data: CSL-JSON formatted author data instance: Existing Contributor to update (creates new if None) save: Whether to save to database

Returns: Contributor: Created or updated instance

class ORCIDTransform#

Bases: fairdm.contrib.contributors.utils.transforms.BaseTransform

Bidirectional transformation for ORCID Public API v3.0 data.

Converts between Person objects and ORCID API response format. See: https://info.orcid.org/documentation/integration-guide/orcid-record/

static fetch_from_api(orcid_id: str) → dict#

Fetch public data for a given ORCID ID from the ORCID Public API.

Args: orcid_id: The ORCID identifier of the researcher

Returns: dict: The JSON response from the ORCID API

Raises: requests.RequestException: If the API request fails

Example: data = ORCIDTransform.fetch_from_api(“0000-0002-1825-0097”)

export(contributor: fairdm.contrib.contributors.models.Contributor) → dict#

Export Person to ORCID API format.

Note: This creates a minimal ORCID-compatible structure for Person data. The full ORCID record has many more fields.

Args: contributor: Person instance (Organizations not supported)

Returns: dict: ORCID-formatted person data

Raises: TypeError: If contributor is not a Person instance

import_data(data: dict, instance: fairdm.contrib.contributors.models.Person | None = None, save: bool = True) → fairdm.contrib.contributors.models.Person#

Import ORCID API data into a Person instance.

Args: data: ORCID API response data instance: Existing Person to update (creates new if None) save: Whether to save to database

Returns: Person: Created or updated Person instance

classmethod update_or_create(orcid: str, force: bool = False, **kwargs) → tuple[fairdm.contrib.contributors.models.Person, bool]#

Update an existing Person or create a new one using ORCID data.

Attempts to find a Person matching the provided kwargs or with an identifier value matching the given ORCID. If found and not recently synced (or force=True), updates the Person with latest ORCID API data. If not found, creates a new Person.

Args: orcid: The ORCID identifier to fetch data for force: If True, always fetch and update from ORCID API **kwargs: Additional lookup parameters for finding an existing Person

Returns: tuple: (Person object, created boolean)

Example: person, created = ORCIDTransform.update_or_create(“0000-0002-1825-0097”)

classmethod get_or_create(orcid: str) → tuple[fairdm.contrib.contributors.models.Person, bool]#

Retrieve a Person instance matching the given ORCID.

If no match is found, a Person instance is created by fetching data from the ORCID Public API.

Args: orcid: The ORCID identifier to search for or create a Person with

Returns: tuple: (Person instance, created boolean)

Example: person, created = ORCIDTransform.get_or_create(“0000-0002-1825-0097”)

class RORTransform#

Bases: fairdm.contrib.contributors.utils.transforms.BaseTransform

Bidirectional transformation for ROR (Research Organization Registry) API data.

Converts between Organization objects and ROR API response format. Records are read in version 2 of ROR’s schema. See: https://ror.readme.io/v2/docs/data-structure

static clean_ror_id(ror_id_or_link: str) → str#

Extract ROR ID from URL or return as-is.

Args: ror_id_or_link: ROR ID or full URL

Returns: str: Clean ROR ID without URL prefix

static fetch_from_api(ror_id: str) → dict#

Fetch public data for a given ROR ID from the ROR API.

Args: ror_id: The ROR identifier of the organization (URL or ID)

Returns: dict: The JSON response from the ROR API

Raises: requests.RequestException: If the API request fails

Example: data = RORTransform.fetch_from_api(“https://ror.org/00x0x0x”)

export(contributor: fairdm.contrib.contributors.models.Contributor) → dict#

Export Organization to ROR API format.

Note: This creates a minimal ROR-compatible structure for Organization data. The full ROR record has many more fields.

Args: contributor: Organization instance (Person not supported)

Returns: dict: ROR-formatted organization data

Raises: TypeError: If contributor is not an Organization instance

import_data(data: dict, instance: fairdm.contrib.contributors.models.Organization | None = None, save: bool = True) → fairdm.contrib.contributors.models.Organization#

Import ROR API data into an Organization instance.

Args: data: ROR API response data instance: Existing Organization to update (creates new if None) save: Whether to save to database

Returns: Organization: Created or updated Organization instance

display_name(data: dict) → str#

Return the name ROR displays for the organization in a ROR record.

Args: data: ROR API response data

Returns: str: The display name, or an empty string when the record has none

import_location(data: dict, org: fairdm.contrib.contributors.models.Organization) → None#

Set the organization’s city, country and location from a ROR record.

Nothing is changed when the record names no place.

Args: data: ROR API response data org: The Organization to update; it is not saved

classmethod update_or_create(ror_id: str, force: bool = False, **kwargs) → tuple[fairdm.contrib.contributors.models.Organization, bool]#

Update an existing Organization or create a new one using ROR data.

Attempts to find an Organization matching the provided kwargs or with an identifier value matching the given ROR ID. If found and not recently synced (or force=True), updates the Organization with latest ROR API data. If not found, creates a new Organization.

Args: ror_id: The ROR identifier to fetch data for force: If True, always fetch and update from ROR API **kwargs: Additional lookup parameters for finding an existing Organization

Returns: tuple: (Organization object, created boolean)

Example: org, created = RORTransform.update_or_create(“https://ror.org/00x0x0x”)

classmethod get_or_create(ror_id: str) → tuple[fairdm.contrib.contributors.models.Organization, bool]#

Retrieve an Organization instance matching the given ROR ID.

If no match is found, an Organization instance is created by fetching data from the ROR API.

Args: ror_id: The ROR identifier to search for or create an Organization with

Returns: tuple: (Organization instance, created boolean)

Example: org, created = RORTransform.get_or_create(“https://ror.org/00x0x0x”)

contributor_to_datacite(contributor: fairdm.contrib.contributors.models.Contributor) → dict#

Export contributor as DataCite JSON.

contributor_to_schema_org(contributor: fairdm.contrib.contributors.models.Contributor) → dict#

Export contributor as Schema.org JSON-LD.

contributor_to_csljson(contributor: fairdm.contrib.contributors.models.Contributor) → dict#

Export contributor as CSL-JSON.

csljson_to_contributor(data: dict, save: bool = True) → fairdm.contrib.contributors.models.Contributor#

Import CSL-JSON data as Contributor.