|
From: <ki...@us...> - 2003-06-25 19:46:42
|
Update of /cvsroot/pymerase/pymerase/pymerase/output
In directory sc8-pr-cvs1:/tmp/cvs-serv4167
Added Files:
CreateTabDelimitedParser.py
Log Message:
Generates Tab Delimited Text Parser
w/ class that can pickle itself out to disk
w/ class that can save to database using generated DBAPI
Generated Code is documented for useage of the parser.
--- NEW FILE: CreateTabDelimitedParser.py ---
###########################################################################
# #
# C O P Y R I G H T N O T I C E #
# Copyright (c) 2003 by: #
# * California Institute of Technology #
# #
# All Rights Reserved. #
# #
# Permission is hereby granted, free of charge, to any person #
# obtaining a copy of this software and associated documentation files #
# (the "Software"), to deal in the Software without restriction, #
# including without limitation the rights to use, copy, modify, merge, #
# publish, distribute, sublicense, and/or sell copies of the Software, #
# and to permit persons to whom the Software is furnished to do so, #
# subject to the following conditions: #
# #
# The above copyright notice and this permission notice shall be #
# included in all copies or substantial portions of the Software. #
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, #
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF #
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND #
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS #
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN #
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN #
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE #
# SOFTWARE. #
###########################################################################
#
# Authors: Brandon King
# Last Modified: $Date: 2003/06/25 19:46:36 $
#
"""Creates a Tab Delimeted File Parser of each Class/Table"""
#Imported System Packages.
import os
import string
import re
from pymerase.ClassMembers import getAllAttributes
from pymerase.ClassMembers import getAllAssociationEnds
from pymerase.util.Warnings import DebugWarning
from pymerase.util.Warnings import InfoWarning
import warnings
from warnings import warn
############################
# Globals
TRANSLATOR_NAME='CreateTabDelimitedParser'
def getTemplate():
template = """#!/usr/bin/env python
###########################################################################
# #
# C O P Y R I G H T N O T I C E #
# Copyright (c) 2003 by: #
# * California Institute of Technology #
# #
# All Rights Reserved. #
# #
# Permission is hereby granted, free of charge, to any person #
# obtaining a copy of this software and associated documentation files #
# (the "Software"), to deal in the Software without restriction, #
# including without limitation the rights to use, copy, modify, merge, #
# publish, distribute, sublicense, and/or sell copies of the Software, #
# and to permit persons to whom the Software is furnished to do so, #
# subject to the following conditions: #
# #
# The above copyright notice and this permission notice shall be #
# included in all copies or substantial portions of the Software. #
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, #
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF #
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND #
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS #
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN #
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN #
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE #
# SOFTWARE. #
###########################################################################
#
# Authors: Brandon King
# Generated By: Pymerase (CreateTabDelimitedParser Output Module)
# Generator Last Modified: $Date: 2003/06/25 19:46:36 $
# Generator Revision: $ Revision: $
#
import os
import string
import re
import sys
import pickle
class %CLASSNAME%Record:
\"\"\"
%CLASSNAME% Record Object
Stores one row from a tab delimeted text file
\"\"\"
def __init__(self):
%VAR_INIT%
%FUNCTIONS%
class %CLASSNAME%Master:
\"\"\"
%CLASSNAME% Base container class for record objects
Meant to have save(self) overriden
to provide more functionality.
\"\"\"
def __init__(self):
#List of records that are stored in this container class
self._recordList = []
#Number of columns in data file. Used for error checking
self.numColumns = %NUM_COLUMNS%
def setRecordList(self, rList):
\"\"\"Stores a list of records\"\"\"
self._recordList = rList
def getRecordList(self):
\"\"\"Returns a list of records\"\"\"
return self._recordList
def appendRecord(self, record):
\"\"\"Appends record to list of records\"\"\"
self._recordList.append(record)
def save(self):
\"\"\" Overide to save data somewhere \"\"\"
raise NotImplementedError, 'Not Implemented, Override this Function to save'
class %CLASSNAME%PickleMaster(%CLASSNAME%Master):
\"\"\"
Description:
Overrides %CLASSNAME%Master save function, allowing
the Class to pickle itself to a file. See below for useage.
USE:
parser = %CLASSNAME%Parser(%CLASSNAME%PickleMaster)
obj = parser.parse(fileName)
obj.save(filePath)
\"\"\"
def save(self, filePath):
filePath = os.path.abspath(filePath)
f = open(filePath, 'w')
pickle.dump(self, f)
f.close()
class %CLASSNAME%DbMaster(%CLASSNAME%Master):
\"\"\"
Description:
Overrides %CLASSNAME%Master save function, allowing
the Class to save record objects to a database
USE:
parser = %CLASSNAME%Parser(%CLASSNAME%DbMaster)
obj = parser.parse(fileName)
obj.save('localhost', 'myDatabase', 'myUser', 'myPassword')
\"\"\"
def save(self, dsn, database, user=None, password=None):
#The following line of code only works if you have
# generated %PACKAGE_NAME% using the Pymerase
# CreateDBAPI output module.
from %PACKAGE_NAME% import DBSession
dbs = DBSession(dsn, database, user, password)
for rec in self._recordList:
dbRec = dbs.%CLASSNAME%()
%OM2DB%
dbRec.commit()
class %CLASSNAME%Parser:
\"\"\"
Description:
%CLASSNAMEParser handles the parsing of a %CLASSNAME% tab
delimited file. Pass a class that overrides the save
function from %CLASSNAME%Master class to add more
functionality to the object which is returned from
%CLASSNAME%Parser's 'parse' function.
Example USE:
parser = %CLASSNAME%Parser(%CLASSNAME%DbMaster)
obj = parser.parse(fileName)
obj.save(filePath)
\"\"\"
def __init__(self, MasterClass=%CLASSNAME%Master):
\"\"\"
Pass in a class that has been inherited from %CLASSNAME%Master
to add more functionality to the class which is returned by this
class' parse function.
Uses %CLASSNAME%Master by default.
See %CLASSNAME%PickleMaster and %CLASSNAME%DbMaster classes for examples
\"\"\"
self._masterClass = MasterClass()
def parse(self, filePath, startLine=0):
\"\"\"
Parses text file given by 'filePath' and stores each line
in a %CLASSNAME%Record object and appends it to a %CLASSNAME%Master
object which is chosen when initiating an instance of %CLASSNAME%Parser.
Examples:
parser = %CLASSNAME%Parser(%CLASSNAME%UserDefinedMaster)
OR
parser = %CLASSNAME%Parser(%CLASSNAME%PickleMaster)
OR
parser = %CLASSNAME%Parser(%CLASSNAME%DbMaster)
OR
parser = %CLASSNAME%Parser(%CLASSNAME%Master)
The 'Master Class' you passed to %CLASSNAME%Parser will be returned
when the parse is done.
\"\"\"
filePath = os.path.abspath(filePath)
if os.path.isfile(filePath):
#Open file for parsing
f = open(filePath, 'r')
#Skip lines if requested
if startLine > 0:
for n in range(0, startLine):
f.readline()
#Process Each Line
line = None
while line != '':
line = f.readline()
#Make Sure we are not at last line
if line != '':
#Remove DOS/Windows \\r\\n formating
line = re.sub('\\r\\n', '\\n', line)
#Remove \\n
line = line.strip()
#Break up line into list
line = line.split('\\t')
#Clean up lines
newLine = []
for item in line:
newLine.append(item.strip())
#Check Length of line
if len(newLine) != self._masterClass.numColumns:
raise ValueError, 'Line(%s) is length %s, should be %s.' % (newLine, len(newLine), self._masterClass.numColumns)
#Process Each Record
newRecord = %CLASSNAME%Record()
%NEW_RECORD_PROCESSING%
self._masterClass.appendRecord(newRecord)
return self._masterClass
else:
raise ValueError, 'FilePath %s is invalid!' % (filePath)
if __name__ == '__main__':
if len(sys.argv) > 1:
fileName = sys.argv[1]
parser = %CLASSNAME%Parser()
obj = parser.parse(fileName)
print 'Data Parsed and returned', obj
else:
print 'Please enter name of file to be processed as an argument to this script.'
"""
return template
def getGetterFunction(getterName, attribName):
code = []
code.append(' def %s(self):' % (getterName))
code.append(' return self.%s' % (attribName))
code.append('')
code.append('%FUNCTIONS%')
return string.join(code, '\n')
def getSetterFunction(setterName, attribName, type):
if type == 'types.StringType':
typeConverter = 'str'
elif type == 'types.IntType':
typeConverter = 'int'
elif type == 'types.FloatType':
typeConverter = 'float'
else:
warn('%s type is not being processed. No converting done... May need to be fixed' % (type), DebugWarning)
typeConverter = ''
code = []
code.append(' def %s(self, %s):' % (setterName, attribName))
code.append(' self.%s = %s(%s)' % (attribName, typeConverter, attribName))
code.append('')
code.append('%FUNCTIONS%')
return string.join(code, '\n')
def getNewRecCode(setterName, colNum):
return ' ' * 10 + 'newRecord.%s(newLine[%s])\n%s' % (setterName, colNum, '%NEW_RECORD_PROCESSING%')
def getOm2DbCode(getterName, setterName):
return ' ' * 6 + 'dbRec.%s(rec.%s())\n%s' % (setterName, getterName, '%OM2DB%')
############################
# Writer components
def write(destination, classList):
"""
Create Report in destination dirctory.
"""
code = getTemplate()
#Iterate through the tables/classes and process the data
for cls in classList:
packageName = cls.getPackage()
#Set Class Title Title
code = re.sub('%CLASSNAME%', cls.getName(TRANSLATOR_NAME), code)
#Set Package name for importing
code = re.sub('%PACKAGE_NAME%', packageName, code)
#Get all attributes
attribList = getAllAttributes(classList, cls, TRANSLATOR_NAME)
#Calculate total number of columns for error checking
numCol = (len(attribList) - 1)
#Record number of columns
code = re.sub('%NUM_COLUMNS%', str(numCol), code)
#Setup column counter
colCounter = 0
##Process each attribute in a given table (class)
for attribute in attribList:
attribName = attribute.getName(TRANSLATOR_NAME)
attribType = attribute.getType().getPythonTypeStr()
getterName = attribute.getGetterName(TRANSLATOR_NAME)
setterName = attribute.getSetterName(TRANSLATOR_NAME)
#Skiping Primary Keys
if attribute.isPrimaryKey():
#Skip
pass
else:
#Process
print 'Processing %s' % (attribute.getName(TRANSLATOR_NAME))
#Create Record INIT Variables
code = re.sub('%VAR_INIT%',
' self.%s = None\n%s' % (attribName, '%VAR_INIT%'),
code)
#Create Getter Functions
code = re.sub('%FUNCTIONS%', getGetterFunction(getterName, attribName), code)
#Create Setter Functions
code = re.sub('%FUNCTIONS%', getSetterFunction(setterName, attribName, attribType), code)
#Create New Record Processing
code = re.sub('%NEW_RECORD_PROCESSING%', getNewRecCode(setterName, colCounter), code)
colCounter += 1
#Create Object Modem 2 Database Code
code = re.sub('%OM2DB%', getOm2DbCode(getterName, setterName), code)
#for assocEnd in getAllAssociationEnds(classList, cls, TRANSLATOR_NAME):
# text.append(" ASSOC END:")
# text.append(" Name = %s" % (assocEnd.getName(TRANSLATOR_NAME)))
# text.append(" AttribName = %s" % \
#Clean Up Code
code = re.sub('%VAR_INIT%', '', code)
code = re.sub('%FUNCTIONS%', '', code)
code = re.sub('%NEW_RECORD_PROCESSING%', '', code)
code = re.sub('%OM2DB%', '', code)
#Save Class
f = open(destination, 'w')
f.write(code)
f.close()
warn("Tab Delimited Parser Generation Complete... Good Bye.", InfoWarning)
|