Source code for firebird.uuid._registry

# SPDX-FileCopyrightText: 2022-present The Firebird Projects <www.firebirdsql.org>
#
# SPDX-License-Identifier: MIT
#
# PROGRAM/MODULE: firebird-uuid
# FILE:           firebird/uuid/registry.py
# DESCRIPTION:    Firebird OID registry
# CREATED:        14.11.2022
#
# The contents of this file are subject to the MIT License
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# Copyright (c) 2022 Firebird Project (www.firebirdsql.org)
# All Rights Reserved.
#
# Contributor(s): Pavel Císař (original code)
#                 ______________________________________

"""Firebird OID registry.

"""

from __future__ import annotations
from typing import List, Optional, Dict
import uuid
from queue import SimpleQueue
from toml import dumps, loads
from firebird.base.types import Error, STOP
from firebird.base.collections import Registry
from ._model import NodeType, Node, build_tree

[docs] class OIDRegistry(Registry): """Firebird OID registry. """
[docs] def get_root(self) -> Optional[Node]: """Returns ROOT node, or None if root node is not registered. """ return self.find(lambda x: x.node_type is NodeType.ROOT)
[docs] def update_from_specifications(self, specifications: Dict[str, str]) -> None: """Updates registered nodes from specifications. Arguments: specifications: Dictionary with `url: spec_dict` as returned by `.parse_specifications`. """ nodes: List[Node] = [Node.from_spec(url, data) for url, data in specifications.items()] for node in nodes: self.update(node.children) self.update(nodes) build_tree(self._reg.values())
[docs] def update_from_toml(self, toml: str) -> None: """Updates registered nodes from TOML document. Arguments: toml: TOML document (as created by `as_toml` method). """ data = loads(toml) # Validate data known = set(self.keys()) has_root_node = False has_known_parent = False for uid, kwargs in data.items(): uid = uuid.UUID(uid) if 'parent' in kwargs: if self.get(uuid.UUID(kwargs['parent'])) in known: has_known_parent = True elif kwargs['node_type'] == 'root': has_root_node = True root: Node = None if root := self.get_root() is not None: if root.uid != uid: raise Error(f"Root node {uid} does not match registered root") if not (has_root_node or has_known_parent): raise Error("TOML does not define either root node or any node with registered parent") # que = SimpleQueue() for uid, kwargs in data.items(): que.put((uid, kwargs)) qsize = que.qsize() que.put(STOP) while not que.empty(): item = que.get() if item is STOP: if not que.empty(): if que.qsize() >= qsize: raise Error(f"TOML contains {qsize - que.qsize()} unlinkable nodes") else: qsize = que.qsize() que.put(STOP) else: uid, kwargs = item parent: Node = None if 'parent' in kwargs: parent = self.get(uuid.UUID(kwargs['parent'])) if parent is None: que.put(item) else: kwargs['parent'] = parent node = Node(**kwargs) parent.children.append(node) self.store(node) elif kwargs['node_type'] == 'root': self.store(Node(**kwargs)) else: raise Error(f"Node {uid} is not root and has no parent node") build_tree(self._reg.values())
[docs] def as_toml(self) -> str: """Returns registry content as TOML document. """ nodes = {str(node.uid): node.as_toml_dict() for node in self._reg.values()} toml = dumps(nodes) return toml
#: Firebird OID registry oid_registry = OIDRegistry()