jp (pubsub/node): added schema (set/edit/get) commands to manipulate PubSub node schema

This commit is contained in:
Goffi 2017-09-06 07:39:10 +02:00
commit e9c0f5e127
2 changed files with 125 additions and 11 deletions

View file

@ -37,6 +37,7 @@ import sys
__commands__ = ["Pubsub"]
PUBSUB_TMP_DIR = u"pubsub"
PUBSUB_SCHEMA_TMP_DIR = PUBSUB_TMP_DIR + "_schema"
ALLOWED_SUBSCRIPTIONS_OWNER = ('subscribed', 'pending', 'none')
# TODO: need to split this class in several modules, plugin should handle subcommands
@ -362,8 +363,119 @@ class NodeSubscriptions(base.CommandBase):
super(NodeSubscriptions, self).__init__(host, 'subscriptions', use_profile=False, help=_(u'get or modify node subscriptions'))
class NodeSchemaSet(base.CommandBase):
def __init__(self, host):
base.CommandBase.__init__(self, host, 'set', use_pubsub_node_req=True, use_verbose=True, help=_(u'set/replace a schema'))
self.need_loop = True
def add_parser_options(self):
self.parser.add_argument('schema', help=_(u"schema to set (must be XML)"))
def psSchemaSetCb(self):
self.disp(_(u'schema has been set'), 1)
self.host.quit()
def start(self):
self.host.bridge.psSchemaSet(
self.args.service,
self.args.node,
self.args.schema,
self.profile,
callback=self.psSchemaSetCb,
errback=partial(self.errback,
msg=_(u"can't set schema: {}"),
exit_code=C.EXIT_BRIDGE_ERRBACK))
class NodeSchemaEdit(base.CommandBase, common.BaseEdit):
use_items=False
def __init__(self, host):
base.CommandBase.__init__(self, host, 'edit', use_pubsub_node_req=True, use_verbose=True, help=_(u'edit a schema'))
common.BaseEdit.__init__(self, self.host, PUBSUB_SCHEMA_TMP_DIR)
self.need_loop=True
def add_parser_options(self):
common.BaseEdit.add_parser_options(self)
def psSchemaSetCb(self):
self.disp(_(u'schema has been set'), 1)
self.host.quit()
def publish(self, schema):
self.host.bridge.psSchemaSet(
self.args.service,
self.args.node,
schema,
self.profile,
callback=self.psSchemaSetCb,
errback=partial(self.errback,
msg=_(u"can't set schema: {}"),
exit_code=C.EXIT_BRIDGE_ERRBACK))
def psSchemaGetCb(self, schema):
try:
from lxml import etree
except ImportError:
self.disp(u"lxml module must be installed to use edit, please install it with \"pip install lxml\"", error=True)
self.host.quit(1)
parser = etree.XMLParser(remove_blank_text=True)
schema_elt = etree.fromstring(schema, parser)
content_file_obj, content_file_path = self.getTmpFile()
content_file_obj.write(etree.tostring(schema_elt, encoding="utf-8", pretty_print=True))
content_file_obj.seek(0)
self.runEditor("pubsub_schema_editor_args", content_file_path, content_file_obj)
def start(self):
common.checkURI(self.args)
self.host.bridge.psSchemaGet(
self.args.service,
self.args.node,
self.profile,
callback=self.psSchemaGetCb,
errback=partial(self.errback,
msg=_(u"can't edit schema: {}"),
exit_code=C.EXIT_BRIDGE_ERRBACK))
class NodeSchemaGet(base.CommandBase):
def __init__(self, host):
base.CommandBase.__init__(self, host, 'get', use_output=C.OUTPUT_XML, use_pubsub_node_req=True, use_verbose=True, help=_(u'get schema'))
self.need_loop=True
def add_parser_options(self):
pass
def psSchemaGetCb(self, schema):
if not schema:
self.disp(_(u'no schema found'), 1)
self.host.quit(1)
self.output(schema)
self.host.quit()
def start(self):
common.checkURI(self.args)
self.host.bridge.psSchemaGet(
self.args.service,
self.args.node,
self.profile,
callback=self.psSchemaGetCb,
errback=partial(self.errback,
msg=_(u"can't get schema: {}"),
exit_code=C.EXIT_BRIDGE_ERRBACK))
class NodeSchema(base.CommandBase):
subcommands = (NodeSchemaSet, NodeSchemaEdit, NodeSchemaGet)
def __init__(self, host):
super(NodeSchema, self).__init__(host, 'schema', use_profile=False, help=_(u"data schema manipulation"))
class Node(base.CommandBase):
subcommands = (NodeInfo, NodeCreate, NodeDelete, NodeSet, NodeAffiliations, NodeSubscriptions)
subcommands = (NodeInfo, NodeCreate, NodeDelete, NodeSet, NodeAffiliations, NodeSubscriptions, NodeSchema)
def __init__(self, host):
super(Node, self).__init__(host, 'node', use_profile=False, help=_('node handling'))
@ -447,7 +559,7 @@ class Delete(base.CommandBase):
class Edit(base.CommandBase, common.BaseEdit):
def __init__(self, host):
base.CommandBase.__init__(self, host, 'edit', use_verbose=True, use_pubsub=True, help=_(u'edit an existing or new pubsub item'))
base.CommandBase.__init__(self, host, 'edit', use_verbose=True, use_pubsub_node_req=True, help=_(u'edit an existing or new pubsub item'))
common.BaseEdit.__init__(self, self.host, PUBSUB_TMP_DIR)
def add_parser_options(self):
@ -980,7 +1092,7 @@ class Hook(base.CommandBase):
subcommands = (HookCreate, HookDelete, HookList)
def __init__(self, host):
super(Hook, self).__init__(host, 'hook', use_profile=False, help=_('trigger action on Pubsub notifications'))
super(Hook, self).__init__(host, 'hook', use_profile=False, use_verbose=True, help=_('trigger action on Pubsub notifications'))
class Pubsub(base.CommandBase):

View file

@ -136,6 +136,8 @@ class BaseEdit(object):
This class allows to edit file for PubSub or something else.
It works with temporary files in SàT local_dir, in a "cat_dir" subdir
"""
# use_items(bool): True if items are used, will then add item related options
use_items=True
def __init__(self, host, cat_dir, use_metadata=False):
"""
@ -152,9 +154,10 @@ class BaseEdit(object):
self.use_metadata = use_metadata
def add_parser_options(self):
group = self.parser.add_mutually_exclusive_group()
group.add_argument("--force-item", action='store_true', help=_(u"don't use magic and take item argument as an actual item"))
group.add_argument("--last-item", action='store_true', help=_(u"take last item instead of creating a new one if no item id is found"))
if self.use_items:
group = self.parser.add_mutually_exclusive_group()
group.add_argument("--force-item", action='store_true', help=_(u"don't use magic and take item argument as an actual item"))
group.add_argument("--last-item", action='store_true', help=_(u"take last item instead of creating a new one if no item id is found"))
def secureUnlink(self, path):
"""Unlink given path after keeping it for a while
@ -311,12 +314,13 @@ class BaseEdit(object):
# if metadata is needed, publish will be called with it last argument
raise NotImplementedError
def getTmpFile(self, suff):
def getTmpFile(self):
"""Create a temporary file
@param suff (str): suffix to use for the filename
@return (tuple(file, str)): opened (w+b) file object and file path
"""
suff = '.' + self.getTmpSuff()
cat_dir_str = self.cat_dir_str
tmp_dir = getTmpDir(self.sat_conf, self.cat_dir_str, self.profile.encode('utf-8'))
if not os.path.exists(tmp_dir):
@ -443,8 +447,7 @@ class BaseEdit(object):
if not force_item and command in ('new', 'last', 'edit'):
# we need a temporary file
tmp_suff = '.' + self.getTmpSuff()
content_file_obj, content_file_path = self.getTmpFile(tmp_suff)
content_file_obj, content_file_path = self.getTmpFile()
if command == 'new':
self.disp(u'Editing a new item', 2)
if self.use_metadata:
@ -475,8 +478,7 @@ class BaseEdit(object):
content_file_obj = open(content_file_path, 'r+b')
else:
# last chance, it should be an item
tmp_suff = '.' + self.getTmpSuff()
content_file_obj, content_file_path = self.getTmpFile(tmp_suff)
content_file_obj, content_file_path = self.getTmpFile()
pubsub_item = self.args.item
try: