Example #1
0
    def table_script_resource_tree_data(self, table=None, res_type=None):
        #pkg,tblname = table.split('.')
        tblobj = self.db.table(table)
        pkg = tblobj.pkg.name
        tblname = tblobj.name
        result = Bag()
        resources = self.site.resource_loader.resourcesAtPath(
            page=self, pkg=None, path='tables/_default/%s' % res_type)
        resources_pkg = self.site.resource_loader.resourcesAtPath(
            page=self, pkg=pkg, path='tables/%s/%s' % (tblname, res_type))
        resources_custom = self.site.resource_loader.resourcesAtPath(
            page=self,
            pkg=self.package.name,
            path='tables/_packages/%s/%s/%s' % (pkg, tblname, res_type))
        resources.update(resources_pkg)
        resources.update(resources_custom)

        forbiddenNodes = []

        def cb(node, _pathlist=None):
            has_parameters = False
            if node.attr['file_ext'] == 'py':
                resmodule = gnrImport(node.attr['abs_path'])
                tags = getattr(resmodule, 'tags', '')
                if tags and not self.application.checkResourcePermission(
                        tags, self.userTags):
                    if node.label == '_doc':
                        forbiddenNodes.append('.'.join(_pathlist))
                    return
                caption = getattr(resmodule, 'caption', node.label)
                description = getattr(resmodule, 'description', '')
                description = getattr(resmodule, 'needSelection', True)
                if node.label == '_doc':
                    result.setAttr(
                        '.'.join(_pathlist),
                        dict(caption=caption,
                             description=description,
                             tags=tags,
                             has_parameters=has_parameters))
                else:
                    mainclass = getattr(resmodule, 'Main', None)
                    assert mainclass, 'Main class is mandatory in tablescript resource'
                    has_parameters = hasattr(mainclass, 'parameters_pane')
                    result.setItem('.'.join(_pathlist + [node.label]),
                                   None,
                                   caption=caption,
                                   description=description,
                                   resource=node.attr['rel_path'][:-3],
                                   has_parameters=has_parameters)

        pl = []
        resources.walk(cb, _pathlist=pl)
        if '_common' in result:
            n = result.popNode('_common')
            if len(result):
                result.setItem('r_zz', None, caption='-')
            result.setItem(n.label, n.value, n.attr)
        for forbidden in forbiddenNodes:
            result.pop(forbidden)
        return result
Example #2
0
    def getMenuBag(self,root_id=None,userTags=None,exportMode=None):
        root_id = root_id or self.rootId()
        q = self.query(where="$hierarchical_pkey LIKE :root_id || '/%%' " ,
                        root_id=root_id,columns='*,$hlevel,$page_label,$page_filepath,$page_tbl,$page_metadata',
                        order_by='$_h_count')

        f = q.fetch()
        if not f:
            return
        result = Bag()
        app = self.db.application
        forbidden = []
        for i,r in enumerate(f):
            if userTags is True or (app.checkResourcePermission(r['tags'], userTags) and not r['parent_id'] in forbidden):
                kw = dict()      
                r = dict(r)   
                if r['page_id']:       
                    kw['table'] = r.pop('page_tbl',None)
                    kw['file'] = r.pop('page_filepath',None)
                    if r['page_metadata']:
                        kw.update(asDict(r['page_metadata']))
                        labelClass = 'menu_shape menu_page'
                else:
                    kw['isDir'] = True
                    labelClass='menu_shape menu_level_%i' %(r['hlevel']-2)
                if not exportMode:
                    kw['labelClass'] = labelClass
                result.setItem(r['hierarchical_pkey'].split('/')[1:],None,label=r['label'],tags=r['tags'],
                                **kw)  
            else:
                forbidden.append(r['id'])
        empty = True

        while empty:
            empty = False
            for pathlist,n in result.getIndex():
                if n.attr.get('isDir') and  ( (n.value is None) or not n.value):
                    result.popNode(pathlist)
                    empty = True
        return result
Example #3
0
 def table_script_resource_tree_data(self, table=None, res_type=None):
     #pkg,tblname = table.split('.')
     tblobj = self.db.table(table)
     pkg = tblobj.pkg.name
     tblname = tblobj.name
     result = Bag()
     resources = self.site.resource_loader.resourcesAtPath(page=self,pkg=None,path='tables/_default/%s' % res_type)
     resources_pkg = self.site.resource_loader.resourcesAtPath(page=self,pkg=pkg, path='tables/%s/%s' % (tblname, res_type))
     resources_custom = self.site.resource_loader.resourcesAtPath(page=self,pkg=self.package.name, path='tables/_packages/%s/%s/%s' % (pkg,tblname, res_type))
     resources.update(resources_pkg)
     resources.update(resources_custom)
     
     
     forbiddenNodes = []
     def cb(node, _pathlist=None):
         has_parameters = False
         if node.attr['file_ext'] == 'py':
             resmodule = gnrImport(node.attr['abs_path'])
             tags = getattr(resmodule, 'tags', '')
             if tags and not self.application.checkResourcePermission(tags, self.userTags):
                 if node.label == '_doc':
                     forbiddenNodes.append('.'.join(_pathlist))
                 return
             caption = getattr(resmodule, 'caption', node.label)
             description = getattr(resmodule, 'description', '')
             description = getattr(resmodule, 'needSelection', True)
             if  node.label == '_doc':
                 result.setAttr('.'.join(_pathlist), dict(caption=caption, description=description, tags=tags,
                                                          has_parameters=has_parameters))
             else:
                 mainclass = getattr(resmodule, 'Main', None)
                 assert mainclass, 'Main class is mandatory in tablescript resource'
                 has_parameters = hasattr(mainclass, 'parameters_pane')
                 result.setItem('.'.join(_pathlist + [node.label]), None, caption=caption, description=description,
                                resource=node.attr['rel_path'][:-3], has_parameters=has_parameters)
     pl=[]     
     resources.walk(cb,_pathlist=pl)
     if '_common' in result:
         n = result.popNode('_common')
         if len(result):
             result.setItem('r_zz',None,caption='-')
         result.setItem(n.label,n.value,n.attr)
     for forbidden in forbiddenNodes:
         result.pop(forbidden)
     return result
Example #4
0
class SharedObject(object):
    default_savedir = 'site:async/sharedobjects'
    def __init__(self,manager,shared_id,expire=None,startData=None,read_tags=None,write_tags=None,
                    filepath=None, dbSaveKw=None, saveInterval=None, autoSave=None, autoLoad=None,**kwargs):

        self.manager = manager
        self.lock=locks.Lock()
        self.server = manager.server
        self.shared_id = shared_id
        self._data = Bag(dict(root=Bag(startData)))
        self.read_tags = read_tags
        self.write_tags = write_tags
        self._data.subscribe('datachanges', any=self._on_data_trigger)
        self.subscribed_pages = dict()
        self.expire = expire or 0
        self.focusedPaths = {}
        if self.expire<0:
            self.expire = 365*24*60*60
        self.timeout=None
        self.autoSave=autoSave
        self.saveInterval=saveInterval
        self.autoLoad=autoLoad
        self.changes=False
        self.dbSaveKw=dbSaveKw
        self.onInit(**kwargs)


    @property
    def savepath(self):
        return self.server.gnrsite.getStaticPath(self.default_savedir,'%s.xml' %self.shared_id)

    @property
    def data(self):
        return self._data['root']

    @property
    def sql_data_column(self):
        return self.dbSaveKw.get('data_column') or 'shared_data'

    @property
    def sql_backup_column(self):
        return self.dbSaveKw.get('backup_column') or 'shared_backup'


    @lockedThreadpool
    def save(self):
        if self.changes :
            if self.dbSaveKw:
                kw = dict(self.dbSaveKw)
                tblobj = self.server.db.table(kw.pop('table'))
                handler = getattr(tblobj, 'saveSharedObject', None)
                if handler:
                    handler(self.shared_id, self.data, **kw)
                else:
                    self.sql_save(tblobj)
                self.server.db.commit()
            else:
                self.data.toXml(self.savepath,unresolved=True,autocreate=True)
        self.changes=False

    @lockedThreadpool
    def load(self):
        if self.dbSaveKw:
            tblobj = self.server.db.table(self.dbSaveKw['table'])
            handler = getattr(tblobj, 'loadSharedObject', None)
            if handler:
                data = handler(self.shared_id)
            else:
                data = self.sql_load(tblobj)
        elif os.path.exists(self.savepath):
            data =  Bag(self.savepath)
        else:
            data = Bag()
        self._data['root'] = data
        self.changes=False

    def sql_save(self, tblobj):
        backup = self.dbSaveKw.get('backup')
        data_column = self.sql_data_column
        with tblobj.recordToUpdate(self.shared_id) as record:
            if not self.data:
                print 'NO DATA IN SAVING', self.shared_id
            record[data_column] = deepcopy(self.data)
            onSavingHandler=getattr(tblobj, 'shared_onSaving',None)
            if onSavingHandler:
                onSavingHandler(record)

            if backup:
                backup_column = self.sql_backup_column
                if not record[backup_column]:
                    record[backup_column] =  Bag()
                    n = 0
                else:
                    n = int(record[backup_column].keys()[-1].split('_')[1])+1
                record[backup_column].setItem('v_%s' % n, record[data_column], ts=datetime.now())
                if len (record[backup_column]) > backup:
                    record[backup_column].popNode('#0')
            

    def sql_load(self, tblobj, version=None):
        record = tblobj.record(self.shared_id).output('bag')
        onLoadingHandler=getattr(tblobj, 'shared_onLoading',None)
        if onLoadingHandler:
            onLoadingHandler(record)

        if not version:
            return record[self.sql_data_column]
        else:
            return record[self.sql_backup_column].getItem('v_%i'% version)



    def onInit(self,**kwargs):
        if self.autoLoad:
            self.load()
        
    def onSubscribePage(self,page_id):
        pass
        #print 'onSubscribePage',self.shared_id,page_id
        
    def onUnsubscribePage(self,page_id):
        pass
        #print 'onUnsubscribePage',self.shared_id,page_id
    
    def onDestroy(self):
        print 'onDestroy',self.shared_id
        if self.autoSave:
            self.save()
        
        
    def onShutdown(self):
        if self.autoSave:
            self.save()
            
    def subscribe(self,page_id=None,**kwargs):
        page = self.server.pages[page_id]
        privilege= self.checkPermission(page)
        if privilege:
            page.sharedObjects.add(self.shared_id)
            subkwargs=dict(kwargs)
            subkwargs['page_id']=page_id
            subkwargs['user']=page.user
            self.subscribed_pages[page_id] = subkwargs
            self.server.sharedStatus.sharedObjectSubscriptionAddPage(self.shared_id,page_id,subkwargs)
            self.onSubscribePage(page)
            result=dict(privilege=privilege,data=self.data)
            return result

    def unsubscribe(self,page_id=None):
        self.subscribed_pages.pop(page_id,None)
        self.server.sharedStatus.sharedObjectSubscriptionRemovePage(self.shared_id,page_id)
        self.onUnsubscribePage(page_id)
        if not self.subscribed_pages:
            self.timeout=self.server.delayedCall(self.expire,self.manager.removeSharedObject,self)
            
    def checkPermission(self,page):
        privilege = 'readwrite' 
        if self.read_tags and not self.server.gnrapp.checkResourcePermission(self.read_tags,page.userTags):
            privilege = None
        elif self.write_tags and not self.server.gnrapp.checkResourcePermission(self.write_tags,page.userTags):
            privilege = 'readonly'
        return privilege
    
    @lockedCoroutine
    def datachange(self,page_id=None,path=None,value=None,attr=None,evt=None,fired=None,**kwargs):
        if fired:
            data = Bag(dict(value=value,attr=attr,path=path,shared_id=self.shared_id,evt=evt,fired=fired))
            self.broadcast(command='som.sharedObjectChange',data=data,from_page_id=page_id)
        else:
            path = 'root' if not path else 'root.%s' %path
            if evt=='del':
                self._data.popNode(path,_reason=page_id)
            else:
                self._data.setItem(path,value,_attributes=attr,_reason=page_id)

    def _on_data_trigger(self, node=None, ind=None, evt=None, pathlist=None,reason=None, **kwargs):
        self.changes=True
        if reason=='autocreate':
            return
        plist = pathlist[1:]
        if evt=='ins' or evt=='del':
            plist = plist+[node.label]
        path = '.'.join(plist)
        data = Bag(dict(value=node.value,attr=node.attr,path=path,shared_id=self.shared_id,evt=evt))
        from_page_id = reason
        self.broadcast(command='som.sharedObjectChange',data=data,from_page_id=from_page_id)

                
    def onPathFocus(self, page_id=None,curr_path=None,focused=None):
        if focused:
            self.focusedPaths[curr_path]=page_id
        else:
            self.focusedPaths.pop(curr_path,None)
        self.broadcast(command='som.onPathLock',from_page_id=page_id,data=Bag(dict(locked=focused,lock_path=curr_path)))

    
    def broadcast(self,command=None, data=None, from_page_id=None,):
        envelope = Bag(dict(command=command,data=data)).toXml()
        channels = self.server.channels
        for p in self.subscribed_pages.keys():
            if p != from_page_id:
                channels.get(p).write_message(envelope)