from roundup.cgi.actions import Action from roundup.cgi import templating from roundup import hyperdb import csv import re from datetime import datetime import inspect """ From: http://www.roundup-tracker.org/cgi-bin/moin.cgi/ExportCSVNames From the web page: Here is a patch that enables exporting csv with actual names of linked items instead of their ids. It adds a new action, "export_csv_names" to the "extensions" directory in your tracker. The action works like export_csv except on columns with the Link type. The action tries to find a column called name in the linked class, or username if the class is user. If it is found, it prints this column instead of the id. Simply change the lines in the desired html pages from export_csv to export_csv_names, copy this file to the extensions directory, and that's it. This action has been evaluated on Roundup 0.8.2 only, and was updated from the original version that ran under 0.7. [BEWARE: get the patch from the wiki page source, not from the html display, since the wiki software removes quotes. Any suggestions of a better way to put this patch online are welcome.] Code is also posted to this pastebin URL: http://pastebin.com/f4f6ad0c0 """ def write_log(message): """ Write a message to a log file. Used for debugging only. """ logfile = open('/tmp/export-csv.log', 'a') # Output the file, line#, date and message logfile.write("ExportCSVNamesAction.py:%s %s %s\n" % (inspect.stack()[1][2], datetime.now().isoformat(), message)) logfile.close() class ExportCSVNamesAction(Action): name = 'export' permissionType = 'View' def handle(self): ''' Export the specified search query as CSV. ''' # figure the request request = templating.HTMLRequest(self.client) filterspec = request.filterspec sort = request.sort group = request.group columns = request.columns klass = self.db.getclass(request.classname) # full-text search if request.search_text: matches = self.db.indexer.search( re.findall(r'\b\w{2,25}\b', request.search_text), klass) else: matches = None h = self.client.additional_headers h['Content-Type'] = 'text/csv; charset=%s' % self.client.charset # some browsers will honor the filename here... h['Content-Disposition'] = 'inline; filename=query.csv' self.client.header() if self.client.env['REQUEST_METHOD'] == 'HEAD': # all done, return a dummy string return 'dummy' wfile = self.client.request.wfile if self.client.charset != self.client.STORAGE_CHARSET: wfile = codecs.EncodedFile(wfile, self.client.STORAGE_CHARSET, self.client.charset, 'replace') writer = csv.writer(wfile) self.client._socket_op(writer.writerow, columns) # Figure out Link columns represent = {} def repr_link(cls,col): def f(x): if x==None: return "" else: return str(cls.get(x,col)) return f def repr_multilink(cls, col): def f(list_x): if list_x==None: return "" elif type(list_x) == type([]): return ','.join([cls.get(y,col) for y in list_x]) else: return str(list_x) return f props = klass.getprops() for col in columns: represent[col] = str if isinstance(props[col], hyperdb.Multilink): cn = props[col].classname cl = self.db.getclass(cn) if cl.getprops().has_key('name'): represent[col] = repr_multilink(cl, 'name') elif cn == 'user': represent[col] = repr_multilink(cl, 'username') if isinstance(props[col], hyperdb.Link): cn = props[col].classname cl = self.db.getclass(cn) if cl.getprops().has_key('name'): represent[col] = repr_link(cl, 'name') elif cn == 'user': represent[col] = repr_link(cl, 'username') # and search for itemid in klass.filter(matches, filterspec, sort, group): self.client._socket_op(writer.writerow, [represent[col](klass.get(itemid, col)) for col in columns]) return '\n' def init(instance): instance.registerAction('export_csv_names', ExportCSVNamesAction) # vim: set filetype=python sts=4 sw=4 et si