changeset 2351:3c0a3fae1862

jp (pubsub/node): added schema (set/edit/get) commands to manipulate PubSub node schema
author Goffi <goffi@goffi.org>
date Wed, 06 Sep 2017 07:39:10 +0200
parents 388226e9c3ff
children 6c26f435a02d
files frontends/src/jp/cmd_pubsub.py frontends/src/jp/common.py
diffstat 2 files changed, 125 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/frontends/src/jp/cmd_pubsub.py	Wed Sep 06 07:38:39 2017 +0200
+++ b/frontends/src/jp/cmd_pubsub.py	Wed Sep 06 07:39:10 2017 +0200
@@ -37,6 +37,7 @@
 __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 @@
         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 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 @@
     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):
--- a/frontends/src/jp/common.py	Wed Sep 06 07:38:39 2017 +0200
+++ b/frontends/src/jp/common.py	Wed Sep 06 07:39:10 2017 +0200
@@ -136,6 +136,8 @@
     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 @@
         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 @@
         # 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 @@
 
         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 @@
                 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: