Added a CSS parser; corrected bug that prevents Appy to create a root folder in a Plone site; allowed methods from an appy tool or flavour to be available in ZPTs.

This commit is contained in:
Gaetan Delannay 2009-09-18 14:42:31 +02:00
parent 741f760bb5
commit f7143a2afd
5 changed files with 51 additions and 10 deletions

View file

@ -149,6 +149,7 @@ class Generator(AbstractGenerator):
destName = '%s.css.dtml' % self.applicationName) destName = '%s.css.dtml' % self.applicationName)
self.copyFile('do.py', self.repls, destFolder=self.skinsFolder, self.copyFile('do.py', self.repls, destFolder=self.skinsFolder,
destName='%s_do.py' % self.applicationName) destName='%s_do.py' % self.applicationName)
if self.config.minimalistPlone:
self.copyFile('colophon.pt', self.repls,destFolder=self.skinsFolder) self.copyFile('colophon.pt', self.repls,destFolder=self.skinsFolder)
self.copyFile('footer.pt', self.repls, destFolder=self.skinsFolder) self.copyFile('footer.pt', self.repls, destFolder=self.skinsFolder)
# Create version.txt # Create version.txt
@ -502,6 +503,7 @@ class Generator(AbstractGenerator):
parentWrapper = '%s_Wrapper' % k.name parentWrapper = '%s_Wrapper' % k.name
wrapperDef = 'class %s_Wrapper(%s, %s):\n' % \ wrapperDef = 'class %s_Wrapper(%s, %s):\n' % \
(c.name, parentWrapper, parentClass) (c.name, parentWrapper, parentClass)
wrapperDef += ' security = ClassSecurityInfo()\n'
titleFound = False titleFound = False
for attrName in c.orderedAttributes: for attrName in c.orderedAttributes:
if attrName == 'title': if attrName == 'title':
@ -519,12 +521,20 @@ class Generator(AbstractGenerator):
# Implicitly, the title will be added by Archetypes. So I need # Implicitly, the title will be added by Archetypes. So I need
# to define a property for it. # to define a property for it.
wrapperDef += self.generateWrapperProperty('title', String()) wrapperDef += self.generateWrapperProperty('title', String())
# For custom tool, flavour and pod template, add a call to a method
# that allows to custom element to update the basic element.
if isinstance(c, CustomToolClassDescriptor) or \ if isinstance(c, CustomToolClassDescriptor) or \
isinstance(c, CustomFlavourClassDescriptor): isinstance(c, CustomFlavourClassDescriptor):
wrapperDef += " if hasattr(%s, 'update'): %s.update(%s.__bases__[1])" % \ # For custom tool and flavour, add a call to a method that
(parentClass, parentClass, parentWrapper) # allows to customize elements from the base class.
wrapperDef += " if hasattr(%s, 'update'):\n " \
"%s.update(%s.__bases__[1])\n" % (
parentClass, parentClass, parentWrapper)
# For custom tool and flavour, add security declaration that
# will allow to call their methods from ZPTs.
wrapperDef += " for elem in dir(%s):\n " \
"if not elem.startswith('_'): security.declarePublic" \
"(elem)\n" % (parentClass)
# Register the class in Zope.
wrapperDef += 'InitializeClass(%s_Wrapper)\n' % c.name
wrappers.append(wrapperDef) wrappers.append(wrapperDef)
repls = self.repls.copy() repls = self.repls.copy()
repls['imports'] = '\n'.join(imports) repls['imports'] = '\n'.join(imports)

View file

@ -105,6 +105,9 @@ class PloneInstaller:
if not hasattr(site.aq_base, self.productName): if not hasattr(site.aq_base, self.productName):
# Temporarily allow me to create Appy large plone folders # Temporarily allow me to create Appy large plone folders
getattr(site.portal_types, self.appyFolderType).global_allow = 1 getattr(site.portal_types, self.appyFolderType).global_allow = 1
# Allow to create Appy large folders in the plone site
getattr(site.portal_types,
'Plone Site').allowed_content_types += (self.appyFolderType,)
site.invokeFactory(self.appyFolderType, self.productName, site.invokeFactory(self.appyFolderType, self.productName,
title=self.productName) title=self.productName)
getattr(site.portal_types, self.appyFolderType).global_allow = 0 getattr(site.portal_types, self.appyFolderType).global_allow = 0

View file

@ -4,6 +4,8 @@ from appy.gen.plone25.wrappers import AbstractWrapper, FileWrapper
from appy.gen.plone25.wrappers.ToolWrapper import ToolWrapper from appy.gen.plone25.wrappers.ToolWrapper import ToolWrapper
from appy.gen.plone25.wrappers.FlavourWrapper import FlavourWrapper from appy.gen.plone25.wrappers.FlavourWrapper import FlavourWrapper
from appy.gen.plone25.wrappers.PodTemplateWrapper import PodTemplateWrapper from appy.gen.plone25.wrappers.PodTemplateWrapper import PodTemplateWrapper
from Globals import InitializeClass
from AccessControl import ClassSecurityInfo
<!imports!> <!imports!>
class PodTemplate(PodTemplateWrapper): class PodTemplate(PodTemplateWrapper):

View file

@ -1,5 +1,5 @@
'''This package contains base classes for wrappers that hide to the Appy '''This package contains base classes for wrappers that hide to the Appy
developer the real classes used by the undelrying web framework.''' developer the real classes used by the underlying web framework.'''
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
import time, os.path, mimetypes import time, os.path, mimetypes

View file

@ -150,7 +150,7 @@ class XmlUnmarshaller(XmlParser):
If "object" is specified, it means that the tag contains sub-tags, each If "object" is specified, it means that the tag contains sub-tags, each
one corresponding to the value of an attribute for this object. one corresponding to the value of an attribute for this object.
if "tuple" is specified, it will be converted to a list.''' if "tuple" is specified, it will be converted to a list.'''
def __init__(self, klass=None): def __init__(self, klass=None, tagTypes={}):
XmlParser.__init__(self) XmlParser.__init__(self)
self.klass = klass # If a klass is given here, instead of creating self.klass = klass # If a klass is given here, instead of creating
# a root UnmarshalledObject instance, we will create an instance of this # a root UnmarshalledObject instance, we will create an instance of this
@ -160,6 +160,13 @@ class XmlUnmarshaller(XmlParser):
# careful: we will not call the constructor of this class. We will # careful: we will not call the constructor of this class. We will
# simply create an instance of UnmarshalledObject and dynamically change # simply create an instance of UnmarshalledObject and dynamically change
# the class of the created instance to this class. # the class of the created instance to this class.
self.tagTypes = tagTypes
# We expect that the parsed XML file will follow some conventions
# (ie, a tag that corresponds to a list has attribute type="list" or a
# tag that corresponds to an object has attribute type="object".). If
# it is not the case of p_xmlContent, you can provide the missing type
# information in p_tagTypes. Here is an example of p_tagTypes:
# {"information": "list", "days": "list", "person": "object"}.
def startDocument(self): def startDocument(self):
self.res = None # The resulting web of Python objects self.res = None # The resulting web of Python objects
@ -179,6 +186,8 @@ class XmlUnmarshaller(XmlParser):
elemType = 'unicode' # Default value elemType = 'unicode' # Default value
if attrs.has_key('type'): if attrs.has_key('type'):
elemType = attrs['type'] elemType = attrs['type']
elif self.tagTypes.has_key(elem):
elemType = self.tagTypes[elem]
if elemType in self.containerTags: if elemType in self.containerTags:
# I must create a new container object. # I must create a new container object.
if elemType == 'object': newObject = UnmarshalledObject() if elemType == 'object': newObject = UnmarshalledObject()
@ -216,7 +225,18 @@ class XmlUnmarshaller(XmlParser):
currentContainer.content += value currentContainer.content += value
else: else:
# Current container is an object # Current container is an object
setattr(currentContainer, name, value) if hasattr(currentContainer, name):
# We have already encountered a sub-object with this name.
# Having several sub-objects with the same name, we will
# create a list.
attrValue = getattr(currentContainer, name)
if not isinstance(attrValue, list):
attrValue = [attrValue, value]
else:
attrValue.append(value)
else:
attrValue = value
setattr(currentContainer, name, attrValue)
def characters(self, content): def characters(self, content):
e = XmlParser.characters(self, content) e = XmlParser.characters(self, content)
@ -246,9 +266,15 @@ class XmlUnmarshaller(XmlParser):
else: else:
e.containerStack.pop() e.containerStack.pop()
# Alias 'unmarshall' -> 'parse' # Alias: "unmarshall" -> "parse"
unmarshall = XmlParser.parse unmarshall = XmlParser.parse
class CssParser(XmlUnmarshaller):
cssTags = {'rss': 'object', 'channel': 'object', 'item': 'object'}
def startDocument(self):
XmlUnmarshaller.startDocument(self)
self.tagTypes.update(self.cssTags)
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
class XmlMarshaller: class XmlMarshaller:
'''This class allows to produce a XML version of a Python object, which '''This class allows to produce a XML version of a Python object, which