import re
__all__ = ["Style", "MixedCaseUnderscoreStyle", "DefaultStyle",
"MixedCaseStyle"]
[docs]class Style(object):
"""
The base Style class, and also the simplest implementation. No
translation occurs -- column names and attribute names match,
as do class names and table names (when using auto class or
schema generation).
"""
def __init__(self, pythonAttrToDBColumn=None,
dbColumnToPythonAttr=None,
pythonClassToDBTable=None,
dbTableToPythonClass=None,
idForTable=None,
longID=False):
if pythonAttrToDBColumn:
self.pythonAttrToDBColumn = \
lambda a, s=self: pythonAttrToDBColumn(s, a)
if dbColumnToPythonAttr:
self.dbColumnToPythonAttr = \
lambda a, s=self: dbColumnToPythonAttr(s, a)
if pythonClassToDBTable:
self.pythonClassToDBTable = \
lambda a, s=self: pythonClassToDBTable(s, a)
if dbTableToPythonClass:
self.dbTableToPythonClass = \
lambda a, s=self: dbTableToPythonClass(s, a)
if idForTable:
self.idForTable = lambda a, s=self: idForTable(s, a)
self.longID = longID
[docs] def pythonAttrToDBColumn(self, attr):
return attr
[docs] def dbColumnToPythonAttr(self, col):
return col
[docs] def pythonClassToDBTable(self, className):
return className
[docs] def dbTableToPythonClass(self, table):
return table
[docs] def idForTable(self, table):
if self.longID:
return self.tableReference(table)
else:
return 'id'
[docs] def pythonClassToAttr(self, className):
return lowerword(className)
[docs] def instanceAttrToIDAttr(self, attr):
return attr + "ID"
[docs] def instanceIDAttrToAttr(self, attr):
return attr[:-2]
[docs] def tableReference(self, table):
return table + "_id"
[docs]class MixedCaseUnderscoreStyle(Style):
"""
This is the default style. Python attributes use mixedCase,
while database columns use underscore_separated.
"""
[docs] def pythonAttrToDBColumn(self, attr):
return mixedToUnder(attr)
[docs] def dbColumnToPythonAttr(self, col):
return underToMixed(col)
[docs] def pythonClassToDBTable(self, className):
return className[0].lower() \
+ mixedToUnder(className[1:])
[docs] def dbTableToPythonClass(self, table):
return table[0].upper() \
+ underToMixed(table[1:])
[docs] def pythonClassToDBTableReference(self, className):
return self.tableReference(self.pythonClassToDBTable(className))
[docs] def tableReference(self, table):
return table + "_id"
DefaultStyle = MixedCaseUnderscoreStyle
[docs]class MixedCaseStyle(Style):
"""
This style leaves columns as mixed-case, and uses long
ID names (like ProductID instead of simply id).
"""
[docs] def pythonAttrToDBColumn(self, attr):
return capword(attr)
[docs] def dbColumnToPythonAttr(self, col):
return lowerword(col)
[docs] def dbTableToPythonClass(self, table):
return capword(table)
[docs] def tableReference(self, table):
return table + "ID"
defaultStyle = DefaultStyle()
def getStyle(soClass, dbConnection=None):
if dbConnection is None:
if hasattr(soClass, '_connection'):
dbConnection = soClass._connection
if hasattr(soClass.sqlmeta, 'style') and soClass.sqlmeta.style:
return soClass.sqlmeta.style
elif dbConnection and dbConnection.style:
return dbConnection.style
else:
return defaultStyle
############################################################
# Text utilities
############################################################
_mixedToUnderRE = re.compile(r'[A-Z]+')
def mixedToUnder(s):
if s.endswith('ID'):
return mixedToUnder(s[:-2] + "_id")
trans = _mixedToUnderRE.sub(mixedToUnderSub, s)
if trans.startswith('_'):
trans = trans[1:]
return trans
def mixedToUnderSub(match):
m = match.group(0).lower()
if len(m) > 1:
return '_%s_%s' % (m[:-1], m[-1])
else:
return '_%s' % m
def capword(s):
return s[0].upper() + s[1:]
def lowerword(s):
return s[0].lower() + s[1:]
_underToMixedRE = re.compile('_.')
def underToMixed(name):
if name.endswith('_id'):
return underToMixed(name[:-3] + "ID")
return _underToMixedRE.sub(lambda m: m.group(0)[1].upper(),
name)