class PatchedDirectory (FileMeta): ftype = fs.DIRECTORY EXISTING = 0 ADDED = 1 REMOVED = 2 def __init__(self, name, parent, uid, gid, mode, mtime_ns): FileMeta.__init__(self, name, parent, uid, gid, mode, mtime_ns) self.adds = PersistentMapping() self.removes = PersistentMapping() self.meta_changes = PersistentMapping() # name => ((to_uid, to_gid, to_mode), (from_uid, from_gid, from_mode)) self.subdirs = PersistentMapping() self.state = PatchedDirectory.EXISTING def pdbg(self, indent = ''): s = { 0 : 'EXISTING', 1 : 'ADDED', 2 : 'REMOVED' } print indent, 'Dir %s %s' % (s[self.state], self.dbg_meta()) if self.adds: print indent, ' ** Adds **' for v in self.adds.itervalues(): v.pdbg( indent + ' ' ) if self.removes: print indent, ' ** Removes **' for v in self.removes.itervalues(): v.pdbg( indent + ' ' ) if self.meta_changes: print indent, ' ** Meta Mods **' for k, v in self.removes.iteritems(): print indent + ' ', k, v for s in self.subdirs.itervalues(): s.pdbg( indent + ' ' )
class Directory (FileMeta): ftype = fs.DIRECTORY def __init__(self, name, parent, uid, gid, mode, mtime_ns): FileMeta.__init__(self, name, parent, uid, gid, mode, mtime_ns) self.content = PersistentMapping() def get_content_set(self): return set( (v.name, v.ftype) for v in self.content.itervalues() ) def get_meta_set(self, filenames): s = set() for fn in filenames: v = self.content[ fn ] s.add( (v.name, v.uid, v.gid, v.mode) ) return s
def checkBasicOps(self): from persistent.mapping import PersistentMapping m = PersistentMapping({'x': 1}, a=2, b=3) m['name'] = 'bob' self.assertEqual(m['name'], "bob") self.assertEqual(m.get('name', 42), "bob") self.assert_('name' in m) try: m['fred'] except KeyError: pass else: self.fail("expected KeyError") self.assert_('fred' not in m) self.assertEqual(m.get('fred'), None) self.assertEqual(m.get('fred', 42), 42) keys = m.keys() keys.sort() self.assertEqual(keys, ['a', 'b', 'name', 'x']) values = m.values() values.sort() self.assertEqual(values, [1, 2, 3, 'bob']) items = m.items() items.sort() self.assertEqual(items, [('a', 2), ('b', 3), ('name', 'bob'), ('x', 1)]) keys = list(m.iterkeys()) keys.sort() self.assertEqual(keys, ['a', 'b', 'name', 'x']) values = list(m.itervalues()) values.sort() self.assertEqual(values, [1, 2, 3, 'bob']) items = list(m.iteritems()) items.sort() self.assertEqual(items, [('a', 2), ('b', 3), ('name', 'bob'), ('x', 1)])
def checkBasicOps(self): from persistent.mapping import PersistentMapping m = PersistentMapping({"x": 1}, a=2, b=3) m["name"] = "bob" self.assertEqual(m["name"], "bob") self.assertEqual(m.get("name", 42), "bob") self.assert_("name" in m) try: m["fred"] except KeyError: pass else: self.fail("expected KeyError") self.assert_("fred" not in m) self.assertEqual(m.get("fred"), None) self.assertEqual(m.get("fred", 42), 42) keys = m.keys() keys.sort() self.assertEqual(keys, ["a", "b", "name", "x"]) values = m.values() values.sort() self.assertEqual(values, [1, 2, 3, "bob"]) items = m.items() items.sort() self.assertEqual(items, [("a", 2), ("b", 3), ("name", "bob"), ("x", 1)]) keys = list(m.iterkeys()) keys.sort() self.assertEqual(keys, ["a", "b", "name", "x"]) values = list(m.itervalues()) values.sort() self.assertEqual(values, [1, 2, 3, "bob"]) items = list(m.iteritems()) items.sort() self.assertEqual(items, [("a", 2), ("b", 3), ("name", "bob"), ("x", 1)])
class Book( Persistent ): ''' This is a user book to include user's orders, one per user ''' def __init__(self, user=None): self.user = user self.orders = PersistentList() self.positions = PersistentMapping() def addOrder(self, order): if order.instrument in self.positions: self.positions[order.instrument].append(order) else: self.positions[order.instrument] = PersistentList(order) def cost(self): cost=0.0 for orders in self.positions.itervalues(): cost += sum([o.cost() for o in orders]) return def marketValue(self): mktval = 0.0 for inst, orders in self.positions.iteritems(): mktval += inst.marketPrice * sum([o.amountMatched for o in orders]) return mktval
class Room( Persistent, RoomBase, Fossilizable ): """ ZODB specific implementation. For documentation of methods see base class. """ fossilizes(IRoomMapFossil, IRoomCalendarFossil) __dalManager = Factory.getDALManager() vcList = [] def __init__(self): RoomBase.__init__( self ) self.customAtts = PersistentMapping() self.avaibleVC = [] self._nonBookableDates = [] def getNonBookableDates(self): try: if self._nonBookableDates: pass except AttributeError: self._nonBookableDates = [] self._p_changed = 1 return self._nonBookableDates def addNonBookableDate(self, udate): self._nonBookableDates.append(udate) self._p_changed = 1 def addNonBookableDateFromParams(self, params): nbd = NonBookableDate(params["startDate"], params["endDate"]) self._nonBookableDates.append(nbd) self._p_changed = 1 def clearNonBookableDates(self): self._nonBookableDates = [] self._p_changed = 1 def isNonBookableDay(self, day): for nbd in self.getNonBookableDates(): if nbd.doesDayOverlap(day): return True return False def getBlockedDay(self, day): blockings = Factory.newRoomBlocking().getByDate(day) for bl in blockings: rbl = bl.getBlockedRoom(self) if rbl and rbl.active is not False: return rbl return None def setAvailableVC(self, avc): self.avaibleVC = avc def getAvailableVC(self): try: return self.avaibleVC except: self.avaibleVC = [] return self.avaibleVC @staticmethod def getRoot(): return Room.__dalManager.getRoot(_ROOMS) def getAllManagers(self): managers = set([self.getResponsible()]) if self.customAtts.get('Simba List'): groups = GroupHolder().match({'name': self.customAtts['Simba List']}, exact=True, forceWithoutExtAuth=True) if not groups: groups = GroupHolder().match({'name': self.customAtts['Simba List']}, exact=True) if groups and len(groups) == 1: managers |= set(groups[0].getMemberList()) return list(managers) def insert( self ): """ Documentation in base class. """ RoomBase.insert( self ) roomsBTree = Room.getRoot() # Ensure ID if self.id == None: # Maximum ID + 1 if len( roomsBTree ) > 0: self.id = roomsBTree.maxKey() + 1 else: self.id = 1 # Can not use maxKey for 1st record in a tree # Add self to the BTree roomsBTree[self.id] = self Catalog.getIdx('user_room').index_obj(self.guid) def update( self ): """ Documentation in base class. """ RoomBase.update( self ) # Check Simba mailing list listName = self.customAtts.get( 'Simba List' ) if listName: from MaKaC.user import GroupHolder groups = GroupHolder().match( { 'name': listName }, forceWithoutExtAuth = True ) if not groups: groups = GroupHolder().match( { 'name': listName } ) if not groups: self.customAtts['Simba List'] = 'Error: unknown mailing list' # reindex - needed due to possible manager changes # super slow, though... Catalog.getIdx('user_room').unindex_obj(self.guid) Catalog.getIdx('user_room').index_obj(self.guid) self._p_changed = True def remove( self ): """ Documentation in base class. """ RoomBase.remove( self ) roomsBTree = Room.getRoot() del roomsBTree[self.id] Catalog.getIdx('user_room').unindex_obj(self.guid) @classmethod def isAvatarResponsibleForRooms(cls, avatar): return Catalog.getIdx('user_room').get(avatar.getId()) is not None @classmethod def getUserRooms(cls, avatar): return Catalog.getIdx('user_room').get(avatar.getId()) # Typical actions @staticmethod def getRooms( *args, **kwargs ): """ Documentation in base class. """ roomsBTree = Room.getRoot() location = kwargs.get( 'location' ) if kwargs.get( 'allFast' ) == True: return [ room for room in roomsBTree.values() if room.isActive and (not location or room.locationName == location) ] if kwargs.get( 'reallyAllFast' ) == True: return [ room for room in roomsBTree.values() if (not location or room.locationName == location) ] if len( kwargs ) == 0: ret_lst = [] for room in roomsBTree.values(): ret_lst.append( room ) roomID = kwargs.get( 'roomID' ) roomName = kwargs.get( 'roomName' ) roomEx = kwargs.get( 'roomExample' ) resvEx = kwargs.get( 'resvExample' ) freeText = kwargs.get( 'freeText' ) available = kwargs.get( 'available' ) countOnly = kwargs.get( 'countOnly' ) minCapacity = kwargs.get( 'minCapacity' ) location = kwargs.get( 'location' ) ownedBy = kwargs.get( 'ownedBy' ) customAtts = kwargs.get( 'customAtts' ) # responsibleID = kwargs.get( 'responsibleID' ) pendingBlockings = kwargs.get( 'pendingBlockings' ) ret_lst = [] counter = 0 if roomID != None: return roomsBTree.get( roomID ) if roomName != None: for room in roomsBTree.itervalues(): if room.name == roomName: if location == None or room.locationName == location: return room return None for room in roomsBTree.itervalues(): # Apply all conditions ========= if location != None: if room.locationName != location: continue if roomEx != None: if not qbeMatch( roomEx, room, Room.__attrSpecialEqual, minCapacity = minCapacity ): continue if not room.__hasEquipment( roomEx.getEquipment() ): continue if freeText != None: if not room.__hasFreeText( freeText.split() ): continue if resvEx != None: resvEx.room = room aval = room.isAvailable( resvEx ) if aval != available: continue blockState = resvEx.getBlockingConflictState(ContextManager.get('currentUser')) if blockState == 'active': continue elif blockState == 'pending' and pendingBlockings: continue if ownedBy != None: if not room.isOwnedBy( ownedBy ): continue if customAtts is not None: if not hasattr(room, "customAtts"): continue discard = False for condition in customAtts: attName = condition["name"] allowEmpty = condition.get("allowEmpty", False) filter = condition.get("filter", None) if not attName in room.customAtts: discard = True break elif not allowEmpty and str(room.customAtts[attName]).strip() == "": discard = True break elif not filter(room.customAtts[attName]): discard = True break if discard: continue # All conditions are met: add room to the results counter += 1 if not countOnly: ret_lst.append( room ) #print "Found %d rooms." % counter if countOnly: return counter else: return ret_lst # Statistics ==================================== @staticmethod def countRooms( *args, **kwargs ): """ Documentation in base class. """ kwargs['countOnly'] = True return Room.getRooms( **kwargs ) @staticmethod def getNumberOfRooms( *args, **kwargs ): """ Documentation in base class. """ location = kwargs.get( 'location', Location.getDefaultLocation().friendlyName ) return Room.countRooms( location = location ) @staticmethod def getNumberOfActiveRooms( *args, **kwargs ): """ Documentation in base class. """ location = kwargs.get( 'location', Location.getDefaultLocation().friendlyName ) room = Factory.newRoom() room.isActive = True return Room.countRooms( roomExample = room, location = location ) @staticmethod def getNumberOfReservableRooms( *args, **kwargs ): """ Documentation in base class. """ location = kwargs.get( 'location', Location.getDefaultLocation().friendlyName ) room = Factory.newRoom() room.isReservable = True room.isActive = True return Room.countRooms( roomExample = room, location = location ) def getLocationName( self ): #from MaKaC.plugins.RoomBooking.default.factory import Factory #return Factory.locationName return self._locationName def setLocationName( self, locationName ): self._locationName = locationName def savePhoto( self, photoPath ): filePath = Config.getInstance().getRoomPhotosDir() fileName = self._doGetPhotoId( force = True ) + ".jpg" try: os.makedirs( filePath ) except: pass fullPath = os.path.join( filePath, fileName ) f = open( fullPath, "wb" ) f.write( photoPath.file.read() ) f.close() def saveSmallPhoto( self, photoPath ): filePath = Config.getInstance().getRoomSmallPhotosDir() fileName = self._doGetPhotoId( force = True ) + ".jpg" try: os.makedirs( filePath ) except: pass fullPath = os.path.join( filePath, fileName ) f = open( fullPath, "wb" ) f.write( photoPath.file.read() ) f.close() # ==== Private =================================================== def _getSafeLocationName( self ): if self.locationName == None: return None s = "" for i in xrange( 0, len( self.locationName ) ): code = ord( self.locationName[i] ) if ( code in xrange( ord( 'a' ), ord( 'z' ) + 1 ) ) or \ ( code in xrange( ord( 'A' ), ord( 'Z' ) + 1 ) ) or \ ( code in xrange( ord( '0' ), ord( '9' ) + 1 ) ): # Valid s += self.locationName[i] else: s += '_' # Replace all other characters with underscore return s def _doGetPhotoId( self, force = False ): photoId = "%s-%s-%s-%s" % ( str( self._getSafeLocationName() ), str( self.building ).strip(), str( self.floor ).strip(), str( self.roomNr ).strip() ) filePath = Config.getInstance().getRoomPhotosDir() fileName = photoId + ".jpg" fullPath = os.path.join( filePath, fileName ) from os.path import exists if exists( fullPath ) or force: return photoId else: return None def _doSetPhotoId( self ): """ For this plugin, photoId is always composed of location-building-floor-room.jpg """ pass def __hasFreeText( self, freeTextList ): # OR for freeText in freeTextList: freeText = freeText.lower() if self.__hasOneFreeText( freeText ): return True return False def __hasOneFreeText( self, freeText ): # Look for freeText in all string and int attributes for attrName in dir( self ): if attrName[0] == '_': continue attrType = eval( 'self.' + attrName + '.__class__.__name__' ) if attrType == 'str': attrVal = eval( 'self.' + attrName ) if attrVal.lower().find( freeText ) != -1: return True # Look for freeText in equipment if self.__hasEquipment( [ freeText ] ): return True # Look for freeText in responsible if self.responsibleId != None: user = self.getResponsible(); if freeText in user.getFullName().lower() or freeText in user.getEmail().lower(): return True # Look for freeText in custom attributes for value in self.customAtts.itervalues(): if value and ( freeText in value.lower() ): return True # Not found return False @staticmethod def __goodCapacity( val1, val2, minCapacity = None ): # Difference in capacity less than 20% if val1 < 1: val1 = 1 if not minCapacity: return abs( val1 - val2 ) / float( val1 ) <= 0.2 else: return val2 > val1 @classmethod def __attrSpecialEqual( cls, attrName, exampleVal, candidateVal, **kwargs ): if attrName in ( 'guid', 'locationName', 'name', 'photoId', 'needsAVCSetup' ): return True # Skip by stating they match if attrName in ( 'responsibleId', 'responsibleID' ): return exampleVal == candidateVal # Just exact string matching if attrName[0:7] == 'verbose': return True if attrName.find( 'capacity' ) != -1: minCapacity = kwargs.get( 'minCapacity' ) return cls.__goodCapacity( exampleVal, candidateVal, minCapacity ) if attrName == 'customAtts': # Check if all values in exampleVal are contained # in corresponding values of candidateVal for k, v in exampleVal.iteritems(): if v: # If value is specified if candidateVal.get( k ) == None: # Candidate does not have the attribute return False if not ( v in candidateVal[k] ): # Candidate's attribute value does not match example return False return True return None def __hasEquipment( self, requiredEquipmentList ): iHave = self.getEquipment() for reqEq in requiredEquipmentList: have = False for myEq in iHave: if myEq.lower().find( reqEq.lower() ) != -1: have = True break if not have: return False return True def getBookingUrl(self): """ Room booking URL """ return str(urlHandlers.UHRoomBookingBookingForm.getURL(target=self)) def getDetailsUrl(self): """ Room details URL """ return str(urlHandlers.UHRoomBookingRoomDetails.getURL(target=self)) def getMarkerDescription(self): """ Room description for the map marker """ infos = [] if self.capacity: infos.append("%s %s" % (self.capacity , _("people"))) if self.isReservable: infos.append(_("public")) else: infos.append(_("private")) if self.resvsNeedConfirmation: infos.append(_("needs confirmation")) else: infos.append(_("auto-confirmation")) if self.needsAVCSetup: infos.append(_("video conference")) return ", ".join(infos) def getTipPhotoURL(self): """ URL of the tip photo of the room """ from MaKaC.webinterface.urlHandlers import UHRoomPhoto photoId = self._doGetPhotoId() if not photoId: photoId = "NoPhoto" return str(UHRoomPhoto.getURL(photoId)) def getIsAutoConfirm(self): """ Has the room auto-confirmation of schedule? """ return not self.resvsNeedConfirmation locationName = property( getLocationName, setLocationName )
class Room( Persistent, RoomBase, Fossilizable ): """ ZODB specific implementation. For documentation of methods see base class. """ fossilizes(IRoomMapFossil, IRoomCalendarFossil) __dalManager = Factory.getDALManager() vcList = [] def __init__(self): RoomBase.__init__( self ) self.customAtts = PersistentMapping() self.avaibleVC = [] self._nonBookableDates = [] def getNonBookableDates(self): try: if self._nonBookableDates: pass except AttributeError: self._nonBookableDates = [] self._p_changed = 1 return self._nonBookableDates def addNonBookableDate(self, udate): self._nonBookableDates.append(udate) self._p_changed = 1 def addNonBookableDateFromParams(self, params): nbd = NonBookableDate(params["startDate"], params["endDate"]) self._nonBookableDates.append(nbd) self._p_changed = 1 def clearNonBookableDates(self): self._nonBookableDates = [] self._p_changed = 1 def isNonBookableDay(self, day): for nbd in self.getNonBookableDates(): if nbd.doesDayOverlap(day): return True return False def getBlockedDay(self, day): blockings = Factory.newRoomBlocking().getByDate(day) for bl in blockings: rbl = bl.getBlockedRoom(self) if rbl and rbl.active is not False: return rbl return None def setAvailableVC(self, avc): self.avaibleVC = avc def getAvailableVC(self): try: return self.avaibleVC except: self.avaibleVC = [] return self.avaibleVC @staticmethod def getRoot(): return Room.__dalManager.getRoot(_ROOMS) def getAllManagers(self): managers = set([self.getResponsible()]) if self.customAtts.get('Simba List'): groups = GroupHolder().match({'name': self.customAtts['Simba List']}, exact=True, forceWithoutExtAuth=True) if not groups: groups = GroupHolder().match({'name': self.customAtts['Simba List']}, exact=True) if groups and len(groups) == 1: managers |= set(groups[0].getMemberList()) return list(managers) def insert( self ): """ Documentation in base class. """ RoomBase.insert( self ) roomsBTree = Room.getRoot() # Ensure ID if self.id == None: # Maximum ID + 1 if len( roomsBTree ) > 0: self.id = roomsBTree.maxKey() + 1 else: self.id = 1 # Can not use maxKey for 1st record in a tree # Add self to the BTree roomsBTree[self.id] = self Catalog.getIdx('user_room').index_obj(self.guid) def update( self ): """ Documentation in base class. """ RoomBase.update( self ) # Check Simba mailing list listName = self.customAtts.get( 'Simba List' ) if listName: from MaKaC.user import GroupHolder groups = GroupHolder().match( { 'name': listName }, forceWithoutExtAuth = True ) if not groups: groups = GroupHolder().match( { 'name': listName } ) if not groups: self.customAtts['Simba List'] = 'Error: unknown mailing list' # reindex - needed due to possible manager changes # super slow, though... Catalog.getIdx('user_room').unindex_obj(self.guid) Catalog.getIdx('user_room').index_obj(self.guid) self._p_changed = True def remove( self ): """ Documentation in base class. """ RoomBase.remove( self ) roomsBTree = Room.getRoot() del roomsBTree[self.id] if Catalog.getIdx('user_room').has_obj(self.guid): Catalog.getIdx('user_room').unindex_obj(self.guid) @classmethod def isAvatarResponsibleForRooms(cls, avatar): return Catalog.getIdx('user_room').get(avatar.getId()) is not None @classmethod def getUserRooms(cls, avatar): return Catalog.getIdx('user_room').get(avatar.getId()) # Typical actions @staticmethod def getRooms( *args, **kwargs ): """ Documentation in base class. """ roomsBTree = Room.getRoot() location = kwargs.get( 'location' ) if kwargs.get( 'allFast' ) == True: return [ room for room in roomsBTree.values() if room.isActive and (not location or room.locationName == location) ] if kwargs.get( 'reallyAllFast' ) == True: return [ room for room in roomsBTree.values() if (not location or room.locationName == location) ] if len( kwargs ) == 0: ret_lst = [] for room in roomsBTree.values(): ret_lst.append( room ) roomID = kwargs.get( 'roomID' ) roomName = kwargs.get( 'roomName' ) roomEx = kwargs.get( 'roomExample' ) resvEx = kwargs.get( 'resvExample' ) freeText = kwargs.get( 'freeText' ) available = kwargs.get( 'available' ) countOnly = kwargs.get( 'countOnly' ) minCapacity = kwargs.get( 'minCapacity' ) location = kwargs.get( 'location' ) ownedBy = kwargs.get( 'ownedBy' ) customAtts = kwargs.get( 'customAtts' ) # responsibleID = kwargs.get( 'responsibleID' ) pendingBlockings = kwargs.get( 'pendingBlockings' ) ret_lst = [] counter = 0 if roomID != None: return roomsBTree.get( roomID ) if roomName != None: for room in roomsBTree.itervalues(): if room.name == roomName: if location == None or room.locationName == location: return room return None for room in roomsBTree.itervalues(): # Apply all conditions ========= if location != None: if room.locationName != location: continue if roomEx != None: if not qbeMatch( roomEx, room, Room.__attrSpecialEqual, minCapacity = minCapacity ): continue if not room.__hasEquipment( roomEx.getEquipment() ): continue if freeText != None: if not room.__hasFreeText( freeText.split() ): continue if resvEx != None: resvEx.room = room aval = room.isAvailable( resvEx ) if aval != available: continue blockState = resvEx.getBlockingConflictState(ContextManager.get('currentUser')) if blockState == 'active': continue elif blockState == 'pending' and pendingBlockings: continue if ownedBy != None: if not room.isOwnedBy( ownedBy ): continue if customAtts is not None: if not hasattr(room, "customAtts"): continue discard = False for condition in customAtts: attName = condition["name"] allowEmpty = condition.get("allowEmpty", False) filter = condition.get("filter", None) if not attName in room.customAtts: discard = True break elif not allowEmpty and str(room.customAtts[attName]).strip() == "": discard = True break elif not filter(room.customAtts[attName]): discard = True break if discard: continue # All conditions are met: add room to the results counter += 1 if not countOnly: ret_lst.append( room ) #print "Found %d rooms." % counter if countOnly: return counter else: return ret_lst # Statistics ==================================== @staticmethod def countRooms( *args, **kwargs ): """ Documentation in base class. """ kwargs['countOnly'] = True return Room.getRooms( **kwargs ) @staticmethod def getNumberOfRooms( *args, **kwargs ): """ Documentation in base class. """ location = kwargs.get( 'location', Location.getDefaultLocation().friendlyName ) return Room.countRooms( location = location ) @staticmethod def getNumberOfActiveRooms( *args, **kwargs ): """ Documentation in base class. """ location = kwargs.get( 'location', Location.getDefaultLocation().friendlyName ) room = Factory.newRoom() room.isActive = True return Room.countRooms( roomExample = room, location = location ) @staticmethod def getNumberOfReservableRooms( *args, **kwargs ): """ Documentation in base class. """ location = kwargs.get( 'location', Location.getDefaultLocation().friendlyName ) room = Factory.newRoom() room.isReservable = True room.isActive = True return Room.countRooms( roomExample = room, location = location ) def getLocationName( self ): #from MaKaC.plugins.RoomBooking.default.factory import Factory #return Factory.locationName return self._locationName def setLocationName( self, locationName ): self._locationName = locationName def savePhoto( self, photoPath ): filePath = Config.getInstance().getRoomPhotosDir() fileName = self._doGetPhotoId( force = True ) + ".jpg" try: os.makedirs( filePath ) except: pass fullPath = os.path.join( filePath, fileName ) f = open( fullPath, "wb" ) f.write( photoPath.file.read() ) f.close() def saveSmallPhoto( self, photoPath ): filePath = Config.getInstance().getRoomSmallPhotosDir() fileName = self._doGetPhotoId( force = True ) + ".jpg" try: os.makedirs( filePath ) except: pass fullPath = os.path.join( filePath, fileName ) f = open( fullPath, "wb" ) f.write( photoPath.file.read() ) f.close() # ==== Private =================================================== def _getSafeLocationName( self ): if self.locationName == None: return None s = "" for i in xrange( 0, len( self.locationName ) ): code = ord( self.locationName[i] ) if ( code in xrange( ord( 'a' ), ord( 'z' ) + 1 ) ) or \ ( code in xrange( ord( 'A' ), ord( 'Z' ) + 1 ) ) or \ ( code in xrange( ord( '0' ), ord( '9' ) + 1 ) ): # Valid s += self.locationName[i] else: s += '_' # Replace all other characters with underscore return s def _doGetPhotoId( self, force = False ): photoId = "%s-%s-%s-%s" % ( str( self._getSafeLocationName() ), str( self.building ).strip(), str( self.floor ).strip(), str( self.roomNr ).strip() ) filePath = Config.getInstance().getRoomPhotosDir() fileName = photoId + ".jpg" fullPath = os.path.join( filePath, fileName ) from os.path import exists if exists( fullPath ) or force: return photoId else: return None def _doSetPhotoId( self ): """ For this plugin, photoId is always composed of location-building-floor-room.jpg """ pass def __hasFreeText( self, freeTextList ): # OR for freeText in freeTextList: freeText = freeText.lower() if self.__hasOneFreeText( freeText ): return True return False def __hasOneFreeText( self, freeText ): # Look for freeText in all string and int attributes for attrName in dir( self ): if attrName[0] == '_': continue attrType = eval( 'self.' + attrName + '.__class__.__name__' ) if attrType == 'str': attrVal = eval( 'self.' + attrName ) if attrVal.lower().find( freeText ) != -1: return True # Look for freeText in equipment if self.__hasEquipment( [ freeText ] ): return True # Look for freeText in responsible if self.responsibleId != None: user = self.getResponsible(); if freeText in user.getFullName().lower() or freeText in user.getEmail().lower(): return True # Look for freeText in custom attributes for value in self.customAtts.itervalues(): if value and ( freeText in value.lower() ): return True # Not found return False @staticmethod def __goodCapacity( val1, val2, minCapacity = None ): # Difference in capacity less than 20% if val1 < 1: val1 = 1 if not minCapacity: return abs( val1 - val2 ) / float( val1 ) <= 0.2 else: return val2 > val1 @classmethod def __attrSpecialEqual( cls, attrName, exampleVal, candidateVal, **kwargs ): if attrName in ( 'guid', 'locationName', 'name', 'photoId', 'needsAVCSetup' ): return True # Skip by stating they match if attrName in ( 'responsibleId', 'responsibleID' ): return exampleVal == candidateVal # Just exact string matching if attrName[0:7] == 'verbose': return True if attrName.find( 'capacity' ) != -1: minCapacity = kwargs.get( 'minCapacity' ) return cls.__goodCapacity( exampleVal, candidateVal, minCapacity ) if attrName == 'customAtts': # Check if all values in exampleVal are contained # in corresponding values of candidateVal for k, v in exampleVal.iteritems(): if v: # If value is specified if candidateVal.get( k ) == None: # Candidate does not have the attribute return False if not ( v in candidateVal[k] ): # Candidate's attribute value does not match example return False return True return None def __hasEquipment( self, requiredEquipmentList ): iHave = self.getEquipment() for reqEq in requiredEquipmentList: have = False for myEq in iHave: if myEq.lower().find( reqEq.lower() ) != -1: have = True break if not have: return False return True def getBookingUrl(self): """ Room booking URL """ return str(urlHandlers.UHRoomBookingBookingForm.getURL(target=self)) def getDetailsUrl(self): """ Room details URL """ return str(urlHandlers.UHRoomBookingRoomDetails.getURL(target=self)) def getMarkerDescription(self): """ Room description for the map marker """ infos = [] if self.capacity: infos.append("%s %s" % (self.capacity , _("people"))) if self.isReservable: infos.append(_("public")) else: infos.append(_("private")) if self.resvsNeedConfirmation: infos.append(_("needs confirmation")) else: infos.append(_("auto-confirmation")) if self.needsAVCSetup: infos.append(_("video conference")) return ", ".join(infos) def getTipPhotoURL(self): """ URL of the tip photo of the room """ from MaKaC.webinterface.urlHandlers import UHRoomPhoto photoId = self._doGetPhotoId() if not photoId: photoId = "NoPhoto" return str(UHRoomPhoto.getURL(photoId)) def getIsAutoConfirm(self): """ Has the room auto-confirmation of schedule? """ return not self.resvsNeedConfirmation locationName = property( getLocationName, setLocationName )
class Room( Persistent, RoomBase ): """ ZODB specific implementation. For documentation of methods see base class. """ __dalManager = Factory.getDALManager() vcList = [] def __init__(self): RoomBase.__init__( self ) self.customAtts = PersistentMapping() self.avaibleVC = [] def setAvailableVC(self, avc): self.avaibleVC = avc def getAvailableVC(self): try: return self.avaibleVC except: self.avaibleVC = [] return self.avaibleVC @staticmethod def getRoot(): return Room.__dalManager.getRoot(_ROOMS) def insert( self ): """ Documentation in base class. """ RoomBase.insert( self ) roomsBTree = Room.getRoot() # Ensure ID if self.id == None: # Maximum ID + 1 if len( roomsBTree ) > 0: self.id = roomsBTree.maxKey() + 1 else: self.id = 1 # Can not use maxKey for 1st record in a tree # Add self to the BTree roomsBTree[self.id] = self def update( self ): """ Documentation in base class. """ RoomBase.update( self ) # Check Simba mailing list listName = self.customAtts.get( 'Simba List' ) if listName: from MaKaC.user import GroupHolder groups = GroupHolder().match( { 'name': listName }, forceWithoutExtAuth = True ) if not groups: groups = GroupHolder().match( { 'name': listName } ) if not groups: self.customAtts['Simba List'] = 'Error: unknown mailing list' self._p_changed = True def remove( self ): """ Documentation in base class. """ RoomBase.remove( self ) roomsBTree = Room.getRoot() del roomsBTree[self.id] from MaKaC.user import AvatarHolder AvatarHolder().invalidateRoomManagerIdList() # Typical actions @staticmethod def getRooms( *args, **kwargs ): """ Documentation in base class. """ roomsBTree = Room.getRoot() location = kwargs.get( 'location' ) if kwargs.get( 'allFast' ) == True: return [ room for room in roomsBTree.values() if room.isActive and (not location or room.locationName == location) ] if kwargs.get( 'reallyAllFast' ) == True: return [ room for room in roomsBTree.values() if (not location or room.locationName == location) ] if len( kwargs ) == 0: ret_lst = [] for room in roomsBTree.values(): ret_lst.append( room ) roomID = kwargs.get( 'roomID' ) roomName = kwargs.get( 'roomName' ) roomEx = kwargs.get( 'roomExample' ) resvEx = kwargs.get( 'resvExample' ) freeText = kwargs.get( 'freeText' ) available = kwargs.get( 'available' ) countOnly = kwargs.get( 'countOnly' ) minCapacity = kwargs.get( 'minCapacity' ) location = kwargs.get( 'location' ) ownedBy = kwargs.get( 'ownedBy' ) customAtts = kwargs.get( 'customAtts' ) # responsibleID = kwargs.get( 'responsibleID' ) ret_lst = [] counter = 0 if roomID != None: return roomsBTree.get( roomID ) if roomName != None: for room in roomsBTree.itervalues(): if room.name == roomName: if location == None or room.locationName == location: return room return None for room in roomsBTree.itervalues(): # Apply all conditions ========= if location != None: if room.locationName != location: continue if roomEx != None: if not qbeMatch( roomEx, room, Room.__attrSpecialEqual, minCapacity = minCapacity ): continue if not room.__hasEquipment( roomEx.getEquipment() ): continue if freeText != None: if not room.__hasFreeText( freeText.split() ): continue if resvEx != None: resvEx.room = room aval = room.isAvailable( resvEx ) if aval != available: continue if ownedBy != None: if not room.isOwnedBy( ownedBy ): continue if customAtts is not None: if not hasattr(room, "customAtts"): continue discard = False for condition in customAtts: attName = condition["name"] allowEmpty = condition.get("allowEmpty", False) filter = condition.get("filter", None) if not attName in room.customAtts: discard = True break elif not allowEmpty and str(room.customAtts[attName]).strip() == "": discard = True break elif not filter(room.customAtts[attName]): discard = True break if discard: continue # All conditions are met: add room to the results counter += 1 if not countOnly: ret_lst.append( room ) #print "Found %d rooms." % counter if countOnly: return counter else: return ret_lst # Statistics ==================================== @staticmethod def countRooms( *args, **kwargs ): """ Documentation in base class. """ kwargs['countOnly'] = True return Room.getRooms( **kwargs ) @staticmethod def getNumberOfRooms( *args, **kwargs ): """ Documentation in base class. """ location = kwargs.get( 'location', Location.getDefaultLocation().friendlyName ) return Room.countRooms( location = location ) @staticmethod def getNumberOfActiveRooms( *args, **kwargs ): """ Documentation in base class. """ location = kwargs.get( 'location', Location.getDefaultLocation().friendlyName ) room = Factory.newRoom() room.isActive = True return Room.countRooms( roomExample = room, location = location ) @staticmethod def getNumberOfReservableRooms( *args, **kwargs ): """ Documentation in base class. """ location = kwargs.get( 'location', Location.getDefaultLocation().friendlyName ) room = Factory.newRoom() room.isReservable = True room.isActive = True return Room.countRooms( roomExample = room, location = location ) def getLocationName( self ): #from MaKaC.plugins.RoomBooking.default.factory import Factory #return Factory.locationName return self._locationName def setLocationName( self, locationName ): self._locationName = locationName def savePhoto( self, photoPath ): filePath = Config.getInstance().getRoomPhotosDir() fileName = self._doGetPhotoId( force = True ) + ".jpg" try: os.makedirs( filePath ) except: pass fullPath = os.path.join( filePath, fileName ) f = open( fullPath, "wb" ) f.write( photoPath.file.read() ) f.close() def saveSmallPhoto( self, photoPath ): filePath = Config.getInstance().getRoomSmallPhotosDir() fileName = self._doGetPhotoId( force = True ) + ".jpg" try: os.makedirs( filePath ) except: pass fullPath = os.path.join( filePath, fileName ) f = open( fullPath, "wb" ) f.write( photoPath.file.read() ) f.close() # ==== Private =================================================== def _getSafeLocationName( self ): if self.locationName == None: return None s = "" for i in xrange( 0, len( self.locationName ) ): code = ord( self.locationName[i] ) if ( code in xrange( ord( 'a' ), ord( 'z' ) + 1 ) ) or \ ( code in xrange( ord( 'A' ), ord( 'Z' ) + 1 ) ) or \ ( code in xrange( ord( '0' ), ord( '9' ) + 1 ) ): # Valid s += self.locationName[i] else: s += '_' # Replace all other characters with underscore return s def _doGetPhotoId( self, force = False ): photoId = "%s-%s-%s-%s" % ( str( self._getSafeLocationName() ), str( self.building ).strip(), str( self.floor ).strip(), str( self.roomNr ).strip() ) filePath = Config.getInstance().getRoomPhotosDir() fileName = photoId + ".jpg" fullPath = os.path.join( filePath, fileName ) from os.path import exists if exists( fullPath ) or force: return photoId else: return None def _doSetPhotoId( self ): """ For this plugin, photoId is always composed of location-building-floor-room.jpg """ pass def __hasFreeText( self, freeTextList ): # OR for freeText in freeTextList: freeText = freeText.lower() if self.__hasOneFreeText( freeText ): return True return False def __hasOneFreeText( self, freeText ): # Look for freeText in all string and int attributes for attrName in dir( self ): if attrName[0] == '_': continue attrType = eval( 'self.' + attrName + '.__class__.__name__' ) if attrType == 'str': attrVal = eval( 'self.' + attrName ) if attrVal.lower().find( freeText ) != -1: return True # Look for freeText in equipment if self.__hasEquipment( [ freeText ] ): return True # Look for freeText in responsible if self.responsibleId != None: user = self.getResponsible(); if freeText in user.getFullName().lower() or freeText in user.getEmail().lower(): return True # Look for freeText in custom attributes for value in self.customAtts.itervalues(): if value and ( freeText in value.lower() ): return True # Not found return False @staticmethod def __goodCapacity( val1, val2, minCapacity = None ): # Difference in capacity less than 20% if val1 < 1: val1 = 1 if not minCapacity: return abs( val1 - val2 ) / float( val1 ) <= 0.2 else: return val2 > val1 @classmethod def __attrSpecialEqual( cls, attrName, exampleVal, candidateVal, **kwargs ): if attrName in ( 'guid', 'locationName', 'name', 'photoId', 'needsAVCSetup' ): return True # Skip by stating they match if attrName in ( 'responsibleId', 'responsibleID' ): return exampleVal == candidateVal # Just exact string matching if attrName[0:7] == 'verbose': return True if attrName.find( 'capacity' ) != -1: minCapacity = kwargs.get( 'minCapacity' ) return cls.__goodCapacity( exampleVal, candidateVal, minCapacity ) if attrName == 'customAtts': # Check if all values in exampleVal are contained # in corresponding values of candidateVal for k, v in exampleVal.iteritems(): if v: # If value is specified if candidateVal.get( k ) == None: # Candidate does not have the attribute return False if not ( v in candidateVal[k] ): # Candidate's attribute value does not match example return False return True return None def __hasEquipment( self, requiredEquipmentList ): iHave = self.getEquipment() for reqEq in requiredEquipmentList: have = False for myEq in iHave: if myEq.lower().find( reqEq.lower() ) != -1: have = True break if not have: return False return True