""" Functions that perform read-write operations """ import json from os import environ as env from urllib.parse import quote_plus as url_encode from pathlib import Path from webfinger.models import JRD, Link DictJRD = dict[str, str | list[str] | dict[str,str] | list[dict[str,str]]] def get_jrd_as_dict(resource: str) -> DictJRD: """ Obtain a JSON Resource Descriptor (JRD) as a dictionary A JRD is a JSON object containing the following: - subject (string value; SHOULD be present) - aliases (array of string values; OPTIONAL) - properties (object containing key-value pairs as strings; OPTIONAL) - links (array of objects containing link relation information; OPTIONAL) Parameters: resource (str): The URI of the resouce Returns: jrd (dict): Parsed JRD dictionary Raises: FileNotFoundError: No JRD file exists in the resource directory OSError: A file may exist, but it is not readable json.JSONDecodeError: A file exists, but does not contain a valid JSON object """ # Get a filename for the resource document. directory = env.get("RESOURCE_DIR") or "resource" filename = resource path = f"{directory}/{filename}.jrd" # If we can't get a file, try percent-encoding if not Path(path).is_file(): filename = url_encode(resource) path = f"{directory}/{filename}.jrd" # Try plain JSON if not Path(path).is_file(): filename = resource path = f"{directory}/{filename}.json" # Try plain JSON and percent-encoding if not Path(path).is_file(): filename = resource path = f"{directory}/{filename}.json" # Open the file and load the JSON as a dictionary. # This may fail and raise an exception. with open(path, mode="r", encoding="utf-8") as file: jrd: DictJRD = json.loads(file.read()) return {k: v for k, v in jrd.items() if v} # remove null values def get_jrd(resource: str) -> JRD: """ Obtain a JSON Resource Descriptor (JRD) as a Pydantic model A JRD is a JSON object containing the following: - subject (string value; SHOULD be present) - aliases (array of string values; OPTIONAL) - properties (object containing key-value pairs as strings; OPTIONAL) - links (array of objects containing link relation information; OPTIONAL) Parameters: resource (str): The URI of the resouce Returns: jrd (JRD): Parsed and valid JRD model Raises: FileNotFoundError: No JRD file exists in the resource directory OSError: A file may exist, but it is not readable json.JSONDecodeError: A file exists, but does not contain a valid JSON object pydantic.ValidationError: A file exists and was parsed, but some properties failed validation """ jrd = get_jrd_as_dict(resource) return JRD( subject = jrd.get('subject') or resource, aliases = jrd.get('aliases'), properties = jrd.get('properties'), links = [ Link( rel = link.get('rel'), type = link.get('type'), href = link.get('href'), titles = link.get('titles'), properties = link.get('properties'), ) for link in jrd.get('links', []) ], )