[CMF-checkins] CVS: CMF/CMFCore - CMFCatalogAware.py:1.2 ActionProviderBase.py:1.5 ActionsTool.py:1.25 DirectoryView.py:1.20 Expression.py:1.4 FSObject.py:1.9 FSPageTemplate.py:1.5 FSPythonScript.py:1.16 MembershipTool.py:1.19 PortalContent.py:1.34 PortalFolder.py:1.30 RegistrationTool.py:1.11 SkinsTool.py:1.14 TypesTool.py:1.32 WorkflowTool.py:1.21
Shane Hathaway
shane@cvs.zope.org
Mon, 25 Feb 2002 11:08:32 -0500
Update of /cvs-repository/CMF/CMFCore
In directory cvs.zope.org:/tmp/cvs-serv31001/CMFCore
Modified Files:
ActionProviderBase.py ActionsTool.py DirectoryView.py
Expression.py FSObject.py FSPageTemplate.py FSPythonScript.py
MembershipTool.py PortalContent.py PortalFolder.py
RegistrationTool.py SkinsTool.py TypesTool.py WorkflowTool.py
Added Files:
CMFCatalogAware.py
Log Message:
Merged cmf-pre-1_3-branch
=== CMF/CMFCore/CMFCatalogAware.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+
+import Globals
+from Acquisition import aq_base
+
+from AccessControl import ClassSecurityInfo
+from CMFCorePermissions import ModifyPortalContent
+from utils import getToolByName
+
+
+class CMFCatalogAware:
+ """Mix-in for notifying portal_catalog and portal_workflow
+ """
+
+ security = ClassSecurityInfo()
+
+ # Cataloging methods
+ # ------------------
+
+ security.declareProtected(ModifyPortalContent, 'indexObject')
+ def indexObject(self):
+ catalog = getToolByName(self, 'portal_catalog', None)
+ if catalog is not None:
+ catalog.indexObject(self)
+
+ security.declareProtected(ModifyPortalContent, 'unindexObject')
+ def unindexObject(self):
+ catalog = getToolByName(self, 'portal_catalog', None)
+ if catalog is not None:
+ catalog.unindexObject(self)
+
+ security.declareProtected(ModifyPortalContent, 'reindexObject')
+ def reindexObject(self):
+ catalog = getToolByName(self, 'portal_catalog', None)
+ if catalog is not None:
+ catalog.reindexObject(self)
+
+ def manage_afterAdd(self, item, container):
+ """
+ Add self to the workflow and catalog.
+ """
+ #
+ # Are we being added (or moved)?
+ #
+ if aq_base(container) is not aq_base(self):
+ wf = getToolByName(self, 'portal_workflow', None)
+ if wf is not None:
+ wf.notifyCreated(self)
+ self.indexObject()
+
+ def manage_beforeDelete(self, item, container):
+ """
+ Remove self from the catalog.
+ """
+ #
+ # Are we going away?
+ #
+ if aq_base(container) is not aq_base(self):
+ self.unindexObject()
+ #
+ # Now let our "aspects" know we are going away.
+ #
+ for item_id, subitem in self.objectItems():
+ # Carefully avoid implicit acquisition of the
+ # name "manage_beforeDelete"
+ if hasattr(aq_base(subitem), 'manage_beforeDelete'):
+ subitem.manage_beforeDelete(item, container)
+
+
+Globals.InitializeClass(CMFCatalogAware)
+
=== CMF/CMFCore/ActionProviderBase.py 1.4 => 1.5 ===
=== CMF/CMFCore/ActionsTool.py 1.24 => 1.25 ===
'id': d.get('id', None),
'name': d['name'],
+ 'action': d['action'],
'url': url,
'permissions': d['permissions'],
'category': d.get('category', 'object'),
=== CMF/CMFCore/DirectoryView.py 1.19 => 1.20 ===
return types
+
+ def _readProperties(self, fp):
+ """Reads the properties file next to an object.
+ """
+ try:
+ f = open(fp, 'rt')
+ except IOError:
+ return None
+ else:
+ lines = f.readlines()
+ f.close()
+ props = {}
+ for line in lines:
+ try: key, value = split(line, '=')
+ except: pass
+ else:
+ props[strip(key)] = strip(value)
+ return props
+
+
if Globals.DevelopmentMode and os.name=='nt':
def _changed(self):
@@ -211,8 +231,11 @@
t = registry.getTypeByExtension(ext)
if t is not None:
+ properties = self._readProperties(
+ e_filepath + '.properties')
try:
- ob = t(name, e_filepath, fullname=entry)
+ ob = t(name, e_filepath, fullname=entry,
+ properties=properties)
except:
import traceback
typ, val, tb = exc_info()
=== CMF/CMFCore/Expression.py 1.3 => 1.4 ===
=== CMF/CMFCore/FSObject.py 1.8 => 1.9 ===
_file_mod_time = 0
+ _parsed = 0
def __init__(self, id, filepath, fullname=None, properties=None):
if properties:
# Since props come from the filesystem, this should be
# safe.
self.__dict__.update(properties)
+ if fullname and properties.get('keep_extension', 0):
+ id = fullname
self.id = id
self.__name__ = id # __name__ is used in traceback reporting
@@ -92,11 +95,13 @@
# Refresh our contents from the filesystem if that is newer and we are
# running in debug mode.
def _updateFromFS(self):
- if Globals.DevelopmentMode:
+ parsed = self._parsed
+ if not parsed or Globals.DevelopmentMode:
fp = expandpath(self._filepath)
try: mtime=stat(fp)[8]
except: mtime=0
- if mtime != self._file_mod_time:
+ if not parsed or mtime != self._file_mod_time:
+ self._parsed = 1
self._file_mod_time = mtime
self._readFile(1)
=== CMF/CMFCore/FSPageTemplate.py 1.4 => 1.5 ===
try: data = file.read()
finally: file.close()
- self.write(data)
+ if reparse:
+ self.write(data)
security.declarePrivate('read')
def read(self):
@@ -90,23 +91,22 @@
self._updateFromFS()
return FSPageTemplate.inheritedAttribute('pt_macros')(self)
- if Globals.DevelopmentMode:
-
- # Redefine pt_render if in debug mode to give a bit more info
-
- def pt_render(self, source=0, extra_context={}):
- # Tie in on an opportunity to auto-reload
- self._updateFromFS()
- try:
- return FSPageTemplate.inheritedAttribute('pt_render')( self,
- source, extra_context )
- except RuntimeError:
+ def pt_render(self, source=0, extra_context={}):
+ self._updateFromFS() # Make sure the template has been loaded.
+ try:
+ return FSPageTemplate.inheritedAttribute('pt_render')(
+ self, source, extra_context )
+ except RuntimeError:
+ if Globals.DevelopmentMode:
err = FSPageTemplate.inheritedAttribute( 'pt_errors' )( self )
err_type = err[0]
err_msg = '<pre>%s</pre>' % replace( err[1], "\'", "'" )
msg = 'FS Page Template %s has errors: %s.<br>%s' % (
self.id, err_type, html_quote(err_msg) )
raise RuntimeError, msg
+ else:
+ raise
+
# Copy over more mothods
security.declareProtected(FTPAccess, 'manage_FTPget')
=== CMF/CMFCore/FSPythonScript.py 1.15 => 1.16 ===
try: data = file.read()
finally: file.close()
- self._write(data, reparse)
+ if reparse:
+ self._write(data, reparse)
def _validateProxy(self, roles=None):
pass
+ def __render_with_namespace__(self, namespace):
+ '''Calls the script.'''
+ self._updateFromFS()
+ return Script.__render_with_namespace__(self, namespace)
+
+ def __call__(self, *args, **kw):
+ '''Calls the script.'''
+ self._updateFromFS()
+ return Script.__call__(self, *args, **kw)
+
#### The following is mainly taken from PythonScript.py ###
def _exec(self, bound_names, args, kw):
@@ -83,15 +94,11 @@
Calling a Python Script is an actual function invocation.
"""
- self._updateFromFS()
# Prepare the function.
f = self._v_f
if f is None:
- # Not yet compiled.
- self._write(self._source, 1)
- f = self._v_f
- if f is None:
- raise RuntimeError, '%s has errors.' % self._filepath
+ # The script has errors.
+ raise RuntimeError, '%s has errors.' % self._filepath
__traceback_info__ = bound_names, args, kw, self.func_defaults
@@ -185,15 +192,21 @@
# This ensures func_code and func_defaults are
# set when the code hasn't been compiled yet,
# just in time for mapply(). Truly odd, but so is mapply(). :P
- self._write(self._source, 1)
+ self._updateFromFS()
return self.__dict__.get('func_defaults', None)
func_defaults = ComputedAttribute(func_defaults, 1)
def func_code(self):
# See func_defaults.
- self._write(self._source, 1)
+ self._updateFromFS()
return self.__dict__.get('func_code', None)
func_code = ComputedAttribute(func_code, 1)
+
+ def title(self):
+ # See func_defaults.
+ self._updateFromFS()
+ return self.__dict__.get('title', None)
+ title = ComputedAttribute(title, 1)
Globals.InitializeClass(FSPythonScript)
=== CMF/CMFCore/MembershipTool.py 1.18 => 1.19 ===
=== CMF/CMFCore/PortalContent.py 1.33 => 1.34 ===
from CMFCorePermissions import AccessContentsInformation, View, FTPAccess
-from CMFCorePermissions import ReviewPortalContent, ModifyPortalContent
from interfaces.Contentish import Contentish
from DynamicType import DynamicType
-from utils import getToolByName, _checkPermission, _getViewFor
+from utils import _checkPermission, _getViewFor
+
+from CMFCatalogAware import CMFCatalogAware
try:
from webdav.Lockable import ResourceLockedError
@@ -43,7 +44,7 @@
NoWL = 1
-class PortalContent(DynamicType, SimpleItem):
+class PortalContent(DynamicType, CMFCatalogAware, SimpleItem):
"""
Base class for portal objects.
@@ -100,58 +101,6 @@
"Returns a concatination of all searchable text"
# Should be overriden by portal objects
return "%s %s" % (self.Title(), self.Description())
-
- # Cataloging methods
- # ------------------
-
- security.declareProtected(ModifyPortalContent, 'indexObject')
- def indexObject(self):
- catalog = getToolByName(self, 'portal_catalog', None)
- if catalog is not None:
- catalog.indexObject(self)
-
- security.declareProtected(ModifyPortalContent, 'unindexObject')
- def unindexObject(self):
- catalog = getToolByName(self, 'portal_catalog', None)
- if catalog is not None:
- catalog.unindexObject(self)
-
- security.declareProtected(ModifyPortalContent, 'reindexObject')
- def reindexObject(self):
- catalog = getToolByName(self, 'portal_catalog', None)
- if catalog is not None:
- catalog.reindexObject(self)
-
- def manage_afterAdd(self, item, container):
- """
- Add self to the workflow and catalog.
- """
- #
- # Are we being added (or moved)?
- #
- if aq_base(container) is not aq_base(self):
- wf = getToolByName(self, 'portal_workflow', None)
- if wf is not None:
- wf.notifyCreated(self)
- self.indexObject()
-
- def manage_beforeDelete(self, item, container):
- """
- Remove self from the catalog.
- """
- #
- # Are we going away?
- #
- if aq_base(container) is not aq_base(self):
- self.unindexObject()
- #
- # Now let our "aspects" know we are going away.
- #
- for it, subitem in self.objectItems():
- si_m_bD = getattr( subitem, 'manage_beforeDelete', None )
- if si_m_bD is not None:
- si_m_bD( item, container )
-
# Contentish interface methods
# ----------------------------
=== CMF/CMFCore/PortalFolder.py 1.29 => 1.30 ===
ADD_CONTENT_PERMISSION = 'Add portal content'
+import sys
import Globals, re, base64, marshal, string
import CMFCorePermissions
@@ -328,6 +329,17 @@
, (type_name, self, id, RESPONSE) + args
, kw
)
+
+ security.declareProtected(AddPortalContent, 'checkIdAvailable')
+ def checkIdAvailable(self, id):
+ try:
+ self._checkId(id)
+ except:
+ if sys.exc_info()[0] == 'Bad Request':
+ return 0
+ raise # Some other exception.
+ else:
+ return 1
def MKCOL_handler(self,id,REQUEST=None,RESPONSE=None):
"""
=== CMF/CMFCore/RegistrationTool.py 1.10 => 1.11 ===
=== CMF/CMFCore/SkinsTool.py 1.13 => 1.14 ===
=== CMF/CMFCore/TypesTool.py 1.31 => 1.32 ===
from Globals import InitializeClass, DTMLFile
from utils import UniqueObject, SimpleItemWithProperties, tuplize
-from utils import _dtmldir, _checkPermission, cookString
from utils import _dtmldir, _checkPermission, cookString, getToolByName
import string
from AccessControl import getSecurityManager, ClassSecurityInfo
@@ -38,22 +37,6 @@
_marker = [] # Create a new marker.
-
-_type_factories = {}
-allowedTypes = ( 'Script (Python)'
- , 'Python Method'
- , 'DTML Method'
- , 'External Method'
- )
-
-def addTypeFactory(factory, id=None):
- # modeled after WorkflowTool.addWorkflowFactory()
- global allowedTypes
- if id is None:
- id = getattr(factory, 'id', '') or getattr(factory, 'meta_type', '')
- _type_factories[id] = factory
- allowedTypes = allowedTypes + (factory.meta_type,)
-
class TypeInformation (SimpleItemWithProperties):
"""
Base class for information about a content type.
@@ -469,7 +452,7 @@
return ob
InitializeClass( FactoryTypeInformation )
-addTypeFactory(FactoryTypeInformation)
+
class ScriptableTypeInformation( TypeInformation ):
"""
@@ -524,13 +507,32 @@
return ob
InitializeClass( ScriptableTypeInformation )
-addTypeFactory(ScriptableTypeInformation)
+
# Provide aliases for backward compatibility.
ContentFactoryMetadata = FactoryTypeInformation
ContentTypeInformation = ScriptableTypeInformation
+typeClasses = [
+ {'class':FactoryTypeInformation,
+ 'name':FactoryTypeInformation.meta_type,
+ 'action':'manage_addFactoryTIForm',
+ 'permission':'Manage portal'},
+ {'class':ScriptableTypeInformation,
+ 'name':ScriptableTypeInformation.meta_type,
+ 'action':'manage_addScriptableTIForm',
+ 'permission':'Manage portal'},
+ ]
+
+
+allowedTypes = [
+ 'Script (Python)',
+ 'Python Method',
+ 'DTML Method',
+ 'External Method',
+ ]
+
class TypesTool( UniqueObject, OFS.Folder.Folder, ActionProviderBase ):
"""
@@ -563,36 +565,23 @@
"""
return self._actions
- def __bobo_traverse__(self, TraversalRequest, name):
- # Nasty hack to get around main.dtml's quoting of
- # all_meta_types' actions
-
- if name=='manage_addTypeInfoForm':
- stack = TraversalRequest['TraversalRequestNameStack']
- if stack:
- TraversalRequest['type_type']=stack[0]
- stack[:]=[]
-
- return getattr(self,name)
-
def all_meta_types(self):
+ """Adds TypesTool-specific meta types."""
all = TypesTool.inheritedAttribute('all_meta_types')(self)
- factypes = []
- for name, fac in _type_factories.items():
- factypes.append({
- 'name': fac.meta_type,
- 'action': 'manage_addTypeInfoForm/%s' % name,
- 'permission': CMFCorePermissions.ManagePortal,
- })
- factypes.extend(all)
- return factypes
+ return tuple(typeClasses) + tuple(all)
def filtered_meta_types(self, user=None):
# Filters the list of available meta types.
+ allowed = {}
+ for tc in typeClasses:
+ allowed[tc['name']] = 1
+ for name in allowedTypes:
+ allowed[name] = 1
+
all = TypesTool.inheritedAttribute('filtered_meta_types')(self)
meta_types = []
for meta_type in self.all_meta_types():
- if meta_type['name'] in allowedTypes:
+ if allowed.get(meta_type['name']):
meta_types.append(meta_type)
return meta_types
@@ -620,17 +609,28 @@
_addTIForm = DTMLFile( 'addTypeInfo', _dtmldir )
- security.declareProtected(ManagePortal, 'manage_addTypeInfoForm')
- def manage_addTypeInfoForm(self, REQUEST={}, type_type=''):
- """ Return the type info form while keeping the list of
- prefab type information up to date """
- return self._addTIForm(self, REQUEST, type_type=type_type,
- types=self.listDefaultTypeInformation())
+ security.declareProtected(ManagePortal, 'manage_addFactoryTIForm')
+ def manage_addFactoryTIForm(self, REQUEST):
+ ' '
+ return self._addTIForm(
+ self, REQUEST,
+ add_meta_type=FactoryTypeInformation.meta_type,
+ types=self.listDefaultTypeInformation())
+
+ security.declareProtected(ManagePortal, 'manage_addScriptableTIForm')
+ def manage_addScriptableTIForm(self, REQUEST):
+ ' '
+ return self._addTIForm(
+ self, REQUEST,
+ add_meta_type=ScriptableTypeInformation.meta_type,
+ types=self.listDefaultTypeInformation())
security.declareProtected(ManagePortal, 'manage_addTypeInformation')
- def manage_addTypeInformation(self, id=None, type_type=None,
+ def manage_addTypeInformation(self, add_meta_type, id=None,
typeinfo_name=None, RESPONSE=None):
- """ Create a TypeInformation in self. """
+ """
+ Create a TypeInformation in self.
+ """
fti = None
if typeinfo_name:
info = self.listDefaultTypeInformation()
@@ -644,11 +644,13 @@
id = fti.get('id', None)
if not id:
raise 'Bad Request', 'An id is required.'
-
- if type_type in _type_factories.keys():
- klass = _type_factories[type_type]
+ for mt in typeClasses:
+ if mt['name'] == add_meta_type:
+ klass = mt['class']
+ break
else:
- klass = FactoryTypeInformation
+ raise ValueError, (
+ 'Meta type %s is not a type class.' % add_meta_type)
id = str(id)
if fti is not None:
fti = fti.copy()
=== CMF/CMFCore/WorkflowTool.py 1.20 => 1.21 ===
from string import join, split, replace, strip
-AUTO_MIGRATE_WORKFLOW_TOOLS = 1 # This will later be set to 0.
+AUTO_MIGRATE_WORKFLOW_TOOLS = 0 # Set to 1 to auto-migrate
_marker = [] # Create a new marker object.