Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
.vscode/

# Generated files
.idea/**/contentModel.xml
Expand Down
2 changes: 1 addition & 1 deletion scripts/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def get_mongo_storage_by_session(client, *args, **kwargs):
while True:
try:
char = raw_input("Please enter a number or enter for all: ")
if char is "":
if char == "":
return client.find(*args, **kwargs)
return client.find_by_session_id(s_lut[int(char)]["id"], *args, **kwargs)
except (EOFError, ValueError, IndexError):
Expand Down
13 changes: 2 additions & 11 deletions src/topic_store/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,19 @@

import pathlib
from abc import ABCMeta, abstractmethod, abstractproperty
from .utils import abstractstatic

__all__ = ["load", "Storage"]


class abstract_static(staticmethod):
__slots__ = ()

def __init__(self, function):
super(abstract_static, self).__init__(function)
function.__isabstractmethod__ = True

__isabstractmethod__ = True


class Storage:
__metaclass__ = ABCMeta

@abstractproperty
def suffix(self):
raise NotImplementedError

@abstract_static
@abstractstatic
def load(path):
"""Storage containers must have a load mechanism"""''
raise NotImplementedError
Expand Down
28 changes: 20 additions & 8 deletions src/topic_store/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import roslib.message
import rospy
from genpy import Message as ROSMessage
from .utils import cached_property

try:
from collections import Mapping as MappingType
Expand Down Expand Up @@ -211,18 +212,29 @@ def __init__(self, data_tree):
if not isinstance(data_tree, dict):
raise ValueError("Data tree must be a dict to construct a TopicStore")
# Ensure passed data tree does not contain ROS msgs
self.__data_tree = DefaultTypeParser()(data_tree)
if "_id" not in self.__data_tree:
self.__data_tree["_id"] = bson.ObjectId()
if "_ts_meta" not in self.__data_tree:
self.__data_tree["_ts_meta"] = dict(session=_session_id, sys_time=time_as_ms(), ros_time=ros_time_as_ms())
self.data_tree = DefaultTypeParser()(data_tree)
if "_id" not in self.data_tree:
self.data_tree["_id"] = bson.ObjectId()
if "_ts_meta" not in self.data_tree:
self.data_tree["_ts_meta"] = dict(session=_session_id, sys_time=time_as_ms(), ros_time=ros_time_as_ms())
# Cache for dict to ROS message parsing
self.__msgs = None

@property
def dict(self):
def data_tree(self):
return self.__data_tree

@data_tree.setter
def data_tree(self, value):
# clears variable cache
del self.to_ros_msg_list
del self.flatten_ros_msg_dict
self.__data_tree = value

@property
def dict(self):
return self.data_tree

@property
def msgs(self):
if self.__msgs is None:
Expand Down Expand Up @@ -418,10 +430,10 @@ def __ros_msg_dict_to_list(ros_msg_dict, return_keys=False, parent=""):
for ret in TopicStore.__ros_msg_dict_to_list(value, return_keys, key if not parent else parent + "." + key):
yield ret

@cached_property
def to_ros_msg_list(self):
# TODO: Cache this operation until self.__data_tree updated
return list(TopicStore.__ros_msg_dict_to_list(self.msgs))

@cached_property
def flatten_ros_msg_dict(self):
# TODO: Cache this operation until self.__data_tree updated
return {k: v for k, v in TopicStore.__ros_msg_dict_to_list(self.msgs, return_keys=True)}
32 changes: 32 additions & 0 deletions src/topic_store/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Peter Lightbody (pet1330) Copyright (c) 2020
# Email: pet1330@gmail.com


"""A decorator to cache instance variables"""
class cached_property(property):
def __init__(self, method):
self.method = method

def __set__(self, obj, value):
obj.__dict__[self.method.__name__] = value

def __delete__(self, obj):
del obj.__dict__[self.method.__name__]

def __get__(self, obj, type=None):
if obj is None:
return self

if not self.method.__name__ in obj.__dict__:
obj.__dict__[self.method.__name__] = self.method(obj)
return obj.__dict__[self.method.__name__]


class abstractstatic(staticmethod):
__slots__ = ()

def __init__(self, function):
super(abstractstatic, self).__init__(function)
function.__isabstractmethod__ = True

__isabstractmethod__ = True