#!/usr/bin/python # -*- coding: utf-8 -*- """ Created on Sat Dec 1 10:04:12 2012 @author: bob02 """ import codecs import csv import argparse import glob import json import os FileNamePattern = 'gnucash2.4.*.json' CsvHdrLine = ["['downloads']", 'Date'] class RelStatObj(object): """ Release Stats Object """ def __init__(self, pathname, monthCntList): """ Initialize a Release Stats Object @param self: instance to initialize @param pathname: Pathname of the json file containing the stats. @param monthCntList: The month, count list """ _, filename = os.path.split(pathname) params = filename[len('gnucash'):] partsList = params.split('.') major, minor, bf, _ = partsList self.major = int(major) self.minor = int(minor) self.bf = int(bf) monthCntList.sort() self.monthCntList = monthCntList def cmdLineHandler(): """ Command Line Handler @param return: Instance of class argparse.Namespace containing all the parsed command line arguments. """ parser = argparse.ArgumentParser(description="GnuCash Stats for Cristian Marchi", usage='%(prog)s [options] jsonPath csvOpath') parser.add_argument('jsonPath', help='Pathname of the directory containing all the ' 'json files containing stats.') parser.add_argument('csvOpath', help='Pathname of csv file to create') args = parser.parse_args() return args """ http://docs.python.org/2/library/csv.html#examples The csv module doesn’t directly support reading and writing Unicode, but it is 8-bit-clean save for some problems with ASCII NUL characters. So you can write functions or classes that handle the encoding and decoding for you as long as you avoid encodings like UTF-16 that use NULs. UTF-8 is recommended. """ def main(): """ Function executed when this file is executed. This function is NOT executed when this module is imported. """ args = cmdLineHandler() pathNamePattern = os.path.join(args.jsonPath, FileNamePattern) globx = glob.glob(pathNamePattern) relStatObjList = list() for pathName in globx: jsonFD = codecs.open(pathName, 'r', encoding='UTF-8') try: jsonTree = json.load(jsonFD) except Exception as exception: raise type(exception)('File: {0} - {1}'.format(pathName, exception.message)) finally: jsonFD.close() relStatObjList.append(RelStatObj(pathName, jsonTree['downloads'])) # Sort into ascending major, then ascending minor, then ascending bf. relStatObjList.sort(key=lambda x: x.bf) relStatObjList.sort(key=lambda x: x.minor) relStatObjList.sort(key=lambda x: x.major) # Calculate the header line and the column for each json file. for rso in relStatObjList: CsvHdrLine.append('GnuCash {0}.{1}.{2}'.format(rso.major, rso.minor, rso.bf)) # Allow the files to contain different sets of dates. dateSet = set() for rso in relStatObjList: dateSet = dateSet | set([mcl[0] for mcl in rso.monthCntList]) dateList = list(dateSet) dateList.sort() # Set the dates column outList = [CsvHdrLine] for datx in dateList: outList.append([None, datx]) # Set the counts Columns for rso in relStatObjList: mcl = rso.monthCntList idxMcl = 0 for idx1, datx in enumerate(dateList): linex = outList[1 + idx1] if datx == mcl[idxMcl][0]: linex.append(mcl[idxMcl][1]) idxMcl = idxMcl + 1 else: linex.append(None) csvFD = open(args.csvOpath, 'w') csvWriter = csv.writer(csvFD, dialect='excel') csvWriter.writerows(outList) csvFD.close() if __name__ == "__main__": main()