Source

hello / cppunit / generate.py

Full commit
#!/usr/bin/env python
#
# @breif what this script does (aims at):
# 1. Generates a C++ class file from template without writing some misc.
#    such as 
#      - class name,
#      - author,
#      - member variables,
#      - member setter, member getter,
#      - member functions,
#      - ctor, dtor,
#    and anything else.
# 2. Generates a cppunit test suite from template without complex syntax.
# 3. Inputs the new class into whole test suite.
#
# usage:
#  $ ./generate.pl NewClassName <members> <methods?> 

import re, socket, pwd, os, time, sys
#from __future__ import with_statement

def get_username():
    return pwd.getpwuid(os.getuid())[0]

def get_loginname():
    return get_username()+"@"+socket.gethostname()

def get_time():
    return time.strftime("%Y/%m/%d %H:%M:%S %Z")

class ClassModel:
    def __init__(self, name, *args):
        self.indent_n = 2
        self.cpp_template = "XXX.cpp.tmpl"
        self.h_template = "XXX.h.tmpl"
        self.test_template = "XXXTest.cpp.tmpl"
        self.utest_data = "test_data.yaml"
        self.name = name.capitalize()
        self.vars = []
        self.set_vars(args)
        self.methods=[ClassModel.Method("", self.name), 
                      ClassModel.Method("", "~"+self.name),
                     # ClassModel.Method("", self.name, args) 
                      ]
        #print dir(self)

    def p(self):
        print self.name, self.vars, "\n", c.format_variables()
        print c.format_methods_declaration() , c.format_methods_implementation()

    def set_vars(self, args):
        """input: [(type, name), (type,name), ...]"""
        self.vars.extend( filter( lambda x:(x.__class__.__name__=='tuple')and(len(x) == 2 ) ,
                                  args)  )
        
    def set_method(self, r, n, *args):
        """input: (return type, name, *input type and input name) """
        self.methods.append( ClassModel.Method(r,n,args) ) 

    def indent(self): return "  "

    def generate(self):
        self.gen_cpp()
        self.gen_header()
        #self.gen_unittest()
        
    class Method:
        def __init__(self, ret_type, name, args=None):
            self.ret_type = ret_type
            self.name = name
            self.args = args

        def declare(self, indent = "  "):#print self.ret_type, self.name, self.args
            ret=  indent + self.ret_type
            if self.ret_type:
                ret += " "
            ret += self.name+"("
            if self.args:
                ret += ", ".join( ["const "+v[0]+"& "+v[1] for v in self.args] )
            ret += ");"
            return ret

        def implement(self, cname):
            ret= self.ret_type
            if self.ret_type:
                ret += " "
            ret += cname+"::"+ self.name+"("
            if self.args:
                ret += ", ".join( ["const "+v[0]+"& "+v[1] for v in self.args] )
            ret += "){\n}"
            return ret

    def format_methods_declaration(self):
        ret = self.indent() + self.name + "("
        ret += ", ".join([ "const "+v[0]+"& "+v[1] for v in self.vars])
        ret += ");\n"
        ret += "\n".join([ m.declare() for m in self.methods]  )
        return ret

    def gen_cpp(self):
        fout = open(self.name+".cpp", "w")
        try:
            fout.write( '#include "'+self.name+'.h"\n\n')
            fout.write( self.format_methods_implementation() )
        finally:
            fout.close()
        print self.name+".cpp generated."

    def format_methods_implementation(self):
        ret =  self.name + "("
        ret += ", ".join([ "const "+v[0]+"& "+v[1] for v in self.vars])
        ret += "):\n"+ ",\n".join([ self.indent() +v[1]+"_( "+v[1]+")"  for v in self.vars]) +"{\n};\n\n"
        ret += "\n\n".join([ m.implement(self.name) for m in self.methods] )
        return ret+"\n"

    def gen_header(self):
        fin = open(self.h_template)
        fout = open(self.name+".h", "w")
        try:
            for line in fin:
#                print self.replace(line.strip())
                fout.write( self.replace( line ) )
 #               print y
        finally:
            fin.close()
            fout.close()
        print self.name+".h generated."

    def replace(self, line ):
        '''read template and replace them all... '''
        if re.search( "\\\\classname", line):
            return   re.sub("\\\\classname", self.name, line) 
        elif re.search( "\\\\CLASSNAME", line):
            return   re.sub("\\\\CLASSNAME", self.name.upper(), line) 
        elif re.search("\\\\variables", line): #self.format_variables() 
            return  "\n".join( [self.indent()+v[0] + " "+ v[1]+ "_;" for v in self.vars]) 
        elif re.search("\\\\methods", line):
            return  self.format_methods_declaration()
        elif re.search("\\\\username", line):
            return  re.sub("\\\\username", get_username(), line)
        elif re.search("\\\\login", line):
            return  re.sub("\\\\login", get_loginname(), line)
        elif re.search("\\\\time", line):
            return  re.sub("\\\\time", get_time(), line)
        else: return  line

    def gen_unittest(self): #pass
        fin = open(self.test_template)
        fout = open(self.name+"Test.h", "w")
        try:
            for line in fin:
#                print self.replace(line.strip())
                fout.write( self.replace( line ) )
 #               print y
        finally:
            fin.close()
            fout.close()
        print self.name+"Test.h generated."


def test():
    c =  ClassModel( "oge", ('int', 'id'), ('string', 'ad'), ('double', 'hoge') )
    c.set_vars( [('double', 'hage'), ('void *', 'moe')] )
    c.set_method('void', 'hoge')
    c.set_method('void', 'hoge2', ('int', 'a'), ('double', 'b'))
#c.p()
#c.gen_cpp()
#c.gen_header()
    c.generate()


#test()
#for line in iter( sys.stdin.readline, "" ):
#    print line,

print "Class Name:",
classname = sys.stdin.readline()
c = ClassModel( classname.strip() )
#print classname.capitalize()
#vars = []
for i in xrange(0,10):
    print "type of var", i ,":",
    type = sys.stdin.readline()
    if len(type)==1 : break
    print "name of var", i ,":",
    name = sys.stdin.readline()
    if len(name)==1 :
        print "name of var empty."
        continue
    c.set_vars( [(type.strip(), name.strip())] )

for i in xrange(0,10):
    print "return type of method", i ,":",
    type = sys.stdin.readline()
    if len(type)==1 : break
    print "       name of method", i ,":",
    name = sys.stdin.readline()
    if len(type)==1 or len(name)==1 :
        continue
    c.set_method( type.strip(), name.strip() )

c.generate()