comparison frontends/src/jp/cmd_pubsub.py @ 2532:772447ec070f

jp: pubsub options refactoring: There is now only "use_pubsub", and specification are set using "pubsub_flags" argument when instantiating CommandBase. Options are more Python Zen compliant by using explicit arguments for item, draft, url instead of trying to guess with magic keyword and type detection. Pubsub node and item are now always using respecively "-n" and "-i" even when required, this way shell history can be used to change command more easily, and it's globally less confusing for user. if --pubsub-url is used, elements can be overwritten with individual option (e.g. change item id with --item). New "use_draft" argument in CommandBase, to re-use current draft or open a file path as draft. Item can now be specified when using a draft. If it already exists, its content will be added to current draft (with a separator), to avoid loosing data. common.BaseEdit.getItemPath could be simplified thanks to those changes. Pubsub URI handling has been moved to base.py.
author Goffi <goffi@goffi.org>
date Wed, 21 Mar 2018 19:13:22 +0100
parents 0046283a285d
children dcc77f23e370
comparison
equal deleted inserted replaced
2531:1dfc5516dead 2532:772447ec070f
44 44
45 45
46 class NodeInfo(base.CommandBase): 46 class NodeInfo(base.CommandBase):
47 47
48 def __init__(self, host): 48 def __init__(self, host):
49 base.CommandBase.__init__(self, host, 'info', use_output=C.OUTPUT_DICT, use_pubsub_node_req=True, help=_(u'retrieve node configuration')) 49 base.CommandBase.__init__(self, host, 'info', use_output=C.OUTPUT_DICT, use_pubsub=True, pubsub_flags={C.NODE}, help=_(u'retrieve node configuration'))
50 self.need_loop=True 50 self.need_loop=True
51 51
52 def add_parser_options(self): 52 def add_parser_options(self):
53 self.parser.add_argument("-k", "--key", type=base.unicode_decoder, action='append', dest='keys', 53 self.parser.add_argument("-k", "--key", type=base.unicode_decoder, action='append', dest='keys',
54 help=_(u"data key to filter")) 54 help=_(u"data key to filter"))
69 self.disp(u"can't get node configuration: {reason}".format( 69 self.disp(u"can't get node configuration: {reason}".format(
70 reason=failure_), error=True) 70 reason=failure_), error=True)
71 self.host.quit(C.EXIT_BRIDGE_ERRBACK) 71 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
72 72
73 def start(self): 73 def start(self):
74 common.checkURI(self.args)
75 self.host.bridge.psNodeConfigurationGet( 74 self.host.bridge.psNodeConfigurationGet(
76 self.args.service, 75 self.args.service,
77 self.args.node, 76 self.args.node,
78 self.profile, 77 self.profile,
79 callback=self.psNodeConfigurationGetCb, 78 callback=self.psNodeConfigurationGetCb,
81 80
82 81
83 class NodeCreate(base.CommandBase): 82 class NodeCreate(base.CommandBase):
84 83
85 def __init__(self, host): 84 def __init__(self, host):
86 base.CommandBase.__init__(self, host, 'create', use_output=C.OUTPUT_DICT, use_pubsub_node_req=True, use_verbose=True, help=_(u'create a node')) 85 base.CommandBase.__init__(self, host, 'create', use_output=C.OUTPUT_DICT, use_pubsub=True, pubsub_flags={C.NODE}, use_verbose=True, help=_(u'create a node'))
87 self.need_loop=True 86 self.need_loop=True
88 87
89 def add_parser_options(self): 88 def add_parser_options(self):
90 self.parser.add_argument("-f", "--field", type=base.unicode_decoder, action='append', nargs=2, dest='fields', 89 self.parser.add_argument("-f", "--field", type=base.unicode_decoder, action='append', nargs=2, dest='fields',
91 default=[], metavar=(u"KEY", u"VALUE"), help=_(u"configuration field to set")) 90 default=[], metavar=(u"KEY", u"VALUE"), help=_(u"configuration field to set"))
121 120
122 121
123 class NodeDelete(base.CommandBase): 122 class NodeDelete(base.CommandBase):
124 123
125 def __init__(self, host): 124 def __init__(self, host):
126 base.CommandBase.__init__(self, host, 'delete', use_pubsub_node_req=True, help=_(u'delete a node')) 125 base.CommandBase.__init__(self, host, 'delete', use_pubsub=True, pubsub_flags={C.NODE}, help=_(u'delete a node'))
127 self.need_loop=True 126 self.need_loop=True
128 127
129 def add_parser_options(self): 128 def add_parser_options(self):
130 self.parser.add_argument('-f', '--force', action='store_true', help=_(u'delete node without confirmation')) 129 self.parser.add_argument('-f', '--force', action='store_true', help=_(u'delete node without confirmation'))
131 130
132 def psNodeDeleteCb(self): 131 def psNodeDeleteCb(self):
133 self.disp(_(u'node [{node}] deleted successfully').format(node=self.args.node)) 132 self.disp(_(u'node [{node}] deleted successfully').format(node=self.args.node))
134 self.host.quit() 133 self.host.quit()
135 134
136 def start(self): 135 def start(self):
137 common.checkURI(self.args)
138 if not self.args.force: 136 if not self.args.force:
139 if not self.args.service: 137 if not self.args.service:
140 message = _(u"Are you sure to delete pep node [{node_id}] ?").format( 138 message = _(u"Are you sure to delete pep node [{node_id}] ?").format(
141 node_id=self.args.node) 139 node_id=self.args.node)
142 else: 140 else:
159 157
160 158
161 class NodeSet(base.CommandBase): 159 class NodeSet(base.CommandBase):
162 160
163 def __init__(self, host): 161 def __init__(self, host):
164 base.CommandBase.__init__(self, host, 'set', use_output=C.OUTPUT_DICT, use_pubsub_node_req=True, use_verbose=True, help=_(u'set node configuration')) 162 base.CommandBase.__init__(self, host, 'set', use_output=C.OUTPUT_DICT, use_pubsub=True, pubsub_flags={C.NODE}, use_verbose=True, help=_(u'set node configuration'))
165 self.need_loop=True 163 self.need_loop=True
166 164
167 def add_parser_options(self): 165 def add_parser_options(self):
168 self.parser.add_argument("-f", "--field", type=base.unicode_decoder, action='append', nargs=2, dest='fields', 166 self.parser.add_argument("-f", "--field", type=base.unicode_decoder, action='append', nargs=2, dest='fields',
169 required=True, metavar=(u"KEY", u"VALUE"), help=_(u"configuration field to set (required)")) 167 required=True, metavar=(u"KEY", u"VALUE"), help=_(u"configuration field to set (required)"))
182 return u'pubsub#' + k 180 return u'pubsub#' + k
183 else: 181 else:
184 return k 182 return k
185 183
186 def start(self): 184 def start(self):
187 common.checkURI(self.args)
188 self.host.bridge.psNodeConfigurationSet( 185 self.host.bridge.psNodeConfigurationSet(
189 self.args.service, 186 self.args.service,
190 self.args.node, 187 self.args.node,
191 {self.getKeyName(k): v for k,v in self.args.fields}, 188 {self.getKeyName(k): v for k,v in self.args.fields},
192 self.profile, 189 self.profile,
195 192
196 193
197 class NodeAffiliationsGet(base.CommandBase): 194 class NodeAffiliationsGet(base.CommandBase):
198 195
199 def __init__(self, host): 196 def __init__(self, host):
200 base.CommandBase.__init__(self, host, 'get', use_output=C.OUTPUT_DICT, use_pubsub_node_req=True, help=_(u'retrieve node affiliations (for node owner)')) 197 base.CommandBase.__init__(self, host, 'get', use_output=C.OUTPUT_DICT, use_pubsub=True, pubsub_flags={C.NODE}, help=_(u'retrieve node affiliations (for node owner)'))
201 self.need_loop=True 198 self.need_loop=True
202 199
203 def add_parser_options(self): 200 def add_parser_options(self):
204 pass 201 pass
205 202
211 self.disp(u"can't get node affiliations: {reason}".format( 208 self.disp(u"can't get node affiliations: {reason}".format(
212 reason=failure_), error=True) 209 reason=failure_), error=True)
213 self.host.quit(C.EXIT_BRIDGE_ERRBACK) 210 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
214 211
215 def start(self): 212 def start(self):
216 common.checkURI(self.args)
217 self.host.bridge.psNodeAffiliationsGet( 213 self.host.bridge.psNodeAffiliationsGet(
218 self.args.service, 214 self.args.service,
219 self.args.node, 215 self.args.node,
220 self.profile, 216 self.profile,
221 callback=self.psNodeAffiliationsGetCb, 217 callback=self.psNodeAffiliationsGetCb,
223 219
224 220
225 class NodeAffiliationsSet(base.CommandBase): 221 class NodeAffiliationsSet(base.CommandBase):
226 222
227 def __init__(self, host): 223 def __init__(self, host):
228 base.CommandBase.__init__(self, host, 'set', use_pubsub_node_req=True, use_verbose=True, help=_(u'set affiliations (for node owner)')) 224 base.CommandBase.__init__(self, host, 'set', use_pubsub=True, pubsub_flags={C.NODE}, use_verbose=True, help=_(u'set affiliations (for node owner)'))
229 self.need_loop=True 225 self.need_loop=True
230 226
231 def add_parser_options(self): 227 def add_parser_options(self):
232 # XXX: we use optional argument syntax for a required one because list of list of 2 elements 228 # XXX: we use optional argument syntax for a required one because list of list of 2 elements
233 # (uses to construct dicts) don't work with positional arguments 229 # (uses to construct dicts) don't work with positional arguments
249 self.disp(u"can't set node affiliations: {reason}".format( 245 self.disp(u"can't set node affiliations: {reason}".format(
250 reason=failure_), error=True) 246 reason=failure_), error=True)
251 self.host.quit(C.EXIT_BRIDGE_ERRBACK) 247 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
252 248
253 def start(self): 249 def start(self):
254 common.checkURI(self.args)
255 affiliations = dict(self.args.affiliations) 250 affiliations = dict(self.args.affiliations)
256 self.host.bridge.psNodeAffiliationsSet( 251 self.host.bridge.psNodeAffiliationsSet(
257 self.args.service, 252 self.args.service,
258 self.args.node, 253 self.args.node,
259 affiliations, 254 affiliations,
270 265
271 266
272 class NodeSubscriptionsGet(base.CommandBase): 267 class NodeSubscriptionsGet(base.CommandBase):
273 268
274 def __init__(self, host): 269 def __init__(self, host):
275 base.CommandBase.__init__(self, host, 'get', use_output=C.OUTPUT_DICT, use_pubsub_node_req=True, help=_(u'retrieve node subscriptions (for node owner)')) 270 base.CommandBase.__init__(self, host, 'get', use_output=C.OUTPUT_DICT, use_pubsub=True, pubsub_flags={C.NODE}, help=_(u'retrieve node subscriptions (for node owner)'))
276 self.need_loop=True 271 self.need_loop=True
277 272
278 def add_parser_options(self): 273 def add_parser_options(self):
279 pass 274 pass
280 275
286 self.disp(u"can't get node subscriptions: {reason}".format( 281 self.disp(u"can't get node subscriptions: {reason}".format(
287 reason=failure_), error=True) 282 reason=failure_), error=True)
288 self.host.quit(C.EXIT_BRIDGE_ERRBACK) 283 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
289 284
290 def start(self): 285 def start(self):
291 common.checkURI(self.args)
292 self.host.bridge.psNodeSubscriptionsGet( 286 self.host.bridge.psNodeSubscriptionsGet(
293 self.args.service, 287 self.args.service,
294 self.args.node, 288 self.args.node,
295 self.profile, 289 self.profile,
296 callback=self.psNodeSubscriptionsGetCb, 290 callback=self.psNodeSubscriptionsGetCb,
318 312
319 313
320 class NodeSubscriptionsSet(base.CommandBase): 314 class NodeSubscriptionsSet(base.CommandBase):
321 315
322 def __init__(self, host): 316 def __init__(self, host):
323 base.CommandBase.__init__(self, host, 'set', use_pubsub_node_req=True, use_verbose=True, help=_(u'set/modify subscriptions (for node owner)')) 317 base.CommandBase.__init__(self, host, 'set', use_pubsub=True, pubsub_flags={C.NODE}, use_verbose=True, help=_(u'set/modify subscriptions (for node owner)'))
324 self.need_loop=True 318 self.need_loop=True
325 319
326 def add_parser_options(self): 320 def add_parser_options(self):
327 # XXX: we use optional argument syntax for a required one because list of list of 2 elements 321 # XXX: we use optional argument syntax for a required one because list of list of 2 elements
328 # (uses to construct dicts) don't work with positional arguments 322 # (uses to construct dicts) don't work with positional arguments
345 self.disp(u"can't set node subscriptions: {reason}".format( 339 self.disp(u"can't set node subscriptions: {reason}".format(
346 reason=failure_), error=True) 340 reason=failure_), error=True)
347 self.host.quit(C.EXIT_BRIDGE_ERRBACK) 341 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
348 342
349 def start(self): 343 def start(self):
350 common.checkURI(self.args)
351 self.host.bridge.psNodeSubscriptionsSet( 344 self.host.bridge.psNodeSubscriptionsSet(
352 self.args.service, 345 self.args.service,
353 self.args.node, 346 self.args.node,
354 self.args.subscriptions, 347 self.args.subscriptions,
355 self.profile, 348 self.profile,
365 358
366 359
367 class NodeSchemaSet(base.CommandBase): 360 class NodeSchemaSet(base.CommandBase):
368 361
369 def __init__(self, host): 362 def __init__(self, host):
370 base.CommandBase.__init__(self, host, 'set', use_pubsub_node_req=True, use_verbose=True, help=_(u'set/replace a schema')) 363 base.CommandBase.__init__(self, host, 'set', use_pubsub=True, pubsub_flags={C.NODE}, use_verbose=True, help=_(u'set/replace a schema'))
371 self.need_loop = True 364 self.need_loop = True
372 365
373 def add_parser_options(self): 366 def add_parser_options(self):
374 self.parser.add_argument('schema', help=_(u"schema to set (must be XML)")) 367 self.parser.add_argument('schema', help=_(u"schema to set (must be XML)"))
375 368
391 384
392 class NodeSchemaEdit(base.CommandBase, common.BaseEdit): 385 class NodeSchemaEdit(base.CommandBase, common.BaseEdit):
393 use_items=False 386 use_items=False
394 387
395 def __init__(self, host): 388 def __init__(self, host):
396 base.CommandBase.__init__(self, host, 'edit', use_pubsub_node_req=True, use_verbose=True, help=_(u'edit a schema')) 389 base.CommandBase.__init__(self, host, 'edit', use_pubsub=True, pubsub_flags={C.NODE}, use_draft=True, use_verbose=True, help=_(u'edit a schema'))
397 common.BaseEdit.__init__(self, self.host, PUBSUB_SCHEMA_TMP_DIR) 390 common.BaseEdit.__init__(self, self.host, PUBSUB_SCHEMA_TMP_DIR)
398 self.need_loop=True 391 self.need_loop=True
399 392
400 def add_parser_options(self): 393 def add_parser_options(self):
401 common.BaseEdit.add_parser_options(self) 394 pass
402 395
403 def psSchemaSetCb(self): 396 def psSchemaSetCb(self):
404 self.disp(_(u'schema has been set'), 1) 397 self.disp(_(u'schema has been set'), 1)
405 self.host.quit() 398 self.host.quit()
406 399
429 content_file_obj.write(etree.tostring(schema_elt, encoding="utf-8", pretty_print=True)) 422 content_file_obj.write(etree.tostring(schema_elt, encoding="utf-8", pretty_print=True))
430 content_file_obj.seek(0) 423 content_file_obj.seek(0)
431 self.runEditor("pubsub_schema_editor_args", content_file_path, content_file_obj) 424 self.runEditor("pubsub_schema_editor_args", content_file_path, content_file_obj)
432 425
433 def start(self): 426 def start(self):
434 common.checkURI(self.args)
435 self.host.bridge.psSchemaGet( 427 self.host.bridge.psSchemaGet(
436 self.args.service, 428 self.args.service,
437 self.args.node, 429 self.args.node,
438 self.profile, 430 self.profile,
439 callback=self.psSchemaGetCb, 431 callback=self.psSchemaGetCb,
443 435
444 436
445 class NodeSchemaGet(base.CommandBase): 437 class NodeSchemaGet(base.CommandBase):
446 438
447 def __init__(self, host): 439 def __init__(self, host):
448 base.CommandBase.__init__(self, host, 'get', use_output=C.OUTPUT_XML, use_pubsub_node_req=True, use_verbose=True, help=_(u'get schema')) 440 base.CommandBase.__init__(self, host, 'get', use_output=C.OUTPUT_XML, use_pubsub=True, pubsub_flags={C.NODE}, use_verbose=True, help=_(u'get schema'))
449 self.need_loop=True 441 self.need_loop=True
450 442
451 def add_parser_options(self): 443 def add_parser_options(self):
452 pass 444 pass
453 445
457 self.host.quit(1) 449 self.host.quit(1)
458 self.output(schema) 450 self.output(schema)
459 self.host.quit() 451 self.host.quit()
460 452
461 def start(self): 453 def start(self):
462 common.checkURI(self.args)
463 self.host.bridge.psSchemaGet( 454 self.host.bridge.psSchemaGet(
464 self.args.service, 455 self.args.service,
465 self.args.node, 456 self.args.node,
466 self.profile, 457 self.profile,
467 callback=self.psSchemaGetCb, 458 callback=self.psSchemaGetCb,
485 476
486 477
487 class Set(base.CommandBase): 478 class Set(base.CommandBase):
488 479
489 def __init__(self, host): 480 def __init__(self, host):
490 base.CommandBase.__init__(self, host, 'set', use_pubsub_node_req=True, help=_(u'publish a new item or update an existing one')) 481 base.CommandBase.__init__(self, host, 'set', use_pubsub=True, pubsub_flags={C.NODE}, help=_(u'publish a new item or update an existing one'))
491 self.need_loop=True 482 self.need_loop=True
492 483
493 def add_parser_options(self): 484 def add_parser_options(self):
494 self.parser.add_argument("item", type=base.unicode_decoder, nargs='?', default=u'', help=_(u"id, URL of the item to update, keyword, or nothing for new item")) 485 self.parser.add_argument("item", type=base.unicode_decoder, nargs='?', default=u'', help=_(u"id, URL of the item to update, keyword, or nothing for new item"))
495 486
504 try: 495 try:
505 from lxml import etree 496 from lxml import etree
506 except ImportError: 497 except ImportError:
507 self.disp(u"lxml module must be installed to use edit, please install it with \"pip install lxml\"", error=True) 498 self.disp(u"lxml module must be installed to use edit, please install it with \"pip install lxml\"", error=True)
508 self.host.quit(1) 499 self.host.quit(1)
509 common.checkURI(self.args)
510 try: 500 try:
511 element = etree.parse(sys.stdin).getroot() 501 element = etree.parse(sys.stdin).getroot()
512 except Exception as e: 502 except Exception as e:
513 self.parser.error(_(u"Can't parse the payload XML in input: {msg}").format(msg=e)) 503 self.parser.error(_(u"Can't parse the payload XML in input: {msg}").format(msg=e))
514 if element.tag in ('item', '{http://jabber.org/protocol/pubsub}item'): 504 if element.tag in ('item', '{http://jabber.org/protocol/pubsub}item'):
530 520
531 521
532 class Get(base.CommandBase): 522 class Get(base.CommandBase):
533 523
534 def __init__(self, host): 524 def __init__(self, host):
535 base.CommandBase.__init__(self, host, 'get', use_output=C.OUTPUT_LIST_XML, use_pubsub_node_req=True, help=_(u'get pubsub item(s)')) 525 base.CommandBase.__init__(self, host, 'get', use_output=C.OUTPUT_LIST_XML, use_pubsub=True, pubsub_flags={C.NODE, C.MULTI_ITEMS}, help=_(u'get pubsub item(s)'))
536 self.need_loop=True 526 self.need_loop=True
537 527
538 def add_parser_options(self): 528 def add_parser_options(self):
539 self.parser.add_argument("-i", "--item", type=base.unicode_decoder, action='append', default=[], dest='items',
540 help=_(u"item(s) id(s) to get (default: request all items)"))
541 self.parser.add_argument("-S", "--sub-id", type=base.unicode_decoder, default=u'', 529 self.parser.add_argument("-S", "--sub-id", type=base.unicode_decoder, default=u'',
542 help=_(u"subscription id")) 530 help=_(u"subscription id"))
543 self.parser.add_argument("-m", "--max", type=int, default=10, help=_(u"maximum number of items to get ({} to get all items)".format(C.NO_LIMIT))) 531 self.parser.add_argument("-m", "--max", type=int, default=10, help=_(u"maximum number of items to get ({} to get all items)".format(C.NO_LIMIT)))
544 # TODO: a key(s) argument to select keys to display 532 # TODO: a key(s) argument to select keys to display
545 # TODO: add MAM filters 533 # TODO: add MAM filters
553 self.disp(u"can't get pubsub items: {reason}".format( 541 self.disp(u"can't get pubsub items: {reason}".format(
554 reason=failure_), error=True) 542 reason=failure_), error=True)
555 self.host.quit(C.EXIT_BRIDGE_ERRBACK) 543 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
556 544
557 def start(self): 545 def start(self):
558 common.checkURI(self.args)
559 self.host.bridge.psItemsGet( 546 self.host.bridge.psItemsGet(
560 self.args.service, 547 self.args.service,
561 self.args.node, 548 self.args.node,
562 self.args.max, 549 self.args.max,
563 self.args.items, 550 self.args.items,
568 errback=self.psItemsGetEb) 555 errback=self.psItemsGetEb)
569 556
570 class Delete(base.CommandBase): 557 class Delete(base.CommandBase):
571 558
572 def __init__(self, host): 559 def __init__(self, host):
573 base.CommandBase.__init__(self, host, 'delete', use_pubsub_node_req=True, help=_(u'delete an item')) 560 base.CommandBase.__init__(self, host, 'delete', use_pubsub=True, pubsub_flags={C.NODE, C.SINGLE_ITEM}, help=_(u'delete an item'))
574 self.need_loop=True 561 self.need_loop=True
575 562
576 def add_parser_options(self): 563 def add_parser_options(self):
577 self.parser.add_argument("item", nargs='?', type=base.unicode_decoder, help=_(u"item to delete"))
578 self.parser.add_argument("-f", "--force", action='store_true', help=_(u"delete without confirmation")) 564 self.parser.add_argument("-f", "--force", action='store_true', help=_(u"delete without confirmation"))
579 self.parser.add_argument("-n", "--notify", action='store_true', help=_(u"notify deletion")) 565 self.parser.add_argument("-N", "--notify", action='store_true', help=_(u"notify deletion"))
580 566
581 def psItemsDeleteCb(self): 567 def psItemsDeleteCb(self):
582 self.disp(_(u'item {item_id} has been deleted').format(item_id=self.args.item)) 568 self.disp(_(u'item {item_id} has been deleted').format(item_id=self.args.item))
583 self.host.quit(C.EXIT_OK) 569 self.host.quit(C.EXIT_OK)
584 570
585 def start(self): 571 def start(self):
586 common.checkURI(self.args)
587 if not self.args.item: 572 if not self.args.item:
588 self.parser.error(_(u"You need to specify an item to delete")) 573 self.parser.error(_(u"You need to specify an item to delete"))
589 if not self.args.force: 574 if not self.args.force:
590 message = _(u"Are you sure to delete item {item_id} ?").format(item_id=self.args.item) 575 message = _(u"Are you sure to delete item {item_id} ?").format(item_id=self.args.item)
591 res = raw_input("{} (y/N)? ".format(message)) 576 res = raw_input("{} (y/N)? ".format(message))
605 590
606 591
607 class Edit(base.CommandBase, common.BaseEdit): 592 class Edit(base.CommandBase, common.BaseEdit):
608 593
609 def __init__(self, host): 594 def __init__(self, host):
610 base.CommandBase.__init__(self, host, 'edit', use_verbose=True, use_pubsub_node_req=True, help=_(u'edit an existing or new pubsub item')) 595 base.CommandBase.__init__(self, host, 'edit', use_verbose=True, use_pubsub=True,
596 pubsub_flags={C.NODE, C.SINGLE_ITEM}, use_draft=True, help=_(u'edit an existing or new pubsub item'))
611 common.BaseEdit.__init__(self, self.host, PUBSUB_TMP_DIR) 597 common.BaseEdit.__init__(self, self.host, PUBSUB_TMP_DIR)
612 598
613 def add_parser_options(self): 599 def add_parser_options(self):
614 self.parser.add_argument("item", type=base.unicode_decoder, nargs='?', default=u'new', help=_(u"URL of the item to edit, or keyword")) 600 pass
615 common.BaseEdit.add_parser_options(self)
616 601
617 def edit(self, content_file_path, content_file_obj): 602 def edit(self, content_file_path, content_file_obj):
618 # we launch editor 603 # we launch editor
619 self.runEditor("pubsub_editor_args", content_file_path, content_file_obj) 604 self.runEditor("pubsub_editor_args", content_file_path, content_file_obj)
620 605
642 self.disp(_(u'Item has not payload'), 1) 627 self.disp(_(u'Item has not payload'), 1)
643 return u'' 628 return u''
644 return etree.tostring(payload, encoding="unicode", pretty_print=True), item_id 629 return etree.tostring(payload, encoding="unicode", pretty_print=True), item_id
645 630
646 def start(self): 631 def start(self):
647 self.pubsub_service, self.pubsub_node, self.pubsub_item, content_file_path, content_file_obj = self.getItemPath(self.args.item) 632 self.pubsub_service, self.pubsub_node, self.pubsub_item, content_file_path, content_file_obj = self.getItemPath()
648
649 self.edit(content_file_path, content_file_obj) 633 self.edit(content_file_path, content_file_obj)
650 634
651 635
652 class Subscribe(base.CommandBase): 636 class Subscribe(base.CommandBase):
653 637
654 def __init__(self, host): 638 def __init__(self, host):
655 base.CommandBase.__init__(self, host, 'subscribe', use_pubsub_node_req=True, use_verbose=True, help=_(u'subscribe to a node')) 639 base.CommandBase.__init__(self, host, 'subscribe', use_pubsub=True, pubsub_flags={C.NODE}, use_verbose=True, help=_(u'subscribe to a node'))
656 self.need_loop=True 640 self.need_loop=True
657 641
658 def add_parser_options(self): 642 def add_parser_options(self):
659 pass 643 pass
660 644
678 662
679 class Unsubscribe(base.CommandBase): 663 class Unsubscribe(base.CommandBase):
680 # TODO: voir pourquoi NodeNotFound sur subscribe juste après unsubscribe 664 # TODO: voir pourquoi NodeNotFound sur subscribe juste après unsubscribe
681 665
682 def __init__(self, host): 666 def __init__(self, host):
683 base.CommandBase.__init__(self, host, 'unsubscribe', use_pubsub_node_req=True, use_verbose=True, help=_(u'unsubscribe from a node')) 667 base.CommandBase.__init__(self, host, 'unsubscribe', use_pubsub=True, pubsub_flags={C.NODE}, use_verbose=True, help=_(u'unsubscribe from a node'))
684 self.need_loop=True 668 self.need_loop=True
685 669
686 def add_parser_options(self): 670 def add_parser_options(self):
687 pass 671 pass
688 672
756 """this command to a search without using MAM, i.e. by checking every items if dound by itself, so it may be heavy in resources both for server and client""" 740 """this command to a search without using MAM, i.e. by checking every items if dound by itself, so it may be heavy in resources both for server and client"""
757 RE_FLAGS = re.MULTILINE | re.UNICODE 741 RE_FLAGS = re.MULTILINE | re.UNICODE
758 EXEC_ACTIONS = (u'exec', u'external') 742 EXEC_ACTIONS = (u'exec', u'external')
759 743
760 def __init__(self, host): 744 def __init__(self, host):
761 base.CommandBase.__init__(self, host, 'search', use_output=C.OUTPUT_XML, use_pubsub=True, use_verbose=True, help=_(u'search items corresponding to filters')) 745 base.CommandBase.__init__(self, host, 'search', use_output=C.OUTPUT_XML, use_pubsub=True, pubsub_flags={C.MULTI_ITEMS},
746 use_verbose=True, help=_(u'search items corresponding to filters'))
762 self.need_loop=True 747 self.need_loop=True
763 748
764 @property 749 @property
765 def etree(self): 750 def etree(self):
766 """load lxml.etree only if needed""" 751 """load lxml.etree only if needed"""
776 def filter_flag(self, value, type_): 761 def filter_flag(self, value, type_):
777 value = C.bool(value) 762 value = C.bool(value)
778 return (type_, value) 763 return (type_, value)
779 764
780 def add_parser_options(self): 765 def add_parser_options(self):
781 self.parser.add_argument("-i", "--item", action="append", default=[], dest='items', type=base.unicode_decoder, help=_(u"item id(s)"))
782 self.parser.add_argument("-D", "--max-depth", type=int, default=0, help=_(u"maximum depth of recursion (will search linked nodes if > 0, default: 0)")) 766 self.parser.add_argument("-D", "--max-depth", type=int, default=0, help=_(u"maximum depth of recursion (will search linked nodes if > 0, default: 0)"))
783 self.parser.add_argument("-m", "--max", type=int, default=30, help=_(u"maximum number of items to get per node ({} to get all items, default: 30)".format(C.NO_LIMIT))) 767 self.parser.add_argument("-m", "--max", type=int, default=30, help=_(u"maximum number of items to get per node ({} to get all items, default: 30)".format(C.NO_LIMIT)))
784 self.parser.add_argument("-N", "--namespace", action='append', nargs=2, default=[], 768 self.parser.add_argument("-N", "--namespace", action='append', nargs=2, default=[],
785 metavar="NAME NAMESPACE", help=_(u"namespace to use for xpath")) 769 metavar="NAME NAMESPACE", help=_(u"namespace to use for xpath"))
786 770
1080 self.to_get = 0 1064 self.to_get = 0
1081 self._etree = None 1065 self._etree = None
1082 if self.args.filters is None: 1066 if self.args.filters is None:
1083 self.args.filters = [] 1067 self.args.filters = []
1084 self.args.namespace = dict(self.args.namespace + [('pubsub', "http://jabber.org/protocol/pubsub")]) 1068 self.args.namespace = dict(self.args.namespace + [('pubsub', "http://jabber.org/protocol/pubsub")])
1085 common.checkURI(self.args)
1086 self.getItems(0, self.args.service, self.args.node, self.args.items) 1069 self.getItems(0, self.args.service, self.args.node, self.args.items)
1087 1070
1088 1071
1089 class Uri(base.CommandBase): 1072 class Uri(base.CommandBase):
1090 1073
1091 def __init__(self, host): 1074 def __init__(self, host):
1092 base.CommandBase.__init__(self, host, 'uri', use_profile=False, use_pubsub_node_req=True, help=_(u'build URI')) 1075 base.CommandBase.__init__(self, host, 'uri', use_profile=False, use_pubsub=True, pubsub_flags={C.NODE, C.SINGLE_ITEM}, help=_(u'build URI'))
1093 self.need_loop=True 1076 self.need_loop=True
1094 1077
1095 def add_parser_options(self): 1078 def add_parser_options(self):
1096 self.parser.add_argument("-i", "--item", type=base.unicode_decoder, help=_(u"item to link"))
1097 self.parser.add_argument("-p", "--profile", type=base.unicode_decoder, default=C.PROF_KEY_DEFAULT, help=_(u"profile (used when no server is specified)")) 1079 self.parser.add_argument("-p", "--profile", type=base.unicode_decoder, default=C.PROF_KEY_DEFAULT, help=_(u"profile (used when no server is specified)"))
1098 1080
1099 def display_uri(self, jid_): 1081 def display_uri(self, jid_):
1100 uri_args = {} 1082 uri_args = {}
1101 if not self.args.service: 1083 if not self.args.service:
1125 1107
1126 1108
1127 class HookCreate(base.CommandBase): 1109 class HookCreate(base.CommandBase):
1128 1110
1129 def __init__(self, host): 1111 def __init__(self, host):
1130 base.CommandBase.__init__(self, host, 'create', use_pubsub_node_req=True, help=_(u'create a Pubsub hook')) 1112 base.CommandBase.__init__(self, host, 'create', use_pubsub=True, pubsub_flags={C.NODE}, help=_(u'create a Pubsub hook'))
1131 self.need_loop=True 1113 self.need_loop=True
1132 1114
1133 def add_parser_options(self): 1115 def add_parser_options(self):
1134 self.parser.add_argument('-t', '--type', default=u'python', choices=('python', 'python_file', 'python_code'), help=_(u"hook type")) 1116 self.parser.add_argument('-t', '--type', default=u'python', choices=('python', 'python_file', 'python_code'), help=_(u"hook type"))
1135 self.parser.add_argument('-P', '--persistent', action='store_true', help=_(u"make hook persistent across restarts")) 1117 self.parser.add_argument('-P', '--persistent', action='store_true', help=_(u"make hook persistent across restarts"))
1141 self.args.hook_arg = os.path.abspath(self.args.hook_arg) 1123 self.args.hook_arg = os.path.abspath(self.args.hook_arg)
1142 if not os.path.isfile(self.args.hook_arg): 1124 if not os.path.isfile(self.args.hook_arg):
1143 self.parser.error(_(u"{path} is not a file").format(path=self.args.hook_arg)) 1125 self.parser.error(_(u"{path} is not a file").format(path=self.args.hook_arg))
1144 1126
1145 def start(self): 1127 def start(self):
1146 common.checkURI(self.args)
1147 self.checkArgs(self) 1128 self.checkArgs(self)
1148 self.host.bridge.psHookAdd( 1129 self.host.bridge.psHookAdd(
1149 self.args.service, 1130 self.args.service,
1150 self.args.node, 1131 self.args.node,
1151 self.args.type, 1132 self.args.type,
1159 1140
1160 1141
1161 class HookDelete(base.CommandBase): 1142 class HookDelete(base.CommandBase):
1162 1143
1163 def __init__(self, host): 1144 def __init__(self, host):
1164 base.CommandBase.__init__(self, host, 'delete', use_pubsub_node_req=True, help=_(u'delete a Pubsub hook')) 1145 base.CommandBase.__init__(self, host, 'delete', use_pubsub=True, pubsub_flags={C.NODE}, help=_(u'delete a Pubsub hook'))
1165 self.need_loop=True 1146 self.need_loop=True
1166 1147
1167 def add_parser_options(self): 1148 def add_parser_options(self):
1168 self.parser.add_argument('-t', '--type', default=u'', choices=('', 'python', 'python_file', 'python_code'), help=_(u"hook type to remove, empty to remove all (default: remove all)")) 1149 self.parser.add_argument('-t', '--type', default=u'', choices=('', 'python', 'python_file', 'python_code'), help=_(u"hook type to remove, empty to remove all (default: remove all)"))
1169 self.parser.add_argument('-a', '--arg', dest='hook_arg', type=base.unicode_decoder, default=u'', help=_(u"argument of the hook to remove, empty to remove all (default: remove all)")) 1150 self.parser.add_argument('-a', '--arg', dest='hook_arg', type=base.unicode_decoder, default=u'', help=_(u"argument of the hook to remove, empty to remove all (default: remove all)"))
1172 self.disp(_(u'{nb_deleted} hook(s) have been deleted').format( 1153 self.disp(_(u'{nb_deleted} hook(s) have been deleted').format(
1173 nb_deleted = nb_deleted)) 1154 nb_deleted = nb_deleted))
1174 self.host.quit() 1155 self.host.quit()
1175 1156
1176 def start(self): 1157 def start(self):
1177 common.checkURI(self.args)
1178 HookCreate.checkArgs(self) 1158 HookCreate.checkArgs(self)
1179 self.host.bridge.psHookRemove( 1159 self.host.bridge.psHookRemove(
1180 self.args.service, 1160 self.args.service,
1181 self.args.node, 1161 self.args.node,
1182 self.args.type, 1162 self.args.type,