Module gundb.backends.backend
Source code
import json
import copy
from ..consts import *
from .resolvers import *
from .utils import *
import logging
#def uniquify(lst):
# #lst might be a list of objects
# res = []
# for r in lst:
# if r not in res:
# res.append(r)
# return res
class BackendMixin:
def get_object_by_id(self, obj_id, schema=None):
pass
def set_object_attr(self, obj, attr, val):
pass
def save_object(self, obj, obj_id, schema=None):
pass
def put(self, soul, key, value, state, graph):
"""
Handles a put request.
Reflect the update graph[soul][key] = value in the database.
First, it finds the root object to which the soul belongs, \
then depending if a list is involved in the path from the root to the changed property, \
update_normal or update_list is called.
Args:
soul (str) : The soul in which the property will be changed.
key (str) : The key that will be changed.
value : The new value associated with the key.
state (dict): The state.
graph (dict): The updated GUN graph.
"""
logging.debug("\n\nPUT REQUEST:\nSoul: {}\nkey: {}\nvalue: {}\n graph:{}\n\n".format(soul, key, value, json.dumps(graph, indent = 4)))
if soul not in self.db:
self.db[soul] = {METADATA:{STATE:{}}}
self.db[soul][key] = value
self.db[soul][METADATA][STATE][key] = state
if isinstance(value, str):
try:
value = json.loads(value)
except:
pass
if is_root_soul(soul): # root object
logging.debug("Direct property of a root object.")
root = soul
path = [key]
else:
logging.debug("Nested soul that must be looked for.")
path = search(soul, graph)
if not path: # Didn't find the soul referenced in any root object
# Ignore the request
logging.debug("Couldn't find soul :(")
#logging.debug("graph: {}\n\n".format(json.dumps(graph, indent = 4)))
return 0
root = path[0]
path = path[1:] + [key]
schema, index = parse_schema_and_id(root)
root_object = self.get_object_by_id(index, schema)
value = fix_lists(resolve_v(value, graph))
list_index = get_first_list_prop(path)
if list_index != -1:
self.update_list(root, path[:list_index + 1], soul, root_object, schema, index, graph)
else:
self.update_normal(path, value, root_object, schema, index)
logging.debug("Updated successfully!")
self.save_object(root_object, index, schema)
def get(self, soul, key=None):
ret = {SOUL: soul, METADATA:{SOUL:soul, STATE:{}}}
res = None
if soul in self.db:
ret[METADATA] = self.db[soul][METADATA]
if key and isinstance(key, str):
res = {**ret, **self.db.get(soul)}
return res.get(key, {})
else:
res = {**ret, **self.db.get(soul)}
return res
return ret
def update_list(self, root, path, soul, root_object, schema, index, graph):
"""
Update list property.
Walks through the graph first to retrieve the soul of the list, \
Then updates the list in the db by resolving it first from the graph.
"""
current = graph[root]
for e in path[:-1]:
current = graph[current[e][METADATA][SOUL]]
list_id = current[path[-1]][SOUL]
self.update_normal(path, fix_lists(resolve_v({SOUL: list_id}, graph)), root_object, schema, index)
return 0
def update_normal(self, path, value, root_object, schema, index):
"""
Update a normal property.
Args:
path (list): The keys to follow from root_object to reach the desired path.
value : The value to be stored in this location.
root_object (dict): The root object from GUN graph.
schema (str) : The schema of the root soul. Root soul is in the format schema://index
index (str) : The index of the root soul.
"""
key = path[-1]
if key.startswith('list_'):
value = listify(value)
current = root_object
for e in path[:-1]:
try:
current = current[e]
except:# The path doesn't exist in the db
# Ignore the request
logging.debug("Couldn't traverse the database for the found path.")
logging.debug('path: {}\n\n'.format(json.dumps([current] + path, indent = 4)))
#logging.debug("graph: {}\n\n".format(json.dumps(graph, indent = 4)))
return 0
current[path[-1]] = value
Classes
class BackendMixin (*args, **kwargs)
-
Source code
class BackendMixin: def get_object_by_id(self, obj_id, schema=None): pass def set_object_attr(self, obj, attr, val): pass def save_object(self, obj, obj_id, schema=None): pass def put(self, soul, key, value, state, graph): """ Handles a put request. Reflect the update graph[soul][key] = value in the database. First, it finds the root object to which the soul belongs, \ then depending if a list is involved in the path from the root to the changed property, \ update_normal or update_list is called. Args: soul (str) : The soul in which the property will be changed. key (str) : The key that will be changed. value : The new value associated with the key. state (dict): The state. graph (dict): The updated GUN graph. """ logging.debug("\n\nPUT REQUEST:\nSoul: {}\nkey: {}\nvalue: {}\n graph:{}\n\n".format(soul, key, value, json.dumps(graph, indent = 4))) if soul not in self.db: self.db[soul] = {METADATA:{STATE:{}}} self.db[soul][key] = value self.db[soul][METADATA][STATE][key] = state if isinstance(value, str): try: value = json.loads(value) except: pass if is_root_soul(soul): # root object logging.debug("Direct property of a root object.") root = soul path = [key] else: logging.debug("Nested soul that must be looked for.") path = search(soul, graph) if not path: # Didn't find the soul referenced in any root object # Ignore the request logging.debug("Couldn't find soul :(") #logging.debug("graph: {}\n\n".format(json.dumps(graph, indent = 4))) return 0 root = path[0] path = path[1:] + [key] schema, index = parse_schema_and_id(root) root_object = self.get_object_by_id(index, schema) value = fix_lists(resolve_v(value, graph)) list_index = get_first_list_prop(path) if list_index != -1: self.update_list(root, path[:list_index + 1], soul, root_object, schema, index, graph) else: self.update_normal(path, value, root_object, schema, index) logging.debug("Updated successfully!") self.save_object(root_object, index, schema) def get(self, soul, key=None): ret = {SOUL: soul, METADATA:{SOUL:soul, STATE:{}}} res = None if soul in self.db: ret[METADATA] = self.db[soul][METADATA] if key and isinstance(key, str): res = {**ret, **self.db.get(soul)} return res.get(key, {}) else: res = {**ret, **self.db.get(soul)} return res return ret def update_list(self, root, path, soul, root_object, schema, index, graph): """ Update list property. Walks through the graph first to retrieve the soul of the list, \ Then updates the list in the db by resolving it first from the graph. """ current = graph[root] for e in path[:-1]: current = graph[current[e][METADATA][SOUL]] list_id = current[path[-1]][SOUL] self.update_normal(path, fix_lists(resolve_v({SOUL: list_id}, graph)), root_object, schema, index) return 0 def update_normal(self, path, value, root_object, schema, index): """ Update a normal property. Args: path (list): The keys to follow from root_object to reach the desired path. value : The value to be stored in this location. root_object (dict): The root object from GUN graph. schema (str) : The schema of the root soul. Root soul is in the format schema://index index (str) : The index of the root soul. """ key = path[-1] if key.startswith('list_'): value = listify(value) current = root_object for e in path[:-1]: try: current = current[e] except:# The path doesn't exist in the db # Ignore the request logging.debug("Couldn't traverse the database for the found path.") logging.debug('path: {}\n\n'.format(json.dumps([current] + path, indent = 4))) #logging.debug("graph: {}\n\n".format(json.dumps(graph, indent = 4))) return 0 current[path[-1]] = value
Subclasses
Methods
def get(self, soul, key=None)
-
Source code
def get(self, soul, key=None): ret = {SOUL: soul, METADATA:{SOUL:soul, STATE:{}}} res = None if soul in self.db: ret[METADATA] = self.db[soul][METADATA] if key and isinstance(key, str): res = {**ret, **self.db.get(soul)} return res.get(key, {}) else: res = {**ret, **self.db.get(soul)} return res return ret
def get_object_by_id(self, obj_id, schema=None)
-
Source code
def get_object_by_id(self, obj_id, schema=None): pass
def put(self, soul, key, value, state, graph)
-
Handles a put request. Reflect the update graph[soul][key] = value in the database. First, it finds the root object to which the soul belongs, then depending if a list is involved in the path from the root to the changed property, update_normal or update_list is called.
Args
- soul (str) : The soul in which the property will be changed.
- key (str) : The key that will be changed.
- value : The new value associated with the key.
state
:dict
- The state.
graph
:dict
- The updated GUN graph.
Source code
def put(self, soul, key, value, state, graph): """ Handles a put request. Reflect the update graph[soul][key] = value in the database. First, it finds the root object to which the soul belongs, \ then depending if a list is involved in the path from the root to the changed property, \ update_normal or update_list is called. Args: soul (str) : The soul in which the property will be changed. key (str) : The key that will be changed. value : The new value associated with the key. state (dict): The state. graph (dict): The updated GUN graph. """ logging.debug("\n\nPUT REQUEST:\nSoul: {}\nkey: {}\nvalue: {}\n graph:{}\n\n".format(soul, key, value, json.dumps(graph, indent = 4))) if soul not in self.db: self.db[soul] = {METADATA:{STATE:{}}} self.db[soul][key] = value self.db[soul][METADATA][STATE][key] = state if isinstance(value, str): try: value = json.loads(value) except: pass if is_root_soul(soul): # root object logging.debug("Direct property of a root object.") root = soul path = [key] else: logging.debug("Nested soul that must be looked for.") path = search(soul, graph) if not path: # Didn't find the soul referenced in any root object # Ignore the request logging.debug("Couldn't find soul :(") #logging.debug("graph: {}\n\n".format(json.dumps(graph, indent = 4))) return 0 root = path[0] path = path[1:] + [key] schema, index = parse_schema_and_id(root) root_object = self.get_object_by_id(index, schema) value = fix_lists(resolve_v(value, graph)) list_index = get_first_list_prop(path) if list_index != -1: self.update_list(root, path[:list_index + 1], soul, root_object, schema, index, graph) else: self.update_normal(path, value, root_object, schema, index) logging.debug("Updated successfully!") self.save_object(root_object, index, schema)
def save_object(self, obj, obj_id, schema=None)
-
Source code
def save_object(self, obj, obj_id, schema=None): pass
def set_object_attr(self, obj, attr, val)
-
Source code
def set_object_attr(self, obj, attr, val): pass
def update_list(self, root, path, soul, root_object, schema, index, graph)
-
Update list property.
Walks through the graph first to retrieve the soul of the list, Then updates the list in the db by resolving it first from the graph.
Source code
def update_list(self, root, path, soul, root_object, schema, index, graph): """ Update list property. Walks through the graph first to retrieve the soul of the list, \ Then updates the list in the db by resolving it first from the graph. """ current = graph[root] for e in path[:-1]: current = graph[current[e][METADATA][SOUL]] list_id = current[path[-1]][SOUL] self.update_normal(path, fix_lists(resolve_v({SOUL: list_id}, graph)), root_object, schema, index) return 0
def update_normal(self, path, value, root_object, schema, index)
-
Update a normal property.
Args
- path (list): The keys to follow from root_object to reach the desired path.
- value : The value to be stored in this location.
root_object
:dict
- The root object from GUN graph.
schema (str) : The schema of the root soul. Root soul is in the format schema://index index (str) : The index of the root soul.
Source code
def update_normal(self, path, value, root_object, schema, index): """ Update a normal property. Args: path (list): The keys to follow from root_object to reach the desired path. value : The value to be stored in this location. root_object (dict): The root object from GUN graph. schema (str) : The schema of the root soul. Root soul is in the format schema://index index (str) : The index of the root soul. """ key = path[-1] if key.startswith('list_'): value = listify(value) current = root_object for e in path[:-1]: try: current = current[e] except:# The path doesn't exist in the db # Ignore the request logging.debug("Couldn't traverse the database for the found path.") logging.debug('path: {}\n\n'.format(json.dumps([current] + path, indent = 4))) #logging.debug("graph: {}\n\n".format(json.dumps(graph, indent = 4))) return 0 current[path[-1]] = value