Exemple #1
0
class DoubleIndex(Index):
    
    def __init__( self, name='' ):
        if name != '':
            self._name = name
        self._words = OOBTree()
        self._ids = OOBTree()
    
    def _addItem( self, value, item ):
        if value != "":
            words = self._words
            if words.has_key(value):
                if item not in words[value]:
                    l = words[value]
                    l.append(item)
                    words[value] = l
            else:
                words[value] = [ item ]
            self.setIndex(words)
            id = self._itemToId(item)
            if self._ids.has_key(value):
                if id not in self._ids[value]:
                    l = self._ids[value]
                    l.append(id)
                    self._ids[value] = l
            else:
                self._ids[value] = [id]
            self._p_changed = 1
            
    def _withdrawItem( self, value, item ):
        if self._words.has_key(value):            
            if item in self._words[value]:
                words = self._words
                l = words[value]
                l.remove(item)
                words[value] = l
                self.setIndex(words)
        id = self._itemToId(item)
        if self._ids.has_key(value):
            if id in self._ids[value]:
                l = self._ids[value]
                l.remove(id)
                self._ids[value] = l
        self._p_changed = 1
    
    def _itemToId(self, item):
        #to be overloaded
        return ""
    
    def initIndex(self):
        self._words = OOBTree()
        self._ids = OOBTree()
        self._p_changed = 1
    
    def getLowerIndex(self):
        if self._words.keys():
            return min(self._words.keys())
        return None
Exemple #2
0
class DoubleIndex(Index):
    def __init__(self, name=''):
        if name != '':
            self._name = name
        self._words = OOBTree()
        self._ids = OOBTree()

    def _addItem(self, value, item):
        if value != "":
            words = self._words
            if words.has_key(value):
                if item not in words[value]:
                    l = words[value]
                    l.append(item)
                    words[value] = l
            else:
                words[value] = [item]
            self.setIndex(words)
            id = self._itemToId(item)
            if self._ids.has_key(value):
                if id not in self._ids[value]:
                    l = self._ids[value]
                    l.append(id)
                    self._ids[value] = l
            else:
                self._ids[value] = [id]
            self._p_changed = 1

    def _withdrawItem(self, value, item):
        if self._words.has_key(value):
            if item in self._words[value]:
                words = self._words
                l = words[value]
                l.remove(item)
                words[value] = l
                self.setIndex(words)
        id = self._itemToId(item)
        if self._ids.has_key(value):
            if id in self._ids[value]:
                l = self._ids[value]
                l.remove(id)
                self._ids[value] = l
        self._p_changed = 1

    def _itemToId(self, item):
        #to be overloaded
        return ""

    def initIndex(self):
        self._words = OOBTree()
        self._ids = OOBTree()
        self._p_changed = 1

    def getLowerIndex(self):
        if self._words.keys():
            return min(self._words.keys())
        return None
Exemple #3
0
class CategoryIndex(Persistent):
    
    def __init__( self ):
        self._idxCategItem = OOBTree()
        
    def dump(self):
        return list(self._idxCategItem.items())
        
    def _indexConfById(self, categid, confid):
        # only the more restrictive setup is taken into account
        categid = str(categid)
        if self._idxCategItem.has_key(categid):
            res = self._idxCategItem[categid]
        else:
            res = []
        res.append(confid)
        self._idxCategItem[categid] = res
        
    def unindexConf(self, conf):
        confid = str(conf.getId())
        self.unindexConfById(confid)
    
    def unindexConfById(self, confid):
        for categid in self._idxCategItem.keys():
            if confid in self._idxCategItem[categid]:
                res = self._idxCategItem[categid]
                res.remove(confid)
                self._idxCategItem[categid] = res
        
    def reindexCateg(self, categ):
        for subcat in categ.getSubCategoryList():
            self.reindexCateg(subcat)
        for conf in categ.getConferenceList():
            self.reindexConf(conf)
        
    def reindexConf(self, conf):
        self.unindexConf(conf)
        self.indexConf(conf)

    def indexConf(self, conf):
        categs = conf.getOwnerPath()
        level = 0 
        for categ in conf.getOwnerPath():
            if conf.getFullVisibility() > level:
                self._indexConfById(categ.getId(),conf.getId())
            level+=1
        if conf.getFullVisibility() > level:
            self._indexConfById("0",conf.getId())
    
    def getItems(self, categid):
        categid = str(categid)
        if self._idxCategItem.has_key(categid):
            return self._idxCategItem[categid]
        else:
            return []
Exemple #4
0
class CategoryDateIndex(Persistent):
    def __init__(self):
        self._idxCategItem = OOBTree()

    def dump(self):
        return map(lambda idx: (idx[0], idx[1].dump()),
                   list(self._idxCategItem.items()))

    def unindexConf(self, conf):
        for owner in conf.getOwnerPath():
            self._idxCategItem[owner.getId()].unindexConf(conf)
        self._idxCategItem['0'].unindexConf(conf)

    def unindexCateg(self, categ):
        for subcat in categ.getSubCategoryList():
            self.unindexCateg(subcat)
        for conf in categ.getConferenceList():
            self.unindexConf(conf)

    def indexCateg(self, categ):
        for subcat in categ.getSubCategoryList():
            self.indexCateg(subcat)
        for conf in categ.getConferenceList():
            self.indexConf(conf)

    def _indexConf(self, categid, conf):
        # only the more restrictive setup is taken into account
        if self._idxCategItem.has_key(categid):
            res = self._idxCategItem[categid]
        else:
            res = CalendarIndex()
        res.indexConf(conf)
        self._idxCategItem[categid] = res

    def indexConf(self, conf):
        categs = conf.getOwnerPath()
        level = 0
        for categ in conf.getOwnerPath():
            self._indexConf(categ.getId(), conf)
        self._indexConf("0", conf)

    def getObjectsIn(self, categid, sDate, eDate):
        categid = str(categid)
        if self._idxCategItem.has_key(categid):
            return self._idxCategItem[categid].getObjectsIn(sDate, eDate)
        else:
            return []

    def getObjectsStartingIn(self, categid, sDate, eDate):
        categid = str(categid)
        if self._idxCategItem.has_key(categid):
            return self._idxCategItem[categid].getObjectsStartingIn(
                sDate, eDate)
        else:
            return []
Exemple #5
0
class CategoryDateIndex(Persistent):
    
    def __init__( self ):
        self._idxCategItem = OOBTree()
        
    def dump(self):
        return map(lambda idx: (idx[0], idx[1].dump()), list(self._idxCategItem.items()))
    
    def unindexConf(self, conf):
        for owner in conf.getOwnerPath():
            self._idxCategItem[owner.getId()].unindexConf(conf)
        self._idxCategItem['0'].unindexConf(conf)

    def unindexCateg(self, categ):
        for subcat in categ.getSubCategoryList():
            self.unindexCateg(subcat)
        for conf in categ.getConferenceList():
            self.unindexConf(conf)

    def indexCateg(self, categ):
        for subcat in categ.getSubCategoryList():
            self.indexCateg(subcat)
        for conf in categ.getConferenceList():
            self.indexConf(conf)
        
    def _indexConf(self, categid, conf):
        # only the more restrictive setup is taken into account
        if self._idxCategItem.has_key(categid):
            res = self._idxCategItem[categid]
        else:
            res = CalendarIndex()
        res.indexConf(conf)
        self._idxCategItem[categid] = res

    def indexConf(self, conf):
        categs = conf.getOwnerPath()
        level = 0 
        for categ in conf.getOwnerPath():
            self._indexConf(categ.getId(), conf)
        self._indexConf("0",conf)
            
    def getObjectsIn(self, categid, sDate, eDate):
        categid = str(categid)
        if self._idxCategItem.has_key(categid):
            return self._idxCategItem[categid].getObjectsIn(sDate, eDate)
        else:
            return []

    def getObjectsStartingIn( self, categid, sDate, eDate):
        categid = str(categid)
        if self._idxCategItem.has_key(categid):
            return self._idxCategItem[categid].getObjectsStartingIn(sDate, eDate)
        else:
            return []
Exemple #6
0
class CategoryIndex(Persistent):
    def __init__(self):
        self._idxCategItem = OOBTree()

    def dump(self):
        return list(self._idxCategItem.items())

    def _indexConfById(self, categid, confid):
        # only the more restrictive setup is taken into account
        categid = str(categid)
        if self._idxCategItem.has_key(categid):
            res = self._idxCategItem[categid]
        else:
            res = []
        res.append(confid)
        self._idxCategItem[categid] = res

    def unindexConf(self, conf):
        confid = str(conf.getId())
        self.unindexConfById(confid)

    def unindexConfById(self, confid):
        for categid in self._idxCategItem.keys():
            if confid in self._idxCategItem[categid]:
                res = self._idxCategItem[categid]
                res.remove(confid)
                self._idxCategItem[categid] = res

    def reindexCateg(self, categ):
        for subcat in categ.getSubCategoryList():
            self.reindexCateg(subcat)
        for conf in categ.getConferenceList():
            self.reindexConf(conf)

    def reindexConf(self, conf):
        self.unindexConf(conf)
        self.indexConf(conf)

    def indexConf(self, conf):
        categs = conf.getOwnerPath()
        level = 0
        for categ in conf.getOwnerPath():
            if conf.getFullVisibility() > level:
                self._indexConfById(categ.getId(), conf.getId())
            level += 1
        if conf.getFullVisibility() > level:
            self._indexConfById("0", conf.getId())

    def getItems(self, categid):
        categid = str(categid)
        if self._idxCategItem.has_key(categid):
            return self._idxCategItem[categid]
        else:
            return []
Exemple #7
0
class BookingManagerConferenceIndex(Persistent):
    def __init__(self):
        self._tree = OOBTree()
        self._name = "bookingManagerByConf"

    def initialize(self, dbi=None):
        for i, conf in enumerate(ConferenceHolder()._getIdx().itervalues()):
            # Store CSBookingManager in the index
            csbm = getattr(conf, "_CSBookingManager", None)
            if csbm is None:
                csbm = CSBookingManager(conf)
            self.index(conf.getId(), csbm)
            if dbi and i % 1000 == 999:
                dbi.commit()
        if dbi:
            dbi.commit()

    def getName(self):
        return self._name

    def index(self, conf, csbm):
        if not self._tree.has_key(conf):
            self._tree[conf] = csbm
            self._tree._p_changed = 1

    def unindex(self, conf):
        del self._tree[conf]
        self._tree._p_changed = 1

    def get(self, conf):
        return self._tree.get(conf, None)

    def dump(self):
        return [(k, s) for k, s in self._tree.iteritems()]
Exemple #8
0
class BookingManagerConferenceIndex(Persistent):

    def __init__(self):
        self._tree = OOBTree()
        self._name = "bookingManagerByConf"

    def initialize(self, dbi=None):
        for i, conf in enumerate(ConferenceHolder()._getIdx().itervalues()):
            # Store CSBookingManager in the index
            csbm = getattr(conf, "_CSBookingManager", None)
            if csbm is None:
                csbm = CSBookingManager(conf)
            self.index(conf.getId(), csbm)
            if dbi and i % 1000 == 999:
                dbi.commit()
        if dbi:
            dbi.commit()

    def getName(self):
        return self._name

    def index(self, conf, csbm):
        if not self._tree.has_key(conf):
            self._tree[conf] = csbm
            self._tree._p_changed = 1

    def unindex(self, conf):
        del self._tree[conf]
        self._tree._p_changed = 1

    def get(self, conf):
        return self._tree.get(conf,None)

    def dump(self):
        return [(k, s) for k, s in self._tree.iteritems()]
Exemple #9
0
class ShortURLStorage(Persistent):
    """Stores short codes and urls to redirect to. """
    implements(IShortURLStorage)

    def __init__(self):
        self._map = OOBTree()

    def add(self, short, target):
        self._map[short] = target

    def remove(self, short):
        if self._map.has_key(short):
            del self._map[short]

    def get(self, short, default=None):
        return self._map.get(short, default)

    def suggest(self):
        try:
            key = self._map.maxKey()
        except ValueError:
            # If the tree is empty
            return 'AAAAA'
        return _increment(key)

    def __getitem__(self, key):
        return self._map.items()[key]

    def __len__(self):
        return len(self._map)
Exemple #10
0
class MobileImageShortURLStorage(ShortURLStorage):
    """ utility to keep track of shortened urls for mobile images
    """

    implements(IMobileImageShortURLStorage)

    def __init__(self):
        self._map = OOBTree()
        self._reverse_map = OOBTree()

    def add(self, short, target):
        self._map[short] = target
        self._reverse_map[target] = short

    def remove(self, short):
        if self._map.has_key(short):
            target = self.get(short)
            del self._map[short]
            del self._reverse_map[target]

    def get(self, short, default=None):
        return self._map.get(short, default)

    def getkey(self, url, default=None):
        return self._reverse_map.get(url, default)
Exemple #11
0
class BookingManagerConferenceIndex(Persistent):

    def __init__(self):
        self._tree = OOBTree()
        self._name =  "bookingManagerByConf"

    def initialize(self, dbi=None):
        pass

    def getName(self):
        return self._name

    def index(self, conf, csbm):
        if not self._tree.has_key(conf):
            self._tree[conf] = csbm
            self._tree._p_changed = 1

    def unindex(self, conf):
        del self._tree[conf]
        self._tree._p_changed = 1

    def get(self, conf):
        return self._tree.get(conf,None)

    def dump(self):
        return [(k, s) for k, s in self._tree.iteritems()]
Exemple #12
0
def index(table_name, attr, data_structure):
    if data_structure == "Btree":
        tree = OOBTree()
        T = tables[table_name]
        indexes = np.arange(len(T.table))
        header = T.header
        header_idx = {k: v for v, k in enumerate(header)}
        attr_idx = header_idx[attr]
        T_table = T.table
        for i in range(len(T_table)):
            value = T_table[i][attr_idx]
            if tree.has_key(value):
                current_idxs = tree[value]
                current_idxs.append(i)
                tree.update({value: current_idxs})

            else:
                tree.update({value: [i]})
        tables[table_name].index = tree
        tables[table_name].index_att = attr
    else:
        dict = {}
        T = tables[table_name]
        indexes = np.arange(len(T.table))
        header = T.header
        header_idx = {k: v for v, k in enumerate(header)}
        attr_idx = header_idx[attr]
        T_table = T.table
        for i in range(len(T_table)):
            value = T_table[i][attr_idx]
            dict.setdefault(value, []).append(i)
        tables[table_name].index = dict
        tables[table_name].index_att = attr
class UIDMappingStorage(Persistent):
    """Stores a mapping between remote uids and local uids.
    """
    implements(IUIDMappingStorage)
    
    def __init__(self):
        self._uidmap = OOBTree()
    
    def add(self, site_id, remote_uid, local_uid):
        if not site_id or not remote_uid or not local_uid:
            return
            
        self._uidmap[(site_id, remote_uid)] = local_uid
        
    def remove(self, site_id, remote_uid):
        del self._uidmap[(site_id, remote_uid)]
        
    def has_remote_uid(self, site_id, remote_uid):
        return bool(self._uidmap.has_key((site_id, remote_uid)))

    def get(self, site_id, remote_uid, default=None):
        return self._uidmap.get((site_id, remote_uid), default)

    def __iter__(self):
        return iter(self._uidmap)
Exemple #14
0
class OfflineEventsModule(Module):
    """
    This module holds all the information needed to keep the creation process of the offline version of the events.
    That means all the news items and other related information.
    """

    id = "offlineEvents"
    _offlineEventTypes = {"Queued": L_("Queued"), "Generated": L_("Generated"), "Failed": L_("Failed"),
                          "Expired": L_("Expired")}

    def __init__(self):
        self._idxConf = OOBTree()
        self._offlineEventCounter = Counter()

    def getOfflineEventIndex(self):
        return self._idxConf

    def getOfflineEventByConfId(self, confId):
        return self._idxConf.get(confId, [])

    def getOfflineEventByFileId(self, confId, fileId):
        offline_request_list = self._idxConf.get(confId, [])
        for req in offline_request_list:
            if req.id == fileId:
                return req
        return None

    def addOfflineEvent(self, offlineEvent):
        confId = offlineEvent.conference.getId()
        if not self._idxConf.has_key(confId):
            lst = []
            self._idxConf[confId] = lst
        else:
            lst = self._idxConf[confId]
        offlineEvent.id = self._offlineEventCounter.newCount()
        lst.append(offlineEvent)
        self._idxConf[confId] = lst

    def removeOfflineEvent(self, offlineEvent, del_file=False):
        if offlineEvent:
            confId = offlineEvent.conference.getId()
            lst = self._idxConf.get(confId,[])
            if offlineEvent in lst:
                lst.remove(offlineEvent)
            self._idxConf[confId] = lst
            if del_file:
                self.removeOfflineFile(offlineEvent)
        else:
            raise Exception(_("OfflineEvent does not exist"))

    def removeOfflineFile(self, offlineEvent):
        filepath = offlineEvent.file.getFilePath()
        if os.path.isfile(filepath):
            os.remove(filepath)
        offlineEvent.status = "Expired"

    @classmethod
    def getOfflineEventTypes(self):
        return OfflineEventsModule._offlineEventTypes
Exemple #15
0
class Day:
    def __init__(self, cal, day):
        self._calendar = cal
        self._day = day
        self._confs = OOBTree()
        self._categs = []

    def _getCalendar(self):
        return self._calendar

    def addConference(self, conf, categList, tz):
        for categ in categList:
            if categ not in self._categs:
                self._categs.append(categ)
        t = conf.getStartDate().astimezone(tz).time()
        if not self._confs.has_key(t):
            self._confs[t] = set()
        self._confs[t].add(conf)

    #sorting functions that caches calculated start times for every conf
    def _sortFunc(self, x, y):
        return cmp(self._cache[x], self._cache[y])

    def _calculateCache(self, confs):
        self._cache = {}
        for conf in confs:
            self._cache[conf] = conf.calculateDayStartTime(self._day).time()

    def getConferences(self):
        return [conf for confs in self._confs.values() for conf in confs]

    def getConferencesWithStartTime(self):
        res = [conf for confs in self._confs.values() for conf in confs]
        self._calculateCache(res)
        if res != []:
            res.sort(self._sortFunc)
        return [(event, self._cache[event]) for event in res]

    def getCategories(self):
        return self._categs

    def getWeekDay(self):
        return calendar.weekday( self._day.year, \
                                    self._day.month, \
                                    self._day.day )

    def getDayNumber(self):
        return self._day.day

    def getDate(self):
        return self._day

    def __str__(self):
        return "CalendarDay at '%s': %s --> %s" % (self._day, self._confs,
                                                   self._categs)
Exemple #16
0
class Day:

    def __init__( self, cal, day ):
        self._calendar = cal
        self._day = day
        self._confs = OOBTree()
        self._categs = []

    def _getCalendar( self ):
        return self._calendar

    def addConference(self,conf,categList,tz):
        for categ in categList:
            if categ not in self._categs:
                self._categs.append(categ)
        t = conf.getStartDate().astimezone(tz).time()
        if not self._confs.has_key(t):
            self._confs[t]=set()
        self._confs[t].add(conf)

    #sorting functions that caches calculated start times for every conf
    def _sortFunc(self, x,y):
        return cmp(self._cache[x], self._cache[y])

    def _calculateCache(self, confs):
        self._cache = {}
        for conf in confs:
            self._cache[conf] = conf.calculateDayStartTime(self._day).time()

    def getConferences(self):
        return [conf for confs in self._confs.values() for conf in confs]

    def getConferencesWithStartTime(self):
        res= [conf for confs in self._confs.values() for conf in confs]
        self._calculateCache(res)
        if res!=[]:
            res.sort(self._sortFunc)
        return [(event, self._cache[event]) for event in res]

    def getCategories(self):
        return self._categs

    def getWeekDay( self ):
        return calendar.weekday( self._day.year, \
                                    self._day.month, \
                                    self._day.day )

    def getDayNumber( self ):
        return self._day.day

    def getDate( self ):
        return self._day

    def __str__( self ):
        return "CalendarDay at '%s': %s --> %s"%(self._day, self._confs, self._categs)
Exemple #17
0
class Day:
    def __init__(self, cal, day):
        self._calendar = cal
        self._day = day
        self._confs = OOBTree()
        self._categs = []

    def _getCalendar(self):
        return self._calendar

    def addConference(self, conf, categList, tz):
        for categ in categList:
            if categ not in self._categs:
                self._categs.append(categ)
        t = conf.getStartDate().astimezone(tz).time()
        if not self._confs.has_key(t):
            self._confs[t] = sets.Set()
        self._confs[t].add(conf.getId())

    def getConferenceIds(self):
        res = []
        for confs in self._confs.values():
            for conf in confs:
                res.append(conf)
        return res

    def getConferences(self):
        res = []
        ch = conference.ConferenceHolder()
        for confId in self.getConferenceIds():
            res.append(ch.getById(confId))
        if res != []:
            res.sort(lambda x, y: cmp(
                x.calculateDayStartTime(self._day).time(),
                y.calculateDayStartTime(self._day).time()))
        return res

    def getCategories(self):
        return self._categs

    def getWeekDay(self):
        return calendar.weekday( self._day.year, \
                                    self._day.month, \
                                    self._day.day )

    def getDayNumber(self):
        return self._day.day

    def getDate(self):
        return self._day

    def __str__(self):
        return "CalendarDay at '%s': %s --> %s" % (self._day, self._confs,
                                                   self._categs)
Exemple #18
0
class Day:
    
    def __init__( self, cal, day ):
        self._calendar = cal
        self._day = day
        self._confs = OOBTree()
        self._categs = []

    def _getCalendar( self ):
        return self._calendar
        
    def addConference(self,conf,categList,tz):
        for categ in categList:
            if categ not in self._categs:
                self._categs.append(categ)
        t = conf.getStartDate().astimezone(tz).time()
        if not self._confs.has_key(t):
            self._confs[t]=sets.Set()
        self._confs[t].add(conf.getId())
        
    def getConferenceIds(self):
        res=[]
        for confs in self._confs.values():
            for conf in confs:
                res.append(conf)
        return res

    def getConferences(self):
        res=[]
        ch=conference.ConferenceHolder()
        for confId in self.getConferenceIds():
            res.append(ch.getById(confId))
        if res!=[]:
            res.sort(lambda x,y: cmp(x.calculateDayStartTime(self._day).time(),y.calculateDayStartTime(self._day).time()))
        return res

    def getCategories(self):
        return self._categs

    def getWeekDay( self ):
        return calendar.weekday( self._day.year, \
                                    self._day.month, \
                                    self._day.day )
                                    
    def getDayNumber( self ):
        return self._day.day

    def getDate( self ):
        return self._day

    def __str__( self ):
        return "CalendarDay at '%s': %s --> %s"%(self._day, self._confs, self._categs)
Exemple #19
0
class CategoryDayIndex(CategoryDateIndex):

    def __init__(self, visibility=True):
        super(CategoryDayIndex, self).__init__()
        self._useVisibility = visibility

    def _indexConf(self, categid, conf):
        # only the more restrictive setup is taken into account
        if self._idxCategItem.has_key(categid):
            res = self._idxCategItem[categid]
        else:
            res = CalendarDayIndex()
        res.indexConf(conf)
        self._idxCategItem[categid] = res

    def reindexConf(self, conf):
        self.unindexConf(conf)
        self.indexConf(conf)

    def indexConf(self, conf):
        level = 0
        for categ in conf.getOwnerPath():
            if not self._useVisibility or conf.getFullVisibility() > level:
                self._indexConf(categ.getId(),conf)
            level+=1
        if not self._useVisibility or conf.getFullVisibility() > level:
            self._indexConf("0",conf)

    def buildIndex(self, dbi):
        self._idxCategItem = OOBTree()
        from MaKaC.conference import CategoryManager
        self.indexCateg(CategoryManager().getById('0'), dbi=dbi)

    def getObjectsInDays(self, categid, sDate, eDate):
        if self._idxCategItem.has_key(categid):
            return self._idxCategItem[categid].getObjectsInDays(sDate, eDate)
        else:
            return []

    def iterateObjectsIn(self, categid, sDate, eDate):
        if categid in self._idxCategItem:
            return self._idxCategItem[categid].iterateObjectsIn(sDate, eDate)
        else:
            return []

    def _check(self, dbi=None):
        """
        Performs some sanity checks
        """
        for categId, calDayIdx in self._idxCategItem.iteritems():
            for problem in calDayIdx._check(dbi=dbi, categId=categId):
                yield problem
Exemple #20
0
class Session(Implicit, Persistent, RoleManager, Item):
    def __init__(self, sessionId):
        self._sessionId = sessionId
        self._questionId = OOBTree()
        self._answer = OOBTree()
        self._nav = OOBTree()
        self._context = OOBTree()
        self._loginStatus = OOBTree()
        self._page = OOBTree()
        self._query = OOBTree()
        self._qstPage = OOTreeSet()

    def addAnswer(self, questionId, answer, nav, time, context, loginStatus,
                  page, query):
        if not self._questionId.has_key(time):
            self._questionId[time] = questionId
            self._answer[time] = answer
            self._nav[time] = nav
            self._context[time] = context
            self._loginStatus[time] = loginStatus
            self._page[time] = page
            self._query[time] = query
            self._qstPage.insert(str(questionId) + str(page))
            return True
        return False

    def getTotFeedback(self):
        return len(self._questionId)

    #note: isAnswered(questionId, sessionId=sessionId, page=url)
    def isAnswered(self, questionId, **kwargs):
        if 'page' in kwargs:
            qstPage = str(questionId) + str(kwargs['page'])
            return True if self._qstPage.has_key(qstPage) else False
        else:
            return True if questionId in self._questionId.values() else False

    def getAnswerList(self):
        answers = []
        for time in self._questionId.keys():
            tmp = [
                self._sessionId, time,
                self._questionId.get(time),
                self._answer.get(time),
                self._nav.get(time),
                self._context.get(time),
                self._loginStatus.get(time),
                self._page.get(time),
                self._query.get(time)
            ]
            answers.append(tmp)
        return answers
Exemple #21
0
class CategoryDayIndex(CategoryDateIndex):

    def __init__(self, visibility=True):
        super(CategoryDayIndex, self).__init__()
        self._useVisibility = visibility

    def _indexConf(self, categid, conf):
        # only the more restrictive setup is taken into account
        if self._idxCategItem.has_key(categid):
            res = self._idxCategItem[categid]
        else:
            res = CalendarDayIndex()
        res.indexConf(conf)
        self._idxCategItem[categid] = res

    def reindexConf(self, conf):
        self.unindexConf(conf)
        self.indexConf(conf)

    def indexConf(self, conf):
        level = 0
        for categ in conf.getOwnerPath():
            if not self._useVisibility or conf.getFullVisibility() > level:
                self._indexConf(categ.getId(),conf)
            level+=1
        if not self._useVisibility or conf.getFullVisibility() > level:
            self._indexConf("0",conf)

    def buildIndex(self, dbi):
        self._idxCategItem = OOBTree()
        from MaKaC.conference import CategoryManager
        self.indexCateg(CategoryManager().getById('0'), dbi=dbi)

    def getObjectsInDays(self, categid, sDate, eDate):
        if self._idxCategItem.has_key(categid):
            return self._idxCategItem[categid].getObjectsInDays(sDate, eDate)
        else:
            return []

    def iterateObjectsIn(self, categid, sDate, eDate):
        if categid in self._idxCategItem:
            return self._idxCategItem[categid].iterateObjectsIn(sDate, eDate)
        else:
            return []

    def _check(self, dbi=None):
        """
        Performs some sanity checks
        """
        for categId, calDayIdx in self._idxCategItem.iteritems():
            for problem in calDayIdx._check(dbi=dbi, categId=categId):
                yield problem
Exemple #22
0
class Folder(Persistent):

    def __init__(self, path):
        self.path = path
        self.mtime = 0
        self.size = 0
        self.messages = OOBTree()

    def _stat(self):
        t = os.stat(self.path)
        self.mtime = t[stat.ST_MTIME]
        self.size = t[stat.ST_SIZE]

    def changed(self):
        t = os.stat(self.path)
        if (t[stat.ST_MTIME] != self.mtime
            or t[stat.ST_SIZE] != self.size):
            return True
        else:
            return False

    def read(self):
        """Return messages added and removed from folder.

        Two sets of message objects are returned.  The first set is
        messages that were added to the folder since the last read.
        The second set is the messages that were removed from the
        folder since the last read.

        The code assumes messages are added and removed but not edited.
        """
        mbox = mailbox.UnixMailbox(open(self.path, "rb"), factory)
        self._stat()
        cur = OOSet()
        new = OOSet()
        while 1:
            msg = mbox.next()
            if msg is None:
                break
            msgid = msg["message-id"]
            cur.insert(msgid)
            if not self.messages.has_key(msgid):
                self.messages[msgid] = msg
                new.insert(msg)

        removed = difference(self.messages, cur)
        for msgid in removed.keys():
            del self.messages[msgid]

        # XXX perhaps just return the OOBTree for removed?
        return new, OOSet(removed.values())
Exemple #23
0
class OOIndex(persistent.Persistent):
    """Base class for the Class-, Attribute- and StructureIndex.

    Stores the values for a key in a BTrees.OOBTree.OOTreeSet.
    """
    def __init__(self):
        self._index = OOBTree()

    def insert(self, key, value):
        "Insert value under key."
        if not self._index.has_key(key):
            self._index[key] = OOTreeSet()
        self._index[key].insert(value)

    def delete(self, key, value):
        """Delete value from key.
        
        If no value is left after deletion, key is deleted from the index.
        """
        if not self._index.has_key(key):
            return
        if value not in self._index[key]:
            return
        self._index[key].remove(value)
        if len(self._index[key]) == 0:
            del self._index[key]

    def get(self, key):
        "Return the OOTreeSet for a given key."
        if self.has_key(key):
            # XXX: why yield?!?!
            for item in self._index[key]:
                yield item

    def has_key(self, key):
        "Check if index has values for key."
        return key in self._index
Exemple #24
0
class Folder(Persistent):
    def __init__(self, path):
        self.path = path
        self.mtime = 0
        self.size = 0
        self.messages = OOBTree()

    def _stat(self):
        t = os.stat(self.path)
        self.mtime = t[stat.ST_MTIME]
        self.size = t[stat.ST_SIZE]

    def changed(self):
        t = os.stat(self.path)
        if (t[stat.ST_MTIME] != self.mtime or t[stat.ST_SIZE] != self.size):
            return True
        else:
            return False

    def read(self):
        """Return messages added and removed from folder.

        Two sets of message objects are returned.  The first set is
        messages that were added to the folder since the last read.
        The second set is the messages that were removed from the
        folder since the last read.

        The code assumes messages are added and removed but not edited.
        """
        mbox = mailbox.UnixMailbox(open(self.path, "rb"), factory)
        self._stat()
        cur = OOSet()
        new = OOSet()
        while 1:
            msg = mbox.next()
            if msg is None:
                break
            msgid = msg["message-id"]
            cur.insert(msgid)
            if not self.messages.has_key(msgid):
                self.messages[msgid] = msg
                new.insert(msg)

        removed = difference(self.messages, cur)
        for msgid in removed.keys():
            del self.messages[msgid]

        # XXX perhaps just return the OOBTree for removed?
        return new, OOSet(removed.values())
class TestBTreesUnicode(unittest.TestCase):
    """ test unicode"""

    def setUp(self):
        """setup an OOBTree with some unicode strings"""

        self.s = unicode('dreit\xe4gigen', 'latin1')

        self.data = [('alien', 1),
                     ('k\xf6nnten', 2),
                     ('fox', 3),
                     ('future', 4),
                     ('quick', 5),
                     ('zerst\xf6rt', 6),
                     (unicode('dreit\xe4gigen','latin1'), 7),
                    ]

        self.tree = OOBTree()
        for k, v in self.data:
            if isinstance(k, str):
                k = unicode(k, 'latin1')
            self.tree[k] = v

    def testAllKeys(self):
        # check every item of the tree
        for k, v in self.data:
            if isinstance(k, str):
                k = unicode(k, encoding)
            self.assert_(self.tree.has_key(k))
            self.assertEqual(self.tree[k], v)

    def testUnicodeKeys(self):
        # try to access unicode keys in tree
        k, v = self.data[-1]
        self.assertEqual(k, self.s)
        self.assertEqual(self.tree[k], v)
        self.assertEqual(self.tree[self.s], v)

    def testAsciiKeys(self):
        # try to access some "plain ASCII" keys in the tree
        for k, v in self.data[0], self.data[2]:
            self.assert_(isinstance(k, str))
            self.assertEqual(self.tree[k], v)
Exemple #26
0
class TestBTreesUnicode(unittest.TestCase):
    """ test unicode"""
    def setUp(self):
        """setup an OOBTree with some unicode strings"""

        self.s = unicode('dreit\xe4gigen', 'latin1')

        self.data = [
            ('alien', 1),
            ('k\xf6nnten', 2),
            ('fox', 3),
            ('future', 4),
            ('quick', 5),
            ('zerst\xf6rt', 6),
            (unicode('dreit\xe4gigen', 'latin1'), 7),
        ]

        self.tree = OOBTree()
        for k, v in self.data:
            if isinstance(k, str):
                k = unicode(k, 'latin1')
            self.tree[k] = v

    def testAllKeys(self):
        # check every item of the tree
        for k, v in self.data:
            if isinstance(k, str):
                k = unicode(k, encoding)
            self.assert_(self.tree.has_key(k))
            self.assertEqual(self.tree[k], v)

    def testUnicodeKeys(self):
        # try to access unicode keys in tree
        k, v = self.data[-1]
        self.assertEqual(k, self.s)
        self.assertEqual(self.tree[k], v)
        self.assertEqual(self.tree[self.s], v)

    def testAsciiKeys(self):
        # try to access some "plain ASCII" keys in the tree
        for k, v in self.data[0], self.data[2]:
            self.assert_(isinstance(k, str))
            self.assertEqual(self.tree[k], v)
class AccessStorage(Persistent):
    """Stores access credentials in an insecure manner into the portal.
    """
    implements(IAccessStorage)
    
    def __init__(self):
        self._data = OOBTree()
    
    def add(self, url, login, password):
        if not url or not login or not password:
            return
        self._data[(url, login)] = password
        
    def remove(self, url, login):
        del self._data[(url, login)]
        
    def has_key(self, url, login):
        return bool(self._data.has_key((url, login) ) )

    def get(self, url, login, default=None):
        return self._data.get((url, login), default)

    def __iter__(self):
        return iter(self._data)
class BaseQuestion(ATCTContent):
    """Base class for survey questions"""
    immediate_view = "base_edit"
    global_allow = 0
    filter_content_types = 1
    allowed_content_types = ()
    include_default_actions = 1
    _at_rename_after_creation = True

    security = ClassSecurityInfo()

    security.declareProtected(permissions.ModifyPortalContent, 'reset')
    def reset(self):
        """Remove answers for all users."""
        self.answers = OOBTree()

    security.declareProtected(permissions.ModifyPortalContent, 'resetForUser')
    def resetForUser(self, userid):
        """Remove answer for a single user"""
        if self.answers.has_key(userid):
            del self.answers[userid]

    security.declareProtected(permissions.View, 'addAnswer')
    def addAnswer(self, value, comments=""):
        """Add an answer and optional comments for a user.
        This method protects _addAnswer from anonymous users specifying a
        userid when they vote, and thus apparently voting as another user
        of their choice.
        """
        # Get hold of the parent survey
        survey = None
        ob = self
        while survey is None:
            ob = ob.aq_parent
            if ob.meta_type == 'Survey':
                survey = ob
            elif getattr(ob, '_isPortalRoot', False):
                raise Exception("Could not find a parent Survey.")
        portal_membership = getToolByName(self, 'portal_membership')
        if portal_membership.isAnonymousUser() and not survey.getAllowAnonymous():
            raise Unauthorized, ("This survey is not available to anonymous users.")
        userid = self.getSurveyId()
        # Call the real method for storing the answer for this user.
        return self._addAnswer(userid, value, comments)

    def _addAnswer(self, userid, value, comments=""):
        """Add an answer and optional comments for a user."""
        # We don't let users over-write answers that they've already made.
        # Their first answer must be explicitly 'reset' before another
        # answer can be supplied.
        # XXX this causes problem when survey fails validation
        # will also cause problem with save function
##        if self.answers.has_key(userid):
##            # XXX Should this get raised?  If so, a more appropriate
##            # exception is probably in order.
##            msg = "User '%s' has already answered this question. Reset the original response to supply a new answer."
##            raise Exception(msg % userid)
##        else:
        self.answers[userid] = PersistentMapping(value=value,
                                                 comments=comments)
        if not isinstance(self.answers, (PersistentMapping, OOBTree)):
            # It must be a standard dictionary from an old install, so
            # we need to inform the ZODB about the change manually.
            self.answers._p_changed = 1

    security.declareProtected(permissions.View, 'getAnswerFor')
    def getAnswerFor(self, userid):
        """Get a specific user's answer"""
        answer = self.answers.get(userid, {}).get('value', None)
        if self.getInputType() in ['multipleSelect', 'checkbox']:
            if type(answer) == 'NoneType':
                return []
        if self.getInputType() in ['radio', 'selectionBox']:
            if not answer:
                return ""
            return str(answer)
        return answer

    security.declareProtected(permissions.View, 'getCommentsFor')
    def getCommentsFor(self, userid):
        """Get a specific user's comments"""
        return self.answers.get(userid, {}).get('comments', None)

    security.declareProtected(permissions.View, 'getComments')
    def getComments(self):
        """Return a userid, comments mapping"""
        mlist = []
        for k, v in self.answers.items():
            mapping = {}
            mapping['userid'] = k
            mapping['comments'] = v.get('comments', '')
            mlist.append(mapping)
        return mlist

    security.declareProtected(permissions.View, 'getNumberOfRespondents')
    def getNumberOfRespondents(self):
        return len(self.answers.keys())

    security.declarePrivate('_get_yes_no_default')
    def _get_yes_no_default(self):
        foo = (_(u'Yes'), _(u'No'))
        translation_service = getToolByName(self,'translation_service')
        return (translation_service.utranslate(domain='plonesurvey',
                                             msgid=u'Yes',
                                             context=self),
                translation_service.utranslate(domain='plonesurvey',
                                             msgid=u'No',
                                             context=self),
                )

    security.declarePrivate('_get_commentLabel_default')
    def _get_commentLabel_default(self):
        foo = _(u'commentLabelDefault', default=u"Comment - mandatory if \"no\"")
        translation_service = getToolByName(self,'translation_service')
        return translation_service.utranslate(domain='plonesurvey',
                                              msgid=u'commentLabelDefault',
                                              default=u'Comment - mandatory if "no"',
                                              context=self)
Exemple #29
0
class VersionHistory(Implicit, Persistent):
    """A version history maintains the information about the changes
       to a particular version-controlled resource over time."""

    def __init__(self, history_id, object):
        # The _versions mapping maps version ids to version objects. All
        # of the actual version data is looked up there. The _labels
        # mapping maps labels to specific version ids. The _branches map
        # manages BranchInfo objects that maintain branch information.
        self._eventLog = EventLog()
        self._versions = OOBTree()
        self._branches = OOBTree()
        self._labels = OOBTree()
        self.createBranch('mainline', None)
        self.id = history_id

    security = ClassSecurityInfo()

    security.declarePublic('getId')
    def getId(self):
        return self.id

    security.declarePrivate('addLogEntry')
    def addLogEntry(self, version_id, action, path=None, message=''):
        """Add a new log entry associated with this version history."""
        entry = LogEntry(version_id, action, path, message)
        self._eventLog.addEntry(entry)

    security.declarePrivate('getLogEntries')
    def getLogEntries(self):
        """Return a sequence of the log entries for this version history."""
        return self._eventLog.getEntries()

    security.declarePrivate('getLabels')
    def getLabels(self):
        return self._labels.keys()

    security.declarePrivate('labelVersion')
    def labelVersion(self, version_id, label, force=0):
        """Associate a particular version in a version history with the
           given label, removing any existing association with that label
           if force is true, or raising an error if force is false and
           an association with the given label already exists."""
        current = self._labels.get(label)
        if current is not None:
            if current == version_id:
                return
            if not force:
                raise VersionControlError(
                    'The label %s is already associated with a version.' % (
                     label
                    ))
            del self._labels[label]
        self._labels[label] = version_id

    security.declarePrivate('createBranch')
    def createBranch(self, branch_id, version_id):
        """Create a new branch associated with the given branch_id. The
           new branch is rooted at the version named by version_id."""
        if self._branches.has_key(branch_id):
            raise VersionControlError(
                'Activity already exists: %s' % branch_id
                )
        branch = BranchInfo(branch_id, version_id)
        self._branches[branch_id] = branch
        return branch

    security.declarePrivate('createVersion')
    def createVersion(self, object, branch_id):
        """Create a new version in the line of descent named by the given
           branch_id, returning the newly created version object."""
        branch = self._branches.get(branch_id)
        if branch is None:
            branch = self.createBranch(branch_id, None)
        if branch.name != 'mainline':
            version_id = '%s.%d' % (branch.name, len(branch) + 1)
        else:
            version_id = '%d' % (len(branch) + 1)
        version = ZopeVersion(version_id, object)

        # Update the  predecessor, successor and branch relationships.
        # This is something of a hedge against the future. Versions will
        # always know enough to reconstruct their lineage without the help
        # of optimized data structures, which will make it easier to change
        # internals in the future if we need to.
        latest = branch.latest()
        if latest is not None:
            last = self._versions[latest]
            last.next = last.next + (version_id,)
            version.prev = latest

        # If the branch is not the mainline, store the branch name in the
        # version. Versions have 'mainline' as the default class attribute
        # which is the common case and saves a minor bit of storage space.
        if branch.name != 'mainline':
            version.branch = branch.name

        branch.append(version)
        self._versions[version_id] = version
        # Call saveState() only after version has been linked into the
        # database, ensuring it goes into the correct database.
        version.saveState(object)
        return version.__of__(self)

    security.declarePrivate('hasVersionId')
    def hasVersionId(self, version_id):
        """Return true if history contains a version with the given id."""
        return self._versions.has_key(version_id)

    security.declarePrivate('isLatestVersion')
    def isLatestVersion(self, version_id, branch_id):
        """Return true if version id is the latest in its branch."""
        branch = self._branches[branch_id]
        return version_id == branch.latest()

    security.declarePrivate('getLatestVersion')
    def getLatestVersion(self, branch_id):
        """Return the latest version object within the given branch, or
           None if the branch contains no versions."""
        branch = self._branches[branch_id]
        version = self._versions[branch.latest()]
        return version.__of__(self)

    security.declarePrivate('findBranchId')
    def findBranchId(self, version_id):
        """Given a version id, return the id of the branch of the version.
           Note that we cheat, since we can find this out from the id."""
        parts = version_id.split('.')
        if len(parts) > 1:
            return parts[-2]
        return 'mainline'

    security.declarePrivate('getVersionById')
    def getVersionById(self, version_id):
        """Return the version object named by the given version id, or
           raise a VersionControlError if the version is not found."""
        version = self._versions.get(version_id)
        if version is None:
            raise VersionControlError(
                'Unknown version id: %s' % version_id
                )
        return version.__of__(self)

    security.declarePrivate('getVersionByLabel')
    def getVersionByLabel(self, label):
        """Return the version associated with the given label, or None
           if no version matches the given label."""
        version_id = self._labels.get(label)
        version = self._versions.get(version_id)
        if version is None:
            return None
        return version.__of__(self)

    security.declarePrivate('getVersionByDate')
    def getVersionByDate(self, branch_id, timestamp):
        """Return the last version committed in the given branch on or
           before the given time value. The timestamp should be a float
           (time.time format) value in UTC."""
        branch = self._branches[branch_id]
        tvalue = int(timestamp / 60.0)
        while 1:
            # Try to find a version with a commit date <= the given time
            # using the timestamp index in the branch information.
            if branch.m_order:
                try:
                    match = branch.m_date.maxKey(tvalue)
                    match = branch.m_order[branch.m_date[match]]
                    return self._versions[match].__of__(self)
                except ValueError:
                    pass

            # If we've run out of lineage without finding a version with
            # a commit date <= the given timestamp, we return None. It is
            # up to the caller to decide what to do in this situation.
            if branch.root is None:
                return None
            
            # If the branch has a root (a version in another branch), then
            # we check the root and do it again with the ancestor branch.
            rootver = self._versions[branch.root]
            if int(rootver.date_created / 60.0) < tvalue:
                return rootver.__of__(self)
            branch = self._branches[rootver.branch]

    security.declarePrivate('getVersionIds')
    def getVersionIds(self, branch_id=None):
        """Return a sequence of version ids for the versions in this
           version history. If a branch_id is given, only version ids
           from that branch will be returned. Note that the sequence
           of ids returned does not include the id of the branch root."""
        if branch_id is not None:
            return self._branches[branch_id].versionIds()
        return self._versions.keys()
Exemple #30
0
class TopicIndex(Persistent, SimpleItem):
    """A TopicIndex maintains a set of FilteredSet objects.

    Every FilteredSet object consists of an expression and and IISet with all
    Ids of indexed objects that eval with this expression to 1.
    """
    implements(ITopicIndex, IPluggableIndex)

    meta_type = "TopicIndex"
    query_options = ('query', 'operator')

    manage_options = ({'label': 'FilteredSets', 'action': 'manage_main'}, )

    def __init__(self, id, caller=None):
        self.id = id
        self.filteredSets = OOBTree()
        self.operators = ('or', 'and')
        self.defaultOperator = 'or'

    def getId(self):
        return self.id

    def clear(self):
        for fs in self.filteredSets.values():
            fs.clear()

    def index_object(self, docid, obj, threshold=100):
        """ hook for (Z)Catalog """
        for fid, filteredSet in self.filteredSets.items():
            filteredSet.index_object(docid, obj)
        return 1

    def unindex_object(self, docid):
        """ hook for (Z)Catalog """

        for fs in self.filteredSets.values():
            try:
                fs.unindex_object(docid)
            except KeyError:
                LOG.debug('Attempt to unindex document'
                          ' with id %s failed' % docid)
        return 1

    def numObjects(self):
        """Return the number of indexed objects."""
        return "n/a"

    def indexSize(self):
        """Return the size of the index in terms of distinct values."""
        return "n/a"

    def search(self, filter_id):
        if self.filteredSets.has_key(filter_id):
            return self.filteredSets[filter_id].getIds()

    def _apply_index(self, request):
        """ hook for (Z)Catalog
            'request' --  mapping type (usually {"topic": "..." }
        """
        record = parseIndexRequest(request, self.id, self.query_options)
        if record.keys is None:
            return None

        operator = record.get('operator', self.defaultOperator).lower()
        if operator == 'or': set_func = union
        else: set_func = intersection

        res = None
        for filter_id in record.keys:
            rows = self.search(filter_id)
            res = set_func(res, rows)

        if res:
            return res, (self.id, )
        else:
            return IITreeSet(), (self.id, )

    def uniqueValues(self, name=None, withLength=0):
        """ needed to be consistent with the interface """
        return self.filteredSets.keys()

    def getEntryForObject(self, docid, default=_marker):
        """ Takes a document ID and returns all the information we have
            on that specific object.
        """
        return self.filteredSets.keys()

    def addFilteredSet(self, filter_id, typeFilteredSet, expr):
        # Add a FilteredSet object.
        if self.filteredSets.has_key(filter_id):
            raise KeyError,\
                'A FilteredSet with this name already exists: %s' % filter_id
        self.filteredSets[filter_id] = factory(
            filter_id,
            typeFilteredSet,
            expr,
        )

    def delFilteredSet(self, filter_id):
        # Delete the FilteredSet object specified by 'filter_id'.
        if not self.filteredSets.has_key(filter_id):
            raise KeyError,\
                'no such FilteredSet:  %s' % filter_id
        del self.filteredSets[filter_id]

    def clearFilteredSet(self, filter_id):
        # Clear the FilteredSet object specified by 'filter_id'.
        if not self.filteredSets.has_key(filter_id):
            raise KeyError,\
                'no such FilteredSet:  %s' % filter_id
        self.filteredSets[filter_id].clear()

    def manage_addFilteredSet(self, filter_id, typeFilteredSet, expr, URL1, \
            REQUEST=None,RESPONSE=None):
        """ add a new filtered set """

        if len(filter_id) == 0: raise RuntimeError, 'Length of ID too short'
        if len(expr) == 0: raise RuntimeError, 'Length of expression too short'

        self.addFilteredSet(filter_id, typeFilteredSet, expr)

        if RESPONSE:
            RESPONSE.redirect(URL1 + '/manage_workspace?'
                              'manage_tabs_message=FilteredSet%20added')

    def manage_delFilteredSet(self, filter_ids=[], URL1=None, \
            REQUEST=None,RESPONSE=None):
        """ delete a list of FilteredSets"""

        for filter_id in filter_ids:
            self.delFilteredSet(filter_id)

        if RESPONSE:
            RESPONSE.redirect(URL1 + '/manage_workspace?'
                              'manage_tabs_message=FilteredSet(s)%20deleted')

    def manage_saveFilteredSet(self,filter_id, expr, URL1=None,\
            REQUEST=None,RESPONSE=None):
        """ save expression for a FilteredSet """

        self.filteredSets[filter_id].setExpression(expr)

        if RESPONSE:
            RESPONSE.redirect(URL1 + '/manage_workspace?'
                              'manage_tabs_message=FilteredSet(s)%20updated')

    def getIndexSourceNames(self):
        """ return names of indexed attributes """
        return ('n/a', )

    def getIndexQueryNames(self):
        return (self.id, )

    def manage_clearFilteredSet(self, filter_ids=[], URL1=None, \
            REQUEST=None,RESPONSE=None):
        """  clear a list of FilteredSets"""

        for filter_id in filter_ids:
            self.clearFilteredSet(filter_id)

        if RESPONSE:
            RESPONSE.redirect(URL1 + '/manage_workspace?'
                              'manage_tabs_message=FilteredSet(s)%20cleared')

    manage = manage_main = DTMLFile('dtml/manageTopicIndex', globals())
    manage_main._setName('manage_main')
    editFilteredSet = DTMLFile('dtml/editFilteredSet', globals())
return_result = list(result)
print("the key in the range: ", return_result)
list8 = []

for i in range(len(return_result)):
    print("i ", return_result[i])
    res = int("". join(map(str, k.get(return_result[i]))))
    list8.append(res)
'''

list8 = []

x = 11
y = 16
c = 1
if k.has_key((11, 1)):
    print("today")
else:
    print("yesterday")

while x <= y:
    new_key = (x, c)
    #print("x:", x)
    #print(new_key)
    if k.has_key(new_key):
        print(new_key, k.get(new_key))
        res = int("".join(map(str, k.get(new_key))))
        list8.append(res)
        x = x + 1
    else:
        x = x + 1
# %%
# our index structure:
# BTree: key = term, value = dictionary [key = docID, value = list with positions of occurance of term]
# docID = docNo_rowNo   [docNo = csv no]

# %%
# For individual csv files :
filename = "BBCNEWS.201701.csv"
index = OOBTree()
print(index)
df = pd.read_csv("./Processed_dataset/" + filename)
doc = "1"
for row, text in enumerate(df["Snippet"]):
    docID = doc + '_' + str(row)
    for pos, term in enumerate(text.split()):
        if index.has_key(term):
            if docID in index[term]:
                index[term][docID].append(pos)
            else:
                index[term][docID] = [pos]
        else:
            index.update({term: {docID: [pos]}})

# %%
# To display index :
x = list(index.items())
x

# %%
# Index for all 417 files together :
my_inverted_index = dict()  #
Exemple #33
0
class ToManyContRelationship(ToManyRelationshipBase):
    """
    ToManyContRelationship is the ToMany side of a realtionship that
    contains its related objects (like the normal Zope ObjectManager)
    """

    meta_type = "ToManyContRelationship"

    security = ClassSecurityInfo()

    def __init__(self, id):
        """set our instance values"""
        self.id = id
        self._objects = OOBTree()

    def _safeOfObjects(self):
        """
        Try to safely return ZenPack objects rather than
        causing imports to fail.
        """
        objs = []
        for ob in self._objects.values():
            try:
                objs.append(ob.__of__(self))
            except AttributeError:
                log.info("Ignoring unresolvable object '%s'", str(ob))
        return objs

    def __call__(self):
        """when we are called return our related object in our aq context"""
        return self._safeOfObjects()

    def __getattr__(self, name):
        """look in the two object stores for related objects"""
        if '_objects' in self.__dict__:
            objects = self._objects
            if objects.has_key(name): return objects[name]
        raise AttributeError("Unable to find the attribute '%s'" % name)

    def __hasattr__(self, name):
        """check to see if we have an object by an id
        this will fail if passed a short id and object is stored
        with fullid (ie: it is related not contained)
        use hasobject to get around this issue"""
        return self._objects.has_key(name)

    def hasobject(self, obj):
        "check to see if we have this object"
        return self._objects.get(obj.id) == obj

    def addRelation(self, obj):
        """Override base to run manage_afterAdd like ObjectManager"""
        if self._objects.has_key(obj.getId()):
            log.debug("obj %s already exists on %s", obj.getPrimaryId(),
                      self.getPrimaryId())

        notify(ObjectWillBeAddedEvent(obj, self, obj.getId()))
        ToManyRelationshipBase.addRelation(self, obj)
        obj = obj.__of__(self)
        o = self._getOb(obj.id)
        notify(ObjectAddedEvent(o, self, obj.getId()))

    def _setObject(self, id, object, roles=None, user=None, set_owner=1):
        """ObjectManager interface to add contained object."""
        unused(user, roles, set_owner)
        object.__primary_parent__ = aq_base(self)
        self.addRelation(object)
        return object.getId()

    def manage_afterAdd(self, item, container):
        # Don't do recursion anymore, a subscriber does that.
        pass

    manage_afterAdd.__five_method__ = True

    def manage_afterClone(self, item):
        # Don't do recursion anymore, a subscriber does that.
        pass

    manage_afterClone.__five_method__ = True

    def manage_beforeDelete(self, item, container):
        # Don't do recursion anymore, a subscriber does that.
        pass

    manage_beforeDelete.__five_method__ = True

    def _add(self, obj):
        """add an object to one side of a ToManyContRelationship.
        """
        id = obj.id
        if self._objects.has_key(id):
            raise RelationshipExistsError
        v = checkValidId(self, id)
        if v is not None: id = v
        self._objects[id] = aq_base(obj)
        obj = aq_base(obj).__of__(self)
        self.setCount()

    def _remove(self, obj=None, suppress_events=False):
        """remove object from our side of a relationship"""
        if obj: objs = [obj]
        else: objs = self.objectValuesAll()
        if not suppress_events:
            for robj in objs:
                notify(ObjectWillBeRemovedEvent(robj, self, robj.getId()))
        if obj:
            id = obj.id
            if not self._objects.has_key(id):
                raise ObjectNotFound("object %s not found on %s" %
                                     (obj.getPrimaryId(), self.getPrimaryId()))
            del self._objects[id]
        else:
            self._objects = OOBTree()
            self.__primary_parent__._p_changed = True
        if not suppress_events:
            for robj in objs:
                notify(ObjectRemovedEvent(robj, self, robj.getId()))
        self.setCount()

    def _remoteRemove(self, obj=None):
        """remove an object from the far side of this relationship
        if no object is passed in remove all objects"""
        if obj:
            if not self._objects.has_key(obj.id):
                raise ObjectNotFound("object %s not found on %s" %
                                     (obj.getPrimaryId(), self.getPrimaryId()))
            objs = [obj]
        else:
            objs = self.objectValuesAll()
        remoteName = self.remoteName()
        for obj in objs:
            rel = getattr(obj, remoteName)
            try:
                rel._remove(self.__primary_parent__)
            except ObjectNotFound:
                message = log_tb(sys.exc_info())
                log.error('Remote remove failed. Run "zenchkrels -r -x1". ' +
                          message)
                continue

    def _getOb(self, id, default=zenmarker):
        """look up in our local store and wrap in our aq_chain"""
        if self._objects.has_key(id):
            return self._objects[id].__of__(self)
        elif default == zenmarker:
            raise AttributeError("Unable to find %s" % id)
        return default

    security.declareProtected('View', 'objectIds')

    def objectIds(self, spec=None):
        """only return contained objects"""
        if spec:
            if isinstance(spec, basestring): spec = [spec]
            return [obj.id for obj in self._objects.values() \
                        if obj.meta_type in spec]
        return [k for k in self._objects.keys()]

    objectIdsAll = objectIds

    security.declareProtected('View', 'objectValues')

    def objectValues(self, spec=None):
        """override to only return owned objects for many to many rel"""
        if spec:
            if isinstance(spec, basestring): spec = [spec]
            return [ob.__of__(self) for ob in self._objects.values() \
                        if ob.meta_type in spec]
        return self._safeOfObjects()

    security.declareProtected('View', 'objectValuesAll')
    objectValuesAll = objectValues

    def objectValuesGen(self):
        """Generator that returns all related objects."""
        return (obj.__of__(self) for obj in self._objects.values())

    def objectItems(self, spec=None):
        """over ride to only return owned objects for many to many rel"""
        if spec:
            if isinstance(spec, basestring): spec = [spec]
            return [(key,value.__of__(self)) \
                for (key,value) in self._objects.items() \
                    if value.meta_type in spec]
        return [(key,value.__of__(self)) \
                    for (key,value) in self._objects.items()]

    objectItemsAll = objectItems

    #FIXME - need to make this work
    #    def all_meta_types(self, interfaces=None):
    #        mts = []
    #        for mt in ToManyRelationshipBase.all_meta_types(self, interfaces):
    #            if (mt.has_key('instance') and mt['instance']):
    #                for cl in self.sub_classes:
    #                    if checkClass(mt['instance'], cl):
    #                        mts.append(mt)
    #        return mts

    def _getCopy(self, container):
        """
        make new relation add copies of contained objs
        and refs if the relation is a many to many
        """
        rel = self.__class__(self.id)
        rel.__primary_parent__ = container
        rel = rel.__of__(container)
        norelcopy = getattr(self, 'zNoRelationshipCopy', [])
        if self.id in norelcopy: return rel
        for oobj in self.objectValuesAll():
            cobj = oobj._getCopy(rel)
            rel._setObject(cobj.id, cobj)
        return rel

    def checkValidId(self, id):
        """
        Is this a valid id for this container?
        """
        try:
            checkValidId(self, id)
        except:
            raise
        else:
            return True

    def exportXml(self, ofile, ignorerels=[]):
        """Return an xml representation of a ToManyContRelationship
        <tomanycont id='interfaces'>
            <object id='hme0'
                module='Products.Confmon.IpInterface' class='IpInterface'>
                <property></property> etc....
            </object>
        </tomanycont>
        """
        if self.countObjects() == 0: return
        ofile.write("<tomanycont id='%s'>\n" % self.id)
        for obj in self.objectValues():
            obj.exportXml(ofile, ignorerels)
        ofile.write("</tomanycont>\n")

    def checkRelation(self, repair=False):
        """Check to make sure that relationship bidirectionality is ok.
        """
        if len(self._objects):
            log.debug("checking relation: %s", self.id)
        else:
            return

        # look for objects that don't point back to us
        # or who should no longer exist in the database
        remoteName = self.remoteName()
        parentObject = self.getPrimaryParent()
        for obj in self._objects.values():
            rrel = getattr(obj, remoteName)
            if not rrel.hasobject(parentObject):
                log.error("remote relation %s doesn't point back to %s",
                          rrel.getPrimaryId(), self.getPrimaryId())
                if repair:
                    log.warn("reconnecting relation %s to relation %s",
                             rrel.getPrimaryId(), self.getPrimaryId())
                    rrel._add(parentObject)
Exemple #34
0
class ReplicationTarget(CremeSimpleItem):

    meta_type = 'ReplicationTarget'

    _properties = (
        {'id':'url', 'type':'string', 'mode':'wd'},
        {'id':'username', 'type':'string', 'mode':'wd'},
        {'id':'password', 'type':'string', 'mode':'wd'},
    )

    def __init__(self, **kw):
        self._transactions = OOBTree()
        CremeSimpleItem.__init__(self, **kw)

    def log(self, entry_dict):
        t_id = self._p_jar._storage._serial
        if not self._transactions.has_key(t_id):
            self._transactions[t_id] = ReplogTransaction(t_id)
        transaction = self._transactions[t_id]
        transaction.add_entry(entry_dict)


    def replicate(self):
        """ replicate log to targets """
        keys = OOSet(self._transactions.keys())
        for key in keys:
            transaction = self._transactions[key]
            try:
                transaction.replicate(self)
                del self._transactions[key]
            except:
                from sys import exc_info
                import traceback
                info = exc_info()
                zlog('Replication',
                     'Could not replicate transaction %s to %s'%(
                        oid2str(transaction.id), self.id)) 
                break

    def html(self, suppress_entries=0):
        """ html log for viewing transactions in the ZMI """
        out = []
        keys = OOSet(self._transactions.keys())
        for t_id in keys:
            t = self._transactions[t_id]
            out.append('''
<h4>Transaction id: %s</h4>
<p>
<em>User:</em> %s<br/>
<em>Description:</em> %s<br/>
</p>
''' % (oid2str(t.id), t.user, t.description))
            if suppress_entries:
                continue
            for entry_id in t._entries.keys():
                entry = t._entries[entry_id]
                out.append('''
<p>
<em>id:</em> %(id)s<br/>
<em>obj:</em> %(path)s<br/>
<em>method:</em> %(method)s<br/>
<em>args:</em> %(args)s<br/>
</p>
''' % entry)
        out = '<hr>'.join(out)
        return '<html><body>%s</body></html>' % out
Exemple #35
0
class Folder(Persistent, Contained):
    """The standard Zope Folder implementation."""

    implements(IContentContainer)

    def __init__(self):
        self.data = OOBTree()

    def keys(self):
        """Return a sequence-like object containing the names
           associated with the objects that appear in the folder
        """
        return self.data.keys()

    def __iter__(self):
        return iter(self.data.keys())

    def values(self):
        """Return a sequence-like object containing the objects that
           appear in the folder.
        """
        return self.data.values()

    def items(self):
        """Return a sequence-like object containing tuples of the form
           (name, object) for the objects that appear in the folder.
        """
        return self.data.items()

    def __getitem__(self, name):
        """Return the named object, or raise ``KeyError`` if the object
           is not found.
        """
        return self.data[name]

    def get(self, name, default=None):
        """Return the named object, or the value of the `default`
           argument if the object is not found.
        """
        return self.data.get(name, default)

    def __contains__(self, name):
        """Return true if the named object appears in the folder."""
        return self.data.has_key(name)

    def __len__(self):
        """Return the number of objects in the folder."""
        return len(self.data)

    def __setitem__(self, name, object):
        """Add the given object to the folder under the given name."""

        if not (isinstance(name, str) or isinstance(name, unicode)):
            raise TypeError("Name must be a string rather than a %s" %
                            name.__class__.__name__)
        try:
            unicode(name)
        except UnicodeError:
            raise TypeError("Non-unicode names must be 7-bit-ascii only")
        if not name:
            raise TypeError("Name must not be empty")

        if name in self.data:
            raise KeyError("name, %s, is already in use" % name)

        setitem(self, self.data.__setitem__, name, object)

    def __delitem__(self, name):
        """Delete the named object from the folder. Raises a KeyError
           if the object is not found."""
        uncontained(self.data[name], self, name)
        del self.data[name]
Exemple #36
0
class VersionHistory(Implicit, Persistent):
    """A version history maintains the information about the changes
       to a particular version-controlled resource over time."""

    def __init__(self, history_id, object):
        # The _versions mapping maps version ids to version objects. All
        # of the actual version data is looked up there. The _labels
        # mapping maps labels to specific version ids. The _branches map
        # manages BranchInfo objects that maintain branch information.
        self._eventLog = EventLog()
        self._versions = OOBTree()
        self._branches = OOBTree()
        self._labels = OOBTree()
        self.createBranch('mainline', None)
        self.id = history_id

    security = ClassSecurityInfo()

    security.declarePublic('getId')
    def getId(self):
        return self.id

    security.declarePrivate('addLogEntry')
    def addLogEntry(self, version_id, action, path=None, message=''):
        """Add a new log entry associated with this version history."""
        entry = LogEntry(version_id, action, path, message)
        self._eventLog.addEntry(entry)

    security.declarePrivate('getLogEntries')
    def getLogEntries(self):
        """Return a sequence of the log entries for this version history."""
        return self._eventLog.getEntries()

    security.declarePrivate('getLabels')
    def getLabels(self):
        return self._labels.keys()

    security.declarePrivate('labelVersion')
    def labelVersion(self, version_id, label, force=0):
        """Associate a particular version in a version history with the
           given label, removing any existing association with that label
           if force is true, or raising an error if force is false and
           an association with the given label already exists."""
        current = self._labels.get(label)
        if current is not None:
            if current == version_id:
                return
            if not force:
                raise VersionControlError(
                    'The label %s is already associated with a version.' % (
                     label
                    ))
            del self._labels[label]
        self._labels[label] = version_id

    security.declarePrivate('createBranch')
    def createBranch(self, branch_id, version_id):
        """Create a new branch associated with the given branch_id. The
           new branch is rooted at the version named by version_id."""
        if self._branches.has_key(branch_id):
            raise VersionControlError(
                'Activity already exists: %s' % branch_id
                )
        branch = BranchInfo(branch_id, version_id)
        self._branches[branch_id] = branch
        return branch

    security.declarePrivate('createVersion')
    def createVersion(self, object, branch_id):
        """Create a new version in the line of descent named by the given
           branch_id, returning the newly created version object."""
        branch = self._branches.get(branch_id)
        if branch is None:
            branch = self.createBranch(branch_id, None)
        if branch.name != 'mainline':
            version_id = '%s.%d' % (branch.name, len(branch) + 1)
        else:
            version_id = '%d' % (len(branch) + 1)
        version = ZopeVersion(version_id, object)

        # Update the  predecessor, successor and branch relationships.
        # This is something of a hedge against the future. Versions will
        # always know enough to reconstruct their lineage without the help
        # of optimized data structures, which will make it easier to change
        # internals in the future if we need to.
        latest = branch.latest()
        if latest is not None:
            last = self._versions[latest]
            last.next = last.next + (version_id,)
            version.prev = latest

        # If the branch is not the mainline, store the branch name in the
        # version. Versions have 'mainline' as the default class attribute
        # which is the common case and saves a minor bit of storage space.
        if branch.name != 'mainline':
            version.branch = branch.name

        branch.append(version)
        self._versions[version_id] = version
        # Call saveState() only after version has been linked into the
        # database, ensuring it goes into the correct database.
        version.saveState(object)
        return version.__of__(self)

    security.declarePrivate('hasVersionId')
    def hasVersionId(self, version_id):
        """Return true if history contains a version with the given id."""
        return self._versions.has_key(version_id)

    security.declarePrivate('isLatestVersion')
    def isLatestVersion(self, version_id, branch_id):
        """Return true if version id is the latest in its branch."""
        branch = self._branches[branch_id]
        return version_id == branch.latest()

    security.declarePrivate('getLatestVersion')
    def getLatestVersion(self, branch_id):
        """Return the latest version object within the given branch, or
           None if the branch contains no versions."""
        branch = self._branches[branch_id]
        version = self._versions[branch.latest()]
        return version.__of__(self)

    security.declarePrivate('findBranchId')
    def findBranchId(self, version_id):
        """Given a version id, return the id of the branch of the version.
           Note that we cheat, since we can find this out from the id."""
        parts = version_id.split('.')
        if len(parts) > 1:
            return parts[-2]
        return 'mainline'

    security.declarePrivate('getVersionById')
    def getVersionById(self, version_id):
        """Return the version object named by the given version id, or
           raise a VersionControlError if the version is not found."""
        version = self._versions.get(version_id)
        if version is None:
            raise VersionControlError(
                'Unknown version id: %s' % version_id
                )
        return version.__of__(self)

    security.declarePrivate('getVersionByLabel')
    def getVersionByLabel(self, label):
        """Return the version associated with the given label, or None
           if no version matches the given label."""
        version_id = self._labels.get(label)
        version = self._versions.get(version_id)
        if version is None:
            return None
        return version.__of__(self)

    security.declarePrivate('getVersionByDate')
    def getVersionByDate(self, branch_id, timestamp):
        """Return the last version committed in the given branch on or
           before the given time value. The timestamp should be a float
           (time.time format) value in UTC."""
        branch = self._branches[branch_id]
        tvalue = int(timestamp / 60.0)
        while 1:
            # Try to find a version with a commit date <= the given time
            # using the timestamp index in the branch information.
            if branch.m_order:
                try:
                    match = branch.m_date.maxKey(tvalue)
                    match = branch.m_order[branch.m_date[match]]
                    return self._versions[match].__of__(self)
                except ValueError:
                    pass

            # If we've run out of lineage without finding a version with
            # a commit date <= the given timestamp, we return None. It is
            # up to the caller to decide what to do in this situation.
            if branch.root is None:
                return None

            # If the branch has a root (a version in another branch), then
            # we check the root and do it again with the ancestor branch.
            rootver = self._versions[branch.root]
            if int(rootver.date_created / 60.0) < tvalue:
                return rootver.__of__(self)
            branch = self._branches[rootver.branch]

    security.declarePrivate('getVersionIds')
    def getVersionIds(self, branch_id=None):
        """Return a sequence of version ids for the versions in this
           version history. If a branch_id is given, only version ids
           from that branch will be returned. Note that the sequence
           of ids returned does not include the id of the branch root."""
        if branch_id is not None:
            return self._branches[branch_id].versionIds()
        return self._versions.keys()
class ChallengeProtocolChooser(BasePlugin):

    """ PAS plugin for choosing challenger protocol based on request
    """

    meta_type = "Challenge Protocol Chooser Plugin"

    security = ClassSecurityInfo()

    manage_options = ({"label": "Mapping", "action": "manage_editProtocolMapping"},) + BasePlugin.manage_options

    def __init__(self, id, title=None, mapping=None):
        self._id = self.id = id
        self.title = title
        self._map = OOBTree()
        if mapping is not None:
            self.manage_updateProtocolMapping(mapping=mapping)

    security.declarePrivate("chooseProtocols")

    def chooseProtocols(self, request):
        pas_instance = self._getPAS()
        plugins = pas_instance._getOb("plugins")

        sniffers = plugins.listPlugins(IRequestTypeSniffer)

        for sniffer_id, sniffer in sniffers:
            request_type = sniffer.sniffRequestType(request)
            if request_type is not None:
                return self._getProtocolsFor(request_type)

    def _getProtocolsFor(self, request_type):
        label = _request_type_bmap.get(request_type, None)
        if label is None:
            return
        return self._map.get(label, None)

    def _listProtocols(self):
        pas_instance = self._getPAS()
        plugins = pas_instance._getOb("plugins")

        challengers = plugins.listPlugins(IChallengePlugin)
        found = []

        for challenger_id, challenger in challengers:
            protocol = getattr(challenger, "protocol", challenger_id)
            if protocol not in found:
                found.append(protocol)

        return found

    manage_editProtocolMappingForm = PageTemplateFile(
        "www/cpcEdit", globals(), __name__="manage_editProtocolMappingForm"
    )

    def manage_editProtocolMapping(self, REQUEST=None):
        """ Edit Protocol Mapping
        """
        info = []
        available_protocols = self._listProtocols()

        request_types = listRequestTypesLabels()
        request_types.sort()

        for label in request_types:
            settings = []
            select_any = False
            info.append({"label": label, "settings": settings})
            protocols = self._map.get(label, None)
            if not protocols:
                select_any = True
            for protocol in available_protocols:
                selected = False
                if protocols and protocol in protocols:
                    selected = True
                settings.append({"label": protocol, "selected": selected, "value": protocol})

            settings.insert(0, {"label": "(any)", "selected": select_any, "value": ""})
        return self.manage_editProtocolMappingForm(info=info, REQUEST=REQUEST)

    def manage_updateProtocolMapping(self, mapping, REQUEST=None):
        """ Update mapping of Request Type to Protocols
        """
        for key, value in mapping.items():
            value = filter(None, value)
            if not value:
                if self._map.has_key(key):
                    del self._map[key]
            else:
                self._map[key] = value

        if REQUEST is not None:
            REQUEST["RESPONSE"].redirect(
                "%s/manage_editProtocolMapping"
                "?manage_tabs_message="
                "Protocol+Mappings+Changed." % self.absolute_url()
            )
Exemple #38
0
class Folder(Persistent, Contained):
    """The standard Zope Folder implementation."""

    implements(IContentContainer)

    def __init__(self):
        self.data = OOBTree()

    def keys(self):
        """Return a sequence-like object containing the names
           associated with the objects that appear in the folder
        """
        return self.data.keys()

    def __iter__(self):
        return iter(self.data.keys())

    def values(self):
        """Return a sequence-like object containing the objects that
           appear in the folder.
        """
        return self.data.values()

    def items(self):
        """Return a sequence-like object containing tuples of the form
           (name, object) for the objects that appear in the folder.
        """
        return self.data.items()

    def __getitem__(self, name):
        """Return the named object, or raise ``KeyError`` if the object
           is not found.
        """
        return self.data[name]

    def get(self, name, default=None):
        """Return the named object, or the value of the `default`
           argument if the object is not found.
        """
        return self.data.get(name, default)

    def __contains__(self, name):
        """Return true if the named object appears in the folder."""
        return self.data.has_key(name)

    def __len__(self):
        """Return the number of objects in the folder."""
        return len(self.data)

    def __setitem__(self, name, object):
        """Add the given object to the folder under the given name."""

        if not (isinstance(name, str) or isinstance(name, unicode)):
            raise TypeError("Name must be a string rather than a %s" %
                            name.__class__.__name__)
        try:
            unicode(name)
        except UnicodeError:
            raise TypeError("Non-unicode names must be 7-bit-ascii only")
        if not name:
            raise TypeError("Name must not be empty")

        if name in self.data:
            raise KeyError("name, %s, is already in use" % name)

        setitem(self, self.data.__setitem__, name, object)

    def __delitem__(self, name):
        """Delete the named object from the folder. Raises a KeyError
           if the object is not found."""
        uncontained(self.data[name], self, name)
        del self.data[name]
Exemple #39
0
class CategoryIndex(Persistent):
    def __init__(self):
        self._idxCategItem = OOBTree()

    def dump(self):
        return list(self._idxCategItem.items())

    def _indexConfById(self, categid, confid):
        # only the more restrictive setup is taken into account
        categid = str(categid)
        if self._idxCategItem.has_key(categid):
            res = self._idxCategItem[categid]
        else:
            res = []
        res.append(confid)
        self._idxCategItem[categid] = res

    def unindexConf(self, conf):
        confid = str(conf.getId())
        self.unindexConfById(confid)

    def unindexConfById(self, confid):
        for categid in self._idxCategItem.keys():
            if confid in self._idxCategItem[categid]:
                res = self._idxCategItem[categid]
                res.remove(confid)
                self._idxCategItem[categid] = res

    def reindexCateg(self, categ):
        for subcat in categ.getSubCategoryList():
            self.reindexCateg(subcat)
        for conf in categ.getConferenceList():
            self.reindexConf(conf)

    def reindexConf(self, conf):
        self.unindexConf(conf)
        self.indexConf(conf)

    def indexConf(self, conf):
        categs = conf.getOwnerPath()
        level = 0
        for categ in conf.getOwnerPath():
            if conf.getFullVisibility() > level:
                self._indexConfById(categ.getId(), conf.getId())
            level += 1
        if conf.getFullVisibility() > level:
            self._indexConfById("0", conf.getId())

    def getItems(self, categid):
        categid = str(categid)
        if self._idxCategItem.has_key(categid):
            return self._idxCategItem[categid]
        else:
            return []

    def _check(self, dbi=None):
        """
        Performs some sanity checks
        """
        i = 0
        from MaKaC.conference import ConferenceHolder
        confIdx = ConferenceHolder()._getIdx()

        for cid, confs in self._idxCategItem.iteritems():
            for confId in confs:
                # it has to be in the conference holder
                if confId not in confIdx:
                    yield "[%s] '%s' not in ConferenceHolder" % (cid, confId)
                # the category has to be one of the owners
                elif cid not in (map(
                        lambda x: x.id,
                        ConferenceHolder().getById(confId).getOwnerPath()) +
                                 ['0']):
                    yield "[%s] Conference '%s' is not owned" % (cid, confId)
            if dbi and i % 100 == 99:
                dbi.sync()
            i += 1
class Repository(Implicit, Persistent):
    """The repository implementation manages the actual data of versions
       and version histories. It does not handle user interface issues."""

    def __init__(self):
        # These keep track of symbolic label and branch names that
        # have been used to ensure that they don't collide.
        self._branches = OIBTree()
        self._branches['mainline'] = 1
        self._labels = OIBTree()

        self._histories = OOBTree()
        self._created = time.time()

    security = ClassSecurityInfo()

    security.declarePrivate('createVersionHistory')
    def createVersionHistory(self, object):
        """Internal: create a new version history for a resource."""
        # When one creates the first version in a version history, neither
        # the version or version history yet have a _p_jar, which causes
        # copy operations to fail. To work around that, we share our _p_jar.
        history_id = None
        while history_id is None or self._histories.has_key(history_id):
            history_id = str(randint(1, 9999999999))
        history = ZopeVersionHistory(history_id, object)
        self._histories[history_id] = history
        return history.__of__(self)

    security.declarePrivate('getVersionHistory')
    def getVersionHistory(self, history_id):
        """Internal: return a version history given a version history id."""
        return self._histories[history_id].__of__(self)

    security.declarePrivate('replaceState')
    def replaceState(self, obj, new_state):
        """Internal: replace the state of a persistent object.
        """
        non_versioned = getNonVersionedData(obj)
        # XXX There ought to be some way to do this more cleanly.
        # This fills the __dict__ of the old object with new state.
        # The other way to achieve the desired effect is to replace
        # the object in its container, but this method preserves the
        # identity of the object.
        if obj.__class__ is not new_state.__class__:
            raise VersionControlError(
                "The class of the versioned object has changed. %s != %s"
                % (repr(obj.__class__, new_state.__class__)))
        obj._p_changed = 1
        for key in obj.__dict__.keys():
            if not new_state.__dict__.has_key(key):
                del obj.__dict__[key]
        for key, value in new_state.__dict__.items():
            obj.__dict__[key] = value
        if non_versioned:
            # Restore the non-versioned data into the new state.
            restoreNonVersionedData(obj, non_versioned)
        return obj

    #####################################################################
    # This is the implementation of the public version control interface.
    #####################################################################

    security.declarePublic('isAVersionableResource')
    def isAVersionableResource(self, obj):
        # For now, an object must be persistent (have its own db record)
        # in order to be considered a versionable resource.
        return isAVersionableResource(obj)

    security.declarePublic('isUnderVersionControl')
    def isUnderVersionControl(self, object):
        return hasattr(object, '__vc_info__')

    security.declarePublic('isResourceUpToDate')
    def isResourceUpToDate(self, object, require_branch=0):
        info = self.getVersionInfo(object)
        history = self.getVersionHistory(info.history_id)
        branch = 'mainline'
        if info.sticky:
            if info.sticky[0] == 'B':
                branch = info.sticky[1]
            elif require_branch:
                # The object is updated to a particular version
                # rather than a branch.  The caller
                # requires a branch.
                return 0
        return history.isLatestVersion(info.version_id, branch)

    security.declarePublic('isResourceChanged')
    def isResourceChanged(self, object):
        # Return true if the state of a resource has changed in a transaction
        # *after* the version bookkeeping was saved. Note that this method is
        # not appropriate for detecting changes within a transaction!
        info = self.getVersionInfo(object)
        itime = getattr(info, '_p_mtime', None)
        if itime is None:
            return 0
        mtime = Utility._findModificationTime(object)
        if mtime is None:
            return 0
        return mtime > itime

    security.declarePublic('getVersionInfo')
    def getVersionInfo(self, object):
        info = getattr(object, '__vc_info__', None)
        if info is not None:
            return info
        raise VersionControlError(
            'The specified resource is not under version control.'
            )

    security.declareProtected(use_vc_permission, 'applyVersionControl')
    def applyVersionControl(self, object, message=None):
        if self.isUnderVersionControl(object):
            raise VersionControlError(
                'The resource is already under version control.'
                )
        if not self.isAVersionableResource(object):
            raise VersionControlError(
                'This resource cannot be put under version control.'
                )

        # Need to check the parent to see if the container of the object
        # being put under version control is itself a version-controlled
        # object. If so, we need to use the branch id of the container.
        branch = 'mainline'
        parent = aq_parent(aq_inner(object))
        p_info = getattr(parent, '__vc_info__', None)
        if p_info is not None:
            sticky = p_info.sticky
            if sticky and sticky[0] == 'B':
                branch = sticky[1]

        # Create a new version history and initial version object.
        history = self.createVersionHistory(object)
        version = history.createVersion(object, branch)

        history_id = history.getId()
        version_id = version.getId()

        # Add bookkeeping information to the version controlled object.
        info = VersionInfo(history_id, version_id, VersionInfo.CHECKED_IN)
        if branch != 'mainline':
            info.sticky = ('B', branch)
        object.__vc_info__ = info

        # Save an audit record of the action being performed.
        history.addLogEntry(version_id,
                            LogEntry.ACTION_CHECKIN,
                            _findPath(object),
                            message is None and 'Initial checkin.' or message
                            )
        return object

    security.declareProtected(use_vc_permission, 'checkoutResource')
    def checkoutResource(self, object):
        info = self.getVersionInfo(object)
        if info.status != info.CHECKED_IN:
            raise VersionControlError(
                'The selected resource is already checked out.'
                )

        if info.sticky and info.sticky[0] != 'B':
            raise VersionControlError(
                'The selected resource has been updated to a particular '
                'version, label or date. The resource must be updated to '
                'the mainline or a branch before it may be checked out.'
                )

        if not self.isResourceUpToDate(object):
            raise VersionControlError(
                'The selected resource is not up to date!'
                )

        history = self.getVersionHistory(info.history_id)
        ob_path = _findPath(object)

        # Save an audit record of the action being performed.
        history.addLogEntry(info.version_id,
                            LogEntry.ACTION_CHECKOUT,
                            ob_path
                            )

        # Update bookkeeping information.
        newinfo = info.clone()
        newinfo.status = newinfo.CHECKED_OUT
        object.__vc_info__ = newinfo
        return object

    security.declareProtected(use_vc_permission, 'checkinResource')
    def checkinResource(self, object, message=''):
        info = self.getVersionInfo(object)
        if info.status != info.CHECKED_OUT:
            raise VersionControlError(
                'The selected resource is not checked out.'
                )

        if info.sticky and info.sticky[0] != 'B':
            raise VersionControlError(
                'The selected resource has been updated to a particular '
                'version, label or date. The resource must be updated to '
                'the mainline or a branch before it may be checked in.'
                )

        if not self.isResourceUpToDate(object):
            raise VersionControlError(
                'The selected resource is not up to date!'
                )

        history = self.getVersionHistory(info.history_id)
        ob_path = _findPath(object)

        branch = 'mainline'
        if info.sticky is not None and info.sticky[0] == 'B':
            branch = info.sticky[1]

        version = history.createVersion(object, branch)

        # Save an audit record of the action being performed.
        history.addLogEntry(version.getId(),
                            LogEntry.ACTION_CHECKIN,
                            ob_path,
                            message
                            )

        # Update bookkeeping information.
        newinfo = info.clone()
        newinfo.version_id = version.getId()
        newinfo.status = newinfo.CHECKED_IN
        object.__vc_info__ = newinfo
        return object

    security.declareProtected(use_vc_permission, 'uncheckoutResource')
    def uncheckoutResource(self, object):
        info = self.getVersionInfo(object)
        if info.status != info.CHECKED_OUT:
            raise VersionControlError(
                'The selected resource is not checked out.'
                )

        history = self.getVersionHistory(info.history_id)
        ob_path = _findPath(object)

        version = history.getVersionById(info.version_id)
        new_obj = version.copyState()

        # Save an audit record of the action being performed.
        history.addLogEntry(info.version_id,
                            LogEntry.ACTION_UNCHECKOUT,
                            ob_path
                            )

        # Replace the state of the object with a reverted state.
        new_obj = self.replaceState(object, new_obj)

        # Update bookkeeping information.
        newinfo = info.clone()
        newinfo.version_id = version.getId()
        newinfo.status = newinfo.CHECKED_IN
        new_obj.__vc_info__ = newinfo
        return new_obj

    security.declareProtected(use_vc_permission, 'updateResource')
    def updateResource(self, object, selector=None):
        info = self.getVersionInfo(object)
        if info.status != info.CHECKED_IN:
            raise VersionControlError(
                'The selected resource must be checked in to be updated.'
                )

        history = self.getVersionHistory(info.history_id)
        version = None
        sticky = info.sticky

        if not selector:
            # If selector is null, update to the latest version taking any
            # sticky attrs into account (branch, date). Note that the sticky
            # tag could also be a date or version id. We don't bother checking
            # for those, since in both cases we do nothing (because we'll
            # always be up to date until the sticky tag changes).
            if sticky and sticky[0] == 'L':
                # A label sticky tag, so update to that label (since it is
                # possible, but unlikely, that the label has been moved).
                version = history.getVersionByLabel(sticky[1])
            elif sticky and sticky[0] == 'B':
                # A branch sticky tag. Update to latest version on branch.
                version = history.getLatestVersion(selector)
            else:
                # Update to mainline, forgetting any date or version id
                # sticky tag that was previously associated with the object.
                version = history.getLatestVersion('mainline')
                sticky = None
        else:
            # If the selector is non-null, we find the version specified
            # and update the sticky tag. Later we'll check the version we
            # found and decide whether we really need to update the object.
            if history.hasVersionId(selector):
                version = history.getVersionById(selector)
                sticky = ('V', selector)

            elif self._labels.has_key(selector):
                version = history.getVersionByLabel(selector)
                sticky = ('L', selector)

            elif self._branches.has_key(selector):
                version = history.getLatestVersion(selector)
                if selector == 'mainline':
                    sticky = None
                else:
                    sticky = ('B', selector)
            else:
                try:    date = DateTime(selector)
                except:
                    raise VersionControlError(
                        'Invalid version selector: %s' % selector
                        )
                else:
                    timestamp = date.timeTime()
                    sticky = ('D', timestamp)
                    # Fix!
                    branch = history.findBranchId(info.version_id)
                    version = history.getVersionByDate(branch, timestamp)

        # If the state of the resource really needs to be changed, do the
        # update and make a log entry for the update.
        version_id = version and version.getId() or info.version_id
        new_object = object
        if version and (version_id != info.version_id):
            new_object = version.copyState()
            new_object = self.replaceState(object, new_object)

            history.addLogEntry(version_id,
                                LogEntry.ACTION_UPDATE,
                                _findPath(new_object)
                                )

        # Update bookkeeping information.
        newinfo = info.clone(1)
        newinfo.version_id = version_id
        newinfo.status = newinfo.CHECKED_IN
        if sticky is not None:
            newinfo.sticky = sticky
        new_object.__vc_info__ = newinfo
        return new_object

    security.declareProtected(use_vc_permission, 'labelResource')
    def labelResource(self, object, label, force=0):
        info = self.getVersionInfo(object)
        if info.status != info.CHECKED_IN:
            raise VersionControlError(
                'The selected resource must be checked in to be labeled.'
                )

        # Make sure that labels and branch ids do not collide.
        if self._branches.has_key(label) or label == 'mainline':
            raise VersionControlError(
                'The label value given is already in use as an activity id.'
                )
        if not self._labels.has_key(label):
            self._labels[label] = 1

        history = self.getVersionHistory(info.history_id)
        history.labelVersion(info.version_id, label, force)
        return object

    security.declareProtected(use_vc_permission, 'makeActivity')
    def makeActivity(self, object, branch_id):
        # Note - this is not part of the official version control API yet.
        # It is here to allow unit testing of the architectural aspects
        # that are already in place to support activities in the future.

        info = self.getVersionInfo(object)
        if info.status != info.CHECKED_IN:
            raise VersionControlError(
                'The selected resource must be checked in.'
                )

        branch_id = branch_id or None

        # Make sure that activity ids and labels do not collide.
        if self._labels.has_key(branch_id) or branch_id == 'mainline':
            raise VersionControlError(
                'The value given is already in use as a version label.'
                )

        if not self._branches.has_key(branch_id):
            self._branches[branch_id] = 1

        history = self.getVersionHistory(info.history_id)

        if history._branches.has_key(branch_id):
            raise VersionControlError(
                'The resource is already associated with the given activity.'
                )

        history.createBranch(branch_id, info.version_id)
        return object

    security.declareProtected(use_vc_permission, 'getVersionOfResource')
    def getVersionOfResource(self, history_id, selector):
        history = self.getVersionHistory(history_id)
        sticky = None

        if not selector or selector == 'mainline':
            version = history.getLatestVersion('mainline')
        else:
            if history.hasVersionId(selector):
                version = history.getVersionById(selector)
                sticky = ('V', selector)

            elif self._labels.has_key(selector):
                version = history.getVersionByLabel(selector)
                sticky = ('L', selector)

            elif self._branches.has_key(selector):
                version = history.getLatestVersion(selector)
                sticky = ('B', selector)
            else:
                try: date = DateTime(selector)
                except:
                    raise VersionControlError(
                        'Invalid version selector: %s' % selector
                        )
                else:
                    timestamp = date.timeTime()
                    sticky = ('D', timestamp)
                    version = history.getVersionByDate('mainline', timestamp)

        object = version.copyState()

        info = VersionInfo(history_id, version.getId(), VersionInfo.CHECKED_IN)
        if sticky is not None:
            info.sticky = sticky
        object.__vc_info__ = info
        return object

    security.declareProtected(use_vc_permission, 'getVersionIds')
    def getVersionIds(self, object):
        info = self.getVersionInfo(object)
        history = self.getVersionHistory(info.history_id)
        return history.getVersionIds()

    security.declareProtected(use_vc_permission, 'getLabelsForResource')
    def getLabelsForResource(self, object):
        info = self.getVersionInfo(object)
        history = self.getVersionHistory(info.history_id)
        return history.getLabels()

    security.declareProtected(use_vc_permission, 'getLogEntries')
    def getLogEntries(self, object):
        info = self.getVersionInfo(object)
        history = self.getVersionHistory(info.history_id)
        return history.getLogEntries()
Exemple #41
0
class LookupTable(base.Base):
    "LookupTable class"

    meta_type = "LookupTable"
    security = ClassSecurityInfo()
    records = None
    recordsLength = None

    drawDict = base.Base.drawDict.copy()
    drawDict['drawTable'] = 'drawTable'

    security.declareProtected('View management screens', 'edit')
    def edit(self, *args, **kw):
        "Inline edit short object"
        format = "<p>Currently there are %s records</p><div>%s</div>"
        if self.records is None:
            self.records = OOBTree()
        lenRecords = self.recordsLength() if self.recordsLength is not None else 0
        return format % (lenRecords, self.create_button('clear', "Clear"))

    security.declarePrivate('processRecorderChanges')
    def processRecorderChanges(self, form):
        "process the recorder changes"
        clear = form.pop('clear', None)
        if clear is not None:
            self.clear()

    security.declarePrivate('after_manage_edit')
    def before_manage_edit(self, form):
        "process the edits"
        self.processRecorderChanges(form)

    security.declareProtected('View management screens', "drawTable")
    def drawTable(self):
        "Render page"
        temp = []
        format = '<p>%s:%s</p>'
        if self.records is not None:
            for key,value in self.records.items():
                temp.append(format % (repr(key), repr(value)))
        return ''.join(temp)

    security.declareProtected('Python Record Modification', 'insert')
    def insert(self, key, value):
        "modify this key and value into the OOBTree"
        if self.records is None:
            self.records = OOBTree()
        if self.recordsLength is None:
            self.setObject('recordsLength' ,BTrees.Length.Length())
        
        if key not in self.records:
            self.recordsLength.change(1)
        self.records.insert(key,value)

    security.declareProtected('Python Record Modification', 'add')
    def add(self, key, value):
        "this this key and value into the OOBTree"
        if self.records is None:
            self.records = OOBTree()
        if self.recordsLength is None:
            self.setObject('recordsLength' ,BTrees.Length.Length())
        
        if key not in self.records:
            self.recordsLength.change(1)
        self.records[key] = value

    security.declareProtected('Python Record Access', 'items')
    def items(self, min=None, max=None):
        "return the items in this OOBTree"
        if self.records is None:
            return []
        return self.records.items(min, max)

    security.declareProtected('Python Record Access', 'values')
    def values(self, min=None, max=None):
        "return the values of this OOBTree"
        if self.records is None:
            return []
        return self.records.values(min, max)

    security.declareProtected('Python Record Modification', 'update')
    def update(self, collection):
        "update our OOBTree with the data in collection"
        if self.records is None:
            self.records = OOBTree()
        if self.recordsLength is None:
            self.setObject('recordsLength' ,BTrees.Length.Length())
        
        records = self.records
        change = self.recordsLength.change
        for key,value in collection.items():
            if key not in records:
                change(1)
            records[key] = value

    security.declareProtected('Python Record Access', 'keys')
    def keys(self, min=None, max=None):
        "return the keys of this OOBTree"
        if self.records is None:
            return []
        return self.records.keys(min,max)

    security.declareProtected('Python Record Modification', '__delitem__')
    def __delitem__(self, key):
        "delete this key from the OOBTree"
        if self.records is not None:
            del self.records[key]
            self.recordsLength.change(-1)

    security.declareProtected('Python Record Modification', 'remove')
    def remove(self, key):
        "delete this key from the OOBTree"
        if self.records is not None:
            del self.records[key]
            self.recordsLength.change(-1)

    security.declareProtected('Python Record Modification', '__setitem__')
    def __setitem__(self, key, value):
        "set this key and value in the OOBTree"
        if self.records is None:
            self.records = OOBTree()
        self.records[key] = value

    security.declareProtected('Python Record Access', '__getitem__')
    def __getitem__(self, index):
        "get this item from the OOBTree"
        if self.records is not None:
            return self.records[index]
        raise KeyError, index

    security.declareProtected('Python Record Access', 'get')
    def get(self, key, default=None):
        "get this item from the OOBTree"
        if self.records is not None:
            return self.records.get(key,default)
        return default

    security.declareProtected('Python Record Access', 'has_key')
    def has_key(self, key):
        "see if we have this key in the OOBTree"
        if self.records is not None:
            return self.records.has_key(key)
        return False

    security.declareProtected('Python Record Modification', 'clear')
    def clear(self):
        "clear the OOBTree"
        self.setObject('records', None)
        self.setObject('recordsLength', None)
        
    security.declarePrivate("PrincipiaSearchSource")
    def PrincipiaSearchSource(self):
        "This is the basic search function"
        return ''
      
    security.declarePrivate('classUpgrader')
    def classUpgrader(self):
        "upgrade this class"
        self.createBTreeLength() 
      
    security.declarePrivate('createBTreeLength')
    def createBTreeLength(self):
        "remove Filters that are not being used"
        if self.records is not None:
            length = BTrees.Length.Length()
            length.set(len(self.records))
            self.setObject('recordsLength', length)
    createBTreeLength = utility.upgradeLimit(createBTreeLength, 165)
Exemple #42
0
class BTreeFolder2Base (Persistent):
    """Base for BTree-based folders.
    """

    security = ClassSecurityInfo()

    manage_options=(
        ({'label':'Contents', 'action':'manage_main',},
         ) + Folder.manage_options[1:]
        )

    security.declareProtected(view_management_screens,
                              'manage_main')
    manage_main = DTMLFile('contents', globals())

    _tree = None      # OOBTree: { id -> object }
    _count = None     # A BTrees.Length
    _v_nextid = 0     # The integer component of the next generated ID
    _mt_index = None  # OOBTree: { meta_type -> OIBTree: { id -> 1 } }
    title = ''


    def __init__(self, id=None):
        if id is not None:
            self.id = id
        self._initBTrees()

    def _initBTrees(self):
        self._tree = OOBTree()
        self._count = Length()
        self._mt_index = OOBTree()


    def _populateFromFolder(self, source):
        """Fill this folder with the contents of another folder.
        """
        for name in source.objectIds():
            value = source._getOb(name, None)
            if value is not None:
                self._setOb(name, aq_base(value))


    security.declareProtected(view_management_screens, 'manage_fixCount')
    def manage_fixCount(self):
        """Calls self._fixCount() and reports the result as text.
        """
        old, new = self._fixCount()
        path = '/'.join(self.getPhysicalPath())
        if old == new:
            return "No count mismatch detected in BTreeFolder2 at %s." % path
        else:
            return ("Fixed count mismatch in BTreeFolder2 at %s. "
                    "Count was %d; corrected to %d" % (path, old, new))


    def _fixCount(self):
        """Checks if the value of self._count disagrees with
        len(self.objectIds()). If so, corrects self._count. Returns the
        old and new count values. If old==new, no correction was
        performed.
        """
        old = self._count()
        new = len(self.objectIds())
        if old != new:
            self._count.set(new)
        return old, new


    security.declareProtected(view_management_screens, 'manage_cleanup')
    def manage_cleanup(self):
        """Calls self._cleanup() and reports the result as text.
        """
        v = self._cleanup()
        path = '/'.join(self.getPhysicalPath())
        if v:
            return "No damage detected in BTreeFolder2 at %s." % path
        else:
            return ("Fixed BTreeFolder2 at %s.  "
                    "See the log for more details." % path)


    def _cleanup(self):
        """Cleans up errors in the BTrees.

        Certain ZODB bugs have caused BTrees to become slightly insane.
        Fortunately, there is a way to clean up damaged BTrees that
        always seems to work: make a new BTree containing the items()
        of the old one.

        Returns 1 if no damage was detected, or 0 if damage was
        detected and fixed.
        """
        from BTrees.check import check
        path = '/'.join(self.getPhysicalPath())
        try:
            check(self._tree)
            for key in self._tree.keys():
                if not self._tree.has_key(key):
                    raise AssertionError(
                        "Missing value for key: %s" % repr(key))
            check(self._mt_index)
            for key, value in self._mt_index.items():
                if (not self._mt_index.has_key(key)
                    or self._mt_index[key] is not value):
                    raise AssertionError(
                        "Missing or incorrect meta_type index: %s"
                        % repr(key))
                check(value)
                for k in value.keys():
                    if not value.has_key(k):
                        raise AssertionError(
                            "Missing values for meta_type index: %s"
                            % repr(key))
            return 1
        except AssertionError:
            LOG.warn( 'Detected damage to %s. Fixing now.' % path,
                exc_info=True)
            try:
                self._tree = OOBTree(self._tree)
                mt_index = OOBTree()
                for key, value in self._mt_index.items():
                    mt_index[key] = OIBTree(value)
                self._mt_index = mt_index
            except:
                LOG.error('Failed to fix %s.' % path,
                    exc_info=True)
                raise
            else:
                LOG.info('Fixed %s.' % path)
            return 0


    def _getOb(self, id, default=_marker):
        """Return the named object from the folder.
        """
        tree = self._tree
        if default is _marker:
            ob = tree[id]
            return ob.__of__(self)
        else:
            ob = tree.get(id, _marker)
            if ob is _marker:
                return default
            else:
                return ob.__of__(self)


    def _setOb(self, id, object):
        """Store the named object in the folder.
        """
        tree = self._tree
        if tree.has_key(id):
            raise KeyError('There is already an item named "%s".' % id)
        tree[id] = object
        self._count.change(1)
        # Update the meta type index.
        mti = self._mt_index
        meta_type = getattr(object, 'meta_type', None)
        if meta_type is not None:
            ids = mti.get(meta_type, None)
            if ids is None:
                ids = OIBTree()
                mti[meta_type] = ids
            ids[id] = 1


    def _delOb(self, id):
        """Remove the named object from the folder.
        """
        tree = self._tree
        meta_type = getattr(tree[id], 'meta_type', None)
        del tree[id]
        self._count.change(-1)
        # Update the meta type index.
        if meta_type is not None:
            mti = self._mt_index
            ids = mti.get(meta_type, None)
            if ids is not None and ids.has_key(id):
                del ids[id]
                if not ids:
                    # Removed the last object of this meta_type.
                    # Prune the index.
                    del mti[meta_type]


    security.declareProtected(view_management_screens, 'getBatchObjectListing')
    def getBatchObjectListing(self, REQUEST=None):
        """Return a structure for a page template to show the list of objects.
        """
        if REQUEST is None:
            REQUEST = {}
        pref_rows = int(REQUEST.get('dtpref_rows', 20))
        b_start = int(REQUEST.get('b_start', 1))
        b_count = int(REQUEST.get('b_count', 1000))
        b_end = b_start + b_count - 1
        url = self.absolute_url() + '/manage_main'
        idlist = self.objectIds()  # Pre-sorted.
        count = self.objectCount()

        if b_end < count:
            next_url = url + '?b_start=%d' % (b_start + b_count)
        else:
            b_end = count
            next_url = ''

        if b_start > 1:
            prev_url = url + '?b_start=%d' % max(b_start - b_count, 1)
        else:
            prev_url = ''

        formatted = []
        formatted.append(listtext0 % pref_rows)
        for i in range(b_start - 1, b_end):
            optID = escape(idlist[i])
            formatted.append(listtext1 % (escape(optID, quote=1), optID))
        formatted.append(listtext2)
        return {'b_start': b_start, 'b_end': b_end,
                'prev_batch_url': prev_url,
                'next_batch_url': next_url,
                'formatted_list': ''.join(formatted)}


    security.declareProtected(view_management_screens,
                              'manage_object_workspace')
    def manage_object_workspace(self, ids=(), REQUEST=None):
        '''Redirects to the workspace of the first object in
        the list.'''
        if ids and REQUEST is not None:
            REQUEST.RESPONSE.redirect(
                '%s/%s/manage_workspace' % (
                self.absolute_url(), quote(ids[0])))
        else:
            return self.manage_main(self, REQUEST)


    security.declareProtected(access_contents_information,
                              'tpValues')
    def tpValues(self):
        """Ensures the items don't show up in the left pane.
        """
        return ()


    security.declareProtected(access_contents_information,
                              'objectCount')
    def objectCount(self):
        """Returns the number of items in the folder."""
        return self._count()


    security.declareProtected(access_contents_information, 'has_key')
    def has_key(self, id):
        """Indicates whether the folder has an item by ID.
        """
        return self._tree.has_key(id)


    security.declareProtected(access_contents_information,
                              'objectIds')
    def objectIds(self, spec=None):
        # Returns a list of subobject ids of the current object.
        # If 'spec' is specified, returns objects whose meta_type
        # matches 'spec'.
        if spec is not None:
            if isinstance(spec, StringType):
                spec = [spec]
            mti = self._mt_index
            set = None
            for meta_type in spec:
                ids = mti.get(meta_type, None)
                if ids is not None:
                    set = union(set, ids)
            if set is None:
                return ()
            else:
                return set.keys()
        else:
            return self._tree.keys()


    security.declareProtected(access_contents_information,
                              'objectValues')
    def objectValues(self, spec=None):
        # Returns a list of actual subobjects of the current object.
        # If 'spec' is specified, returns only objects whose meta_type
        # match 'spec'.
        return LazyMap(self._getOb, self.objectIds(spec))


    security.declareProtected(access_contents_information,
                              'objectItems')
    def objectItems(self, spec=None):
        # Returns a list of (id, subobject) tuples of the current object.
        # If 'spec' is specified, returns only objects whose meta_type match
        # 'spec'
        return LazyMap(lambda id, _getOb=self._getOb: (id, _getOb(id)),
                       self.objectIds(spec))


    security.declareProtected(access_contents_information,
                              'objectMap')
    def objectMap(self):
        # Returns a tuple of mappings containing subobject meta-data.
        return LazyMap(lambda (k, v):
                       {'id': k, 'meta_type': getattr(v, 'meta_type', None)},
                       self._tree.items(), self._count())

    # superValues() looks for the _objects attribute, but the implementation
    # would be inefficient, so superValues() support is disabled.
    _objects = ()


    security.declareProtected(access_contents_information,
                              'objectIds_d')
    def objectIds_d(self, t=None):
        ids = self.objectIds(t)
        res = {}
        for id in ids:
            res[id] = 1
        return res


    security.declareProtected(access_contents_information,
                              'objectMap_d')
    def objectMap_d(self, t=None):
        return self.objectMap()


    def _checkId(self, id, allow_dup=0):
        if not allow_dup and self.has_key(id):
            raise BadRequestException, ('The id "%s" is invalid--'
                                        'it is already in use.' % id)


    def _setObject(self, id, object, roles=None, user=None, set_owner=1,
                   suppress_events=False):
        ob = object # better name, keep original function signature
        v = self._checkId(id)
        if v is not None:
            id = v

        # If an object by the given id already exists, remove it.
        if self.has_key(id):
            self._delObject(id)

        if not suppress_events:
            notify(ObjectWillBeAddedEvent(ob, self, id))

        self._setOb(id, ob)
        ob = self._getOb(id)

        if set_owner:
            # TODO: eventify manage_fixupOwnershipAfterAdd
            # This will be called for a copy/clone, or a normal _setObject.
            ob.manage_fixupOwnershipAfterAdd()

            # Try to give user the local role "Owner", but only if
            # no local roles have been set on the object yet.
            if getattr(ob, '__ac_local_roles__', _marker) is None:
                user = getSecurityManager().getUser()
                if user is not None:
                    userid = user.getId()
                    if userid is not None:
                        ob.manage_setLocalRoles(userid, ['Owner'])

        if not suppress_events:
            notify(ObjectAddedEvent(ob, self, id))
            notifyContainerModified(self)

        OFS.subscribers.compatibilityCall('manage_afterAdd', ob, ob, self)

        return id


    def _delObject(self, id, dp=1, suppress_events=False):
        ob = self._getOb(id)

        OFS.subscribers.compatibilityCall('manage_beforeDelete', ob, ob, self)

        if not suppress_events:
            notify(ObjectWillBeRemovedEvent(ob, self, id))

        self._delOb(id)

        if not suppress_events:
            notify(ObjectRemovedEvent(ob, self, id))
            notifyContainerModified(self)


    # Aliases for mapping-like access.
    __len__ = objectCount
    keys = objectIds
    values = objectValues
    items = objectItems

    # backward compatibility
    hasObject = has_key

    security.declareProtected(access_contents_information, 'get')
    def get(self, name, default=None):
        return self._getOb(name, default)


    # Utility for generating unique IDs.

    security.declareProtected(access_contents_information, 'generateId')
    def generateId(self, prefix='item', suffix='', rand_ceiling=999999999):
        """Returns an ID not used yet by this folder.

        The ID is unlikely to collide with other threads and clients.
        The IDs are sequential to optimize access to objects
        that are likely to have some relation.
        """
        tree = self._tree
        n = self._v_nextid
        attempt = 0
        while 1:
            if n % 4000 != 0 and n <= rand_ceiling:
                id = '%s%d%s' % (prefix, n, suffix)
                if not tree.has_key(id):
                    break
            n = randint(1, rand_ceiling)
            attempt = attempt + 1
            if attempt > MAX_UNIQUEID_ATTEMPTS:
                # Prevent denial of service
                raise ExhaustedUniqueIdsError
        self._v_nextid = n + 1
        return id

    def __getattr__(self, name):
        # Boo hoo hoo!  Zope 2 prefers implicit acquisition over traversal
        # to subitems, and __bobo_traverse__ hooks don't work with
        # restrictedTraverse() unless __getattr__() is also present.
        # Oh well.
        res = self._tree.get(name)
        if res is None:
            raise AttributeError, name
        return res
Exemple #43
0
class Scanner:
    """Scanning for an ApeStorage.

    Uses gateways to scan for changes.
    """
    def __init__(self):
        self.current = OOBTree()  # OOBTree({ oid -> {source->state} })
        self.future = {}  # { oid -> ({source->state}, atime) }
        self.lock = allocate_lock()
        self.storage = None

    def set_oids(self, oids):
        """Sets the list of OIDs to scan.

        Gathers source information about new OIDs and discards
        source information for OIDs no longer in use.
        """
        new_sources = {}  # { oid -> sourcedict }
        self.lock.acquire()
        try:
            removed = difference(self.current, oids)
            for oid in removed.keys():
                del self.current[oid]
            added = difference(oids, self.current)
            for oid in added.keys():
                if self.future.has_key(oid):
                    # Source info for this OID was provided earlier.
                    sources, atime = self.future[oid]
                    del self.future[oid]
                    self.current[oid] = sources
                else:
                    new_sources[oid] = None
        finally:
            self.lock.release()
        if new_sources:
            # Load source info the slow way.
            if self.storage is not None:
                LOG('Ape', DEBUG,
                    'Getting sources for %d oids.' % len(new_sources))
                new_sources = self.storage.get_all_sources(new_sources.keys())
            else:
                LOG(
                    'Ape', DEBUG, "Can't get sources for %d oids. "
                    "Assuming no sources!" % len(new_sources))
                # This will cause the scanner to miss changes, but
                # since no storage is known, there is little we can
                # do.
                for oid in new_sources.keys():
                    new_sources[oid] = {}
            self.lock.acquire()
            try:
                for oid, sources in new_sources.items():
                    if not self.current.has_key(oid):
                        self.current[oid] = sources
                    # else something else added the source info
                    # while self.lock was released.
            finally:
                self.lock.release()

    def after_load(self, oid, sources):
        """Called by the storage after an object is loaded.
        """
        if sources is None:
            sources = {}
        self.lock.acquire()
        try:
            if not self.current.has_key(oid):
                # This object is being loaded for the first time.
                # Make a record of its current state immediately
                # so that the next scan can pick up changes.
                self.future[oid] = (sources, time())
            # else we already have info about this object, and now
            # isn't a good time to update self.current since that
            # would prevent changes from being detected at a time when
            # it's possible to send invalidation messages.
        finally:
            self.lock.release()

    def scan(self):
        """Scan sources, returning the OIDs of changed objects.
        """
        to_scan = {}  # { repo -> { source -> state } }
        to_invalidate = {}  # { oid -> 1 }
        self.lock.acquire()  # lock because oid_states might be self.current.
        try:
            for oid, sources in self.current.items():
                for source, state in sources.items():
                    repo, location = source
                    to_scan.setdefault(repo, {})[source] = state
        finally:
            self.lock.release()
        changes = {}
        for repo, d in to_scan.items():
            c = repo.poll(d)
            if c:
                changes.update(c)
        if changes:
            # Something changed.  Map the changes back to oids and
            # update self.current.
            self.lock.acquire()
            try:
                for oid, sources in self.current.items():
                    for source, state in sources.items():
                        if changes.has_key(source):
                            to_invalidate[oid] = 1
                            sources[source] = changes[source]
            finally:
                self.lock.release()
        return to_invalidate.keys()

    def prune_future(self):
        """Prunes the cache of future source information.
        """
        if self.future:
            self.lock.acquire()
            try:
                # OIDs older than some timeout will probably never be loaded.
                cutoff = time() - future_timeout
                for oid, (sources, atime) in self.future.items():
                    if atime < cutoff:
                        del self.future[oid]
            finally:
                self.lock.release()
            LOG('Ape', DEBUG,
                'Future sources cache size: %d objects.' % len(self.future))

    def changed_sources(self, oid, sources):
        """Records changes to sources made by ZODB.
        """
        self.current[oid] = sources
        if self.future.has_key(oid):
            del self.future[oid]
Exemple #44
0
class TagNode(persistent.Persistent):
    """ Node of TagTree.
    """

    def __init__(self, name, parent=None):
        """
        :param name:
            Name of this TaggedNode. (Not a full name.) None means
            that this node is a root of tree.
        :type name: unicode or None
        :param parent: Parent node of this.
        :type parent: TagNode
        """

        self._name = name
        self._parent = parent
        self._children = OOBTree()
        self._objects = IOBTree()

    def destroy(self):
        """ Untags all objects, tagged by this TagNode, and also destroys
        all children recursively.
        """

        for node in self._children.values():
            node.destroy()

        tag = self.get_tag()
        for obj in list(self._objects.values()):
            obj.remove_tag(tag)

    def get_parent(self):
        """ Returns parent node.
        """
        return self._parent

    def get_name(self):
        """ Returns name (tag level) of this node.
        """
        return self._name

    def create_child_node(self, name):
        """ Creates and returns child node.
        """

        if self._children.has_key(name):
            raise KeyError(
                    u'TagNode already has child with name {0}.'.format(
                        name))
        else:
            self._children[name] = TagNode(name, self)
            return self._children[name]

    def delete_child_node(self, name):
        """ Deletes child node.
        """

        if not self._children.has_key(name):
            raise KeyError(
                    u'TagNode does not have child with name {0}.'.format(
                        name))
        else:
            self._children[name].destroy()
            del self._children[name]

    def get_child_node(self, name):
        """ Returns child node.
        """

        try:
            return self._children[name]
        except KeyError:
            raise KeyError(
                    u'TagNode does not have child with name {0}.'.format(
                        name))

    def get_tag(self):
        """ Returns :py:class:`Tag`, which this node represents.
        """

        levels = []
        node = self
        while node.get_parent():
            levels.append(node.get_name())
            node = node.get_parent()
        return Tag(reversed(levels))

    def add_object(self, obj):
        """ Adds object to tagged objects list.
        """

        if self._objects.has_key(obj.get_id()):
            raise KeyError(u'Object already tagged.')
        else:
            self._objects[obj.get_id()] = obj

    def remove_object(self, obj):
        """ Removes object from tagged objects list.

        :param obj: TaggedObject id or TaggedObject itself.
        """

        if isinstance(obj, int):
            del self._objects[obj]
        else:
            del self._objects[obj.get_id()]

    def get_object(self, object_id):
        """ Returns object by its id.
        """

        return self._objects[object_id]

    def get_object_dict(self, tag, filter):
        """ Returns dict (id->object) of all children nodes objects tagged
        with tag for which filter returns True.

        If ``tag`` is None, returns all objects (nodes and its children)
        which pass filter.

        :type tag: list of unicode strings or None
        """

        if tag is None or len(tag) == 0:
            # Collect all objects.
            objects = dict([
                (obj.get_id(), obj)
                for obj in self._objects.values() if filter(obj)])
            for node in self._children.values():
                objects.update(node.get_object_dict(None, filter))
            return objects
        else:
            # Recursively call child node.
            name = tag.pop()
            return self._children[name].get_object_dict(tag, filter)

    def get_object_list(self, tag=None, filter=lambda x: True):
        """ Returns list of all objects which passes tag and filter.

        +   If ``tag`` is None, returns all objects, which passes filter.
        +   Otherwise returns objects, which belongs to child TagNode
            with full name ``tag``, and which passes filter.

        :type tag: Tag or None
        """

        if tag is None:
            return self.get_object_dict(tag, filter).values()
        else:
            return self.get_object_dict(
                    list(reversed(tag.as_tuple())), filter).values()
Exemple #45
0
class TopicIndex(Persistent, SimpleItem):

    """A TopicIndex maintains a set of FilteredSet objects.

    Every FilteredSet object consists of an expression and and IISet with all
    Ids of indexed objects that eval with this expression to 1.
    """
    implements(ITopicIndex, IPluggableIndex)

    meta_type="TopicIndex"
    query_options = ('query', 'operator')

    manage_options= (
        {'label': 'FilteredSets', 'action': 'manage_main'},
    )

    def __init__(self,id,caller=None):
        self.id = id
        self.filteredSets  = OOBTree()
        self.operators = ('or','and')
        self.defaultOperator = 'or'

    def getId(self):
        return self.id

    def clear(self):
        for fs in self.filteredSets.values():
            fs.clear()

    def index_object(self, docid, obj ,threshold=100):
        """ hook for (Z)Catalog """
        for fid, filteredSet in self.filteredSets.items():
            filteredSet.index_object(docid,obj)
        return 1

    def unindex_object(self,docid):
        """ hook for (Z)Catalog """

        for fs in self.filteredSets.values():
            try:
                fs.unindex_object(docid)
            except KeyError:
                LOG.debug('Attempt to unindex document'
                          ' with id %s failed' % docid)
        return 1

    def numObjects(self):
        """Return the number of indexed objects."""
        return "n/a"

    def indexSize(self):
        """Return the size of the index in terms of distinct values."""
        return "n/a"

    def search(self,filter_id):
        if self.filteredSets.has_key(filter_id):
            return self.filteredSets[filter_id].getIds()

    def _apply_index(self, request):
        """ hook for (Z)Catalog
            'request' --  mapping type (usually {"topic": "..." }
        """
        record = parseIndexRequest(request, self.id, self.query_options)
        if record.keys is None:
            return None

        operator = record.get('operator', self.defaultOperator).lower()
        if operator == 'or':  set_func = union
        else: set_func = intersection

        res = None
        for filter_id in record.keys:
            rows = self.search(filter_id)
            res = set_func(res,rows)

        if res:
            return res, (self.id,)
        else:
            return IITreeSet(), (self.id,)

    def uniqueValues(self,name=None, withLength=0):
        """ needed to be consistent with the interface """
        return self.filteredSets.keys()

    def getEntryForObject(self,docid, default=_marker):
        """ Takes a document ID and returns all the information we have
            on that specific object.
        """
        return self.filteredSets.keys()

    def addFilteredSet(self, filter_id, typeFilteredSet, expr):
        # Add a FilteredSet object.
        if self.filteredSets.has_key(filter_id):
            raise KeyError,\
                'A FilteredSet with this name already exists: %s' % filter_id
        self.filteredSets[filter_id] = factory(filter_id,
                                               typeFilteredSet,
                                               expr,
                                              )

    def delFilteredSet(self, filter_id):
        # Delete the FilteredSet object specified by 'filter_id'.
        if not self.filteredSets.has_key(filter_id):
            raise KeyError,\
                'no such FilteredSet:  %s' % filter_id
        del self.filteredSets[filter_id]

    def clearFilteredSet(self, filter_id):
        # Clear the FilteredSet object specified by 'filter_id'.
        if not self.filteredSets.has_key(filter_id):
            raise KeyError,\
                'no such FilteredSet:  %s' % filter_id
        self.filteredSets[filter_id].clear()

    def manage_addFilteredSet(self, filter_id, typeFilteredSet, expr, URL1, \
            REQUEST=None,RESPONSE=None):
        """ add a new filtered set """

        if len(filter_id) == 0: raise RuntimeError,'Length of ID too short'
        if len(expr) == 0: raise RuntimeError,'Length of expression too short'

        self.addFilteredSet(filter_id, typeFilteredSet, expr)

        if RESPONSE:
            RESPONSE.redirect(URL1+'/manage_workspace?'
            'manage_tabs_message=FilteredSet%20added')

    def manage_delFilteredSet(self, filter_ids=[], URL1=None, \
            REQUEST=None,RESPONSE=None):
        """ delete a list of FilteredSets"""

        for filter_id in filter_ids:
            self.delFilteredSet(filter_id)

        if RESPONSE:
            RESPONSE.redirect(URL1+'/manage_workspace?'
            'manage_tabs_message=FilteredSet(s)%20deleted')

    def manage_saveFilteredSet(self,filter_id, expr, URL1=None,\
            REQUEST=None,RESPONSE=None):
        """ save expression for a FilteredSet """

        self.filteredSets[filter_id].setExpression(expr)

        if RESPONSE:
            RESPONSE.redirect(URL1+'/manage_workspace?'
            'manage_tabs_message=FilteredSet(s)%20updated')

    def getIndexSourceNames(self):
        """ return names of indexed attributes """
        return ('n/a',)

    def getIndexQueryNames(self):
        return (self.id,)

    def manage_clearFilteredSet(self, filter_ids=[], URL1=None, \
            REQUEST=None,RESPONSE=None):
        """  clear a list of FilteredSets"""

        for filter_id in filter_ids:
            self.clearFilteredSet(filter_id)

        if RESPONSE:
            RESPONSE.redirect(URL1+'/manage_workspace?'
             'manage_tabs_message=FilteredSet(s)%20cleared')

    manage = manage_main = DTMLFile('dtml/manageTopicIndex',globals())
    manage_main._setName('manage_main')
    editFilteredSet = DTMLFile('dtml/editFilteredSet',globals())
Exemple #46
0
class Issue(ListText):
    "this object represents a single votable Issue"

    security = ClassSecurityInfo()
    meta_type = "Issue"
    storage = None
    votes = None
    description = ""
    addType = "IssueChoice"
    selectionType = "radio"
    selectionLimit = 1
    selectionLimitMin = 0
    format = "<div>%s</div>"
    MustSelectOne = "<strong>At least one choice must be made.</strong>"
    TooManyItems = "<strong>Too many items where selected.</strong>"
    NotEnoughItems = "<strong>Not Enough items where selected.</strong>"
    BadItemSelected = """<strong>An item was selected that does not exist.
    You should never see this message please email the webmaster.</strong>"""
    voteText = """%(error)s<div class="issue"><div class="issueDescription">%(description)s</div>
      <div class="issueChoices">%(issues)s</div></div>
    """
    alreadyVotedText = "<p>You have already voted</p>"
    noVotingAllowed = "<p>Voting is not currently allowed</p>"
    thankYouText = "<p>Thank you for voting</p>"
    deleteButtonText = "Delete Issue Choice"
    addButtonText = "Add Issue Choice"

    selectionAllowedTypes = (("radio", "Single Selection"), ("checkbox", "Multiple Selection"))

    classConfig = {}
    classConfig["selectionLimit"] = {
        "name": "If you have selected multiple selection mode how many choices can people make (MAX)?",
        "type": "int",
    }
    classConfig["selectionLimitMin"] = {
        "name": "If you have selected multiple selection mode how many choices do people have to make? (MIN)",
        "type": "int",
    }
    classConfig["selectionType"] = {"name": "Allowed Selections", "type": "list", "values": selectionAllowedTypes}
    classConfig["description"] = {"name": "Issue Description", "type": "text"}

    drawDict = ListText.drawDict.copy()
    drawDict["vote"] = "drawVote"
    drawDict["voteChecked"] = "drawVoteChecked"
    drawDict["report"] = "drawReport"

    security.declareProtected("View management screens", "edit")

    def edit(self, *args, **kw):
        "Inline edit view"
        temp = self.editSingleConfig("description")
        temp += self.editSingleConfig("selectionType")
        temp += self.editSingleConfig("selectionLimit")
        temp += self.editSingleConfig("selectionLimitMin")
        return temp + ListText.edit(self)

    security.declareProtected("CompoundDoc: Voting", "alternate_security_edit")

    def alternate_security_edit(self, dict):
        "save the voting information if it is okay to do so"
        choices = None
        if "choices" in dict:
            choices = dict.get("choices").values()
            del dict["choices"]
        if choices:
            choices = [choice for choice in choices if choice]
            uid = self.getUID()
            if self.isOkayToVote(uid):
                self.vote(uid, choices)

    security.declareProtected("CompoundDoc: Voting", "drawVote")

    def drawVote(self):
        "draw the voting interface"
        return self.drawVoteChecked()[1]

    security.declareProtected("CompoundDoc: Voting", "drawVoteChecked")

    def drawVoteChecked(self):
        "draw the voting interface"
        structure = self.voteStructure()
        structure["error"], messageType = self.drawError()
        uid = self.getUID()
        if messageType == "thankYouText":
            return (False, self.getMessage("thankYouText", structure))
        if self.voteEnabled:
            if self.isOkayToVote(uid):
                return (True, self.getMessage("voteText", structure))
            elif self.alreadyVoted(uid):
                return (False, self.getMessage("alreadyVotedText", structure))
            else:
                return (False, self.getMessage("notAllowedToVote", structure))
        else:
            return (False, self.getMessage("noVotingAllowed", structure))

    security.declarePrivate("getMessage")

    def getMessage(self, messageType, lookup):
        """if we have a url for a set of messages to use on errors go ahead and use that otherwise use the default string we have
        and get variables from this lookup(dictionary) object"""
        folder = self.getMessageFolder()
        if folder is not None:
            item = getattr(folder, messageType, None)
            if item is not None:
                return item.__of__(self)(lookup)
        return getattr(self, messageType) % lookup

    security.declarePrivate("drawError")

    def drawError(self):
        "draw any needed any message"
        return self.getErrorMessage()

    def hasErrorMessage(self):
        "do we have an error message to draw?"
        messages = self.REQUEST.other.get("messages", {})
        return self.getPhysicalPath() in messages

    def getErrorMessage(self):
        "get the current Error Message"
        messages = self.REQUEST.other.get("messages", {})
        return messages.get(self.getPhysicalPath(), ("", ""))

    def writeErrorMessage(self, message, messageType):
        "write the current error message so we can get it later"
        messages = self.REQUEST.other.get("messages", {})
        messages[self.getPhysicalPath()] = (message, messageType)
        self.REQUEST.other["messages"] = messages

    security.declarePrivate("voteStructure")

    def voteStructure(self):
        "get the voting data structure"
        lookup = {}
        lookup["description"] = self.description

        temp = []
        if len(self):
            if self.selectionType == "radio":
                choices = [(choice.view(), choice.view()) for choice in self]
                temp = self.radio_list("radio", choices, containers=("choices",))
                formName = self.formName("radio", "string", ("choices",))
                temp.append('<input type="hidden" name="%s:default" value="">' % formName)
            elif self.selectionType == "checkbox":
                formName = self.formName("default", "string", ("choices",))
                temp.append('<input type="hidden" name="%s:default" value="">' % formName)
                for choice in self:
                    temp.append(self.check_box(choice.getId(), choice.view(), ("choices",)) + choice.view())
            if temp:
                temp = [self.format % i for i in temp]

        lookup["issues"] = "".join(temp)
        return lookup

    security.declarePrivate("isOkayToVote")

    def isOkayToVote(self, uid):
        "is it okay to vote"
        try:
            if (
                getSecurityManager().validate(None, self, "drawVote", self.drawVote)
                and self.voteEnabled
                and not self.alreadyVoted(uid)
                and self.isOkayToVoteUserDefined()
            ):
                return True
        except Unauthorized:
            pass

    security.declarePrivate("alreadyVoted")

    def alreadyVoted(self, uid):
        "is it okay to vote"
        return self.getStorage().has_key(uid)

    security.declarePrivate("drawReport")

    def drawReport(self):
        "draw a basic report of the voting results"
        results = self.report()
        results = [(votes, issueName) for issueName, votes in results]
        results.sort(reverse=True)
        results.insert(0, ("Number of Votes", "Choice"))
        results.append(("Total Number of Votes", len(self.getStorage())))
        temp = "<p>%s</p>" % self.description
        temp += self.createTable(results)
        return temp

    security.declarePrivate("report")

    def report(self):
        "return the report of how the votes went"
        return self.getVotes().items()

    security.declareProtected("CompoundDoc: Voting Stats", "getVotes")

    def getVotes(self):
        "get the current vote information"
        if self.votes is not None:
            return self.votes
        return OOBTree()

    security.declareProtected("CompoundDoc: Voting Stats", "getStorage")

    def getStorage(self):
        "get the current storage information which is a mapping of who has voted"
        if self.storage is not None:
            return self.storage
        return OOBTree()

    security.declareProtected("View", "vote")

    def vote(self, uid, choices):
        "increase the count for this choice in votes if this uid is not already recorded"
        if self.isValidChoices(choices) and not self.getStorage().has_key(uid):
            self.uidVoted(uid)
            self.choiceSelected(choices)

    security.declarePrivate("isValidChoices")

    def isValidChoices(self, choices):
        "return true if all of the choices given are valid given the state of this object"
        allowedLength = 1
        allowedLengthMin = 0
        lookup = {}
        if self.selectionType == "checkbox":
            allowedLength = self.selectionLimit
            allowedLengthMin = self.selectionLimitMin
        lookup["selected"] = len(choices)
        lookup["max_selected"] = allowedLength
        lookup["min_selected"] = allowedLengthMin
        lookup["bad_choice"] = ""
        if not len(choices):
            self.writeErrorMessage(self.getMessage("MustSelectOne", lookup), "MustSelectOne")
            return 0
        if len(choices) > allowedLength:
            self.writeErrorMessage(self.getMessage("TooManyItems", lookup), "TooManyItems")
            return 0
        if len(choices) < allowedLengthMin:
            self.writeErrorMessage(self.getMessage("NotEnoughItems", lookup), "NotEnoughItems")
            return 0
        allowedChoices = [i.view() for i in self]
        for choice in choices:
            if choice not in allowedChoices:
                lookup["bad_choice"] = choice
                self.writeErrorMessage(self.getMessage("BadItemSelected", lookup), "BadItemSelected")
                return 0
        return 1

    security.declarePrivate("uidVoted")

    def uidVoted(self, uid):
        "record that this uid has voted for this issue"
        if self.storage is None:
            self.storage = OOBTree()
        if not self.storage.has_key(uid):
            self.storage[uid] = True

    security.declarePrivate("choiceSelected")

    def choiceSelected(self, choices):
        "increment the counter for this choice"
        if self.votes is None:
            self.votes = OOBTree()
        lookup = {}
        lookup["choices"] = choices
        self.writeErrorMessage(self.getMessage("thankYouText", lookup), "thankYouText")
        for choice in choices:
            count = self.votes.get(choice, 0)
            count += 1
            self.votes[choice] = count

    security.declarePrivate("classUpgrader")

    def classUpgrader(self):
        "upgrade this class"
        return None
Exemple #47
0
class Calendar:
    """This class represents a calendar which is a set of days which contain
        information about which conferences whithin certain categories are
        happening for each of these days and for a certain access. This class
        allows to configure the date interval and the category set to be
        considered and provides operations which allow to know about what's
        happening on each of those days.

       Attributes:
        _aw - (accessControl.AccessWrapper) Information about the access for
            which the calendar will be built.
        _sDate - (datetime) Starting date for the calendar.
        _eDate - (datetime) Ending date for the calendar.
        _categList - (List) List of categories to be considered.
        _days - (OOBTree) Index of days which build up the calendar.
    """
    def __init__(self, aw, sDate, eDate, categList=[]):
        self._aw = aw
        self._tz = sDate.tzinfo
        self._sDate = sDate.replace(hour=0, minute=0, second=0, microsecond=0)
        self._eDate = eDate.replace(hour=23,
                                    minute=59,
                                    second=59,
                                    microsecond=0)
        self._categList = categList
        self._icons = {}
        self._days = None

    def getIcons(self):
        try:
            return self._icons
        except:
            self._icons = {}
            return {}

    def setIcons(self, categ):
        """Retrieves the list of icons in a given category tree
        """
        if categ.getIcon() != None:
            return [categ.getId()]
        res = []
        for subcat in categ.getSubCategoryList():
            res += self.setIcons(subcat)
        return res

    def getStartDate(self):
        return self._sDate

    def getEndDate(self):
        return self._eDate

    def getCategoryList(self):
        return self._categList

    def getLocator(self):
        """Returns the generic locator for the current object. This locator
            contains the folloing entries corresponding to values for which
            the calendar is configured:
                selCateg -> List of category ids.
                sDate -> Starting date.
                eDate -> Ending date.
        """
        l = Locators.Locator()
        ids = []
        for c in self.getCategoryList():
            ids.append(c.getId())
        l["selCateg"] = ids
        l["sDate"] = self.getStartDate().strftime("%Y-%m-%d")
        l["eDate"] = self.getStartDate().strftime("%Y-%m-%d")
        return l

    def _mapConferenceToDays(self, conf, categList):
        """Registers a given conference for the days on which it is taking place
            whithin the calendar date interval.

           Parameters:
            conf - (conference.Conference) Conference to be mapped.
            categList - (List) List of calendar categories in which the
                specified conference is found.
        """

        inc = timedelta(1)
        d = max(
            conf.getStartDate().astimezone(self._tz).replace(hour=0,
                                                             minute=0,
                                                             second=0),
            self.getStartDate().astimezone(self._tz).replace(hour=0,
                                                             minute=0,
                                                             second=0))
        ed = min(conf.getEndDate().astimezone(self._tz),
                 self.getEndDate().astimezone(self._tz))
        if ed > self.getEndDate():
            ed = self.getEndDate()

        while d <= ed:
            #norm_date=d.tzinfo.normalize(d)
            #norm_date=norm_date.replace(hour=0)
            norm_date = self.getNormDate(d)
            if not self._days.has_key(norm_date):
                self._days[norm_date] = Day(self, d)

            self._days[norm_date].addConference(conf, categList, self._tz)
            d += inc

    def _initialiseDays(self):
        """
        """
        self._days = OOBTree()
        res = set()
        self._categIdx = {}
        self._icons = {}
        catDayIdx = indexes.IndexesHolder().getIndex("categoryDate")
        for categ in self.getCategoryList():
            confs = catDayIdx.getObjectsInDays(categ.getId(),
                                               self.getStartDate(),
                                               self.getEndDate())
            for conf in confs:
                confId = conf.getId()
                if not self._categIdx.has_key(confId):
                    self._categIdx[confId] = []
                self._categIdx[confId].append(categ)
            res.update(confs)
        for conf in res:
            #getting icon from the nearest owner category
            owner = conf.getOwner()
            while owner != None and owner.getId() != "0":
                if owner.getIcon():
                    if self._icons.has_key(owner.getId()):
                        self._icons[owner.getId()].append(conf.getId())
                    else:
                        self._icons[owner.getId()] = [conf.getId()]
                    break
                owner = owner.getOwner()
            #mapping conf to days
            self._mapConferenceToDays(conf, self._categIdx[conf.getId()])

    def getNormDate(self, date):
        # we have to normalize, but as we are going over all the days, we have to keep the date
        # and just normalize the tzinfo.
        norm_date = date.tzinfo.normalize(date)
        norm_date = norm_date.replace(year=date.year,
                                      month=date.month,
                                      day=date.day,
                                      hour=0)
        return norm_date

    def getDay(self, date):
        if not self._days:
            self._initialiseDays()
        norm_date = self.getNormDate(date)
        if not self._days.has_key(norm_date):
            self._days[norm_date] = Day(self, date)
        return self._days[norm_date]

    def getDayList(self):
        inc = timedelta(1)
        d = self.getStartDate()
        l = []
        while d < self.getEndDate():
            l.append(self.getDay(d))
            d += inc
        return l

    def getConferenceCategories(self, conf):
        return self._categIdx[conf.getId()]

    def __str__(self):
        l = []
        if self._days:
            for day in self._days.values():
                l.append("%s" % day)
        str =  _("Calendar between %s and %s: %s")%(\
                            self.getStartDate().strftime("%Y-%m-%d"), \
                            self.getEndDate().strftime("%Y-%m-%d"), \
                            "\n\t\t".join(l) )
        return str
class ExtendedPathIndex(PathIndex):
    """ A path index stores all path components of the physical
    path of an object:

    Internal datastructure (regular pathindex):

    - a physical path of an object is split into its components

    - every component is kept as a  key of a OOBTree in self._indexes

    - the value is a mapping 'level of the path component' to
      'all docids with this path component on this level'

    In addition
    
    - there is a terminator (None) signifying the last component in the path

    """

    meta_type = "ExtendedPathIndex"

    manage_options = ({
        'label':
        'Settings',
        'action':
        'manage_main',
        'help': ('ExtendedPathIndex', 'ExtendedPathIndex_Settings.stx')
    }, )

    query_options = ("query", "level", "operator", "depth", "navtree",
                     "navtree_start")

    def __init__(self, id, extra=None, caller=None):
        """ ExtendedPathIndex supports indexed_attrs """
        PathIndex.__init__(self, id, caller)

        def get(o, k, default):
            if isinstance(o, dict):
                return o.get(k, default)
            else:
                return getattr(o, k, default)

        attrs = get(extra, 'indexed_attrs', None)
        if attrs is None:
            return
        if isinstance(attrs, str):
            attrs = attrs.split(',')
        attrs = filter(None, [a.strip() for a in attrs])

        if attrs:
            # We only index the first attribute so snip off the rest
            self.indexed_attrs = tuple(attrs[:1])

    def clear(self):
        PathIndex.clear(self)
        self._index_parents = OOBTree()
        self._index_items = OIBTree()

    def insertEntry(self, comp, id, level, parent_path=None, object_path=None):
        """Insert an entry.

           parent_path is the path of the parent object

           path is the object path, it is assumed to be unique, i.e. there
           is a one to one mapping between physical paths and docids.  This
           will be large, and is only used for breadcrumbs.

           id is the docid
        """

        PathIndex.insertEntry(self, comp, id, level)

        if parent_path is not None:
            if not self._index_parents.has_key(parent_path):
                self._index_parents[parent_path] = IISet()

            self._index_parents[parent_path].insert(id)

        # We make the assumption that a full path corresponds one and only
        # one object.

        if object_path is not None:
            self._index_items[object_path] = id

    def index_object(self, docid, obj, threshold=100):
        """ hook for (Z)Catalog """

        # PathIndex first checks for an attribute matching its id and
        # falls back to getPhysicalPath only when failing to get one.
        # The presence of 'indexed_attrs' overrides this behavior and
        # causes indexing of the custom attribute.

        attrs = getattr(self, 'indexed_attrs', None)
        if attrs:
            index = attrs[0]
        else:
            index = self.id

        f = getattr(obj, index, None)
        if f is not None:
            if safe_callable(f):
                try:
                    path = f()
                except AttributeError:
                    return 0
            else:
                path = f

            if not isinstance(path, (str, tuple)):
                raise TypeError('path value must be string or tuple '
                                'of strings: (%r, %s)' % (index, repr(path)))
        else:
            try:
                path = obj.getPhysicalPath()
            except AttributeError:
                return 0

        if isinstance(path, (list, tuple)):
            path = '/' + '/'.join(path[1:])
        comps = filter(None, path.split('/'))
        parent_path = '/' + '/'.join(comps[:-1])

        # Make sure we reindex properly when path change
        if self._unindex.has_key(docid) and self._unindex.get(docid) != path:
            self.unindex_object(docid)

        if not self._unindex.has_key(docid):
            self._length.change(1)

        for i in range(len(comps)):
            self.insertEntry(comps[i], docid, i)

        # Add terminator
        self.insertEntry(None, docid, len(comps) - 1, parent_path, path)

        self._unindex[docid] = path
        return 1

    def unindex_object(self, docid):
        """ hook for (Z)Catalog """

        if not self._unindex.has_key(docid):
            logger.log(
                logging.INFO, 'Attempt to unindex nonexistent object with id '
                '%s' % docid)
            return

        # There is an assumption that paths start with /
        path = self._unindex[docid]
        if not path.startswith('/'):
            path = '/' + path
        comps = path.split('/')
        parent_path = '/'.join(comps[:-1])

        def unindex(comp,
                    level,
                    docid=docid,
                    parent_path=None,
                    object_path=None):
            try:
                self._index[comp][level].remove(docid)

                if not self._index[comp][level]:
                    del self._index[comp][level]

                if not self._index[comp]:
                    del self._index[comp]
                # Remove parent_path and object path elements
                if parent_path is not None:
                    self._index_parents[parent_path].remove(docid)
                    if not self._index_parents[parent_path]:
                        del self._index_parents[parent_path]
                if object_path is not None:
                    del self._index_items[object_path]
            except KeyError:
                logger.log(
                    logging.INFO, 'Attempt to unindex object with id '
                    '%s failed' % docid)

        for level in range(len(comps[1:])):
            comp = comps[level + 1]
            unindex(comp, level)

        # Remove the terminator
        level = len(comps[1:])
        comp = None
        unindex(comp, level - 1, parent_path=parent_path, object_path=path)

        self._length.change(-1)
        del self._unindex[docid]

    def search(self,
               path,
               default_level=0,
               depth=-1,
               navtree=0,
               navtree_start=0):
        """
        path is either a string representing a
        relative URL or a part of a relative URL or
        a tuple (path,level).

        level >= 0  starts searching at the given level
        level <  0  not implemented yet
        """

        if isinstance(path, basestring):
            startlevel = default_level
        else:
            startlevel = int(path[1])
            path = path[0]

        absolute_path = isinstance(path, basestring) and path.startswith('/')

        comps = filter(None, path.split('/'))

        orig_comps = [''] + comps[:]
        # Optimization - avoid using the root set
        # as it is common for all objects anyway and add overhead
        # There is an assumption about catalog/index having
        # the same container as content
        if default_level == 0:
            indexpath = list(filter(None, self.getPhysicalPath()))
            while min(len(indexpath), len(comps)):
                if indexpath[0] == comps[0]:
                    del indexpath[0]
                    del comps[0]
                    startlevel += 1
                else:
                    break

        if len(comps) == 0:
            if depth == -1 and not navtree:
                return IISet(self._unindex.keys())

        # Make sure that we get depth = 1 if in navtree mode
        # unless specified otherwise

        orig_depth = depth
        if depth == -1:
            depth = 0 or navtree

        # Optimized navtree starting with absolute path
        if absolute_path and navtree and depth == 1 and default_level == 0:
            set_list = []
            # Insert root element
            if navtree_start >= len(orig_comps):
                navtree_start = 0
            # create a set of parent paths to search
            for i in range(len(orig_comps), navtree_start, -1):
                parent_path = '/'.join(orig_comps[:i])
                parent_path = parent_path and parent_path or '/'
                try:
                    set_list.append(self._index_parents[parent_path])
                except KeyError:
                    pass
            return multiunion(set_list)
        # Optimized breadcrumbs
        elif absolute_path and navtree and depth == 0 and default_level == 0:
            item_list = IISet()
            # Insert root element
            if navtree_start >= len(orig_comps):
                navtree_start = 0
            # create a set of parent paths to search
            for i in range(len(orig_comps), navtree_start, -1):
                parent_path = '/'.join(orig_comps[:i])
                parent_path = parent_path and parent_path or '/'
                try:
                    item_list.insert(self._index_items[parent_path])
                except KeyError:
                    pass
            return item_list
        # Specific object search
        elif absolute_path and orig_depth == 0 and default_level == 0:
            try:
                return IISet([self._index_items[path]])
            except KeyError:
                return IISet()
        # Single depth search
        elif absolute_path and orig_depth == 1 and default_level == 0:
            # only get objects contained in requested folder
            try:
                return self._index_parents[path]
            except KeyError:
                return IISet()
        # Sitemaps, relative paths, and depth queries
        elif startlevel >= 0:

            pathset = None  # Same as pathindex
            navset = None  # For collecting siblings along the way
            depthset = None  # For limiting depth

            if navtree and depth and \
                   self._index.has_key(None) and \
                   self._index[None].has_key(startlevel):
                navset = self._index[None][startlevel]

            for level in range(startlevel, startlevel + len(comps) + depth):
                if level - startlevel < len(comps):
                    comp = comps[level - startlevel]
                    if not self._index.has_key(
                            comp) or not self._index[comp].has_key(level):
                        # Navtree is inverse, keep going even for
                        # nonexisting paths
                        if navtree:
                            pathset = IISet()
                        else:
                            return IISet()
                    else:
                        pathset = intersection(pathset,
                                               self._index[comp][level])
                    if navtree and depth and \
                           self._index.has_key(None) and \
                           self._index[None].has_key(level+depth):
                        navset = union(
                            navset,
                            intersection(pathset,
                                         self._index[None][level + depth]))
                if level - startlevel >= len(comps) or navtree:
                    if self._index.has_key(None) and self._index[None].has_key(
                            level):
                        depthset = union(
                            depthset,
                            intersection(pathset, self._index[None][level]))

            if navtree:
                return union(depthset, navset) or IISet()
            elif depth:
                return depthset or IISet()
            else:
                return pathset or IISet()

        else:
            results = IISet()
            for level in range(0, self._depth + 1):
                ids = None
                error = 0
                for cn in range(0, len(comps)):
                    comp = comps[cn]
                    try:
                        ids = intersection(ids, self._index[comp][level + cn])
                    except KeyError:
                        error = 1
                if error == 0:
                    results = union(results, ids)
            return results

    def _apply_index(self, request, cid=''):
        """ hook for (Z)Catalog
            'request' --  mapping type (usually {"path": "..." }
             additionaly a parameter "path_level" might be passed
             to specify the level (see search())

            'cid' -- ???
        """

        record = parseIndexRequest(request, self.id, self.query_options)
        if record.keys == None: return None

        level = record.get("level", 0)
        operator = record.get('operator', self.useOperator).lower()
        depth = getattr(record, 'depth', -1)  # Set to 0 or navtree later
        # use getattr to get 0 value
        navtree = record.get('navtree', 0)
        navtree_start = record.get('navtree_start', 0)

        # depending on the operator we use intersection of union
        if operator == "or": set_func = union
        else: set_func = intersection

        res = None
        for k in record.keys:
            rows = self.search(k, level, depth, navtree, navtree_start)
            res = set_func(res, rows)

        if res:
            return res, (self.id, )
        else:
            return IISet(), (self.id, )

    def getIndexSourceNames(self):
        """ return names of indexed attributes """

        # By default PathIndex advertises getPhysicalPath even
        # though the logic in index_object is different.

        try:
            return tuple(self.indexed_attrs)
        except AttributeError:
            return ('getPhysicalPath', )

    index_html = DTMLFile('dtml/index', globals())
    manage_workspace = DTMLFile('dtml/manageExtendedPathIndex', globals())
Exemple #49
0
class Calendar:
    """This class represents a calendar which is a set of days which contain
        information about which conferences whithin certain categories are
        happening for each of these days and for a certain access. This class
        allows to configure the date interval and the category set to be
        considered and provides operations which allow to know about what's
        happening on each of those days.

       Attributes:
        _aw - (accessControl.AccessWrapper) Information about the access for
            which the calendar will be built.
        _sDate - (datetime) Starting date for the calendar.
        _eDate - (datetime) Ending date for the calendar.
        _categList - (List) List of categories to be considered.
        _days - (OOBTree) Index of days which build up the calendar.
    """

    def __init__( self, aw, sDate, eDate, categList=[] ):
        self._aw = aw
        self._tz = sDate.tzinfo
        self._sDate = sDate.replace(hour=0, minute=0, second=0, microsecond=0)
        self._eDate = eDate.replace(hour=23, minute=59, second=59, microsecond=0)
        self._categList = categList
        self._icons = {}
        self._days = None

    def getIcons( self ):
        try:
            return self._icons
        except:
            self._icons = {}
            return {}

    def setIcons(self, categ):
        """Retrieves the list of icons in a given category tree
        """
        if categ.getIcon() != None:
            return [categ.getId()]
        res = []
        for subcat in categ.getSubCategoryList():
            res += self.setIcons(subcat)
        return res

    def getStartDate( self ):
        return self._sDate

    def getEndDate( self ):
        return self._eDate

    def getCategoryList( self ):
        return self._categList

    def getLocator( self ):
        """Returns the generic locator for the current object. This locator
            contains the folloing entries corresponding to values for which
            the calendar is configured:
                selCateg -> List of category ids.
                sDate -> Starting date.
                eDate -> Ending date.
        """
        l = Locators.Locator()
        ids = []
        for c in self.getCategoryList():
            ids.append( c.getId() )
        l["selCateg"] = ids
        l["sDate"] = self.getStartDate().strftime("%Y-%m-%d")
        l["eDate"] = self.getStartDate().strftime("%Y-%m-%d")
        return l

    def _mapConferenceToDays(self,conf,categList):
        """Registers a given conference for the days on which it is taking place
            whithin the calendar date interval.

           Parameters:
            conf - (conference.Conference) Conference to be mapped.
            categList - (List) List of calendar categories in which the
                specified conference is found.
        """

        inc = timedelta(1)
        d = max(conf.getStartDate().astimezone(self._tz).replace(hour=0,minute=0,second=0),
                self.getStartDate().astimezone(self._tz).replace(hour=0,minute=0,second=0))
        ed = min(conf.getEndDate().astimezone(self._tz), self.getEndDate().astimezone(self._tz))
        if ed > self.getEndDate():
            ed = self.getEndDate()

        while d <= ed:
            #norm_date=d.tzinfo.normalize(d)
            #norm_date=norm_date.replace(hour=0)
            norm_date=self.getNormDate(d)
            if not self._days.has_key( norm_date ):
                self._days[norm_date] = Day( self, d )

            self._days[norm_date].addConference( conf, categList, self._tz )
            d += inc

    def _initialiseDays( self ):
        """
        """
        self._days = OOBTree()
        res = set()
        self._categIdx = {}
        self._icons={}
        catDayIdx = indexes.IndexesHolder().getIndex("categoryDate")
        for categ in self.getCategoryList():
            confs = catDayIdx.getObjectsInDays(categ.getId(), self.getStartDate(), self.getEndDate())
            for conf in confs:
                confId = conf.getId()
                if not self._categIdx.has_key(confId):
                    self._categIdx[confId]=[]
                self._categIdx[confId].append(categ)
            res.update(confs)
        for conf in res:
            #getting icon from the nearest owner category
            owner = conf.getOwner()
            while owner != None and owner.getId() != "0":
                if owner.getIcon():
                    if self._icons.has_key(owner.getId()):
                        self._icons[owner.getId()].append(conf.getId())
                    else:
                        self._icons[owner.getId()] = [conf.getId()]
                    break
                owner = owner.getOwner()
            #mapping conf to days
            self._mapConferenceToDays(conf ,self._categIdx[conf.getId()])



    def getNormDate(self,date):
        # we have to normalize, but as we are going over all the days, we have to keep the date
        # and just normalize the tzinfo.
        norm_date=date.tzinfo.normalize(date)
        norm_date=norm_date.replace(year=date.year, month=date.month,day=date.day, hour=0)
        return norm_date

    def getDay( self, date ):
        if not self._days:
            self._initialiseDays()
        norm_date=self.getNormDate(date)
        if not self._days.has_key( norm_date ):
            self._days[norm_date] = Day( self, date )
        return self._days[norm_date]

    def getDayList( self ):
        inc = timedelta( 1 )
        d = self.getStartDate()
        l = []
        while d<self.getEndDate():
            l.append( self.getDay( d ) )
            d += inc
        return l

    def getConferenceCategories( self, conf ):
        return self._categIdx[conf.getId()]

    def __str__(self):
        l = []
        if self._days:
            for day in self._days.values():
                l.append("%s"%day)
        str =  _("Calendar between %s and %s: %s")%(\
                            self.getStartDate().strftime("%Y-%m-%d"), \
                            self.getEndDate().strftime("%Y-%m-%d"), \
                            "\n\t\t".join(l) )
        return str
class ChallengeProtocolChooser(BasePlugin):
    """ PAS plugin for choosing challenger protocol based on request
    """
    meta_type = 'Challenge Protocol Chooser Plugin'

    security = ClassSecurityInfo()

    manage_options = (({
        'label': 'Mapping',
        'action': 'manage_editProtocolMapping'
    }, ) + BasePlugin.manage_options)

    def __init__(self, id, title=None, mapping=None):
        self._id = self.id = id
        self.title = title
        self._map = OOBTree()
        if mapping is not None:
            self.manage_updateProtocolMapping(mapping=mapping)

    security.declarePrivate('chooseProtocol')

    def chooseProtocols(self, request):
        pas_instance = self._getPAS()
        plugins = pas_instance._getOb('plugins')

        sniffers = plugins.listPlugins(IRequestTypeSniffer)

        for sniffer_id, sniffer in sniffers:
            request_type = sniffer.sniffRequestType(request)
            if request_type is not None:
                return self._getProtocolsFor(request_type)

    def _getProtocolsFor(self, request_type):
        label = _request_type_bmap.get(request_type, None)
        if label is None:
            return
        return self._map.get(label, None)

    def _listProtocols(self):
        pas_instance = self._getPAS()
        plugins = pas_instance._getOb('plugins')

        challengers = plugins.listPlugins(IChallengePlugin)
        found = []

        for challenger_id, challenger in challengers:
            protocol = getattr(challenger, 'protocol', challenger_id)
            if protocol not in found:
                found.append(protocol)

        return found

    manage_editProtocolMappingForm = PageTemplateFile(
        'www/cpcEdit', globals(), __name__='manage_editProtocolMappingForm')

    def manage_editProtocolMapping(self, REQUEST=None):
        """ Edit Protocol Mapping
        """
        info = []
        available_protocols = self._listProtocols()

        request_types = listRequestTypesLabels()
        request_types.sort()

        for label in request_types:
            settings = []
            select_any = False
            info.append({'label': label, 'settings': settings})
            protocols = self._map.get(label, None)
            if not protocols:
                select_any = True
            for protocol in available_protocols:
                selected = False
                if protocols and protocol in protocols:
                    selected = True
                settings.append({
                    'label': protocol,
                    'selected': selected,
                    'value': protocol,
                })

            settings.insert(0, {
                'label': '(any)',
                'selected': select_any,
                'value': '',
            })
        return self.manage_editProtocolMappingForm(info=info, REQUEST=REQUEST)

    def manage_updateProtocolMapping(self, mapping, REQUEST=None):
        """ Update mapping of Request Type to Protocols
        """
        for key, value in mapping.items():
            value = filter(None, value)
            if not value:
                if self._map.has_key(key):
                    del self._map[key]
            else:
                self._map[key] = value

        if REQUEST is not None:
            REQUEST['RESPONSE'].redirect('%s/manage_editProtocolMapping'
                                         '?manage_tabs_message='
                                         'Protocol+Mappings+Changed.' %
                                         self.absolute_url())
class ToManyContRelationship(ToManyRelationshipBase):
    """
    ToManyContRelationship is the ToMany side of a realtionship that
    contains its related objects (like the normal Zope ObjectManager)
    """

    meta_type = "ToManyContRelationship"

    security = ClassSecurityInfo()


    def __init__(self, id):
        """set our instance values"""
        self.id = id
        self._objects = OOBTree()


    def _safeOfObjects(self):
        """
        Try to safely return ZenPack objects rather than
        causing imports to fail.
        """
        objs = []
        for ob in self._objects.values():
            try:
                objs.append(ob.__of__(self))
            except AttributeError:
                log.info("Ignoring unresolvable object '%s'", str(ob))
        return objs

    def __call__(self):
        """when we are called return our related object in our aq context"""
        return self._safeOfObjects()


    def __getattr__(self, name):
        """look in the two object stores for related objects"""
        if '_objects' in self.__dict__:
            objects = self._objects
            if objects.has_key(name): return objects[name]
        raise AttributeError( "Unable to find the attribute '%s'" % name )


    def __hasattr__(self, name):
        """check to see if we have an object by an id
        this will fail if passed a short id and object is stored
        with fullid (ie: it is related not contained)
        use hasobject to get around this issue"""
        return self._objects.has_key(name)


    def hasobject(self, obj):
        "check to see if we have this object"
        return self._objects.get(obj.id) == obj


    def addRelation(self, obj):
        """Override base to run manage_afterAdd like ObjectManager"""
        if self._objects.has_key(obj.getId()):
            log.debug("obj %s already exists on %s", obj.getPrimaryId(),
                        self.getPrimaryId())

        notify(ObjectWillBeAddedEvent(obj, self, obj.getId()))
        ToManyRelationshipBase.addRelation(self, obj)
        obj = obj.__of__(self)
        o = self._getOb(obj.id)
        notify(ObjectAddedEvent(o, self, obj.getId()))


    def _setObject(self,id,object,roles=None,user=None,set_owner=1):
        """ObjectManager interface to add contained object."""
        unused(user, roles, set_owner)
        object.__primary_parent__ = aq_base(self)
        self.addRelation(object)
        return object.getId()


    def manage_afterAdd(self, item, container):
        # Don't do recursion anymore, a subscriber does that.
        pass
    manage_afterAdd.__five_method__ = True

    def manage_afterClone(self, item):
        # Don't do recursion anymore, a subscriber does that.
        pass
    manage_afterClone.__five_method__ = True

    def manage_beforeDelete(self, item, container):
        # Don't do recursion anymore, a subscriber does that.
        pass
    manage_beforeDelete.__five_method__ = True

    def _add(self,obj):
        """add an object to one side of a ToManyContRelationship.
        """
        id = obj.id
        if self._objects.has_key(id):
            raise RelationshipExistsError
        v=checkValidId(self, id)
        if v is not None: id=v
        self._objects[id] = aq_base(obj)
        obj = aq_base(obj).__of__(self)


    def _remove(self, obj=None, suppress_events=False):
        """remove object from our side of a relationship"""
        if obj: objs = [obj]
        else: objs = self.objectValuesAll()
        if not suppress_events:
            for robj in objs:
                notify(ObjectWillBeRemovedEvent(robj, self, robj.getId()))
        if obj:
            id = obj.id
            if not self._objects.has_key(id):
                raise ObjectNotFound(
                    "object %s not found on %s" % (
                    obj.getPrimaryId(), self.getPrimaryId()))
            del self._objects[id]
        else:
            self._objects = OOBTree()
            self.__primary_parent__._p_changed = True
        if not suppress_events:
            for robj in objs:
                notify(ObjectRemovedEvent(robj, self, robj.getId()))


    def _remoteRemove(self, obj=None):
        """remove an object from the far side of this relationship
        if no object is passed in remove all objects"""
        if obj:
            if not self._objects.has_key(obj.id):
                raise ObjectNotFound("object %s not found on %s" % (
                    obj.getPrimaryId(), self.getPrimaryId()))
            objs = [obj]
        else: objs = self.objectValuesAll()
        remoteName = self.remoteName()
        for obj in objs:
            rel = getattr(obj, remoteName)
            try:
                rel._remove(self.__primary_parent__)
            except ObjectNotFound:
                message = log_tb(sys.exc_info())
                log.error('Remote remove failed. Run "zenchkrels -r -x1". ' + message)
                continue


    def _getOb(self, id, default=zenmarker):
        """look up in our local store and wrap in our aq_chain"""
        if self._objects.has_key(id):
            return self._objects[id].__of__(self)
        elif default == zenmarker:
            raise AttributeError( "Unable to find %s" % id )
        return default


    security.declareProtected('View', 'objectIds')
    def objectIds(self, spec=None):
        """only return contained objects"""
        if spec:
            if isinstance(spec,basestring): spec=[spec]
            return [obj.id for obj in self._objects.values() \
                        if obj.meta_type in spec]
        return [ k for k in self._objects.keys() ]
    objectIdsAll = objectIds


    security.declareProtected('View', 'objectValues')
    def objectValues(self, spec=None):
        """override to only return owned objects for many to many rel"""
        if spec:
            if isinstance(spec,basestring): spec=[spec]
            return [ob.__of__(self) for ob in self._objects.values() \
                        if ob.meta_type in spec]
        return self._safeOfObjects()
    security.declareProtected('View', 'objectValuesAll')
    objectValuesAll = objectValues


    def objectValuesGen(self):
        """Generator that returns all related objects."""
        return (obj.__of__(self) for obj in self._objects.values())


    def objectItems(self, spec=None):
        """over ride to only return owned objects for many to many rel"""
        if spec:
            if isinstance(spec,basestring): spec=[spec]
            return [(key,value.__of__(self)) \
                for (key,value) in self._objects.items() \
                    if value.meta_type in spec]
        return [(key,value.__of__(self)) \
                    for (key,value) in self._objects.items()]
    objectItemsAll = objectItems


#FIXME - need to make this work
#    def all_meta_types(self, interfaces=None):
#        mts = []
#        for mt in ToManyRelationshipBase.all_meta_types(self, interfaces):
#            if (mt.has_key('instance') and mt['instance']):
#                for cl in self.sub_classes:
#                    if checkClass(mt['instance'], cl):
#                        mts.append(mt)
#        return mts


    def _getCopy(self, container):
        """
        make new relation add copies of contained objs
        and refs if the relation is a many to many
        """
        rel = self.__class__(self.id)
        rel.__primary_parent__ = container
        rel = rel.__of__(container)
        norelcopy = getattr(self, 'zNoRelationshipCopy', [])
        if self.id in norelcopy: return rel
        for oobj in self.objectValuesAll():
            cobj = oobj._getCopy(rel)
            rel._setObject(cobj.id, cobj)
        return rel

    def checkValidId(self, id):
        """
        Is this a valid id for this container?
        """
        try:
            checkValidId(self, id)
        except:
            raise
        else:
            return True

    def exportXml(self, ofile, ignorerels=[]):
        """Return an xml representation of a ToManyContRelationship
        <tomanycont id='interfaces'>
            <object id='hme0'
                module='Products.Confmon.IpInterface' class='IpInterface'>
                <property></property> etc....
            </object>
        </tomanycont>
        """
        if self.countObjects() == 0: return
        ofile.write("<tomanycont id='%s'>\n" % self.id)
        for obj in self.objectValues():
            obj.exportXml(ofile, ignorerels)
        ofile.write("</tomanycont>\n")


    def checkRelation(self, repair=False):
        """Check to make sure that relationship bidirectionality is ok.
        """
        if len(self._objects):
            log.debug("checking relation: %s", self.id)
        else:
            return

        # look for objects that don't point back to us
        # or who should no longer exist in the database
        remoteName = self.remoteName()
        parentObject = self.getPrimaryParent()
        for obj in self._objects.values():
            if not hasattr(obj, remoteName):
                path = parentObject.getPrimaryUrlPath()
                if repair:
                    log.warn("Deleting %s object '%s' relation '%s' (missing remote relation '%s')",
                             path, obj, self.id, remoteName)
                    self._remove(obj, True)
                    continue
                else:
                    msg = "%s object '%s' relation '%s' missing remote relation '%s'" % (
                             path, obj, self.id, remoteName)
                    raise AttributeError(msg)

            rrel = getattr(obj, remoteName)
            if not rrel.hasobject(parentObject):
                log.error("remote relation %s doesn't point back to %s",
                                rrel.getPrimaryId(), self.getPrimaryId())
                if repair:
                    log.warn("reconnecting relation %s to relation %s",
                            rrel.getPrimaryId(),self.getPrimaryId())
                    rrel._add(parentObject)
Exemple #52
0
class CategoryDateIndex(Persistent):

    def __init__( self ):
        self._idxCategItem = OOBTree()

    def dump(self):
        return map(lambda idx: (idx[0], idx[1].dump()), list(self._idxCategItem.items()))

    def unindexConf(self, conf):
        for owner in conf.getOwnerPath():
            if self._idxCategItem.has_key(owner.getId()):
                self._idxCategItem[owner.getId()].unindexConf(conf)
        if self._idxCategItem.has_key('0'):
            self._idxCategItem['0'].unindexConf(conf)


    def reindexCateg(self, categ):
        for subcat in categ.getSubCategoryList():
            self.reindexCateg(subcat)
        for conf in categ.getConferenceList():
            self.unindexConf(conf)
            self.indexConf(conf)
#        from indico.core.db import DBMgr
#        dbi = DBMgr.getInstance()
#        for subcat in categ.getSubCategoryList():
#            self.reindexCateg(subcat)
#        for conf in categ.getConferenceList():
#            while True:
#                try:
#                    dbi.sync()
#                    self.unindexConf(conf)
#                    self.indexConf(conf)
#                    dbi.commit()
#                    break
#                except:
#                    print 'Exception commiting conf %s'%conf.getId()

    def unindexCateg(self, categ):
        for subcat in categ.getSubCategoryList():
            self.unindexCateg(subcat)
        for conf in categ.getConferenceList():
            self.unindexConf(conf)

    def indexCateg(self, categ, dbi=None, counter=0):
        for subcat in categ.getSubCategoryList():
            self.indexCateg(subcat, dbi=dbi, counter=counter+1)
            if dbi and counter < 2:
                dbi.commit()
        for conf in categ.getConferenceList():
            self.indexConf(conf)

    def _indexConf(self, categid, conf):
        # only the more restrictive setup is taken into account
        if categid in self._idxCategItem:
            res = self._idxCategItem[categid]
        else:
            res = CalendarIndex()
        res.indexConf(conf)
        self._idxCategItem[categid] = res

    # TOREMOVE?? defined in CategoryDayIndex
    def indexConf(self, conf):
        for categ in conf.getOwnerPath():
            self._indexConf(categ.getId(), conf)
        self._indexConf("0",conf)

    def getObjectsIn(self, categid, sDate, eDate):
        categid = str(categid)
        if categid in self._idxCategItem:
            return self._idxCategItem[categid].getObjectsIn(sDate, eDate)
        else:
            return []

    def getObjectsStartingIn(self, categid, sDate, eDate):
        categid = str(categid)
        if categid in self._idxCategItem:
            return self._idxCategItem[categid].getObjectsStartingIn(sDate, eDate)
        else:
            return []

    def getObjectsInDay(self, categid, sDate):
        categid = str(categid)
        if categid in self._idxCategItem:
            return self._idxCategItem[categid].getObjectsInDay(sDate)
        else:
            return []

    def hasObjectsAfter(self, categid, sDate):
        categid = str(categid)
        if categid in self._idxCategItem:
            return self._idxCategItem[categid].hasObjectsAfter(sDate)
        else:
            return False

    def getObjectsEndingAfter(self, categid, sDate):
        categid = str(categid)
        if categid in self._idxCategItem:
            return self._idxCategItem[categid].getObjectsEndingAfter(sDate)
        else:
            return []
Exemple #53
0
class CategoryDateIndex(Persistent):
    def __init__(self):
        self._idxCategItem = OOBTree()

    def dump(self):
        return map(lambda idx: (idx[0], idx[1].dump()),
                   list(self._idxCategItem.items()))

    def unindexConf(self, conf):
        for owner in conf.getOwnerPath():
            if self._idxCategItem.has_key(owner.getId()):
                self._idxCategItem[owner.getId()].unindexConf(conf)
        if self._idxCategItem.has_key('0'):
            self._idxCategItem['0'].unindexConf(conf)

    def reindexCateg(self, categ):
        for subcat in categ.getSubCategoryList():
            self.reindexCateg(subcat)
        for conf in categ.getConferenceList():
            self.unindexConf(conf)
            self.indexConf(conf)


#        from MaKaC.common import DBMgr
#        dbi = DBMgr.getInstance()
#        for subcat in categ.getSubCategoryList():
#            self.reindexCateg(subcat)
#        for conf in categ.getConferenceList():
#            while True:
#                try:
#                    dbi.sync()
#                    self.unindexConf(conf)
#                    self.indexConf(conf)
#                    dbi.commit()
#                    break
#                except:
#                    print 'Exception commiting conf %s'%conf.getId()

    def unindexCateg(self, categ):
        for subcat in categ.getSubCategoryList():
            self.unindexCateg(subcat)
        for conf in categ.getConferenceList():
            self.unindexConf(conf)

    def indexCateg(self, categ, dbi=None, counter=0):
        for subcat in categ.getSubCategoryList():
            self.indexCateg(subcat, dbi=dbi, counter=counter + 1)
            if dbi and counter < 2:
                dbi.commit()
        for conf in categ.getConferenceList():
            self.indexConf(conf)

    def _indexConf(self, categid, conf):
        # only the more restrictive setup is taken into account
        if self._idxCategItem.has_key(categid):
            res = self._idxCategItem[categid]
        else:
            res = CalendarIndex()
        res.indexConf(conf)
        self._idxCategItem[categid] = res

    # TOREMOVE?? defined in CategoryDayIndex
    def indexConf(self, conf):
        for categ in conf.getOwnerPath():
            self._indexConf(categ.getId(), conf)
        self._indexConf("0", conf)

    def getObjectsIn(self, categid, sDate, eDate):
        categid = str(categid)
        if self._idxCategItem.has_key(categid):
            return self._idxCategItem[categid].getObjectsIn(sDate, eDate)
        else:
            return []

    def getObjectsStartingIn(self, categid, sDate, eDate):
        categid = str(categid)
        if self._idxCategItem.has_key(categid):
            return self._idxCategItem[categid].getObjectsStartingIn(
                sDate, eDate)
        else:
            return []

    def getObjectsInDay(self, categid, sDate):
        categid = str(categid)
        if self._idxCategItem.has_key(categid):
            return self._idxCategItem[categid].getObjectsInDay(sDate)
        else:
            return []

    def getObjectsEndingAfter(self, categid, sDate):
        categid = str(categid)
        if self._idxCategItem.has_key(categid):
            return self._idxCategItem[categid].getObjectsEndingAfter(sDate)
        else:
            return []
Exemple #54
0
class PathIndex(Persistent, SimpleItem):

    """Index for paths returned by getPhysicalPath.

    A path index stores all path components of the physical path of an object.

    Internal datastructure:

    - a physical path of an object is split into its components

    - every component is kept as a  key of a OOBTree in self._indexes

    - the value is a mapping 'level of the path component' to
      'all docids with this path component on this level'
    """

    __implements__ = (PluggableIndex.UniqueValueIndex,)
    implements(IPathIndex, IUniqueValueIndex)

    meta_type="PathIndex"

    manage_options= (
        {'label': 'Settings',
         'action': 'manage_main',
         'help': ('PathIndex','PathIndex_Settings.stx')},
    )

    query_options = ("query", "level", "operator")

    def __init__(self,id,caller=None):
        self.id = id
        self.operators = ('or','and')
        self.useOperator = 'or'
        self.clear()

    def clear(self):
        self._depth = 0
        self._index = OOBTree()
        self._unindex = IOBTree()
        self._length = Length(0)

    def insertEntry(self, comp, id, level):
        """Insert an entry.

           comp is a path component
           id is the docid
           level is the level of the component inside the path
        """

        if not self._index.has_key(comp):
            self._index[comp] = IOBTree()

        if not self._index[comp].has_key(level):
            self._index[comp][level] = IITreeSet()

        self._index[comp][level].insert(id)
        if level > self._depth:
            self._depth = level

    def index_object(self, docid, obj ,threshold=100):
        """ hook for (Z)Catalog """

        f = getattr(obj, self.id, None)
        if f is not None:
            if safe_callable(f):
                try:
                    path = f()
                except AttributeError:
                    return 0
            else:
                path = f

            if not isinstance(path, (StringType, TupleType)):
                raise TypeError('path value must be string or tuple of strings')
        else:
            try:
                path = obj.getPhysicalPath()
            except AttributeError:
                return 0

        if isinstance(path, (ListType, TupleType)):
            path = '/'+ '/'.join(path[1:])
        comps = filter(None, path.split('/'))

        if not self._unindex.has_key(docid):
            self._length.change(1)

        for i in range(len(comps)):
            self.insertEntry(comps[i], docid, i)
        self._unindex[docid] = path
        return 1

    def unindex_object(self, docid):
        """ hook for (Z)Catalog """

        if not self._unindex.has_key(docid):
            LOG.debug('Attempt to unindex nonexistent document with id %s'
                      % docid)
            return

        comps =  self._unindex[docid].split('/')

        for level in range(len(comps[1:])):
            comp = comps[level+1]

            try:
                self._index[comp][level].remove(docid)

                if not self._index[comp][level]:
                    del self._index[comp][level]

                if not self._index[comp]:
                    del self._index[comp]
            except KeyError:
                LOG.debug('Attempt to unindex document with id %s failed'
                          % docid)

        self._length.change(-1)
        del self._unindex[docid]

    def search(self, path, default_level=0):
        """
        path is either a string representing a
        relative URL or a part of a relative URL or
        a tuple (path,level).

        level >= 0  starts searching at the given level
        level <  0  not implemented yet
        """

        if isinstance(path, StringType):
            level = default_level
        else:
            level = int(path[1])
            path  = path[0]

        comps = filter(None, path.split('/'))

        if len(comps) == 0:
            return IISet(self._unindex.keys())

        if level >= 0:
            results = []
            for i in range(len(comps)):
                comp = comps[i]
                if not self._index.has_key(comp): return IISet()
                if not self._index[comp].has_key(level+i): return IISet()
                results.append( self._index[comp][level+i] )

            res = results[0]
            for i in range(1,len(results)):
                res = intersection(res,results[i])
            return res

        else:
            results = IISet()
            for level in range(0,self._depth + 1):
                ids = None
                error = 0
                for cn in range(0,len(comps)):
                    comp = comps[cn]
                    try:
                        ids = intersection(ids,self._index[comp][level+cn])
                    except KeyError:
                        error = 1
                if error==0:
                    results = union(results,ids)
            return results

    def numObjects(self):
        """ return the number distinct values """
        return len(self._unindex)

    def indexSize(self):
        """ return the number of indexed objects"""
        return len(self)

    def __len__(self):
        return self._length()

    def _apply_index(self, request, cid=''):
        """ hook for (Z)Catalog
            'request' --  mapping type (usually {"path": "..." }
             additionaly a parameter "path_level" might be passed
             to specify the level (see search())

            'cid' -- ???
        """

        record = parseIndexRequest(request,self.id,self.query_options)
        if record.keys==None: return None

        level    = record.get("level",0)
        operator = record.get('operator',self.useOperator).lower()

        # depending on the operator we use intersection of union
        if operator == "or":  set_func = union
        else: set_func = intersection

        res = None
        for k in record.keys:
            rows = self.search(k,level)
            res = set_func(res,rows)

        if res:
            return res, (self.id,)
        else:
            return IISet(), (self.id,)

    def hasUniqueValuesFor(self, name):
        """has unique values for column name"""
        return name == self.id

    def uniqueValues(self, name=None, withLength=0):
        """ needed to be consistent with the interface """
        return self._index.keys()

    def getIndexSourceNames(self):
        """ return names of indexed attributes """
        return ('getPhysicalPath', )

    def getEntryForObject(self, docid, default=_marker):
        """ Takes a document ID and returns all the information
            we have on that specific object.
        """
        try:
            return self._unindex[docid]
        except KeyError:
            # XXX Why is default ignored?
            return None

    manage = manage_main = DTMLFile('dtml/managePathIndex', globals())
    manage_main._setName('manage_main')
class ZODBContinuousIncreasingIdGenerator(IdGenerator):
    """
    Create some Ids with the zodb storage
  """
    zope.interface.implements(interfaces.IIdGenerator)
    # CMF Type Definition
    meta_type = 'ERP5 ZODB Continous Increasing Id Generator'
    portal_type = 'ZODB Continous Increasing Id Generator'
    add_permission = Permissions.AddPortalContent

    # Declarative security
    security = ClassSecurityInfo()
    security.declareObjectProtected(Permissions.AccessContentsInformation)

    def _generateNewId(self, id_group, id_count=1, default=None, poison=False):
        """
     Return the new_id from the last_id of the zodb
     Use int to store the last_id, use also a persistant mapping for to be
     persistent.
    """
        if id_group in (None, 'None'):
            raise ValueError, '%s is not a valid group Id.' % (
                repr(id_group), )
        if default is None:
            default = 0
        last_id_dict = getattr(self, 'last_id_dict', None)
        if last_id_dict is None:
            # If the dictionary not exist initialize generator
            self.initializeGenerator()
            last_id_dict = self.last_id_dict
        # Retrieve the last id and increment
        new_id = last_id_dict.get(id_group, default - 1) + id_count
        # Store the new_id in the dictionary
        last_id_dict[id_group] = None if poison else new_id
        return new_id

    security.declareProtected(Permissions.AccessContentsInformation,
                              'generateNewId')

    def generateNewId(self, id_group=None, default=None, poison=False):
        """
      Generate the next id in the sequence of ids of a particular group
    """
        return self._generateNewId(id_group=id_group,
                                   default=default,
                                   poison=poison)

    security.declareProtected(Permissions.AccessContentsInformation,
                              'generateNewIdList')

    def generateNewIdList(self,
                          id_group=None,
                          id_count=1,
                          default=None,
                          poison=False):
        """
      Generate a list of next ids in the sequence of ids of a particular group
    """
        new_id = 1 + self._generateNewId(id_group=id_group,
                                         id_count=id_count,
                                         default=default,
                                         poison=poison)
        return range(new_id - id_count, new_id)

    security.declareProtected(Permissions.ModifyPortalContent,
                              'initializeGenerator')

    def initializeGenerator(self):
        """
      Initialize generator. This is mostly used when a new ERP5 site
      is created. Some generators will need to do some initialization like
      prepare some data in ZODB
    """
        LOG('initialize ZODB Generator', INFO, 'Id Generator: %s' % (self, ))
        if getattr(self, 'last_id_dict', None) is None:
            self.last_id_dict = OOBTree()

        # XXX compatiblity code below, dump the old dictionnaries
        portal_ids = getattr(self, 'portal_ids', None)
        # Dump the dict_ids dictionary
        if getattr(portal_ids, 'dict_ids', None) is not None:
            for id_group, last_id in portal_ids.dict_ids.items():
                if not isinstance(id_group, str):
                    id_group = repr(id_group)
                if self.last_id_dict.has_key(id_group) and \
                   self.last_id_dict[id_group] > last_id:
                    continue
                self.last_id_dict[id_group] = last_id

    security.declareProtected(Permissions.ModifyPortalContent,
                              'clearGenerator')

    def clearGenerator(self):
        """
      Clear generators data. This can be usefull when working on a
      development instance or in some other rare cases. This will
      loose data and must be use with caution

      This can be incompatible with some particular generator implementation,
      in this case a particular error will be raised (to be determined and
      added here)
    """
        # Remove dictionary
        self.last_id_dict = OOBTree()

    security.declareProtected(Permissions.ModifyPortalContent,
                              'exportGeneratorIdDict')

    def exportGeneratorIdDict(self):
        """
      Export last id values in a dictionnary in the form { group_id : last_id }
    """
        return dict(self.last_id_dict)

    security.declareProtected(Permissions.ModifyPortalContent,
                              'importGeneratorIdDict')

    def importGeneratorIdDict(self, id_dict, clear=False):
        """
      Import data, this is usefull if we want to replace a generator by
      another one.
    """
        if clear:
            self.clearGenerator()
        if not isinstance(id_dict, dict):
            raise TypeError, 'the argument given is not a dictionary'
        for value in id_dict.values():
            if not isinstance(value, (int, long)):
                raise TypeError, 'the value given in dictionary is not a integer'
        self.last_id_dict.update(id_dict)

    security.declareProtected(Permissions.ModifyPortalContent,
                              'rebuildGeneratorIdDict')

    def rebuildGeneratorIdDict(self):
        """
      Rebuild generator id dict.
      In fact, export it, clear it and import it into new dict.
      This is mostly intendted to use when we are migrating the id dict
      structure.
    """
        id_dict = self.exportGeneratorIdDict()
        self.importGeneratorIdDict(id_dict=id_dict, clear=True)
Exemple #56
0
class Repository(Implicit, Persistent):
    """The repository implementation manages the actual data of versions
       and version histories. It does not handle user interface issues."""

    def __init__(self):
        # These keep track of symbolic label and branch names that
        # have been used to ensure that they don't collide.
        self._branches = OIBTree()
        self._branches['mainline'] = 1
        self._labels = OIBTree()

        self._histories = OOBTree()
        self._created = time.time()

    security = ClassSecurityInfo()

    security.declarePrivate('createVersionHistory')
    def createVersionHistory(self, object):
        """Internal: create a new version history for a resource."""
        # When one creates the first version in a version history, neither
        # the version or version history yet have a _p_jar, which causes
        # copy operations to fail. To work around that, we share our _p_jar.
        history_id = None
        while history_id is None or self._histories.has_key(history_id):
            history_id = str(randint(1, 9999999999))
        history = ZopeVersionHistory(history_id, object)
        self._histories[history_id] = history
        return history.__of__(self)

    security.declarePrivate('getVersionHistory')
    def getVersionHistory(self, history_id):
        """Internal: return a version history given a version history id."""
        return self._histories[history_id].__of__(self)

    security.declarePrivate('replaceState')
    def replaceState(self, obj, new_state):
        """Internal: replace the state of a persistent object.
        """
        non_versioned = getNonVersionedData(obj)
        # XXX There ought to be some way to do this more cleanly.
        # This fills the __dict__ of the old object with new state.
        # The other way to achieve the desired effect is to replace
        # the object in its container, but this method preserves the
        # identity of the object.
        if obj.__class__ is not new_state.__class__:
            raise VersionControlError(
                "The class of the versioned object has changed. %s != %s"
                % (repr(obj.__class__, new_state.__class__)))
        obj._p_changed = 1
        for key in obj.__dict__.keys():
            if not new_state.__dict__.has_key(key):
                del obj.__dict__[key]
        for key, value in new_state.__dict__.items():
            obj.__dict__[key] = value
        if non_versioned:
            # Restore the non-versioned data into the new state.
            restoreNonVersionedData(obj, non_versioned)
        return obj

    #####################################################################
    # This is the implementation of the public version control interface.
    #####################################################################

    security.declarePublic('isAVersionableResource')
    def isAVersionableResource(self, obj):
        # For now, an object must be persistent (have its own db record)
        # in order to be considered a versionable resource.
        return isAVersionableResource(obj)

    security.declarePublic('isUnderVersionControl')
    def isUnderVersionControl(self, object):
        return hasattr(object, '__vc_info__')

    security.declarePublic('isResourceUpToDate')
    def isResourceUpToDate(self, object, require_branch=0):
        info = self.getVersionInfo(object)
        history = self.getVersionHistory(info.history_id)
        branch = 'mainline'
        if info.sticky:
            if info.sticky[0] == 'B':
                branch = info.sticky[1]
            elif require_branch:
                # The object is updated to a particular version
                # rather than a branch.  The caller
                # requires a branch.
                return 0
        return history.isLatestVersion(info.version_id, branch)

    security.declarePublic('isResourceChanged')
    def isResourceChanged(self, object):
        # Return true if the state of a resource has changed in a transaction
        # *after* the version bookkeeping was saved. Note that this method is
        # not appropriate for detecting changes within a transaction!
        info = self.getVersionInfo(object)
        itime = getattr(info, '_p_mtime', None)
        if itime is None:
            return 0
        mtime = Utility._findModificationTime(object)
        if mtime is None:
            return 0
        return mtime > itime

    security.declarePublic('getVersionInfo')
    def getVersionInfo(self, object):
        info = getattr(object, '__vc_info__', None)
        if info is not None:
            return info
        raise VersionControlError(
            'The specified resource is not under version control.'
            )

    security.declareProtected(use_vc_permission, 'applyVersionControl')
    def applyVersionControl(self, object, message=None):
        if self.isUnderVersionControl(object):
            raise VersionControlError(
                'The resource is already under version control.'
                )
        if not self.isAVersionableResource(object):
            raise VersionControlError(
                'This resource cannot be put under version control.'
                )

        # Need to check the parent to see if the container of the object
        # being put under version control is itself a version-controlled
        # object. If so, we need to use the branch id of the container.
        branch = 'mainline'
        parent = aq_parent(aq_inner(object))
        p_info = getattr(parent, '__vc_info__', None)
        if p_info is not None:
            sticky = p_info.sticky
            if sticky and sticky[0] == 'B':
                branch = sticky[1]

        # Create a new version history and initial version object.
        history = self.createVersionHistory(object)
        version = history.createVersion(object, branch)

        history_id = history.getId()
        version_id = version.getId()

        # Add bookkeeping information to the version controlled object.
        info = VersionInfo(history_id, version_id, VersionInfo.CHECKED_IN)
        if branch != 'mainline':
            info.sticky = ('B', branch)
        object.__vc_info__ = info

        # Save an audit record of the action being performed.
        history.addLogEntry(version_id,
                            LogEntry.ACTION_CHECKIN,
                            _findPath(object),
                            message is None and 'Initial checkin.' or message
                            )
        return object

    security.declareProtected(use_vc_permission, 'checkoutResource')
    def checkoutResource(self, object):
        info = self.getVersionInfo(object)
        if info.status != info.CHECKED_IN:
            raise VersionControlError(
                'The selected resource is already checked out.'
                )

        if info.sticky and info.sticky[0] != 'B':
            raise VersionControlError(
                'The selected resource has been updated to a particular '
                'version, label or date. The resource must be updated to '
                'the mainline or a branch before it may be checked out.'
                )

        if not self.isResourceUpToDate(object):
            raise VersionControlError(
                'The selected resource is not up to date!'
                )

        history = self.getVersionHistory(info.history_id)
        ob_path = _findPath(object)

        # Save an audit record of the action being performed.
        history.addLogEntry(info.version_id,
                            LogEntry.ACTION_CHECKOUT,
                            ob_path
                            )

        # Update bookkeeping information.
        newinfo = info.clone()
        newinfo.status = newinfo.CHECKED_OUT
        object.__vc_info__ = newinfo
        return object

    security.declareProtected(use_vc_permission, 'checkinResource')
    def checkinResource(self, object, message=''):
        info = self.getVersionInfo(object)
        if info.status != info.CHECKED_OUT:
            raise VersionControlError(
                'The selected resource is not checked out.'
                )

        if info.sticky and info.sticky[0] != 'B':
            raise VersionControlError(
                'The selected resource has been updated to a particular '
                'version, label or date. The resource must be updated to '
                'the mainline or a branch before it may be checked in.'
                )

        if not self.isResourceUpToDate(object):
            raise VersionControlError(
                'The selected resource is not up to date!'
                )

        history = self.getVersionHistory(info.history_id)
        ob_path = _findPath(object)

        branch = 'mainline'
        if info.sticky is not None and info.sticky[0] == 'B':
            branch = info.sticky[1]

        version = history.createVersion(object, branch)

        # Save an audit record of the action being performed.
        history.addLogEntry(version.getId(),
                            LogEntry.ACTION_CHECKIN,
                            ob_path,
                            message
                            )

        # Update bookkeeping information.
        newinfo = info.clone()
        newinfo.version_id = version.getId()
        newinfo.status = newinfo.CHECKED_IN
        object.__vc_info__ = newinfo
        return object

    security.declareProtected(use_vc_permission, 'uncheckoutResource')
    def uncheckoutResource(self, object):
        info = self.getVersionInfo(object)
        if info.status != info.CHECKED_OUT:
            raise VersionControlError(
                'The selected resource is not checked out.'
                )

        history = self.getVersionHistory(info.history_id)
        ob_path = _findPath(object)

        version = history.getVersionById(info.version_id)
        new_obj = version.copyState()

        # Save an audit record of the action being performed.
        history.addLogEntry(info.version_id,
                            LogEntry.ACTION_UNCHECKOUT,
                            ob_path
                            )

        # Replace the state of the object with a reverted state.
        new_obj = self.replaceState(object, new_obj)

        # Update bookkeeping information.
        newinfo = info.clone()
        newinfo.version_id = version.getId()
        newinfo.status = newinfo.CHECKED_IN
        new_obj.__vc_info__ = newinfo
        return new_obj

    security.declareProtected(use_vc_permission, 'updateResource')
    def updateResource(self, object, selector=None):
        info = self.getVersionInfo(object)
        if info.status != info.CHECKED_IN:
            raise VersionControlError(
                'The selected resource must be checked in to be updated.'
                )

        history = self.getVersionHistory(info.history_id)
        version = None
        sticky = info.sticky

        if not selector:
            # If selector is null, update to the latest version taking any
            # sticky attrs into account (branch, date). Note that the sticky
            # tag could also be a date or version id. We don't bother checking
            # for those, since in both cases we do nothing (because we'll
            # always be up to date until the sticky tag changes).
            if sticky and sticky[0] == 'L':
                # A label sticky tag, so update to that label (since it is
                # possible, but unlikely, that the label has been moved).
                version = history.getVersionByLabel(sticky[1])
            elif sticky and sticky[0] == 'B':
                # A branch sticky tag. Update to latest version on branch.
                version = history.getLatestVersion(selector)
            else:
                # Update to mainline, forgetting any date or version id
                # sticky tag that was previously associated with the object.
                version = history.getLatestVersion('mainline')
                sticky = None
        else:
            # If the selector is non-null, we find the version specified
            # and update the sticky tag. Later we'll check the version we
            # found and decide whether we really need to update the object.
            if history.hasVersionId(selector):
                version = history.getVersionById(selector)
                sticky = ('V', selector)

            elif self._labels.has_key(selector):
                version = history.getVersionByLabel(selector)
                sticky = ('L', selector)

            elif self._branches.has_key(selector):
                version = history.getLatestVersion(selector)
                if selector == 'mainline':
                    sticky = None
                else:
                    sticky = ('B', selector)
            else:
                try:    date = DateTime(selector)
                except:
                    raise VersionControlError(
                        'Invalid version selector: %s' % selector
                        )
                else:
                    timestamp = date.timeTime()
                    sticky = ('D', timestamp)
                    # Fix!
                    branch = history.findBranchId(info.version_id)
                    version = history.getVersionByDate(branch, timestamp)

        # If the state of the resource really needs to be changed, do the
        # update and make a log entry for the update.
        version_id = version and version.getId() or info.version_id
        new_object = object
        if version and (version_id != info.version_id):
            new_object = version.copyState()
            new_object = self.replaceState(object, new_object)

            history.addLogEntry(version_id,
                                LogEntry.ACTION_UPDATE,
                                _findPath(new_object)
                                )

        # Update bookkeeping information.
        newinfo = info.clone(1)
        newinfo.version_id = version_id
        newinfo.status = newinfo.CHECKED_IN
        if sticky is not None:
            newinfo.sticky = sticky
        new_object.__vc_info__ = newinfo
        return new_object

    security.declareProtected(use_vc_permission, 'labelResource')
    def labelResource(self, object, label, force=0):
        info = self.getVersionInfo(object)
        if info.status != info.CHECKED_IN:
            raise VersionControlError(
                'The selected resource must be checked in to be labeled.'
                )

        # Make sure that labels and branch ids do not collide.
        if self._branches.has_key(label) or label == 'mainline':
            raise VersionControlError(
                'The label value given is already in use as an activity id.'
                )
        if not self._labels.has_key(label):
            self._labels[label] = 1

        history = self.getVersionHistory(info.history_id)
        history.labelVersion(info.version_id, label, force)
        return object

    security.declareProtected(use_vc_permission, 'makeActivity')
    def makeActivity(self, object, branch_id):
        # Note - this is not part of the official version control API yet.
        # It is here to allow unit testing of the architectural aspects
        # that are already in place to support activities in the future.

        info = self.getVersionInfo(object)
        if info.status != info.CHECKED_IN:
            raise VersionControlError(
                'The selected resource must be checked in.'
                )

        branch_id = branch_id or None

        # Make sure that activity ids and labels do not collide.
        if self._labels.has_key(branch_id) or branch_id == 'mainline':
            raise VersionControlError(
                'The value given is already in use as a version label.'
                )

        if not self._branches.has_key(branch_id):
            self._branches[branch_id] = 1

        history = self.getVersionHistory(info.history_id)

        if history._branches.has_key(branch_id):
            raise VersionControlError(
                'The resource is already associated with the given activity.'
                )

        history.createBranch(branch_id, info.version_id)
        return object

    security.declareProtected(use_vc_permission, 'getVersionOfResource')
    def getVersionOfResource(self, history_id, selector):
        history = self.getVersionHistory(history_id)
        sticky = None

        if not selector or selector == 'mainline':
            version = history.getLatestVersion('mainline')
        else:
            if history.hasVersionId(selector):
                version = history.getVersionById(selector)
                sticky = ('V', selector)

            elif self._labels.has_key(selector):
                version = history.getVersionByLabel(selector)
                sticky = ('L', selector)

            elif self._branches.has_key(selector):
                version = history.getLatestVersion(selector)
                sticky = ('B', selector)
            else:
                try: date = DateTime(selector)
                except:
                    raise VersionControlError(
                        'Invalid version selector: %s' % selector
                        )
                else:
                    timestamp = date.timeTime()
                    sticky = ('D', timestamp)
                    version = history.getVersionByDate('mainline', timestamp)

        object = version.copyState()

        info = VersionInfo(history_id, version.getId(), VersionInfo.CHECKED_IN)
        if sticky is not None:
            info.sticky = sticky
        object.__vc_info__ = info
        return object

    security.declareProtected(use_vc_permission, 'getVersionIds')
    def getVersionIds(self, object):
        info = self.getVersionInfo(object)
        history = self.getVersionHistory(info.history_id)
        return history.getVersionIds()

    security.declareProtected(use_vc_permission, 'getLabelsForResource')
    def getLabelsForResource(self, object):
        info = self.getVersionInfo(object)
        history = self.getVersionHistory(info.history_id)
        return history.getLabels()

    security.declareProtected(use_vc_permission, 'getLogEntries')
    def getLogEntries(self, object):
        info = self.getVersionInfo(object)
        history = self.getVersionHistory(info.history_id)
        return history.getLogEntries()
Exemple #57
0
class Issue(ListText):
    "this object represents a single votable Issue"

    security = ClassSecurityInfo()
    meta_type = "Issue"
    storage = None
    votes = None
    description = ''
    addType = 'IssueChoice'
    selectionType = "radio"
    selectionLimit = 1
    selectionLimitMin = 0
    format = '<div>%s</div>'
    MustSelectOne = '<strong>At least one choice must be made.</strong>'
    TooManyItems = '<strong>Too many items where selected.</strong>'
    NotEnoughItems = '<strong>Not Enough items where selected.</strong>'
    BadItemSelected = '''<strong>An item was selected that does not exist.
    You should never see this message please email the webmaster.</strong>'''
    voteText = '''%(error)s<div class="issue"><div class="issueDescription">%(description)s</div>
      <div class="issueChoices">%(issues)s</div></div>
    '''
    alreadyVotedText = '<p>You have already voted</p>'
    noVotingAllowed = '<p>Voting is not currently allowed</p>'
    thankYouText = '<p>Thank you for voting</p>'
    deleteButtonText = 'Delete Issue Choice'
    addButtonText = 'Add Issue Choice'

    selectionAllowedTypes = (('radio', 'Single Selection'),
                             ('checkbox', 'Multiple Selection'))

    classConfig = {}
    classConfig['selectionLimit'] = {
        'name':
        'If you have selected multiple selection mode how many choices can people make (MAX)?',
        'type': 'int'
    }
    classConfig['selectionLimitMin'] = {
        'name':
        'If you have selected multiple selection mode how many choices do people have to make? (MIN)',
        'type': 'int'
    }
    classConfig['selectionType'] = {
        'name': 'Allowed Selections',
        'type': 'list',
        'values': selectionAllowedTypes
    }
    classConfig['description'] = {'name': 'Issue Description', 'type': 'text'}

    drawDict = ListText.drawDict.copy()
    drawDict['vote'] = 'drawVote'
    drawDict['voteChecked'] = 'drawVoteChecked'
    drawDict['report'] = 'drawReport'

    security.declareProtected('View management screens', 'edit')

    def edit(self, *args, **kw):
        "Inline edit view"
        temp = self.editSingleConfig('description')
        temp += self.editSingleConfig('selectionType')
        temp += self.editSingleConfig('selectionLimit')
        temp += self.editSingleConfig('selectionLimitMin')
        return temp + ListText.edit(self)

    security.declareProtected('CompoundDoc: Voting', 'alternate_security_edit')

    def alternate_security_edit(self, dict):
        "save the voting information if it is okay to do so"
        choices = None
        if 'choices' in dict:
            choices = dict.get('choices').values()
            del dict['choices']
        if choices:
            choices = [choice for choice in choices if choice]
            uid = self.getUID()
            if self.isOkayToVote(uid):
                self.vote(uid, choices)

    security.declareProtected('CompoundDoc: Voting', 'drawVote')

    def drawVote(self):
        "draw the voting interface"
        return self.drawVoteChecked()[1]

    security.declareProtected('CompoundDoc: Voting', 'drawVoteChecked')

    def drawVoteChecked(self):
        "draw the voting interface"
        structure = self.voteStructure()
        structure['error'], messageType = self.drawError()
        uid = self.getUID()
        if messageType == 'thankYouText':
            return (False, self.getMessage('thankYouText', structure))
        if self.voteEnabled:
            if self.isOkayToVote(uid):
                return (True, self.getMessage('voteText', structure))
            elif self.alreadyVoted(uid):
                return (False, self.getMessage('alreadyVotedText', structure))
            else:
                return (False, self.getMessage('notAllowedToVote', structure))
        else:
            return (False, self.getMessage('noVotingAllowed', structure))

    security.declarePrivate('getMessage')

    def getMessage(self, messageType, lookup):
        """if we have a url for a set of messages to use on errors go ahead and use that otherwise use the default string we have
        and get variables from this lookup(dictionary) object"""
        folder = self.getMessageFolder()
        if folder is not None:
            item = getattr(folder, messageType, None)
            if item is not None:
                return item.__of__(self)(lookup)
        return getattr(self, messageType) % lookup

    security.declarePrivate('drawError')

    def drawError(self):
        "draw any needed any message"
        return self.getErrorMessage()

    def hasErrorMessage(self):
        "do we have an error message to draw?"
        messages = self.REQUEST.other.get('messages', {})
        return self.getPhysicalPath() in messages

    def getErrorMessage(self):
        "get the current Error Message"
        messages = self.REQUEST.other.get('messages', {})
        return messages.get(self.getPhysicalPath(), ('', ''))

    def writeErrorMessage(self, message, messageType):
        "write the current error message so we can get it later"
        messages = self.REQUEST.other.get('messages', {})
        messages[self.getPhysicalPath()] = (message, messageType)
        self.REQUEST.other['messages'] = messages

    security.declarePrivate('voteStructure')

    def voteStructure(self):
        "get the voting data structure"
        lookup = {}
        lookup['description'] = self.description

        temp = []
        if len(self):
            if self.selectionType == 'radio':
                choices = [(choice.view(), choice.view()) for choice in self]
                temp = self.radio_list('radio',
                                       choices,
                                       containers=('choices', ))
                formName = self.formName('radio', 'string', ('choices', ))
                temp.append(
                    '<input type="hidden" name="%s:default" value="">' %
                    formName)
            elif self.selectionType == 'checkbox':
                formName = self.formName('default', 'string', ('choices', ))
                temp.append(
                    '<input type="hidden" name="%s:default" value="">' %
                    formName)
                for choice in self:
                    temp.append(
                        self.check_box(choice.getId(), choice.view(),
                                       ('choices', )) + choice.view())
            if temp:
                temp = [self.format % i for i in temp]

        lookup['issues'] = ''.join(temp)
        return lookup

    security.declarePrivate('isOkayToVote')

    def isOkayToVote(self, uid):
        "is it okay to vote"
        try:
            if getSecurityManager().validate(
                    None, self, 'drawVote', self.drawVote
            ) and self.voteEnabled and not self.alreadyVoted(
                    uid) and self.isOkayToVoteUserDefined():
                return True
        except Unauthorized:
            pass

    security.declarePrivate('alreadyVoted')

    def alreadyVoted(self, uid):
        "is it okay to vote"
        return self.getStorage().has_key(uid)

    security.declarePrivate('drawReport')

    def drawReport(self):
        "draw a basic report of the voting results"
        results = self.report()
        results = [(votes, issueName) for issueName, votes in results]
        results.sort(reverse=True)
        results.insert(0, ('Number of Votes', 'Choice'))
        results.append(('Total Number of Votes', len(self.getStorage())))
        temp = '<p>%s</p>' % self.description
        temp += self.createTable(results)
        return temp

    security.declarePrivate('report')

    def report(self):
        "return the report of how the votes went"
        return self.getVotes().items()

    security.declareProtected('CompoundDoc: Voting Stats', 'getVotes')

    def getVotes(self):
        "get the current vote information"
        if self.votes is not None:
            return self.votes
        return OOBTree()

    security.declareProtected('CompoundDoc: Voting Stats', 'getStorage')

    def getStorage(self):
        "get the current storage information which is a mapping of who has voted"
        if self.storage is not None:
            return self.storage
        return OOBTree()

    security.declareProtected('View', 'vote')

    def vote(self, uid, choices):
        "increase the count for this choice in votes if this uid is not already recorded"
        if self.isValidChoices(choices) and not self.getStorage().has_key(uid):
            self.uidVoted(uid)
            self.choiceSelected(choices)

    security.declarePrivate('isValidChoices')

    def isValidChoices(self, choices):
        "return true if all of the choices given are valid given the state of this object"
        allowedLength = 1
        allowedLengthMin = 0
        lookup = {}
        if self.selectionType == "checkbox":
            allowedLength = self.selectionLimit
            allowedLengthMin = self.selectionLimitMin
        lookup['selected'] = len(choices)
        lookup['max_selected'] = allowedLength
        lookup['min_selected'] = allowedLengthMin
        lookup['bad_choice'] = ''
        if not len(choices):
            self.writeErrorMessage(self.getMessage('MustSelectOne', lookup),
                                   'MustSelectOne')
            return 0
        if len(choices) > allowedLength:
            self.writeErrorMessage(self.getMessage('TooManyItems', lookup),
                                   'TooManyItems')
            return 0
        if len(choices) < allowedLengthMin:
            self.writeErrorMessage(self.getMessage('NotEnoughItems', lookup),
                                   'NotEnoughItems')
            return 0
        allowedChoices = [i.view() for i in self]
        for choice in choices:
            if choice not in allowedChoices:
                lookup['bad_choice'] = choice
                self.writeErrorMessage(
                    self.getMessage('BadItemSelected', lookup),
                    'BadItemSelected')
                return 0
        return 1

    security.declarePrivate('uidVoted')

    def uidVoted(self, uid):
        "record that this uid has voted for this issue"
        if self.storage is None:
            self.storage = OOBTree()
        if not self.storage.has_key(uid):
            self.storage[uid] = True

    security.declarePrivate('choiceSelected')

    def choiceSelected(self, choices):
        "increment the counter for this choice"
        if self.votes is None:
            self.votes = OOBTree()
        lookup = {}
        lookup['choices'] = choices
        self.writeErrorMessage(self.getMessage('thankYouText', lookup),
                               'thankYouText')
        for choice in choices:
            count = self.votes.get(choice, 0)
            count += 1
            self.votes[choice] = count

    security.declarePrivate('classUpgrader')

    def classUpgrader(self):
        "upgrade this class"
        return None
Exemple #58
0
class BTreeFolder2Base(Persistent):
    """Base for BTree-based folders.
    """

    security = ClassSecurityInfo()

    manage_options = (({
        'label': 'Contents',
        'action': 'manage_main',
    }, ) + Folder.manage_options[1:])

    security.declareProtected(view_management_screens, 'manage_main')
    manage_main = DTMLFile('contents', globals())

    _tree = None  # OOBTree: { id -> object }
    _count = None  # A BTrees.Length
    _v_nextid = 0  # The integer component of the next generated ID
    _mt_index = None  # OOBTree: { meta_type -> OIBTree: { id -> 1 } }
    title = ''

    def __init__(self, id=None):
        if id is not None:
            self.id = id
        self._initBTrees()

    def _initBTrees(self):
        self._tree = OOBTree()
        self._count = Length()
        self._mt_index = OOBTree()

    def _populateFromFolder(self, source):
        """Fill this folder with the contents of another folder.
        """
        for name in source.objectIds():
            value = source._getOb(name, None)
            if value is not None:
                self._setOb(name, aq_base(value))

    security.declareProtected(view_management_screens, 'manage_fixCount')

    def manage_fixCount(self):
        """Calls self._fixCount() and reports the result as text.
        """
        old, new = self._fixCount()
        path = '/'.join(self.getPhysicalPath())
        if old == new:
            return "No count mismatch detected in BTreeFolder2 at %s." % path
        else:
            return ("Fixed count mismatch in BTreeFolder2 at %s. "
                    "Count was %d; corrected to %d" % (path, old, new))

    def _fixCount(self):
        """Checks if the value of self._count disagrees with
        len(self.objectIds()). If so, corrects self._count. Returns the
        old and new count values. If old==new, no correction was
        performed.
        """
        old = self._count()
        new = len(self.objectIds())
        if old != new:
            self._count.set(new)
        return old, new

    security.declareProtected(view_management_screens, 'manage_cleanup')

    def manage_cleanup(self):
        """Calls self._cleanup() and reports the result as text.
        """
        v = self._cleanup()
        path = '/'.join(self.getPhysicalPath())
        if v:
            return "No damage detected in BTreeFolder2 at %s." % path
        else:
            return ("Fixed BTreeFolder2 at %s.  "
                    "See the log for more details." % path)

    def _cleanup(self):
        """Cleans up errors in the BTrees.

        Certain ZODB bugs have caused BTrees to become slightly insane.
        Fortunately, there is a way to clean up damaged BTrees that
        always seems to work: make a new BTree containing the items()
        of the old one.

        Returns 1 if no damage was detected, or 0 if damage was
        detected and fixed.
        """
        from BTrees.check import check
        path = '/'.join(self.getPhysicalPath())
        try:
            check(self._tree)
            for key in self._tree.keys():
                if not self._tree.has_key(key):
                    raise AssertionError("Missing value for key: %s" %
                                         repr(key))
            check(self._mt_index)
            for key, value in self._mt_index.items():
                if (not self._mt_index.has_key(key)
                        or self._mt_index[key] is not value):
                    raise AssertionError(
                        "Missing or incorrect meta_type index: %s" % repr(key))
                check(value)
                for k in value.keys():
                    if not value.has_key(k):
                        raise AssertionError(
                            "Missing values for meta_type index: %s" %
                            repr(key))
            return 1
        except AssertionError:
            LOG.warn('Detected damage to %s. Fixing now.' % path,
                     exc_info=sys.exc_info())
            try:
                self._tree = OOBTree(self._tree)
                mt_index = OOBTree()
                for key, value in self._mt_index.items():
                    mt_index[key] = OIBTree(value)
                self._mt_index = mt_index
            except:
                LOG.error('Failed to fix %s.' % path, exc_info=sys.exc_info())
                raise
            else:
                LOG.info('Fixed %s.' % path)
            return 0

    def _getOb(self, id, default=_marker):
        """Return the named object from the folder.
        """
        tree = self._tree
        if default is _marker:
            ob = tree[id]
            return ob.__of__(self)
        else:
            ob = tree.get(id, _marker)
            if ob is _marker:
                return default
            else:
                return ob.__of__(self)

    def _setOb(self, id, object):
        """Store the named object in the folder.
        """
        tree = self._tree
        if tree.has_key(id):
            raise KeyError('There is already an item named "%s".' % id)
        tree[id] = object
        self._count.change(1)
        # Update the meta type index.
        mti = self._mt_index
        meta_type = getattr(object, 'meta_type', None)
        if meta_type is not None:
            ids = mti.get(meta_type, None)
            if ids is None:
                ids = OIBTree()
                mti[meta_type] = ids
            ids[id] = 1

    def _delOb(self, id):
        """Remove the named object from the folder.
        """
        tree = self._tree
        meta_type = getattr(tree[id], 'meta_type', None)
        del tree[id]
        self._count.change(-1)
        # Update the meta type index.
        if meta_type is not None:
            mti = self._mt_index
            ids = mti.get(meta_type, None)
            if ids is not None and ids.has_key(id):
                del ids[id]
                if not ids:
                    # Removed the last object of this meta_type.
                    # Prune the index.
                    del mti[meta_type]

    security.declareProtected(view_management_screens, 'getBatchObjectListing')

    def getBatchObjectListing(self, REQUEST=None):
        """Return a structure for a page template to show the list of objects.
        """
        if REQUEST is None:
            REQUEST = {}
        pref_rows = int(REQUEST.get('dtpref_rows', 20))
        b_start = int(REQUEST.get('b_start', 1))
        b_count = int(REQUEST.get('b_count', 1000))
        b_end = b_start + b_count - 1
        url = self.absolute_url() + '/manage_main'
        idlist = self.objectIds()  # Pre-sorted.
        count = self.objectCount()

        if b_end < count:
            next_url = url + '?b_start=%d' % (b_start + b_count)
        else:
            b_end = count
            next_url = ''

        if b_start > 1:
            prev_url = url + '?b_start=%d' % max(b_start - b_count, 1)
        else:
            prev_url = ''

        formatted = []
        formatted.append(listtext0 % pref_rows)
        for i in range(b_start - 1, b_end):
            optID = escape(idlist[i])
            formatted.append(listtext1 % (escape(optID, quote=1), optID))
        formatted.append(listtext2)
        return {
            'b_start': b_start,
            'b_end': b_end,
            'prev_batch_url': prev_url,
            'next_batch_url': next_url,
            'formatted_list': ''.join(formatted)
        }

    security.declareProtected(view_management_screens,
                              'manage_object_workspace')

    def manage_object_workspace(self, ids=(), REQUEST=None):
        '''Redirects to the workspace of the first object in
        the list.'''
        if ids and REQUEST is not None:
            REQUEST.RESPONSE.redirect('%s/%s/manage_workspace' %
                                      (self.absolute_url(), quote(ids[0])))
        else:
            return self.manage_main(self, REQUEST)

    security.declareProtected(access_contents_information, 'tpValues')

    def tpValues(self):
        """Ensures the items don't show up in the left pane.
        """
        return ()

    security.declareProtected(access_contents_information, 'objectCount')

    def objectCount(self):
        """Returns the number of items in the folder."""
        return self._count()

    security.declareProtected(access_contents_information, 'has_key')

    def has_key(self, id):
        """Indicates whether the folder has an item by ID.
        """
        return self._tree.has_key(id)

    security.declareProtected(access_contents_information, 'objectIds')

    def objectIds(self, spec=None):
        # Returns a list of subobject ids of the current object.
        # If 'spec' is specified, returns objects whose meta_type
        # matches 'spec'.

        mti = self._mt_index
        if spec is None:
            spec = mti.keys()  #all meta types

        if isinstance(spec, StringType):
            spec = [spec]
        set = None
        for meta_type in spec:
            ids = mti.get(meta_type, None)
            if ids is not None:
                set = union(set, ids)
        if set is None:
            return ()
        else:
            return set.keys()

    security.declareProtected(access_contents_information, 'objectValues')

    def objectValues(self, spec=None):
        # Returns a list of actual subobjects of the current object.
        # If 'spec' is specified, returns only objects whose meta_type
        # match 'spec'.
        return LazyMap(self._getOb, self.objectIds(spec))

    security.declareProtected(access_contents_information, 'objectItems')

    def objectItems(self, spec=None):
        # Returns a list of (id, subobject) tuples of the current object.
        # If 'spec' is specified, returns only objects whose meta_type match
        # 'spec'
        return LazyMap(lambda id, _getOb=self._getOb: (id, _getOb(id)),
                       self.objectIds(spec))

    security.declareProtected(access_contents_information, 'objectMap')

    def objectMap(self):
        # Returns a tuple of mappings containing subobject meta-data.
        return LazyMap(
            lambda (k, v): {
                'id': k,
                'meta_type': getattr(v, 'meta_type', None)
            }, self._tree.items(), self._count())

    # superValues() looks for the _objects attribute, but the implementation
    # would be inefficient, so superValues() support is disabled.
    _objects = ()

    security.declareProtected(access_contents_information, 'objectIds_d')

    def objectIds_d(self, t=None):
        ids = self.objectIds(t)
        res = {}
        for id in ids:
            res[id] = 1
        return res

    security.declareProtected(access_contents_information, 'objectMap_d')

    def objectMap_d(self, t=None):
        return self.objectMap()

    def _checkId(self, id, allow_dup=0):
        if not allow_dup and self.has_key(id):
            raise BadRequestException, ('The id "%s" is invalid--'
                                        'it is already in use.' % id)

    def _setObject(self,
                   id,
                   object,
                   roles=None,
                   user=None,
                   set_owner=1,
                   suppress_events=False):
        ob = object  # better name, keep original function signature
        v = self._checkId(id)
        if v is not None:
            id = v

        # If an object by the given id already exists, remove it.
        if self.has_key(id):
            self._delObject(id)

        if not suppress_events:
            notify(ObjectWillBeAddedEvent(ob, self, id))

        self._setOb(id, ob)
        ob = self._getOb(id)

        if set_owner:
            # TODO: eventify manage_fixupOwnershipAfterAdd
            # This will be called for a copy/clone, or a normal _setObject.
            ob.manage_fixupOwnershipAfterAdd()

            # Try to give user the local role "Owner", but only if
            # no local roles have been set on the object yet.
            if getattr(ob, '__ac_local_roles__', _marker) is None:
                user = getSecurityManager().getUser()
                if user is not None:
                    userid = user.getId()
                    if userid is not None:
                        ob.manage_setLocalRoles(userid, ['Owner'])

        if not suppress_events:
            notify(ObjectAddedEvent(ob, self, id))
            notifyContainerModified(self)

        OFS.subscribers.compatibilityCall('manage_afterAdd', ob, ob, self)

        return id

    def _delObject(self, id, dp=1, suppress_events=False):
        ob = self._getOb(id)

        OFS.subscribers.compatibilityCall('manage_beforeDelete', ob, ob, self)

        if not suppress_events:
            notify(ObjectWillBeRemovedEvent(ob, self, id))

        self._delOb(id)

        if not suppress_events:
            notify(ObjectRemovedEvent(ob, self, id))
            notifyContainerModified(self)

    # Aliases for mapping-like access.
    __len__ = objectCount
    keys = objectIds
    values = objectValues
    items = objectItems

    # backward compatibility
    hasObject = has_key

    security.declareProtected(access_contents_information, 'get')

    def get(self, name, default=None):
        return self._getOb(name, default)

    # Utility for generating unique IDs.

    security.declareProtected(access_contents_information, 'generateId')

    def generateId(self, prefix='item', suffix='', rand_ceiling=999999999):
        """Returns an ID not used yet by this folder.

        The ID is unlikely to collide with other threads and clients.
        The IDs are sequential to optimize access to objects
        that are likely to have some relation.
        """
        tree = self._tree
        n = self._v_nextid
        attempt = 0
        while 1:
            if n % 4000 != 0 and n <= rand_ceiling:
                id = '%s%d%s' % (prefix, n, suffix)
                if not tree.has_key(id):
                    break
            n = randint(1, rand_ceiling)
            attempt = attempt + 1
            if attempt > MAX_UNIQUEID_ATTEMPTS:
                # Prevent denial of service
                raise ExhaustedUniqueIdsError
        self._v_nextid = n + 1
        return id

    def __getattr__(self, name):
        # Boo hoo hoo!  Zope 2 prefers implicit acquisition over traversal
        # to subitems, and __bobo_traverse__ hooks don't work with
        # restrictedTraverse() unless __getattr__() is also present.
        # Oh well.
        res = self._tree.get(name)
        if res is None:
            raise AttributeError, name
        return res