comparison roundup-admin @ 438:9d97c1a4ddad

Notes from changes. >From CHANGES: . Added the "display" command to the admin tool - displays a node's values . [SF#489760] [issue] only subject . fixed the doc/index.html to include the quoting in the mail alias. Also: . fixed roundup-admin so it works with transactions . disabled the back_anydbm module if anydbm tries to use dumbdbm
author Richard Jones <richard@users.sourceforge.net>
date Mon, 10 Dec 2001 00:57:38 +0000
parents a28a80b714f9
children 208697858c8b
comparison
equal deleted inserted replaced
437:a1e778940f92 438:9d97c1a4ddad
14 # BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 14 # BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
15 # FOR A PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" 15 # FOR A PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
16 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, 16 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
17 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 17 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
18 # 18 #
19 # $Id: roundup-admin,v 1.50 2001-12-02 05:06:16 richard Exp $ 19 # $Id: roundup-admin,v 1.51 2001-12-10 00:57:38 richard Exp $
20 20
21 import sys 21 import sys
22 if not hasattr(sys, 'version_info') or sys.version_info[:2] < (2,1): 22 if not hasattr(sys, 'version_info') or sys.version_info[:2] < (2,1):
23 print 'Roundup requires python 2.1 or later.' 23 print 'Roundup requires python 2.1 or later.'
24 sys.exit(1) 24 sys.exit(1)
62 self.commands[k[3:]] = getattr(self, k) 62 self.commands[k[3:]] = getattr(self, k)
63 self.help = {} 63 self.help = {}
64 for k in AdminTool.__dict__.keys(): 64 for k in AdminTool.__dict__.keys():
65 if k[:5] == 'help_': 65 if k[:5] == 'help_':
66 self.help[k[5:]] = getattr(self, k) 66 self.help[k[5:]] = getattr(self, k)
67 self.instance_home = ''
67 self.db = None 68 self.db = None
68 69
69 def usage(self, message=''): 70 def usage(self, message=''):
70 if message: message = 'Problem: '+message+'\n\n' 71 if message: message = 'Problem: '+message+'\n\n'
71 print '''%sUsage: roundup-admin [-i instance home] [-u login] [-c] <command> <arguments> 72 print '''%sUsage: roundup-admin [-i instance home] [-u login] [-c] <command> <arguments>
203 password may be specified on the command-line as arguments, in that 204 password may be specified on the command-line as arguments, in that
204 order. 205 order.
205 206
206 See also initopts help. 207 See also initopts help.
207 ''' 208 '''
209 if len(args) < 1:
210 raise UsageError, 'Not enough arguments supplied'
208 # select template 211 # select template
209 import roundup.templates 212 import roundup.templates
210 templates = roundup.templates.listTemplates() 213 templates = roundup.templates.listTemplates()
211 template = len(args) > 1 and args[1] or '' 214 template = len(args) > 1 and args[1] or ''
212 if template not in templates: 215 if template not in templates:
241 '''Usage: get property designator[,designator]* 244 '''Usage: get property designator[,designator]*
242 Get the given property of one or more designator(s). 245 Get the given property of one or more designator(s).
243 246
244 Retrieves the property value of the nodes specified by the designators. 247 Retrieves the property value of the nodes specified by the designators.
245 ''' 248 '''
249 if len(args) < 2:
250 raise UsageError, 'Not enough arguments supplied'
246 propname = args[0] 251 propname = args[0]
247 designators = string.split(args[1], ',') 252 designators = string.split(args[1], ',')
248 l = [] 253 l = []
249 for designator in designators: 254 for designator in designators:
250 # decode the node designator 255 # decode the node designator
277 '''Usage: set designator[,designator]* propname=value ... 282 '''Usage: set designator[,designator]* propname=value ...
278 Set the given property of one or more designator(s). 283 Set the given property of one or more designator(s).
279 284
280 Sets the property to the value for all designators given. 285 Sets the property to the value for all designators given.
281 ''' 286 '''
287 if len(args) < 2:
288 raise UsageError, 'Not enough arguments supplied'
282 from roundup import hyperdb 289 from roundup import hyperdb
283 290
284 designators = string.split(args[0], ',') 291 designators = string.split(args[0], ',')
285 props = {} 292 props = {}
286 for prop in args[1:]: 293 for prop in args[1:]:
338 Find the nodes of the given class with a given link property value. 345 Find the nodes of the given class with a given link property value.
339 346
340 Find the nodes of the given class with a given link property value. The 347 Find the nodes of the given class with a given link property value. The
341 value may be either the nodeid of the linked node, or its key value. 348 value may be either the nodeid of the linked node, or its key value.
342 ''' 349 '''
350 if len(args) < 1:
351 raise UsageError, 'Not enough arguments supplied'
343 classname = args[0] 352 classname = args[0]
344 # get the class 353 # get the class
345 try: 354 try:
346 cl = self.db.getclass(classname) 355 cl = self.db.getclass(classname)
347 except KeyError: 356 except KeyError:
399 '''Usage: specification classname 408 '''Usage: specification classname
400 Show the properties for a classname. 409 Show the properties for a classname.
401 410
402 This lists the properties for a given class. 411 This lists the properties for a given class.
403 ''' 412 '''
413 if len(args) < 1:
414 raise UsageError, 'Not enough arguments supplied'
404 classname = args[0] 415 classname = args[0]
405 # get the class 416 # get the class
406 try: 417 try:
407 cl = self.db.getclass(classname) 418 cl = self.db.getclass(classname)
408 except KeyError: 419 except KeyError:
414 if keyprop == key: 425 if keyprop == key:
415 print '%s: %s (key property)'%(key, value) 426 print '%s: %s (key property)'%(key, value)
416 else: 427 else:
417 print '%s: %s'%(key, value) 428 print '%s: %s'%(key, value)
418 429
430 def do_display(self, args):
431 '''Usage: display designator
432 Show the property values for the given node.
433
434 This lists the properties and their associated values for the given
435 node.
436 '''
437 if len(args) < 1:
438 raise UsageError, 'Not enough arguments supplied'
439
440 # decode the node designator
441 try:
442 classname, nodeid = roundupdb.splitDesignator(args[0])
443 except roundupdb.DesignatorError, message:
444 raise UsageError, message
445
446 # get the class
447 try:
448 cl = self.db.getclass(classname)
449 except KeyError:
450 raise UsageError, 'invalid class "%s"'%classname
451
452 # display the values
453 for key in cl.properties.keys():
454 value = cl.get(nodeid, key)
455 print '%s: %s'%(key, value)
456
419 def do_create(self, args): 457 def do_create(self, args):
420 '''Usage: create classname property=value ... 458 '''Usage: create classname property=value ...
421 Create a new entry of a given class. 459 Create a new entry of a given class.
422 460
423 This creates a new entry of the given class using the property 461 This creates a new entry of the given class using the property
424 name=value arguments provided on the command line after the "create" 462 name=value arguments provided on the command line after the "create"
425 command. 463 command.
426 ''' 464 '''
465 if len(args) < 1:
466 raise UsageError, 'Not enough arguments supplied'
427 from roundup import hyperdb 467 from roundup import hyperdb
428 468
429 classname = args[0] 469 classname = args[0]
430 470
431 # get the class 471 # get the class
506 Lists all instances of the given class. If the property is not 546 Lists all instances of the given class. If the property is not
507 specified, the "label" property is used. The label property is tried 547 specified, the "label" property is used. The label property is tried
508 in order: the key, "name", "title" and then the first property, 548 in order: the key, "name", "title" and then the first property,
509 alphabetically. 549 alphabetically.
510 ''' 550 '''
551 if len(args) < 1:
552 raise UsageError, 'Not enough arguments supplied'
511 classname = args[0] 553 classname = args[0]
512 554
513 # get the class 555 # get the class
514 try: 556 try:
515 cl = self.db.getclass(classname) 557 cl = self.db.getclass(classname)
546 1 fatal-bug 588 1 fatal-bug
547 2 bug 589 2 bug
548 3 usability 590 3 usability
549 4 feature 591 4 feature
550 ''' 592 '''
593 if len(args) < 1:
594 raise UsageError, 'Not enough arguments supplied'
551 classname = args[0] 595 classname = args[0]
552 596
553 # get the class 597 # get the class
554 try: 598 try:
555 cl = self.db.getclass(classname) 599 cl = self.db.getclass(classname)
598 '''Usage: history designator 642 '''Usage: history designator
599 Show the history entries of a designator. 643 Show the history entries of a designator.
600 644
601 Lists the journal entries for the node identified by the designator. 645 Lists the journal entries for the node identified by the designator.
602 ''' 646 '''
647 if len(args) < 1:
648 raise UsageError, 'Not enough arguments supplied'
603 try: 649 try:
604 classname, nodeid = roundupdb.splitDesignator(args[0]) 650 classname, nodeid = roundupdb.splitDesignator(args[0])
605 except roundupdb.DesignatorError, message: 651 except roundupdb.DesignatorError, message:
606 raise UsageError, message 652 raise UsageError, message
607 653
635 The changes made during an interactive session are not 681 The changes made during an interactive session are not
636 automatically written to the database - they must be committed 682 automatically written to the database - they must be committed
637 manually. This command undoes all those changes, so a commit 683 manually. This command undoes all those changes, so a commit
638 immediately after would make no changes to the database. 684 immediately after would make no changes to the database.
639 ''' 685 '''
640 self.db.commit() 686 self.db.rollback()
641 return 0 687 return 0
642 688
643 def do_retire(self, args): 689 def do_retire(self, args):
644 '''Usage: retire designator[,designator]* 690 '''Usage: retire designator[,designator]*
645 Retire the node specified by designator. 691 Retire the node specified by designator.
646 692
647 This action indicates that a particular node is not to be retrieved by 693 This action indicates that a particular node is not to be retrieved by
648 the list or find commands, and its key value may be re-used. 694 the list or find commands, and its key value may be re-used.
649 ''' 695 '''
696 if len(args) < 1:
697 raise UsageError, 'Not enough arguments supplied'
650 designators = string.split(args[0], ',') 698 designators = string.split(args[0], ',')
651 for designator in designators: 699 for designator in designators:
652 try: 700 try:
653 classname, nodeid = roundupdb.splitDesignator(designator) 701 classname, nodeid = roundupdb.splitDesignator(designator)
654 except roundupdb.DesignatorError, message: 702 except roundupdb.DesignatorError, message:
668 This action exports the current data from the database into 716 This action exports the current data from the database into
669 tab-separated-value files that are placed in the nominated destination 717 tab-separated-value files that are placed in the nominated destination
670 directory. The journals are not exported. 718 directory. The journals are not exported.
671 ''' 719 '''
672 if len(args) < 2: 720 if len(args) < 2:
673 print do_export.__doc__ 721 raise UsageError, 'Not enough arguments supplied'
674 return 1
675 classes = string.split(args[0], ',') 722 classes = string.split(args[0], ',')
676 dir = args[1] 723 dir = args[1]
677 724
678 # use the csv parser if we can - it's faster 725 # use the csv parser if we can - it's faster
679 if csv is not None: 726 if csv is not None:
832 879
833 # get the instance 880 # get the instance
834 try: 881 try:
835 instance = roundup.instance.open(self.instance_home) 882 instance = roundup.instance.open(self.instance_home)
836 except ValueError, message: 883 except ValueError, message:
884 self.instance_home = ''
837 print "Couldn't open instance: %s"%message 885 print "Couldn't open instance: %s"%message
838 return 1 886 return 1
839 self.db = instance.open('admin') 887
840 888 # only open the database once!
841 if len(args) < 2: 889 if not self.db:
842 print function.__doc__ 890 self.db = instance.open('admin')
843 return 1
844 891
845 # do the command 892 # do the command
846 ret = 0 893 ret = 0
847 try: 894 try:
848 ret = function(args[1:]) 895 ret = function(args[1:])
868 915
869 while 1: 916 while 1:
870 try: 917 try:
871 command = raw_input('roundup> ') 918 command = raw_input('roundup> ')
872 except EOFError: 919 except EOFError:
873 print '.. exit' 920 print 'exit...'
874 return 0 921 break
922 if not command: continue
875 args = ws_re.split(command) 923 args = ws_re.split(command)
876 if not args: continue 924 if not args: continue
877 if args[0] in ('quit', 'exit'): return 0 925 if args[0] in ('quit', 'exit'): break
878 self.run_command(args) 926 self.run_command(args)
927
928 # exit.. check for transactions
929 if self.db and self.db.transactions:
930 commit = raw_input("There are unsaved changes. Commit them (y/N)? ")
931 if commit[0].lower() == 'y':
932 self.db.commit()
933 return 0
879 934
880 def main(self): 935 def main(self):
881 try: 936 try:
882 opts, args = getopt.getopt(sys.argv[1:], 'i:u:hc') 937 opts, args = getopt.getopt(sys.argv[1:], 'i:u:hc')
883 except getopt.GetoptError, e: 938 except getopt.GetoptError, e:
916 tool = AdminTool() 971 tool = AdminTool()
917 sys.exit(tool.main()) 972 sys.exit(tool.main())
918 973
919 # 974 #
920 # $Log: not supported by cvs2svn $ 975 # $Log: not supported by cvs2svn $
976 # Revision 1.50 2001/12/02 05:06:16 richard
977 # . We now use weakrefs in the Classes to keep the database reference, so
978 # the close() method on the database is no longer needed.
979 # I bumped the minimum python requirement up to 2.1 accordingly.
980 # . #487480 ] roundup-server
981 # . #487476 ] INSTALL.txt
982 #
983 # I also cleaned up the change message / post-edit stuff in the cgi client.
984 # There's now a clearly marked "TODO: append the change note" where I believe
985 # the change note should be added there. The "changes" list will obviously
986 # have to be modified to be a dict of the changes, or somesuch.
987 #
988 # More testing needed.
989 #
921 # Revision 1.49 2001/12/01 07:17:50 richard 990 # Revision 1.49 2001/12/01 07:17:50 richard
922 # . We now have basic transaction support! Information is only written to 991 # . We now have basic transaction support! Information is only written to
923 # the database when the commit() method is called. Only the anydbm 992 # the database when the commit() method is called. Only the anydbm
924 # backend is modified in this way - neither of the bsddb backends have been. 993 # backend is modified in this way - neither of the bsddb backends have been.
925 # The mail, admin and cgi interfaces all use commit (except the admin tool 994 # The mail, admin and cgi interfaces all use commit (except the admin tool

Roundup Issue Tracker: http://roundup-tracker.org/