Commit eaa28b6f authored by Eelco van der Wel's avatar Eelco van der Wel :speech_balloon:
Browse files

Merge branch 'schema-types' into 'dev'

Schema types

See merge request !76
parents b1c32b2f ac9005fb
Pipeline #3634 passed with stages
in 5 minutes and 22 seconds
Showing with 276 additions and 115 deletions
+276 -115
%% Cell type:code id: tags:
``` python
%load_ext autoreload
%autoreload 2
# default_exp data.itembase
```
%% Cell type:markdown id: tags:
# Itembase
%% Cell type:markdown id: tags:
Any data class in pymemri inherits from `Item`. It is a base class for items with some handy functionalities to create new items and edges, retrieve all edges to other items, and sync with the pod.
%% Cell type:code id: tags:
``` python
# export
# hide
from typing import Optional
from pymemri.imports import *
ALL_EDGES = "allEdges"
SOURCE, TARGET, TYPE, EDGE_TYPE, LABEL, SEQUENCE = "_source", "_target", "_type", "_type", "label", "sequence"
```
%% Cell type:code id: tags:
``` python
#hide
from nbdev.showdoc import *
```
%% Cell type:code id: tags:
``` python
# export
# hide
def parse_base_item_json(json):
id = json.get("id", None)
dateAccessed = json.get("dateAccessed", None)
dateCreated = json.get("dateCreated", None)
dateModified = json.get("dateModified", None)
deleted = json.get("deleted", None)
externalId = json.get("externalId", None)
itemDescription = json.get("itemDescription", None)
starred = json.get("starred", None)
version = json.get("version", None)
return id, dateAccessed, dateCreated, dateModified, deleted, externalId, itemDescription, starred, version, None, None
```
%% Cell type:code id: tags:
``` python
# export
class Edge():
"""Edges makes a link between two `ItemBase` Items. You won't use this class a lot in practice, as edges are
abstracted away for normal users. When items are retrieved from the database, the edges are parsed automatically.
When you add an edge between to items within pymemri, you will often use `ItemBase.add_edge`"""
def __init__(self, source, target, _type, label=None, sequence=None, created=False, reverse=True):
self.source = source
self.target = target
self._type = _type
self.label = label
self.sequence = sequence
self.created = created
self.reverse = reverse
@classmethod
def from_json(cls, json):
from pymemri.data.schema import get_constructor
# we only set the target here
_type = json[EDGE_TYPE]
json_target = json[TARGET]
target_type = json_target["_type"]
plugin_class = json_target.get("pluginClass", None)
target_constructor = get_constructor(target_type, plugin_class)
target = target_constructor.from_json(json_target)
return cls(source=None, target=target, _type=_type)
def __repr__(self):
return f"{self.source} --{self._type}-> {self.target}"
def update(self, api):
if self.created:
api.create_edges([self])
def __eq__(self, other):
return self.source is other.source and self.target is other.target \
and self._type == other._type and self.reverse == other.reverse and self.created == other.created \
and self.label == other.label
def traverse(self, start):
"""We can traverse an edge starting from the source to the target or vice versa. In practice we often call
item.some_edge_type, which calls item.traverse(edgetype), which in turn calls this function."""
if start == self.source:
return self.target
elif start == self.target:
return self.source
else:
raise ValueError
```
%% Cell type:code id: tags:
``` python
show_doc(Edge.traverse)
```
%% Output
<h4 id="Edge.traverse" class="doc_header"><code>Edge.traverse</code><a href="__main__.py#L39" class="source_link" style="float:right">[source]</a></h4>
> <code>Edge.traverse</code>(**`start`**)
We can traverse an edge starting from the source to the target or vice versa. In practice we often call
item.some_edge_type, which calls item.traverse(edgetype), which in turn calls this function.
%% Cell type:code id: tags:
``` python
ITEMBASE_PROPERTIES = ["dateAccessed", "dateCreated", "dateModified", "deleted", "externalId", "itemDescription",
"starred", "version", "id", "importJson", "name", "repository", "icon", "bundleImage",
"runDestination", "pluginClass"]
```
%% Cell type:code id: tags:
``` python
# export
# hide
class ItemBase():
"""Provides a base class for all items.
All items in the schema inherit from this class, and it provides some
basic functionality for consistency and to enable easier usage."""
def __init__(self, id=None):
self.id=id
def __init__(self, id: str = None):
self.id: Optional[str] = id
def __getattribute__(self, name):
val = object.__getattribute__(self, name)
if isinstance(val, Edge):
edge = val
return edge.traverse(start=self)
if isinstance(val, list) and len(val) > 0 and isinstance(val[0], Edge):
edges = val
return [edge.traverse(start=self) for edge in edges]
else:
return val
def add_edge(self, name, val):
"""Creates an edge of type name and makes it point to val"""
val = Edge(self, val, name, created=True)
if name not in self.__dict__:
raise NameError(f"object {self} does not have edge with name {name}")
existing = object.__getattribute__(self, name)
if val not in existing:
res = existing + [val]
self.__setattr__(name, res)
def is_expanded(self):
"""returns whether the node is expanded. An expanded node retrieved nodes that are
*directly* connected to it
from the pod, and stored their values via edges in the object."""
return len(self.get_all_edges()) > 0
def get_edges(self, name):
return object.__getattribute__(self, name)
def get_all_edges(self):
return [e for attr in self.__dict__.values() if self.attr_is_edge(attr) for e in attr]
def get_all_edge_names(self):
return [k for k,v in self.__dict__.items() if self.attr_is_edge(v)]
def get_property_names(self):
return [k for k, v in self.__dict__.items() if not type(v) == list]
@staticmethod
def attr_is_edge(attr):
return isinstance(attr, list) and len(attr)>0 and isinstance(attr[0], Edge)
def update(self, api, edges=True, create_if_not_exists=True, skip_nodes=False):
if not self.exists(api):
print(f"creating {self}")
api.create(self)
else:
print(f"updating {self}")
api.update_item(self)
if edges:
for e in self.get_all_edges():
e.update(api)
def exists(self, api):
return api.exists(self.id) if self.id else None
# def expand(self, api):
# """Expands a node (retrieves all directly connected nodes ands adds to object)."""
# self._expanded = True
# res = api.get(self.id, expanded=True)
# for edge_name in res.get_all_edge_names():
# edges = res.get_edges(edge_name)
# for e in edges:
# e.source = self
# self.__setattr__(edge_name, edges)
# # self.edges = res.edges
# return self
def __repr__(self):
id = self.id
_type = self.__class__.__name__
return f"{_type} (#{id})"
@classmethod
def from_data(cls, *args, **kwargs):
edges = dict()
new_kwargs = dict()
for k, v in kwargs.items():
if isinstance(v, ItemBase):
edge = Edge(None, v, k)
edges[k] = edge
new_kwargs[k] = edge
else:
new_kwargs[k] = v
res = cls(*args, **new_kwargs)
for v in edges.values():
v.source = res
return res
# def inherit_funcs(self, other):
# """This function can be used to inherit new functionalities from a subclass. This is a patch to solve
# the fact that python does provide extensions of classes that are defined in a different file that are
# dynamic enough for our use case."""
# assert issubclass(other, self.__class__)
# self.__class__ = other
```
%% Cell type:code id: tags:
``` python
# export
class Item(ItemBase):
"""Item is the baseclass for all of the data classes."""
properties = ["dateAccessed", "dateCreated", "dateModified", "deleted", "externalId", "itemDescription",
"starred", "version", "id", "importJson", "pluginClass"]
properties = [
"dateAccessed",
"dateCreated",
"dateModified",
"deleted",
"externalId",
"itemDescription",
"starred",
"version",
"id",
"importJson",
"pluginClass",
]
edges = ["changelog", "label", "genericAttribute", "measure", "sharedWith"]
def __init__(self, **kwargs):
super().__init__(kwargs.get("id"))
for p in self.properties:
if p == "id":
continue
setattr(self, p, kwargs.get(p, None))
for e in self.edges:
setattr(self, e, kwargs.get(e, []))
def __init__(
self,
dateAccessed: str = None,
dateCreated: str = None,
dateModified: str = None,
deleted: str = None,
externalId: str = None,
itemDescription: str = None,
starred: str = None,
version: str = None,
id: str = None,
importJson: str = None,
pluginClass: str = None,
changelog: list = None,
label: list = None,
genericAttribute: list = None,
measure: list = None,
sharedWith: list = None
):
super().__init__(id)
# Properties
self.dateAccessed: Optional[str] = dateAccessed
self.dateCreated: Optional[str] = dateCreated
self.dateModified: Optional[str] = dateModified
self.deleted: Optional[str] = deleted
self.externalId: Optional[str] = externalId
self.itemDescription: Optional[str] = itemDescription
self.starred: Optional[str] = starred
self.version: Optional[str] = version
self.importJson: Optional[str] = importJson
self.pluginClass: Optional[str] = pluginClass
# Edges
self.changelog: list = changelog if changelog is not None else []
self.label: list = label if label is not None else []
self.genericAttribute: list = genericAttribute if genericAttribute is not None else []
self.measure: list = measure if measure is not None else []
self.sharedWith: list = sharedWith if sharedWith is not None else []
@classmethod
def parse_json(self, cls, json):
property_kwargs = Item.parse_properties(cls, json)
edge_kwargs = Item.parse_edges(cls, json)
return {**property_kwargs, **edge_kwargs}
@classmethod
def parse_properties(self, cls, json):
return {p: json.get(p, None) for p in cls.properties}
@classmethod
def parse_edges(self, cls, json):
all_edges = json.get(ALL_EDGES, None)
edge_kwargs = dict()
reverse_edges = [f"~{e}" for e in cls.edges]
if all_edges is not None:
for edge_json in all_edges:
edge = Edge.from_json(edge_json)
if edge.type in self.edges + reverse_edges:
edge_name = self.remove_prefix(edge.type)
if edge_name in edge_kwargs:
edge_kwargs[edge_name] += [edge]
else:
edge_kwargs[edge_name] = [edge]
return edge_kwargs
@classmethod
def remove_prefix(s, prefix="~"):
return s[1:] if s[0] == "`" else s
@classmethod
def from_json(cls, json):
kwargs = Item.parse_json(cls, json)
res = cls(**kwargs)
for e in res.get_all_edges(): e.source = res
for e in res.get_all_edges():
e.source = res
return res
```
%% Cell type:code id: tags:
``` python
show_doc(ItemBase.add_edge)
```
%% Output
<h4 id="ItemBase.add_edge" class="doc_header"><code>ItemBase.add_edge</code><a href="__main__.py#L29" class="source_link" style="float:right">[source]</a></h4>
> <code>ItemBase.add_edge</code>(**`name`**, **`val`**)
Creates an edge of type name and makes it point to val
%% Cell type:code id: tags:
``` python
show_doc(ItemBase.is_expanded)
```
%% Output
<h4 id="ItemBase.is_expanded" class="doc_header"><code>ItemBase.is_expanded</code><a href="__main__.py#L39" class="source_link" style="float:right">[source]</a></h4>
> <code>ItemBase.is_expanded</code>()
returns whether the node is expanded. An expanded node retrieved nodes that are
*directly* connected to it
from the pod, and stored their values via edges in the object.
%% Cell type:markdown id: tags:
# Usage
%% Cell type:markdown id: tags:
With the `Item` and `Edge` classes we can create an item and its surrounding graph. The schema is defined in schema.py, in general we want to use the from_data staticmethod to generate new items, because it ensures that edges are linked from both the source and the target object. Let's make a new item and add it to the pod.
%% Cell type:code id: tags:
``` python
class MyItem(Item):
properties = Item.properties + ["name", "age"]
edges = Item.edges + ["friend"]
def __init__(self, name=None, age=None,friend=None, **kwargs):
super().__init__(**kwargs)
self.name = name
self.age = age
self.friend = fried if friend is not None else []
```
%% Cell type:code id: tags:
``` python
from pymemri.pod.client import PodClient
client = PodClient()
```
%% Cell type:code id: tags:
``` python
assert client.add_to_schema(MyItem(name="abc", age=1))
```
%% Cell type:code id: tags:
``` python
x = MyItem(name="me", age=30)
x.add_edge("friend", MyItem(name="my friend", age=31))
```
%% Cell type:markdown id: tags:
We can now create our `MyItem`, as a side-effect of creating it, it will receive an id
%% Cell type:code id: tags:
``` python
print(x.id)
```
%% Output
None
%% Cell type:code id: tags:
``` python
assert client.create(x)
```
%% Cell type:code id: tags:
``` python
print(x.id)
```
%% Output
bfec09ee3c0eee83e4fb4a63674704f5
%% Cell type:code id: tags:
``` python
y = client.get(x.id)
```
%% Cell type:code id: tags:
``` python
assert len(y.friend) > 0
```
%% Cell type:code id: tags:
``` python
assert y.friend[0].name == "my friend"
assert y.name == "me"
assert y.age == 30
# One year later
y.age = 31
y.add_edge("friend", MyItem(name="my friend2", age=29))
y.update(client)
assert y.age == 31
assert len(y.friend) == 2
```
%% Output
'my friend'
%% Cell type:markdown id: tags:
# Export -
%% Cell type:code id: tags:
``` python
# hide
from nbdev.export import *
notebook2script()
```
%% Output
Converted basic.ipynb.
Converted data.photo.ipynb.
Converted importers.Importer.ipynb.
Converted importers.util.ipynb.
Converted index.ipynb.
Converted indexers.indexer.ipynb.
Converted itembase.ipynb.
Converted plugin.pluginbase.ipynb.
Converted pod.client.ipynb.
%% Cell type:code id: tags:
``` python
```
......
%% Cell type:code id: tags:
%% Cell type:code id:6167ac20 tags:
``` python
# default_exp plugin.schema
```
%% Cell type:code id: tags:
%% Cell type:code id:132fb927 tags:
``` python
# export
# hide
import random, string
from typing import Optional
from pymemri.data.itembase import Item
```
%% Cell type:code id: tags:
%% Cell type:code id:8653a9d6 tags:
``` python
# export
# hide
class Account(Item):
properties = Item.properties + ['service', "identifier", "secret", "code", "refreshToken", "errorMessage"]
properties = Item.properties + [
"service",
"identifier",
"secret",
"code",
"refreshToken",
"errorMessage",
]
edges = Item.edges
def __init__(self, service=None, identifier=None, secret=None, code=None, refreshToken=None,
errorMessage=None, **kwargs):
def __init__(
self,
service: str = None,
identifier: str = None,
secret: str = None,
code: str = None,
refreshToken: str = None,
errorMessage: str = None,
**kwargs
):
super().__init__(**kwargs)
self.service = service
self.identifier = identifier
self.secret = secret
self.refreshToken = refreshToken
self.code = code
self.errorMessage = errorMessage
# Properties
self.service: Optional[str] = service
self.identifier: Optional[str] = identifier
self.secret: Optional[str] = secret
self.refreshToken: Optional[str] = refreshToken
self.code: Optional[str] = code
self.errorMessage: Optional[str] = errorMessage
```
%% Cell type:code id: tags:
%% Cell type:code id:78653ae8 tags:
``` python
# export
# hide
class PluginRun(Item):
properties = Item.properties + ["containerImage", "pluginModule", "pluginName", "status", "targetItemId",
"authUrl", "error", "settings"]
properties = Item.properties + [
"containerImage",
"pluginModule",
"pluginName",
"status",
"targetItemId",
"authUrl",
"error",
"settings",
]
edges = Item.edges + ["view", "persistentState", "account"]
def __init__(self, containerImage, pluginModule, pluginName, status=None, settings=None, view=None,
targetItemId=None, authUrl=None, error=None, persistentState=None, account=None,
**kwargs):
"""
PluginRun defines a the run of plugin `plugin_module.plugin_name`,
with an optional `settings` string.
Args:
plugin_module (str): module of the plugin.
plugin_name (str): class name of the plugin.
settings (str, optional): Optional plugin configuration. For example,
this could be a `json.dumps` of a configuration dict. Defaults to None.
"""
def __init__(
self,
containerImage: str = None,
pluginModule: str = None,
pluginName: str = None,
status: str = None,
settings: str = None,
targetItemId: str = None,
authUrl: str = None,
error: str = None,
persistentState: list = None,
account: list = None,
view: list = None,
**kwargs
):
super().__init__(**kwargs)
self.pluginModule = pluginModule
self.pluginName = pluginName
self.containerImage=containerImage
id_ = "".join([random.choice(string.hexdigits) for i in range(32)]) if targetItemId is None else targetItemId
self.targetItemId=id_
self.id=id_
self.status = status # for stateful plugins
self.settings = settings
self.authUrl = authUrl # for authenticated plugins
self.error = error # universa
self.account = account if account is not None else []
self.persistentState = persistentState if persistentState is not None else []
self.view = view if view is not None else []
id_ = (
"".join([random.choice(string.hexdigits) for i in range(32)])
if targetItemId is None
else targetItemId
)
# Properties
self.pluginModule: Optional[str] = pluginModule
self.pluginName: Optional[str] = pluginName
self.containerImage: Optional[str] = containerImage
self.targetItemId: Optional[str] = id_
self.id: Optional[str] = id_
self.status: Optional[str] = status
self.settings: Optional[str] = settings
self.authUrl: Optional[str] = authUrl
self.error: Optional[str] = error
# Edges
self.account: list = account if account is not None else []
self.persistentState: list = persistentState if persistentState is not None else []
self.view: list = view if view is not None else []
```
%% Cell type:code id: tags:
%% Cell type:code id:68e3d23d tags:
``` python
run = PluginRun("image", "module", "name", account=[Account()])
```
%% Cell type:code id: tags:
%% Cell type:code id:35a88959 tags:
``` python
# export
# hide
class PersistentState(Item):
""" Persistent state variables saved for plugin such as views, accounts, the last state to resume from etc. """
# TODO remove this schema, it is no longer needed with the updated PluginRun
properties = Item.properties + ["pluginId", "state"]
edges = Item.edges + ["account", "view"]
def __init__(self, pluginName=None, state=None, account=None, view=None, **kwargs):
super().__init__(**kwargs)
self.pluginName = pluginName
self.status = state
self.account = account if account is not None else []
self.view = view if view is not None else []
def get_state(self):
return self.status
def set_state(self, client, state_str):
self.status = state_str
client.update_item(self)
def get_account(self):
if len(self.account) == 0:
return None
else:
return self.account[0]
def set_account(self, client, account):
if len(self.account) == 0:
if not account.id:
client.create(account)
self.add_edge('account', account)
self.add_edge("account", account)
self.update(client)
else:
existing_account = self.account[0]
for prop in account.properties:
value = getattr(account, prop, None)
if value and hasattr(existing_account, prop):
setattr(existing_account, prop, value)
existing_account.update(client)
def get_view_by_name(self, view_name):
for cvu in self.view:
if cvu.name == view_name:
return cvu
def set_views(self, client, views=None):
for view in views:
client.create(view)
self.add_edge('view', view)
self.add_edge("view", view)
self.update(client)
return True
```
%% Cell type:code id: tags:
``` python
```
......
......@@ -4,6 +4,7 @@ __all__ = ['ALL_EDGES', 'parse_base_item_json', 'Edge', 'ItemBase', 'Item']
# Cell
# hide
from typing import Optional
from ..imports import *
ALL_EDGES = "allEdges"
......@@ -79,8 +80,8 @@ class ItemBase():
All items in the schema inherit from this class, and it provides some
basic functionality for consistency and to enable easier usage."""
def __init__(self, id=None):
self.id=id
def __init__(self, id: str = None):
self.id: Optional[str] = id
def __getattribute__(self, name):
val = object.__getattribute__(self, name)
......@@ -188,18 +189,61 @@ class ItemBase():
# Cell
class Item(ItemBase):
"""Item is the baseclass for all of the data classes."""
properties = ["dateAccessed", "dateCreated", "dateModified", "deleted", "externalId", "itemDescription",
"starred", "version", "id", "importJson", "pluginClass"]
properties = [
"dateAccessed",
"dateCreated",
"dateModified",
"deleted",
"externalId",
"itemDescription",
"starred",
"version",
"id",
"importJson",
"pluginClass",
]
edges = ["changelog", "label", "genericAttribute", "measure", "sharedWith"]
def __init__(self, **kwargs):
super().__init__(kwargs.get("id"))
for p in self.properties:
if p == "id":
continue
setattr(self, p, kwargs.get(p, None))
for e in self.edges:
setattr(self, e, kwargs.get(e, []))
def __init__(
self,
dateAccessed: str = None,
dateCreated: str = None,
dateModified: str = None,
deleted: str = None,
externalId: str = None,
itemDescription: str = None,
starred: str = None,
version: str = None,
id: str = None,
importJson: str = None,
pluginClass: str = None,
changelog: list = None,
label: list = None,
genericAttribute: list = None,
measure: list = None,
sharedWith: list = None
):
super().__init__(id)
# Properties
self.dateAccessed: Optional[str] = dateAccessed
self.dateCreated: Optional[str] = dateCreated
self.dateModified: Optional[str] = dateModified
self.deleted: Optional[str] = deleted
self.externalId: Optional[str] = externalId
self.itemDescription: Optional[str] = itemDescription
self.starred: Optional[str] = starred
self.version: Optional[str] = version
self.importJson: Optional[str] = importJson
self.pluginClass: Optional[str] = pluginClass
# Edges
self.changelog: list = changelog if changelog is not None else []
self.label: list = label if label is not None else []
self.genericAttribute: list = genericAttribute if genericAttribute is not None else []
self.measure: list = measure if measure is not None else []
self.sharedWith: list = sharedWith if sharedWith is not None else []
@classmethod
def parse_json(self, cls, json):
......@@ -235,5 +279,6 @@ class Item(ItemBase):
def from_json(cls, json):
kwargs = Item.parse_json(cls, json)
res = cls(**kwargs)
for e in res.get_all_edges(): e.source = res
for e in res.get_all_edges():
e.source = res
return res
\ No newline at end of file
......@@ -5,65 +5,101 @@ __all__ = ['Account', 'PluginRun', 'PersistentState']
# Cell
# hide
import random, string
from typing import Optional
from ..data.itembase import Item
# Cell
# hide
class Account(Item):
properties = Item.properties + ['service', "identifier", "secret", "code", "refreshToken", "errorMessage"]
properties = Item.properties + [
"service",
"identifier",
"secret",
"code",
"refreshToken",
"errorMessage",
]
edges = Item.edges
def __init__(self, service=None, identifier=None, secret=None, code=None, refreshToken=None,
errorMessage=None, **kwargs):
def __init__(
self,
service: str = None,
identifier: str = None,
secret: str = None,
code: str = None,
refreshToken: str = None,
errorMessage: str = None,
**kwargs
):
super().__init__(**kwargs)
self.service = service
self.identifier = identifier
self.secret = secret
self.refreshToken = refreshToken
self.code = code
self.errorMessage = errorMessage
# Properties
self.service: Optional[str] = service
self.identifier: Optional[str] = identifier
self.secret: Optional[str] = secret
self.refreshToken: Optional[str] = refreshToken
self.code: Optional[str] = code
self.errorMessage: Optional[str] = errorMessage
# Cell
# hide
class PluginRun(Item):
properties = Item.properties + ["containerImage", "pluginModule", "pluginName", "status", "targetItemId",
"authUrl", "error", "settings"]
properties = Item.properties + [
"containerImage",
"pluginModule",
"pluginName",
"status",
"targetItemId",
"authUrl",
"error",
"settings",
]
edges = Item.edges + ["view", "persistentState", "account"]
def __init__(self, containerImage, pluginModule, pluginName, status=None, settings=None, view=None,
targetItemId=None, authUrl=None, error=None, persistentState=None, account=None,
**kwargs):
"""
PluginRun defines a the run of plugin `plugin_module.plugin_name`,
with an optional `settings` string.
Args:
plugin_module (str): module of the plugin.
plugin_name (str): class name of the plugin.
settings (str, optional): Optional plugin configuration. For example,
this could be a `json.dumps` of a configuration dict. Defaults to None.
"""
def __init__(
self,
containerImage: str = None,
pluginModule: str = None,
pluginName: str = None,
status: str = None,
settings: str = None,
targetItemId: str = None,
authUrl: str = None,
error: str = None,
persistentState: list = None,
account: list = None,
view: list = None,
**kwargs
):
super().__init__(**kwargs)
self.pluginModule = pluginModule
self.pluginName = pluginName
self.containerImage=containerImage
id_ = "".join([random.choice(string.hexdigits) for i in range(32)]) if targetItemId is None else targetItemId
self.targetItemId=id_
self.id=id_
self.status = status # for stateful plugins
self.settings = settings
self.authUrl = authUrl # for authenticated plugins
self.error = error # universa
self.account = account if account is not None else []
self.persistentState = persistentState if persistentState is not None else []
self.view = view if view is not None else []
id_ = (
"".join([random.choice(string.hexdigits) for i in range(32)])
if targetItemId is None
else targetItemId
)
# Properties
self.pluginModule: Optional[str] = pluginModule
self.pluginName: Optional[str] = pluginName
self.containerImage: Optional[str] = containerImage
self.targetItemId: Optional[str] = id_
self.id: Optional[str] = id_
self.status: Optional[str] = status
self.settings: Optional[str] = settings
self.authUrl: Optional[str] = authUrl
self.error: Optional[str] = error
# Edges
self.account: list = account if account is not None else []
self.persistentState: list = persistentState if persistentState is not None else []
self.view: list = view if view is not None else []
# Cell
# hide
class PersistentState(Item):
""" Persistent state variables saved for plugin such as views, accounts, the last state to resume from etc. """
# TODO remove this schema, it is no longer needed with the updated PluginRun
properties = Item.properties + ["pluginId", "state"]
edges = Item.edges + ["account", "view"]
......@@ -92,7 +128,7 @@ class PersistentState(Item):
if len(self.account) == 0:
if not account.id:
client.create(account)
self.add_edge('account', account)
self.add_edge("account", account)
self.update(client)
else:
existing_account = self.account[0]
......@@ -110,6 +146,6 @@ class PersistentState(Item):
def set_views(self, client, views=None):
for view in views:
client.create(view)
self.add_edge('view', view)
self.add_edge("view", view)
self.update(client)
return True
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment