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:
parent
741f760bb5
commit
f7143a2afd
|
@ -149,7 +149,8 @@ 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)
|
||||
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')
|
||||
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue