Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 34 additions & 32 deletions Products/zms/ZMSMetaobjManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,34 @@ def renderTemplate(self, obj):
obj.clear_request_context(obj.REQUEST, prefix)
return v


def __aq_metaobjs__(self, aqs=[]):
"""
Resolve acquired meta-object entries from portal master.
"""
aq_obs = {}
if not aqs: return aq_obs
unresolved = []
for aq in aqs:
subobjects = aq.get('subobjects')
ob = self.model.get(aq['id'])
if ob and not ob.get('acquired') == 1:
aq_ob = {'acquired': 1, 'subobjects': subobjects, **ob}
aq_obs[id] = aq_ob
if aq_ob.get('type') == 'ZMSPackage' and subobjects == 1:
package = aq_ob['id']
for sub_id, sub_ob in self.model.items():
if sub_ob.get('package') == package:
aq_sub_ob = {'acquired': 1, **sub_ob}
aq_obs[sub_id] = aq_sub_ob
else:
unresolved.append(aq)
if unresolved:
portalMaster = self.getPortalMaster()
if portalMaster:
# merge, portal master first to allow local override
aq_obs = {**portalMaster.metaobj_manager.__aq_metaobjs__(unresolved), **aq_obs}
return aq_obs

def __get_metaobjs__(self):
"""
Return all meta-objects, including acquired entries from portal master.
Expand All @@ -523,36 +550,11 @@ def __get_metaobjs__(self):
try: return self.fetchReqBuff(reqBuffId)
except: pass
# Get value.
obs = {}
m = self.model
aq_obs = None
for id in m:
ob = m[id]
# handle acquisition
if ob.get('acquired', 0) == 1:
acquired = 1
subobjects = ob.get('subobjects', 1)
if aq_obs is None:
portalMaster = self.getPortalMaster()
if portalMaster is not None:
aq_obs = portalMaster.metaobj_manager.__get_metaobjs__()
if aq_obs is not None:
if id in aq_obs:
ob = aq_obs[id].copy()
else:
ob = {'id':id,'type':'ZMSUnknown'}
ob['acquired'] = acquired
ob['subobjects'] = subobjects
obs[id] = ob
if ob['type'] == 'ZMSPackage' and ob['subobjects'] == 1:
for aq_id in aq_obs:
ob = aq_obs[aq_id].copy()
if ob.get( 'package') == id:
ob['acquired'] = 1
obs[aq_id] = ob
else:
obs[id] = ob
return self.storeReqBuff( reqBuffId, obs)
own_obs = {id: ob for id, ob in self.model.items() if not ob.get('acquired') == 1}
aq_obs = [ob for ob in self.model.values() if ob.get('acquired') == 1]
master_obs = self.__aq_metaobjs__(aq_obs)
total_obs = {**own_obs, **master_obs}
return self.storeReqBuff( reqBuffId, total_obs)


def __get_metaobj__(self, id):
Expand Down Expand Up @@ -620,7 +622,7 @@ def getMetaobjIds(self, sort=None, excl_ids=[]):
if sort == True:
ids = sorted(ids,key=lambda x:self.display_type(meta_id=x))
elif sort == False:
ids = sorted(ids,key=lambda x:obs[x].get('name',x))
ids = sorted(ids,key=lambda x:obs.get(x, {}).get('name', x))
return ids


Expand Down
95 changes: 82 additions & 13 deletions Products/zms/_cachemanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,50 @@
from Products.zms import standard
from zope.globalrequest import getRequest

ram_cache_enabled = True
ram_cache_key = 'ram_cache'

class DummyCacheable:
def __init__(self, ob):
self._ob = ob

def ZCacheable_getModTime(self, *args, **kwargs):
return 0

def ZCacheable_getIdentifier(self):
return "/".join(self._ob.getPhysicalPath())

def ZCacheable_isCachingEnabled(self):
return True

def getPhysicalPath(self):
return self._ob.getPhysicalPath()

def get_cache(self):
cache = None
if ram_cache_enabled:
ram_cache = getattr(self, ram_cache_key)
cache = ram_cache.ZCacheManager_getCache()
return cache

def get_request(self):
request = getattr(self, 'REQUEST', None)
if request:
return request
return getRequest()

buff_key = '__buff__'

def get_buff(request):
buff = getattr(request, buff_key, None)
if buff is None:
buff = Buff()
setattr(request, buff_key, buff)
return buff

def set_buff(request, buff):
setattr(request, buff_key, buff)

class Buff(object):
"""Lightweight attribute container used for request-local buffering."""
pass
Expand All @@ -44,7 +88,8 @@ def getReqBuffId(self, key):
@return: Namespaced buffer key.
@rtype: C{str}
"""
return '%s_%s'%('_'.join(self.getPhysicalPath()[2:]), key)
path = self.getPhysicalPath()
return f"{hash(path)}_{key}"


def clearReqBuff(self, prefix='', REQUEST=None):
Expand All @@ -56,15 +101,16 @@ def clearReqBuff(self, prefix='', REQUEST=None):
@param REQUEST: Optional request object.
@type REQUEST: C{object}
"""
request = getattr(self, 'REQUEST', getRequest())
buff = request.get('__buff__', Buff())
reqBuffId = self.getReqBuffId(prefix)
request = get_request(self)
buff = get_buff(request)
if len(prefix) > 0:
reqBuffId += '.'
for key in list(buff.__dict__):
if key.startswith(reqBuffId):
delattr(buff, key)

set_buff(request, buff)


def fetchReqBuff(self, key=None, REQUEST=None):
"""
Expand All @@ -75,11 +121,26 @@ def fetchReqBuff(self, key=None, REQUEST=None):
@return: The buffered value.
@rtype: C{object}
"""
request = getattr(self, 'REQUEST', getRequest())
if key is None: # For debugging purposes, return whole buffer.
return None # request.get('__buff__',{})
buff = request['__buff__']
reqBuffId = self.getReqBuffId(key)
request = get_request(self)
buff = get_buff(request)
if not hasattr(buff, reqBuffId):
# RAM cache is optional, so we ignore errors if it's not available.
try:
cache = get_cache(self)
if cache:
cacheable = DummyCacheable(self)
# Note: keywords/view_name can be used for namespacing if needed.
value = cache.ZCache_get(cacheable, view_name='shared', keywords={'key': key})
if value:
#print("RAMCacheManager.get", key, value is not None)
# Store the value in the request buffer for future access.
setattr(buff, reqBuffId, value)
set_buff(request, buff)
return value
except Exception as e:
print("RAMCacheManager not available:", key, e)
pass
return getattr(buff, reqBuffId)


Expand All @@ -96,11 +157,19 @@ def storeReqBuff(self, key, value, REQUEST=None):
@return: The value that was stored.
@rtype: C{object}
"""
request = getattr(self, 'REQUEST', getRequest())
buff = request.get('__buff__', None)
if buff is None:
buff = Buff()
reqBuffId = self.getReqBuffId(key)
request = get_request(self)
buff = get_buff(request)
setattr(buff, reqBuffId, value)
request.set('__buff__', buff)
set_buff(request, buff)
# RAM cache is optional, so we ignore errors if it's not available.
try:
cache = get_cache(self)
if cache:
cacheable = DummyCacheable(self)
cache.ZCache_set(cacheable, value, view_name='shared', keywords={'key': key})
#print("RAMCacheManager.set", key, value is not None)
except Exception as e:
print("RAMCacheManager not available:", key, e)
pass
return value
53 changes: 31 additions & 22 deletions Products/zms/_confmanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -608,12 +608,7 @@ def getConfProperties(self, prefix=None, inherited=False, REQUEST=None):
r = {x:d[x] for x in d if x.startswith(prefix+'.')}
return json.dumps(r)
if inherited:
d = list(d)
portalMaster = self.getPortalMaster()
if portalMaster is not None:
l = portalMaster.getConfProperties(prefix,inherited,REQUEST)
l = [x for x in l if x not in d and x[:x.find('.')] not in UNINHERITED_PROPERTIES]
d.extend(l)
d = self.__aq_conf__()
return d


Expand Down Expand Up @@ -647,6 +642,25 @@ def getReqProperty(self, key, default=None, REQUEST=None):
return REQUEST.get(key, default)


def __aq_conf__(self, deep=0):
if deep == 0:
reqBuffId = 'CacheManager.__aq_conf__'
try: return self.fetchReqBuff(reqBuffId)
except: pass
aq_conf = self.get_conf_properties()
portalMaster = self.getPortalMaster()
if portalMaster:
# merge, portal master first to allow local override
master_conf = {k:v for k,v in portalMaster.__aq_conf__(deep+1).items() \
if not k in UNINHERITED_PROPERTIES \
and not k[:k.find('.')] in UNINHERITED_PROPERTIES \
and not k in ['UniBE.Alias', 'UniBE.Server']}
aq_conf = {**master_conf, **aq_conf}
if deep == 0:
return self.storeReqBuff( reqBuffId, aq_conf)
return aq_conf


def get_conf_property(self, *args, **kwargs):
"""
Return a configuration value, resolving local and inherited defaults.
Expand Down Expand Up @@ -675,19 +689,15 @@ def get_conf_property(self, *args, **kwargs):
if key in OFS.misc_.misc_.zms['confdict']:
default = OFS.misc_.misc_.zms['confdict'].get(key)
value = default
confdict = self.getConfProperties()
confdict = self.getConfProperties(inherited=True)
if key in confdict:
value = confdict.get(key)
elif key is not None and not key[:key.find('.')] in UNINHERITED_PROPERTIES and not key in ['UniBE.Alias', 'UniBE.Server']:
portalMaster = self.getPortalMaster()
if portalMaster is not None:
value = portalMaster.getConfProperty( key)
if value is None:
if 'default' in kwargs:
value = default
else:
for default in [x for x in self.default_conf_properties if x['key'] == key]:
value = default.get('default', None)
else:
if 'default' in kwargs:
value = default
else:
for default in [x for x in self.default_conf_properties if x['key'] == key]:
value = default.get('default', None)
return value


Expand Down Expand Up @@ -718,14 +728,13 @@ def setConfProperty(self, key, value):
"""
if key.startswith("Portal"):
self.clearReqBuff()
d = self.getConfProperties()
d = getattr( self, '__attr_conf_dict__', {})
if value is None:
if key in d:
del d[key]
else:
d[key] = value
self.__attr_conf_dict__ = d
self.__attr_conf_dict__ = self.__attr_conf_dict__.copy()
setattr(self, '__attr_conf_dict__', d.copy())

def manage_customizeSystem(self, btn, key, lang, REQUEST, RESPONSE=None):
"""
Expand Down Expand Up @@ -977,7 +986,7 @@ def manage_customizeDesign(self, btn, lang, REQUEST, RESPONSE):
return RESPONSE.redirect('manage_customizeDesignForm?lang=%s&manage_tabs_message=%s'%(lang, message))


def getZMSSysConf(self):
def getZMSSysConf(self, createIfNotExists=True):
"""
Return the ZMSSysConf object, creating and initializing it if it does not already exist.

Expand All @@ -990,7 +999,7 @@ def getZMSSysConf(self):
@rtype: ZMSSysConf
"""
sys_conf = getattr(self,"sys_conf",None)
if sys_conf is None:
if sys_conf is None and createIfNotExists:
sys_conf = _conf.ZMSSysConf()
self._setObject(sys_conf.id, sys_conf)
sys_conf = getattr(self, sys_conf.id, None)
Expand Down
1 change: 0 additions & 1 deletion Products/zms/rest_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,6 @@ def __init__(self, context=None, TraversalRequest=None):
self.ids = [x for x in self.path_to_handle if x != '++rest_api'] # remove ++rest_api as first element
while self.ids:
id = self.ids[0]
print(id,context)
if id.startswith('uid:'):
context = context.getLinkObj('{$%s}'%id)
elif id not in context.getPhysicalPath():
Expand Down
Loading