Mercurial > p > roundup > code
comparison roundup/admin.py @ 1767:fdaa0b751355
python2.3 CSV support, also missing thankyou in index.txt :)
| author | Richard Jones <richard@users.sourceforge.net> |
|---|---|
| date | Thu, 28 Aug 2003 04:46:54 +0000 |
| parents | ab7760caf6ff |
| children | d4c0c65adb2c |
comparison
equal
deleted
inserted
replaced
| 1765:14a2f1529759 | 1767:fdaa0b751355 |
|---|---|
| 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: admin.py,v 1.56 2003-08-26 00:06:55 richard Exp $ | 19 # $Id: admin.py,v 1.57 2003-08-28 04:46:39 richard Exp $ |
| 20 | 20 |
| 21 '''Administration commands for maintaining Roundup trackers. | 21 '''Administration commands for maintaining Roundup trackers. |
| 22 ''' | 22 ''' |
| 23 | 23 |
| 24 import sys, os, getpass, getopt, re, UserDict, shutil, rfc822 | 24 import sys, os, getpass, getopt, re, UserDict, shutil, rfc822 |
| 25 try: | 25 from roundup import date, hyperdb, roundupdb, init, password, token, rcsv |
| 26 import csv | |
| 27 except ImportError: | |
| 28 csv = None | |
| 29 from roundup import date, hyperdb, roundupdb, init, password, token | |
| 30 from roundup import __version__ as roundup_version | 26 from roundup import __version__ as roundup_version |
| 31 import roundup.instance | 27 import roundup.instance |
| 32 from roundup.i18n import _ | 28 from roundup.i18n import _ |
| 33 | 29 |
| 34 class CommandDict(UserDict.UserDict): | 30 class CommandDict(UserDict.UserDict): |
| 1061 | 1057 |
| 1062 This action exports the current data from the database into | 1058 This action exports the current data from the database into |
| 1063 colon-separated-value files that are placed in the nominated | 1059 colon-separated-value files that are placed in the nominated |
| 1064 destination directory. The journals are not exported. | 1060 destination directory. The journals are not exported. |
| 1065 ''' | 1061 ''' |
| 1066 # we need the CSV module | |
| 1067 if csv is None: | |
| 1068 raise UsageError, \ | |
| 1069 _('Sorry, you need the csv module to use this function.\n' | |
| 1070 'Get it from: http://www.object-craft.com.au/projects/csv/') | |
| 1071 | |
| 1072 # grab the directory to export to | 1062 # grab the directory to export to |
| 1073 if len(args) < 1: | 1063 if len(args) < 1: |
| 1074 raise UsageError, _('Not enough arguments supplied') | 1064 raise UsageError, _('Not enough arguments supplied') |
| 1065 if rcsv.error: | |
| 1066 raise UsageError, _(rcsv.error) | |
| 1067 | |
| 1075 dir = args[-1] | 1068 dir = args[-1] |
| 1076 | 1069 |
| 1077 # get the list of classes to export | 1070 # get the list of classes to export |
| 1078 if len(args) == 2: | 1071 if len(args) == 2: |
| 1079 classes = args[0].split(',') | 1072 classes = args[0].split(',') |
| 1080 else: | 1073 else: |
| 1081 classes = self.db.classes.keys() | 1074 classes = self.db.classes.keys() |
| 1082 | 1075 |
| 1083 # use the csv parser if we can - it's faster | |
| 1084 p = csv.parser(field_sep=':') | |
| 1085 | |
| 1086 # do all the classes specified | 1076 # do all the classes specified |
| 1087 for classname in classes: | 1077 for classname in classes: |
| 1088 cl = self.get_class(classname) | 1078 cl = self.get_class(classname) |
| 1089 f = open(os.path.join(dir, classname+'.csv'), 'w') | 1079 f = open(os.path.join(dir, classname+'.csv'), 'w') |
| 1080 writer = rcsv.writer(f, rcsv.colon_separated) | |
| 1090 properties = cl.getprops() | 1081 properties = cl.getprops() |
| 1091 propnames = properties.keys() | 1082 propnames = properties.keys() |
| 1092 propnames.sort() | 1083 propnames.sort() |
| 1093 l = propnames[:] | 1084 fields = propnames[:] |
| 1094 l.append('is retired') | 1085 fields.append('is retired') |
| 1095 print >> f, p.join(l) | 1086 writer.writerow(fields) |
| 1096 | 1087 |
| 1097 # all nodes for this class (not using list() 'cos it doesn't | 1088 # all nodes for this class (not using list() 'cos it doesn't |
| 1098 # include retired nodes) | 1089 # include retired nodes) |
| 1099 | 1090 |
| 1100 for nodeid in self.db.getclass(classname).getnodeids(): | 1091 for nodeid in self.db.getclass(classname).getnodeids(): |
| 1101 # get the regular props | 1092 # get the regular props |
| 1102 print >>f, p.join(cl.export_list(propnames, nodeid)) | 1093 writer.writerow (cl.export_list(propnames, nodeid)) |
| 1103 | 1094 |
| 1104 # close this file | 1095 # close this file |
| 1105 f.close() | 1096 f.close() |
| 1106 return 0 | 1097 return 0 |
| 1107 | 1098 |
| 1120 create a new database using the imported data, then create a new | 1111 create a new database using the imported data, then create a new |
| 1121 database (or, tediously, retire all the old data.) | 1112 database (or, tediously, retire all the old data.) |
| 1122 ''' | 1113 ''' |
| 1123 if len(args) < 1: | 1114 if len(args) < 1: |
| 1124 raise UsageError, _('Not enough arguments supplied') | 1115 raise UsageError, _('Not enough arguments supplied') |
| 1125 if csv is None: | 1116 if rcsv.error: |
| 1126 raise UsageError, \ | 1117 raise UsageError, _(rcsv.error) |
| 1127 _('Sorry, you need the csv module to use this function.\n' | |
| 1128 'Get it from: http://www.object-craft.com.au/projects/csv/') | |
| 1129 | |
| 1130 from roundup import hyperdb | 1118 from roundup import hyperdb |
| 1131 | 1119 |
| 1132 for file in os.listdir(args[0]): | 1120 for file in os.listdir(args[0]): |
| 1133 # we only care about CSV files | 1121 # we only care about CSV files |
| 1134 if not file.endswith('.csv'): | 1122 if not file.endswith('.csv'): |
| 1139 # get the classname | 1127 # get the classname |
| 1140 classname = os.path.splitext(file)[0] | 1128 classname = os.path.splitext(file)[0] |
| 1141 | 1129 |
| 1142 # ensure that the properties and the CSV file headings match | 1130 # ensure that the properties and the CSV file headings match |
| 1143 cl = self.get_class(classname) | 1131 cl = self.get_class(classname) |
| 1144 p = csv.parser(field_sep=':') | 1132 reader = rcsv.reader(f, rcsv.colon_separated) |
| 1145 file_props = p.parse(f.readline()) | 1133 file_props = None |
| 1134 maxid = 1 | |
| 1146 | 1135 |
| 1147 # loop through the file and create a node for each entry | 1136 # loop through the file and create a node for each entry |
| 1148 maxid = 1 | 1137 for r in reader: |
| 1149 while 1: | 1138 if file_props is None: |
| 1150 line = f.readline() | 1139 file_props = r |
| 1151 if not line: break | 1140 continue |
| 1152 | |
| 1153 # parse lines until we get a complete entry | |
| 1154 while 1: | |
| 1155 l = p.parse(line) | |
| 1156 if l: break | |
| 1157 line = f.readline() | |
| 1158 if not line: | |
| 1159 raise ValueError, "Unexpected EOF during CSV parse" | |
| 1160 | 1141 |
| 1161 # do the import and figure the current highest nodeid | 1142 # do the import and figure the current highest nodeid |
| 1162 maxid = max(maxid, int(cl.import_list(file_props, l))) | 1143 maxid = max(maxid, int(cl.import_list(file_props, r))) |
| 1163 | 1144 |
| 1145 # set the id counter | |
| 1164 print 'setting', classname, maxid+1 | 1146 print 'setting', classname, maxid+1 |
| 1165 self.db.setid(classname, str(maxid+1)) | 1147 self.db.setid(classname, str(maxid+1)) |
| 1166 return 0 | 1148 return 0 |
| 1167 | 1149 |
| 1168 def do_pack(self, args): | 1150 def do_pack(self, args): |
