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,8 +149,9 @@ class Generator(AbstractGenerator):
destName = '%s.css.dtml' % self.applicationName)
self.copyFile('do.py', self.repls, destFolder=self.skinsFolder,
destName='%s_do.py' % self.applicationName)
self.copyFile('colophon.pt', self.repls, destFolder=self.skinsFolder)
self.copyFile('footer.pt', self.repls, destFolder=self.skinsFolder)
if self.config.minimalistPlone:
self.copyFile('colophon.pt', self.repls,destFolder=self.skinsFolder)
self.copyFile('footer.pt', self.repls, destFolder=self.skinsFolder)
# Create version.txt
f = open(os.path.join(self.outputFolder, 'version.txt'), 'w')
f.write(self.version)
@ -502,6 +503,7 @@ class Generator(AbstractGenerator):
parentWrapper = '%s_Wrapper' % k.name
wrapperDef = 'class %s_Wrapper(%s, %s):\n' % \
(c.name, parentWrapper, parentClass)
wrapperDef += ' security = ClassSecurityInfo()\n'
titleFound = False
for attrName in c.orderedAttributes:
if attrName == 'title':
@ -519,12 +521,20 @@ class Generator(AbstractGenerator):
# Implicitly, the title will be added by Archetypes. So I need
# to define a property for it.
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 \
isinstance(c, CustomFlavourClassDescriptor):
wrapperDef += " if hasattr(%s, 'update'): %s.update(%s.__bases__[1])" % \
(parentClass, parentClass, parentWrapper)
# For custom tool and flavour, add a call to a method that
# 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)
repls = self.repls.copy()
repls['imports'] = '\n'.join(imports)

View file

@ -105,6 +105,9 @@ class PloneInstaller:
if not hasattr(site.aq_base, self.productName):
# Temporarily allow me to create Appy large plone folders
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,
title=self.productName)
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.FlavourWrapper import FlavourWrapper
from appy.gen.plone25.wrappers.PodTemplateWrapper import PodTemplateWrapper
from Globals import InitializeClass
from AccessControl import ClassSecurityInfo
<!imports!>
class PodTemplate(PodTemplateWrapper):

View file

@ -1,5 +1,5 @@
'''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

View file

@ -150,7 +150,7 @@ class XmlUnmarshaller(XmlParser):
If "object" is specified, it means that the tag contains sub-tags, each
one corresponding to the value of an attribute for this object.
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)
self.klass = klass # If a klass is given here, instead of creating
# 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
# simply create an instance of UnmarshalledObject and dynamically change
# 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):
self.res = None # The resulting web of Python objects
@ -179,6 +186,8 @@ class XmlUnmarshaller(XmlParser):
elemType = 'unicode' # Default value
if attrs.has_key('type'):
elemType = attrs['type']
elif self.tagTypes.has_key(elem):
elemType = self.tagTypes[elem]
if elemType in self.containerTags:
# I must create a new container object.
if elemType == 'object': newObject = UnmarshalledObject()
@ -216,7 +225,18 @@ class XmlUnmarshaller(XmlParser):
currentContainer.content += value
else:
# 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):
e = XmlParser.characters(self, content)
@ -246,9 +266,15 @@ class XmlUnmarshaller(XmlParser):
else:
e.containerStack.pop()
# Alias 'unmarshall' -> 'parse'
# Alias: "unmarshall" -> "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:
'''This class allows to produce a XML version of a Python object, which