Source code for ewoksserver.app.backends.json_backend

import json
import logging
from pathlib import Path
from typing import Iterator, Union, Optional, Mapping, Dict


ResourceIdentifierType = str
ResourceUrlType = Path
ResourceContentType = Dict


_logger = logging.getLogger(__name__)


[docs]def root_url(root_url: Union[str, Path, None], category: str) -> ResourceUrlType: if not root_url: root_url = Path(".") elif isinstance(root_url, str): root_url = Path(root_url) return root_url / category
[docs]def resource_identifiers(root: ResourceUrlType) -> Iterator[ResourceIdentifierType]: for url in _resource_urls(root): yield _url_to_identifier(url)
[docs]def resources(root: ResourceUrlType) -> Iterator[ResourceContentType]: for url in _resource_urls(root): yield _load_url(url)
[docs]def resource_exists(root: ResourceUrlType, identifier: ResourceIdentifierType) -> bool: return _identifier_to_url(root, identifier).exists()
def _resource_urls(root: ResourceUrlType) -> Iterator[ResourceUrlType]: if not root.exists(): return for url in root.iterdir(): if _is_resource(url): yield url def _is_resource(url: ResourceUrlType) -> bool: return url.is_file() and url.name.endswith(".json")
[docs]def save_resource( root: ResourceUrlType, identifier: ResourceIdentifierType, resource: ResourceContentType, ): url = _identifier_to_url(root, identifier) _save_url(url, resource)
[docs]def load_resource( root: ResourceUrlType, identifier: ResourceIdentifierType ) -> ResourceContentType: url = _identifier_to_url(root, identifier) return _load_url(url)
[docs]def delete_resource(root: ResourceUrlType, identifier: ResourceIdentifierType) -> None: url = _identifier_to_url(root, identifier) _delete_url(url)
def _identifier_to_url(root: ResourceUrlType, identifier: ResourceIdentifierType): return root / (identifier + ".json") def _url_to_identifier(url: ResourceUrlType) -> ResourceIdentifierType: return url.stem def _save_url(url: ResourceUrlType, resource: ResourceContentType): _logger.debug("Save file '%s'", url) url.parent.mkdir(parents=True, exist_ok=True) with open(url, "w") as f: json.dump(resource, f, indent=2) def _load_url(url: ResourceUrlType) -> ResourceContentType: try: with open(url, "r") as f: return json.load(f) except FileNotFoundError: _logger.error(f"'{url}' not found") raise def _delete_url(url: ResourceUrlType) -> ResourceContentType: _logger.debug("Delete file '%s'", url) url.unlink()
[docs]def merge_mappings(d1: Optional[Mapping], d2: Optional[Mapping]) -> dict: """Same as `{**d1, **d2}` but then recursive""" if d1 is None: merged = dict() else: merged = dict(d1) if not d2: return merged for key, value2 in d2.items(): value1 = merged.get(key) if isinstance(value1, Mapping) and isinstance(value2, Mapping): value2 = merge_mappings(value1, value2) merged[key] = value2 return merged