Source code for nosqlapi.graphdb.odm

#!/usr/bin/env python3
# -*- encoding: utf-8 -*-
# vim: se ts=4 et syn=python:

# created by: matteo.guadrini
# odm -- nosqlapi
#
#     Copyright (C) 2022 Matteo Guadrini <matteo.guadrini@hotmail.it>
#
#     This program is free software: you can redistribute it and/or modify
#     it under the terms of the GNU General Public License as published by
#     the Free Software Foundation, either version 3 of the License, or
#     (at your option) any later version.
#
#     This program is distributed in the hope that it will be useful,
#     but WITHOUT ANY WARRANTY; without even the implied warranty of
#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#     GNU General Public License for more details.
#
#     You should have received a copy of the GNU General Public License
#     along with this program.  If not, see <http://www.gnu.org/licenses/>.

"""ODM module for graph NOSQL database."""

# region Imports
from collections import namedtuple
from functools import wraps

from nosqlapi.kvdb.odm import Keyspace
from ..common.odm import Text

# endregion

# region global variable
__all__ = ['Label', 'Property', 'RelationshipType', 'Database', 'Node', 'Relationship', 'Index', 'prop', 'node']


# endregion


# region Classes
[docs]class Label(Text): """Label of node""" pass
[docs]class Property(dict): """Property of node"""
[docs] def __repr__(self): out = [] for key, value in self.items(): pair = f'{key}: ' if isinstance(value, str): pair += f"'{value}'" else: pair += f'{value}' out.append(pair) return '{{{pairs}}}'.format(pairs=', '.join(out))
[docs]class RelationshipType(Label): """Type of relationship like a label""" pass
[docs]class Database(Keyspace): """Represents database"""
[docs] def __init__(self, name, address=None, role=None, status='online', default=False): """Database object :param name: Name of database :param address: Address of database server :param role: Role of database :param status: Status of database (default online) :param default: Default value or function """ super().__init__(name=name) self.address = address self.role = role self.status = status self.default = default
@property def online(self): """Status of database""" if self.status == 'online': return True else: return False
[docs]class Node: """Represents node"""
[docs] def __init__(self, labels, properties=None, var=''): """Node object :param labels: Label of node :param properties: Properties of Node :param var: Name variable """ self.labels = [] self.labels.extend(labels) self.properties = Property() self.var = var if properties: self.properties.update(properties)
[docs] def add_label(self, label): """Add label to node :param label: Label string or object :return: None """ self.labels.append(label)
[docs] def delete_label(self, index=-1): """Delete label :param index: Number of index :return: None """ self.labels.pop(index)
def __getitem__(self, item): return self.properties[item] def __setitem__(self, key, value): self.properties[key] = value def __delitem__(self, key): del self.properties[key]
[docs] def __str__(self): return f'({self.var}:{":".join(self.labels)} {self.properties})'
[docs] def __repr__(self): return f'{self.__class__.__name__} object, labels={self.labels}>'
[docs]class Relationship(Node): """Represents relationship among nodes"""
[docs] def __str__(self): return f'[{self.var}:{":".join(self.labels)} {self.properties}]'
[docs] def __repr__(self): return f'{self.__class__.__name__} object, type={self.labels}>'
# endregion # region Other objects Index = namedtuple('Index', ['name', 'node', 'properties', 'options'], defaults=(None,)) # endregion # region Functions
[docs]def prop(func): """Decorator function to transform dictionary object to Property object :param func: function to decorate :return: Property object """ @wraps(func) def inner(*args, **kwargs): data = func(*args, **kwargs) if not isinstance(data, dict): raise ValueError(f"function {func.__name__} doesn't return a dict") return Property(**data) return inner
[docs]def node(func): """Decorator function to transform dictionary object to Node object :param func: function to decorate :return: Node object """ @wraps(func) def inner(*args, **kwargs): data = func(*args, **kwargs) if not isinstance(data, dict): raise ValueError(f"function {func.__name__} doesn't return a dict") return Node(labels=[func.__name__], properties=data) return inner
# endregion