diff --git a/src/python/dm/aps_user_db/__init__.py b/src/python/dm/aps_user_db/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/python/dm/aps_user_db/api/__init__.py b/src/python/dm/aps_user_db/api/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/python/dm/aps_user_db/api/apsUserDbApi.py b/src/python/dm/aps_user_db/api/apsUserDbApi.py new file mode 100755 index 0000000000000000000000000000000000000000..e9a2edeeebbfbbcfb66f1b1d7e1887b0e83a6528 --- /dev/null +++ b/src/python/dm/aps_user_db/api/apsUserDbApi.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python + +from dm.aps_user_db.api.apsUserDbApiBase import ApsUserDbApiBase +from dm.aps_user_db.impl.apsUserInfoHandler import ApsUserInfoHandler + +class ApsUserDbApi(ApsUserDbApiBase): + """ APS User DB API class. """ + def __init__(self): + ApsUserDbApiBase.__init__(self) + self.userInfoHandler = ApsUserInfoHandler() + + @ApsUserDbApiBase.executeQuery + def getApsUsers(self, **kwargs): + session = kwargs['session'] + dbUsers = self.userInfoHandler.getApsUsers(session) + return self.toDmObjectList(dbUsers) + + @ApsUserDbApiBase.executeQuery + def getApsUserByBadgeNumber(self, badgeNumber, **kwargs): + session = kwargs['session'] + dbUserInfo = self.userInfoHandler.getApsUserByBadgeNumber(session, badgeNumber) + return dbUserInfo.getDmObject() + +####################################################################### +# Testing. +if __name__ == '__main__': + api = ApsUserDbApi() + #users = api.getApsUsers() + #for u in users: + # print u + print api.getApsUserByBadgeNumber(225159) + + diff --git a/src/python/dm/aps_user_db/api/apsUserDbApiBase.py b/src/python/dm/aps_user_db/api/apsUserDbApiBase.py new file mode 100755 index 0000000000000000000000000000000000000000..ec0bbaf5c7b3db83511f274b2aac15dfc04e8136 --- /dev/null +++ b/src/python/dm/aps_user_db/api/apsUserDbApiBase.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python + +from dm.common.exceptions.dmException import DmException +from dm.common.exceptions.internalError import InternalError +from dm.common.utility.loggingManager import LoggingManager +from dm.aps_user_db.impl.apsUserDbManager import ApsUserDbManager + +class ApsUserDbApiBase: + """ APS User DB API base class. """ + def __init__(self): + self.logger = LoggingManager.getInstance().getLogger(self.__class__.__name__) + self.dbManager = ApsUserDbManager.getInstance() + + # Decorator for all DB queries + @classmethod + def executeQuery(cls, func): + def query(*args, **kwargs): + try: + dbManager = ApsUserDbManager.getInstance() + session = dbManager.openSession() + kwargs['session'] = session + try: + return func(*args, **kwargs) + except DmException, ex: + raise + except Exception, ex: + cls.getLogger().exception('%s' % ex) + raise DmException(exception=ex) + finally: + dbManager.closeSession(session) + return query + + # Decorator for all DB transactions + @classmethod + def executeTransaction(cls, func): + def transaction(*args, **kwargs): + try: + dbManager = ApsUserDbManager.getInstance() + session = dbManager.openSession() + kwargs['session'] = session + try: + result = func(*args, **kwargs) + session.commit() + return result + except DmException, ex: + session.rollback() + raise + except Exception, ex: + session.rollback() + cls.getLogger().exception('%s' % ex) + raise DmException(exception=ex) + finally: + dbManager.closeSession(session) + return transaction + + @classmethod + def getLogger(cls): + logger = LoggingManager.getInstance().getLogger(cls.__name__) + return logger + + @classmethod + def executeConnectionQuery(cls, query): + connection = None + try: + connection = ApsUserDbManager.getInstance().acquireConnection() + try: + return connection.execute(query) + except DmException, ex: + raise + except Exception, ex: + cls.getLogger().exception('%s' % ex) + raise + finally: + ApsUserDbManager.getInstance().releaseConnection(connection) + + + def loadRelation(self, dbObject, relationName): + if not relationName in dir(dbObject): + raise InternalError('Relation %s not valid for class %s' + % (relationName, dbObject.__class__.__name__)) + o = None + exec 'o = dbObject.%s' % (relationName) + return o + + def loadRelations(self, dbObject, optionDict): + for k in optionDict.keys(): + # The optionDict contains key-value pairs of relation name + # and a boolean to indicate whether to load that relation + if not optionDict[k]: + continue + + try: + self.loadRelation(dbObject, k) + except InternalError, ex: + self.logger.error(ex) + + def toDmObjectList(self, dbEntityList): + dmObjectList = [] + for dbEntity in dbEntityList: + dmObjectList.append(dbEntity.getDmObject()) + return dmObjectList + + +####################################################################### +# Testing. +if __name__ == '__main__': + api = ApsUserDbApiBase() + + diff --git a/src/python/dm/aps_user_db/entities/__init__.py b/src/python/dm/aps_user_db/entities/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/python/dm/aps_user_db/entities/apsUserDbEntityMap.py b/src/python/dm/aps_user_db/entities/apsUserDbEntityMap.py new file mode 100755 index 0000000000000000000000000000000000000000..3fe8fbb3cf04896e41e95403e51b0dbfc520d87f --- /dev/null +++ b/src/python/dm/aps_user_db/entities/apsUserDbEntityMap.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python + +from dm.aps_user_db.entities.apsUserInfo import ApsUserInfo + +# Map db table/db entity class +# Use generic 'self' key as name for primary key mapping (needed by sqlalchemy) +APS_USER_DB_ENTITY_MAP = { + 'FL$03_BL_APV_VIEW_V2' : (ApsUserInfo, {'self' : {'primary_key' : 'badge_no'}}), +} + diff --git a/src/python/dm/aps_user_db/entities/apsUserInfo.py b/src/python/dm/aps_user_db/entities/apsUserInfo.py new file mode 100755 index 0000000000000000000000000000000000000000..3a82a9df451534405a994e9e97c930a0c25cab75 --- /dev/null +++ b/src/python/dm/aps_user_db/entities/apsUserInfo.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python + +from dm.common.db.entities.dmDbEntity import DmDbEntity +from dm.common.objects import apsUserInfo + +class ApsUserInfo(DmDbEntity): + + mappedColumnDict = { + 'badge_no' : 'badgeNumber', + 'first_name' : 'firstName', + 'middle_name' : 'middleName', + 'last_name' : 'lastName', + 'last_change_date' : 'lastChangeDate', + 'pwd_hash_value' : 'passwordHashValue', + 'is_usr_not_anl_emp' : 'isUserNotAnlEmployee', + } + dmObjectClass = apsUserInfo.ApsUserInfo + + def __init__(self, **kwargs): + DmDbEntity.__init__(self, **kwargs) + + + diff --git a/src/python/dm/aps_user_db/impl/__init__.py b/src/python/dm/aps_user_db/impl/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/python/dm/aps_user_db/impl/apsUserDbManager.py b/src/python/dm/aps_user_db/impl/apsUserDbManager.py new file mode 100755 index 0000000000000000000000000000000000000000..1f7d169456ab5727fb1c8f0a393b4bc8ad710c14 --- /dev/null +++ b/src/python/dm/aps_user_db/impl/apsUserDbManager.py @@ -0,0 +1,199 @@ +#!/usr/bin/env python + +import threading +import os.path +import sqlalchemy +from sqlalchemy.orm import sessionmaker +from sqlalchemy.orm import mapper +from sqlalchemy.orm import relationship + +from dm.common.exceptions.commandFailed import CommandFailed +from dm.common.exceptions.configurationError import ConfigurationError +from dm.common.utility.loggingManager import LoggingManager +from dm.common.utility.configurationManager import ConfigurationManager +from dm.aps_user_db.entities import apsUserDbEntityMap + + +class ApsUserDbManager: + """ Singleton class for db management. """ + + DB_CONNECTION_POOL_SIZE = 10 + DB_CONNECTION_POOL_MAX_OVERFLOW = 2 + DB_CONNECTION_POOL_RECYCYLE_TIME = 600 + DB_CONNECTION_POOL_TIMEOUT = 60 + DB_CONNECTION_LOGGING_FLAG = False + + CONFIG_SECTION_NAME = 'ApsUserDbManager' + CONFIG_OPTION_NAME_LIST = [ 'dbHost', 'dbPort', 'dbUser', 'dbPasswordFile', 'dbName', 'dbSchema' ] + + # Singleton. + __lock = threading.RLock() + __instance = None + + @classmethod + def getInstance(cls): + from dm.aps_user_db.impl.apsUserDbManager import ApsUserDbManager + try: + mgr = ApsUserDbManager() + except ApsUserDbManager, ex: + mgr = ex + return mgr + + def __init__(self): + ApsUserDbManager.__lock.acquire() + try: + if ApsUserDbManager.__instance is not None: + raise ApsUserDbManager.__instance + ApsUserDbManager.__instance = self + self.lock = threading.RLock() + self.logger = LoggingManager.getInstance().getLogger(self.__class__.__name__) + cm = ConfigurationManager.getInstance() + #cm.setOptionsFromConfigFile(ApsUserDbManager.CONFIG_SECTION_NAME, ApsUserDbManager.CONFIG_OPTION_NAME_LIST) + + #dbUser = cm.getDbUser() + #self.logger.debug('Using DB user: %s' % dbUser) + #dbSchema = cm.getDbSchema() + #dbPasswordFile = cm.getDbPasswordFile() + #self.logger.debug('Using DB password file: %s' % dbPasswordFile) + #dbPassword = open(dbPasswordFile, 'r').readline().strip() + #dbPort = cm.getDbPort() + #dbHost = cm.getDbHost() + #db = cm.getDb() + db = "oracle" + dbPort = 1527 + dbHost = "ra.aps.anl.gov" + dbName = "aps1" + dbSchema = "DCC" + dbUser = "glob_conn" + dbPassword = "ur2ytkownicy2u" + engineUrl = '%s://%s:%s@%s:%s/%s' % (db, dbUser, dbPassword, dbHost, dbPort, dbName) + self.logger.debug('Using engine URL: %s' % engineUrl) + self.engine = sqlalchemy.create_engine(engineUrl, + pool_size=ApsUserDbManager.DB_CONNECTION_POOL_SIZE, + max_overflow=ApsUserDbManager.DB_CONNECTION_POOL_MAX_OVERFLOW, + pool_recycle=ApsUserDbManager.DB_CONNECTION_POOL_RECYCYLE_TIME, + echo=ApsUserDbManager.DB_CONNECTION_LOGGING_FLAG, + pool_timeout=ApsUserDbManager.DB_CONNECTION_POOL_TIMEOUT) + self.metadata = sqlalchemy.MetaData(engineUrl, schema=dbSchema) + + self.logger.debug('Mapping DB tables') + for (dbTableName, (dbEntityClass, dbRelationDict)) in apsUserDbEntityMap.APS_USER_DB_ENTITY_MAP.items(): + self.mapTable(dbEntityClass, dbTableName, dbRelationDict) + self.logger.debug('Initialized SQLalchemy engines') + + finally: + ApsUserDbManager.__lock.release() + + def getLogger(self): + return self.logger + + def inspectTables(self): + from sqlalchemy import inspect + inspector = inspect(self.engine) + self.logger.debug('Inspecting tables') + for tableName in inspector.get_table_names(): + self.logger.debug('Table: %s' % tableName) + for column in inspector.get_columns(tableName): + self.logger.debug('Column: %s' % column['name']) + + def inspectTables2(self): + from sqlalchemy import MetaData + m = MetaData() + m.reflect(self.engine) + self.logger.debug('Inspecting tables via metadata') + for table in m.tables.values(): + self.logger.debug('Table: %s' % table.name) + for column in table.c: + self.logger.debug('Column: %s' % column.name) + + def initTable(self, tableClass, tableName): + """ Initialize DB table. """ + self.lock.acquire() + try: + tbl = sqlalchemy.Table(tableName, self.metadata, autoload=True) + tableClass.columns = tbl.columns + return tbl + finally: + self.lock.release() + + def mapTable(self, tableClass, tableName, relationDict): + """ Map DB table to a given class. """ + self.lock.acquire() + try: + table = sqlalchemy.Table(tableName, self.metadata, autoload=True) + tableClass.columns = table.columns + + # Build relations from specified foreign key columns and other properties. + tableRelations = {} + primaryKey = None + for (name, propertyDict) in relationDict.items(): + if name == 'self': + primaryKey = propertyDict.get('primary_key') + continue + lazy = propertyDict.get('lazy') + parentEntity = propertyDict.get('parentEntity') + foreignKeyColumns = propertyDict.get('foreignKeyColumns', []) + if len(foreignKeyColumns): + fkList = [] + for fk in foreignKeyColumns: + fkList.append(table.columns.get(fk)) + tableRelations[name] = relationship(parentEntity, foreign_keys=fkList, lazy=lazy) + else: + tableRelations[name] = relationship(parentEntity, lazy=lazy) + + if primaryKey: + mapper(tableClass, table, tableRelations, primary_key=table.columns.get(primaryKey)) + else: + mapper(tableClass, table, tableRelations) + return table + finally: + self.lock.release() + + def getMetadataTable(self, table): + return self.metadata.tables[table] + + def openSession(self): + """ Open db session. """ + self.lock.acquire() + try: + Session = sessionmaker(bind=self.engine) + return Session() + finally: + self.lock.release() + + def closeSession(self, session): + """ Close db session. """ + self.lock.acquire() + try: + session.close() + finally: + self.lock.release() + + def acquireConnection(self): + """ Get db connection. """ + self.lock.acquire() + try: + return self.engine.connect() + finally: + self.lock.release() + + def releaseConnection(self, connection): + """ Release db connection. """ + self.lock.acquire() + try: + if connection: + connection.close() + finally: + self.lock.release() + +####################################################################### +# Testing. +if __name__ == '__main__': + ConfigurationManager.getInstance().setConsoleLogLevel('debug') + mgr = ApsUserDbManager.getInstance() + mgr.acquireConnection() + mgr.inspectTables() + mgr.inspectTables2() + print 'Got connection' + + diff --git a/src/python/dm/aps_user_db/impl/apsUserInfoHandler.py b/src/python/dm/aps_user_db/impl/apsUserInfoHandler.py new file mode 100755 index 0000000000000000000000000000000000000000..68d9606543db7fabd3e86547af6b27307ba98fcd --- /dev/null +++ b/src/python/dm/aps_user_db/impl/apsUserInfoHandler.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python + +from sqlalchemy import and_ +from sqlalchemy.orm.exc import NoResultFound + +from dm.common.exceptions.objectAlreadyExists import ObjectAlreadyExists +from dm.common.exceptions.objectNotFound import ObjectNotFound +from dm.common.exceptions.objectAlreadyExists import ObjectAlreadyExists +from dm.common.db.impl.dmDbEntityHandler import DmDbEntityHandler +from dm.aps_user_db.entities.apsUserInfo import ApsUserInfo + +class ApsUserInfoHandler(DmDbEntityHandler): + + def __init__(self): + DmDbEntityHandler.__init__(self) + + def getApsUsers(self, session): + dbUserInfos = session.query(ApsUserInfo).all() + return dbUserInfos + + def getApsUserByBadgeNumber(self, session, badgeNumber): + try: + dbUserInfo = session.query(ApsUserInfo).filter(ApsUserInfo.badge_no==badgeNumber).one() + return dbUserInfo + except NoResultFound, ex: + raise ObjectNotFound('APS user with badge number %s does not exist.' % (badgeNumber)) + diff --git a/src/python/dm/aps_user_db/impl/oracleDbManager.py.working b/src/python/dm/aps_user_db/impl/oracleDbManager.py.working new file mode 100755 index 0000000000000000000000000000000000000000..2dc35ae753287b3a0d1bcdc577ec150df38228e6 --- /dev/null +++ b/src/python/dm/aps_user_db/impl/oracleDbManager.py.working @@ -0,0 +1,222 @@ +#!/usr/bin/env python + +import threading +import os.path +import sqlalchemy +from sqlalchemy.orm import sessionmaker +from sqlalchemy.orm import mapper +from sqlalchemy.orm import relationship + +from dm.common.exceptions.commandFailed import CommandFailed +from dm.common.exceptions.configurationError import ConfigurationError +from dm.common.utility.loggingManager import LoggingManager +from dm.common.utility.configurationManager import ConfigurationManager +from dm.common.oracle.entities import oracleDbEntityMap + + +class OracleDbManager: + """ Singleton class for db management. """ + + DB_CONNECTION_POOL_SIZE = 10 + DB_CONNECTION_POOL_MAX_OVERFLOW = 2 + DB_CONNECTION_POOL_RECYCYLE_TIME = 600 + DB_CONNECTION_POOL_TIMEOUT = 60 + DB_CONNECTION_LOGGING_FLAG = False + + CONFIG_SECTION_NAME = 'OracleDbManager' + CONFIG_OPTION_NAME_LIST = [ 'dbSchema', 'dbUser', 'dbPasswordFile' ] + + # Singleton. + __lock = threading.RLock() + __instance = None + + @classmethod + def getInstance(cls): + from dm.common.oracle.impl.oracleDbManager import OracleDbManager + try: + mgr = OracleDbManager() + except OracleDbManager, ex: + mgr = ex + return mgr + + def __init__(self): + OracleDbManager.__lock.acquire() + try: + if OracleDbManager.__instance is not None: + raise OracleDbManager.__instance + OracleDbManager.__instance = self + self.lock = threading.RLock() + self.logger = LoggingManager.getInstance().getLogger(self.__class__.__name__) + cm = ConfigurationManager.getInstance() + #cm.setOptionsFromConfigFile(OracleDbManager.CONFIG_SECTION_NAME, OracleDbManager.CONFIG_OPTION_NAME_LIST) + + #dbUser = cm.getDbUser() + #self.logger.debug('Using DB user: %s' % dbUser) + #dbSchema = cm.getDbSchema() + #dbPasswordFile = cm.getDbPasswordFile() + #self.logger.debug('Using DB password file: %s' % dbPasswordFile) + #dbPassword = open(dbPasswordFile, 'r').readline().strip() + #dbPort = cm.getDbPort() + #dbHost = cm.getDbHost() + #db = cm.getDb() + db = "oracle" + dbPort = 1527 + dbHost = "ra.aps.anl.gov" + dbSchema = "aps1" + dbUser = "glob_conn" + dbPassword = "ur2ytkownicy2u" + #self.logger.debug('DB schema: %s' % dbSchema) + #self.logger.debug('DB password file: %s' % dbPasswordFile) + engineUrl = '%s://%s:%s@%s:%s/%s' % (db, dbUser, dbPassword, dbHost, dbPort, dbSchema) + self.logger.debug('Using engine URL: %s' % engineUrl) + self.engine = sqlalchemy.create_engine(engineUrl, + pool_size=OracleDbManager.DB_CONNECTION_POOL_SIZE, + max_overflow=OracleDbManager.DB_CONNECTION_POOL_MAX_OVERFLOW, + pool_recycle=OracleDbManager.DB_CONNECTION_POOL_RECYCYLE_TIME, + echo=OracleDbManager.DB_CONNECTION_LOGGING_FLAG, + pool_timeout=OracleDbManager.DB_CONNECTION_POOL_TIMEOUT) + self.metadata = sqlalchemy.MetaData(engineUrl, schema='DCC') + print self.metadata + # 'DCC.FL$03_BL_APV_VIEW_V2' + self.metadata.reflect(self.engine, schema='DCC') + print self.metadata.tables + print self.metadata.__dict__ + view = sqlalchemy.Table('FL$03_BL_APV_VIEW_V2', self.metadata, autoload=True) #, schema='DCC') + print 'VIEW:', view.__dict__ + view.c.badge_no.primary_key=True + #view.c.last_name.primary_key=True + for column in view.columns: + self.logger.debug('Column: %s' % column.name) + self.logger.debug('%s' % column.__dict__) + + self.logger.debug('Mapping DB tables') + from dm.common.oracle.entities.oracleUserInfo import OracleUserInfo + #mapper(OracleUserInfo, view, primary_key=[view.c.last_name]) + mapper(OracleUserInfo, view, primary_key=[view.c.badge_no]) + #for (dbTableName, (dbEntityClass, dbRelationDict)) in oracleDbEntityMap.ORACLE_DB_ENTITY_MAP.items(): + # self.mapTable(dbEntityClass, dbTableName, dbRelationDict) + self.logger.debug('Initialized SQLalchemy engines') + + finally: + OracleDbManager.__lock.release() + + def getLogger(self): + return self.logger + + def inspectTables(self): + from sqlalchemy import inspect + inspector = inspect(self.engine) + self.logger.debug('Inspecting tables') + for tableName in inspector.get_table_names(): + self.logger.debug('Table: %s' % tableName) + for column in inspector.get_columns(tableName): + self.logger.debug('Column: %s' % column['name']) + + def inspectTables2(self): + from sqlalchemy import MetaData + m = MetaData() + m.reflect(self.engine) + self.logger.debug('Inspecting tables via metadata') + for table in m.tables.values(): + self.logger.debug('Table: %s' % table.name) + for column in table.c: + self.logger.debug('Column: %s' % column.name) + + def initTable(self, tableClass, tableName): + """ Initialize DB table. """ + self.lock.acquire() + try: + tbl = sqlalchemy.Table(tableName, self.metadata, autoload=True) + tableClass.columns = tbl.columns + return tbl + finally: + self.lock.release() + + def mapTable(self, tableClass, tableName, relationDict): + """ Map DB table to a given class. """ + self.lock.acquire() + try: + table = sqlalchemy.Table(tableName, self.metadata, autoload=True) + tableClass.columns = table.columns + + # Build relations from specified foreign key columns and other properties. + tableRelations = {} + primaryKey = None + for (name, propertyDict) in relationDict.items(): + if name == 'self': + primaryKey = propertyDict.get('primary_key') + continue + lazy = propertyDict.get('lazy') + parentEntity = propertyDict.get('parentEntity') + foreignKeyColumns = propertyDict.get('foreignKeyColumns', []) + if len(foreignKeyColumns): + fkList = [] + for fk in foreignKeyColumns: + fkList.append(table.columns.get(fk)) + tableRelations[name] = relationship(parentEntity, foreign_keys=fkList, lazy=lazy) + else: + tableRelations[name] = relationship(parentEntity, lazy=lazy) + + if primaryKey: + print 'MAPPED PK:', table.columns.get(primaryKey) + mapper(tableClass, table, tableRelations, primary_key=table.columns.get(primaryKey)) + else: + mapper(tableClass, table, tableRelations) + return table + finally: + self.lock.release() + + def getMetadataTable(self, table): + return self.metadata.tables[table] + + def openSession(self): + """ Open db session. """ + self.lock.acquire() + try: + Session = sessionmaker(bind=self.engine) + return Session() + finally: + self.lock.release() + + def closeSession(self, session): + """ Close db session. """ + self.lock.acquire() + try: + session.close() + finally: + self.lock.release() + + def acquireConnection(self): + """ Get db connection. """ + self.lock.acquire() + try: + return self.engine.connect() + finally: + self.lock.release() + + def releaseConnection(self, connection): + """ Release db connection. """ + self.lock.acquire() + try: + if connection: + connection.close() + finally: + self.lock.release() + +####################################################################### +# Testing. +if __name__ == '__main__': + ConfigurationManager.getInstance().setConsoleLogLevel('debug') + mgr = OracleDbManager.getInstance() + mgr.acquireConnection() + mgr.inspectTables() + mgr.inspectTables2() + print 'Got connection' + from oracleUserInfoHandler import OracleUserInfoHandler + handler = OracleUserInfoHandler() + session = mgr.openSession() + users = handler.getUsers(session) + for u in users: + print u.badge_no, u.last_name + + diff --git a/src/python/dm/common/objects/apsUserInfo.py b/src/python/dm/common/objects/apsUserInfo.py new file mode 100755 index 0000000000000000000000000000000000000000..832288759fb74a176bafc2b03f44ac877c0222d2 --- /dev/null +++ b/src/python/dm/common/objects/apsUserInfo.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python + +from dmObject import DmObject + +class ApsUserInfo(DmObject): + + DEFAULT_KEY_LIST = [ 'id', 'badgeNumber', 'firstName', 'middleName', 'lastName', 'email' ] + + def __init__(self, dict): + DmObject.__init__(self, dict) +