diff --git a/bin/generate.py b/bin/generate.py
index 72375e4..c92faf2 100644
--- a/bin/generate.py
+++ b/bin/generate.py
@@ -3,18 +3,15 @@
# ------------------------------------------------------------------------------
import sys, os.path
from optparse import OptionParser
-from appy.gen.generator import GeneratorError
+from appy.gen.generator import GeneratorError, ZopeGenerator
from appy.shared.utils import LinesCounter
import appy.version
# ------------------------------------------------------------------------------
ERROR_CODE = 1
-VALID_PRODUCT_TYPES = ('zope', 'odt')
APP_NOT_FOUND = 'Application not found at %s.'
WRONG_NG_OF_ARGS = 'Wrong number of arguments.'
WRONG_OUTPUT_FOLDER = 'Output folder not found. Please create it first.'
-PRODUCT_TYPE_ERROR = 'Wrong product type. Product type may be one of the ' \
- 'following: %s' % str(VALID_PRODUCT_TYPES)
C_OPTION = 'Removes from i18n files all labels that are not automatically ' \
'generated from your gen-application. It can be useful during ' \
'development, when you do lots of name changes (classes, ' \
@@ -37,7 +34,7 @@ S_OPTION = 'Sorts all i18n labels. If you use this option, among the ' \
'set of translation files.'
class GeneratorScript:
- '''usage: %prog [options] app productType outputFolder
+ '''usage: %prog [options] app outputFolder
"app" is the path to your Appy application, which must be a
Python package (= a folder containing a file named
@@ -47,44 +44,29 @@ class GeneratorScript:
generated product, stored or symlinked in
/Products.
- "productType" is the kind of product you want to generate. "zope" is
- the only available production-ready target.
- "odt" is experimental.
-
"outputFolder" is the folder where the Zope product will be generated.
For example, if you develop your application in
/home/gdy/MyProject/MyProject, you typically specify
"/home/gdy/MyProject/zope" as outputFolder.
'''
-
- def generateProduct(self, options, application, productType, outputFolder):
- if productType == 'odt':
- exec 'from appy.gen.odt.generator import Generator'
- else:
- from appy.gen.generator import ZopeGenerator as Generator
- Generator(application, outputFolder, options).run()
-
def manageArgs(self, parser, options, args):
# Check number of args
- if len(args) != 3:
+ if len(args) != 2:
print WRONG_NG_OF_ARGS
parser.print_help()
sys.exit(ERROR_CODE)
- # Check productType
- if args[1] not in VALID_PRODUCT_TYPES:
- print PRODUCT_TYPE_ERROR
- sys.exit(ERROR_CODE)
# Check existence of application
if not os.path.exists(args[0]):
print APP_NOT_FOUND % args[0]
sys.exit(ERROR_CODE)
- # Check existence of outputFolder basic type
- if not os.path.exists(args[2]):
+ # Check existence of outputFolder
+ if not os.path.exists(args[1]):
print WRONG_OUTPUT_FOLDER
sys.exit(ERROR_CODE)
# Convert all paths in absolute paths
- for i in (0,2):
+ for i in (0,1):
args[i] = os.path.abspath(args[i])
+
def run(self):
optParser = OptionParser(usage=GeneratorScript.__doc__)
optParser.add_option("-c", "--i18n-clean", action='store_true',
@@ -95,8 +77,8 @@ class GeneratorScript:
try:
self.manageArgs(optParser, options, args)
print 'Appy version:', appy.version.verbose
- print 'Generating %s product in %s...' % (args[1], args[2])
- self.generateProduct(options, *args)
+ print 'Generating Zope product in %s...' % args[1]
+ ZopeGenerator(args[0], args[1], options).run()
# Give the user some statistics about its code
LinesCounter(args[0]).run()
except GeneratorError, ge:
diff --git a/gen/__init__.py b/gen/__init__.py
index 5c88e7b..6322b28 100644
--- a/gen/__init__.py
+++ b/gen/__init__.py
@@ -1026,8 +1026,7 @@ class String(Type):
it will be given by the Appy validation machinery, so it must be
specified as parameter. The function returns True if the check is
successful.'''
- if not value: return True # Plone calls me erroneously for
- # non-mandatory fields.
+ if not value: return True
# First, remove any non-digit char
v = ''
for c in value:
@@ -1058,8 +1057,7 @@ class String(Type):
'''Checks that p_value corresponds to a valid IBAN number. IBAN stands
for International Bank Account Number (ISO 13616). If the number is
valid, the method returns True.'''
- if not value: return True # Plone calls me erroneously for
- # non-mandatory fields.
+ if not value: return True
# First, remove any non-digit or non-letter char
v = ''
for c in value:
@@ -1088,8 +1086,7 @@ class String(Type):
'''Checks that p_value corresponds to a valid BIC number. BIC stands
for Bank Identifier Code (ISO 9362). If the number is valid, the
method returns True.'''
- if not value: return True # Plone calls me erroneously for
- # non-mandatory fields.
+ if not value: return True
# BIC number must be 8 or 11 chars
if len(value) not in (8, 11): return False
# 4 first chars, representing bank name, must be letters
@@ -1176,15 +1173,7 @@ class String(Type):
else: return value
if isinstance(value, basestring) and self.isMultiValued():
value = [value]
- # Some backward compatibilities with Archetypes.
- elif value.__class__.__name__ == 'BaseUnit':
- try:
- value = unicode(value)
- except UnicodeDecodeError:
- value = str(value)
elif isinstance(value, tuple):
- # When Appy storage was based on Archetype, multivalued string
- # fields stored values as tuples of unicode strings.
value = list(value)
return value
@@ -1207,12 +1196,6 @@ class String(Type):
res = [t('%s_list_%s' % (self.labelId, v)) for v in value]
else:
res = t('%s_list_%s' % (self.labelId, value))
- elif not isinstance(value, basestring):
- # Archetypes "Description" fields may hold a BaseUnit instance.
- try:
- res = unicode(value)
- except UnicodeDecodeError:
- res = str(value)
# If value starts with a carriage return, add a space; else, it will
# be ignored.
if isinstance(res, basestring) and \
@@ -1384,8 +1367,8 @@ class Boolean(Type):
return value
def getFormattedValue(self, obj, value):
- if value: res = obj.translate('yes', domain='plone')
- else: res = obj.translate('no', domain='plone')
+ if value: res = obj.translate('yes')
+ else: res = obj.translate('no')
return res
def getStorableValue(self, value):
@@ -1517,7 +1500,7 @@ class File(Type):
def getFormattedValue(self, obj, value):
if not value: return value
- return value._atFile
+ return value._zopeFile
def getRequestValue(self, request):
return request.get('%s_file' % self.name)
@@ -1591,7 +1574,7 @@ class File(Type):
elif isinstance(value, OFSImageFile):
setattr(obj, self.name, value)
elif isinstance(value, FileWrapper):
- setattr(obj, self.name, value._atFile)
+ setattr(obj, self.name, value._zopeFile)
elif isinstance(value, basestring):
setattr(obj, self.name, File.getFileObject(value, zope=True))
elif type(value) in sequenceTypes:
@@ -2189,7 +2172,7 @@ class Pod(Type):
def store(self, obj, value):
'''Stores (=freezes) a document (in p_value) in the field.'''
if isinstance(value, FileWrapper):
- value = value._atFile
+ value = value._zopeFile
setattr(obj, self.name, value)
class List(Type):
@@ -2283,19 +2266,18 @@ appyToZopePermissions = {
class Role:
'''Represents a role.'''
- ploneRoles = ('Manager', 'Member', 'Owner', 'Reviewer', 'Anonymous',
- 'Authenticated')
- ploneLocalRoles = ('Owner',)
- ploneUngrantableRoles = ('Anonymous', 'Authenticated')
+ zopeRoles = ('Manager', 'Owner', 'Anonymous', 'Authenticated')
+ zopeLocalRoles = ('Owner',)
+ zopeUngrantableRoles = ('Anonymous', 'Authenticated')
def __init__(self, name, local=False, grantable=True):
self.name = name
self.local = local # True if it can be used as local role only.
- # It is a standard Plone role or an application-specific one?
- self.plone = name in self.ploneRoles
- if self.plone and (name in self.ploneLocalRoles):
+ # It is a standard Zope role or an application-specific one?
+ self.zope = name in self.zopeRoles
+ if self.zope and (name in self.zopeLocalRoles):
self.local = True
self.grantable = grantable
- if self.plone and (name in self.ploneUngrantableRoles):
+ if self.zope and (name in self.zopeUngrantableRoles):
self.grantable = False
# An ungrantable role is one that is, like the Anonymous or
# Authenticated roles, automatically attributed to a user.
@@ -2575,8 +2557,7 @@ class Transition:
# Return a message to the user if needed
if not doSay or (transitionName == '_init_'): return
if not msg:
- msg = obj.translate(u'Your content\'s status has been modified.',
- domain='plone')
+ msg = obj.translate(u'Changes saved.')
obj.say(msg)
class Permission:
diff --git a/gen/descriptors.py b/gen/descriptors.py
index 3459b05..40b05dd 100644
--- a/gen/descriptors.py
+++ b/gen/descriptors.py
@@ -4,7 +4,7 @@
# ------------------------------------------------------------------------------
import types, copy
-from appy.gen import State, Transition, Type
+import appy.gen as gen
from po import PoMessage
from model import ModelClass, toolFieldPrefixes
from utils import produceNiceMessage, getClassName
@@ -27,8 +27,7 @@ class ClassDescriptor(Descriptor):
'''This class gives information about an Appy class.'''
def __init__(self, klass, orderedAttributes, generator):
- appy.gen.descriptors.ClassDescriptor.__init__(self, klass,
- orderedAttributes, generator)
+ Descriptor.__init__(self, klass, orderedAttributes, generator)
self.methods = '' # Needed method definitions will be generated here
# We remember here encountered pages and groups defined in the Appy
# type. Indeed, after having parsed all application classes, we will
@@ -70,7 +69,7 @@ class ClassDescriptor(Descriptor):
except AttributeError:
attrValue = getattr(self.modelClass, attrName)
hookClass = self.modelClass
- if isinstance(attrValue, Type):
+ if isinstance(attrValue, gen.Type):
if not condition or eval(condition):
attrs.append( (attrName, attrValue, hookClass) )
# Then, add attributes from parent classes
@@ -142,7 +141,7 @@ class ClassDescriptor(Descriptor):
attrValue = getattr(self.klass, attrName)
except AttributeError:
attrValue = getattr(self.modelClass, attrName)
- if isinstance(attrValue, Type):
+ if isinstance(attrValue, gen.Type):
if configClass:
attrValue = copy.copy(attrValue)
attrValue.optional = False
@@ -184,13 +183,13 @@ class ClassDescriptor(Descriptor):
res = []
if self.klass.__dict__.has_key('creators') and self.klass.creators:
for creator in self.klass.creators:
- if isinstance(creator, Role):
+ if isinstance(creator, gen.Role):
if creator.local:
raise 'Local role "%s" cannot be used as a creator.' % \
creator.name
res.append(creator)
else:
- res.append(Role(creator))
+ res.append(gen.Role(creator))
return res
def getCreateMean(self, type='Import'):
@@ -213,13 +212,17 @@ class ClassDescriptor(Descriptor):
res = []
if klass.__dict__.has_key('search'):
searches = klass.__dict__['search']
- if isinstance(searches, basestring): res.append(Search(searches))
- elif isinstance(searches, Search): res.append(searches)
+ if isinstance(searches, basestring):
+ res.append(gen.Search(searches))
+ elif isinstance(searches, gen.Search):
+ res.append(searches)
else:
# It must be a list of searches.
for search in searches:
- if isinstance(search, basestring):res.append(Search(search))
- else: res.append(search)
+ if isinstance(search, basestring):
+ res.append(gen.Search(search))
+ else:
+ res.append(search)
return res
@staticmethod
@@ -268,11 +271,10 @@ class FieldDescriptor:
'''This class gathers information about a specific typed attribute defined
in a gen-class.'''
- singleValuedTypes = ('Integer', 'Float', 'Boolean', 'Date', 'File')
# Although Appy allows to specify a multiplicity[0]>1 for those types, it is
- # not supported by Archetypes. So we will always generate single-valued type
- # definitions for them.
- specialParams = ('title', 'description')
+ # not currently. So we will always generate single-valued type definitions
+ # for them.
+ singleValuedTypes = ('Integer', 'Float', 'Boolean', 'Date', 'File')
def __init__(self, fieldName, appyType, classDescriptor):
self.appyType = appyType
@@ -387,8 +389,7 @@ class FieldDescriptor:
if self.appyType.editDefault:
self.generator.tool.addDefaultField(self)
# - put an index on this field?
- if self.appyType.indexed and \
- (self.fieldName not in ('title', 'description')):
+ if self.appyType.indexed and (self.fieldName != 'title'):
self.classDescr.addIndexMethod(self)
# i18n labels
messages = self.generator.labels
@@ -477,7 +478,7 @@ class ToolClassDescriptor(ClassDescriptor):
self.addField(fieldName, fieldType)
fieldType.validator.append(fieldDescr.fieldName)
fieldType.page.name = 'data'
- fieldType.group = Group(fieldDescr.classDescr.klass.__name__)
+ fieldType.group = gen.Group(fieldDescr.classDescr.klass.__name__)
def addDefaultField(self, fieldDescr):
className = fieldDescr.classDescr.name
@@ -485,22 +486,22 @@ class ToolClassDescriptor(ClassDescriptor):
fieldType = fieldDescr.appyType.clone()
self.addField(fieldName, fieldType)
fieldType.page.name = 'data'
- fieldType.group = Group(fieldDescr.classDescr.klass.__name__)
+ fieldType.group = gen.Group(fieldDescr.classDescr.klass.__name__)
def addPodRelatedFields(self, fieldDescr):
'''Adds the fields needed in the Tool for configuring a Pod field.'''
className = fieldDescr.classDescr.name
# On what page and group to display those fields ?
pg = {'page': 'documentGeneration',
- 'group': Group(fieldDescr.classDescr.klass.__name__, ['50%']*2)}
+ 'group':gen.Group(fieldDescr.classDescr.klass.__name__,['50%']*2)}
# Add the field that will store the pod template.
fieldName = 'podTemplateFor%s_%s' % (className, fieldDescr.fieldName)
- fieldType = File(**pg)
+ fieldType = gen.File(**pg)
self.addField(fieldName, fieldType)
# Add the field that will store the output format(s)
fieldName = 'formatsFor%s_%s' % (className, fieldDescr.fieldName)
- fieldType = String(validator=Selection('getPodOutputFormats'),
- multiplicity=(1,None), default=('odt',), **pg)
+ fieldType = gen.String(validator=gen.Selection('getPodOutputFormats'),
+ multiplicity=(1,None), default=('odt',), **pg)
self.addField(fieldName, fieldType)
def addQueryResultColumns(self, classDescr):
@@ -508,7 +509,7 @@ class ToolClassDescriptor(ClassDescriptor):
to select what default columns will be shown on query results.'''
className = classDescr.name
fieldName = 'resultColumnsFor%s' % className
- fieldType = String(multiplicity=(0,None), validator=Selection(
+ fieldType = gen.String(multiplicity=(0,None), validator=gen.Selection(
'_appy_getAllFields*%s' % className), page='userInterface',
group=classDescr.klass.__name__)
self.addField(fieldName, fieldType)
@@ -520,21 +521,21 @@ class ToolClassDescriptor(ClassDescriptor):
# Field that defines if advanced search is enabled for class
# p_classDescr or not.
fieldName = 'enableAdvancedSearchFor%s' % className
- fieldType = Boolean(default=True, page='userInterface',
- group=classDescr.klass.__name__)
+ fieldType = gen.Boolean(default=True, page='userInterface',
+ group=classDescr.klass.__name__)
self.addField(fieldName, fieldType)
# Field that defines how many columns are shown on the custom search
# screen.
fieldName = 'numberOfSearchColumnsFor%s' % className
- fieldType = Integer(default=3, page='userInterface',
- group=classDescr.klass.__name__)
+ fieldType = gen.Integer(default=3, page='userInterface',
+ group=classDescr.klass.__name__)
self.addField(fieldName, fieldType)
# Field that allows to select, among all indexed fields, what fields
# must really be used in the search screen.
fieldName = 'searchFieldsFor%s' % className
defaultValue = [a[0] for a in classDescr.getOrderedAppyAttributes(
condition='attrValue.indexed')]
- fieldType = String(multiplicity=(0,None), validator=Selection(
+ fieldType = gen.String(multiplicity=(0,None), validator=gen.Selection(
'_appy_getSearchableFields*%s' % className), default=defaultValue,
page='userInterface', group=classDescr.klass.__name__)
self.addField(fieldName, fieldType)
@@ -546,8 +547,8 @@ class ToolClassDescriptor(ClassDescriptor):
# Field that defines the path of the files to import.
fieldName = 'importPathFor%s' % className
defValue = classDescr.getCreateMean('Import').path
- fieldType = String(page='data', multiplicity=(1,1), default=defValue,
- group=classDescr.klass.__name__)
+ fieldType = gen.String(page='data', multiplicity=(1,1),
+ default=defValue,group=classDescr.klass.__name__)
self.addField(fieldName, fieldType)
def addWorkflowFields(self, classDescr):
@@ -560,13 +561,13 @@ class ToolClassDescriptor(ClassDescriptor):
if classDescr.isRoot() or issubclass(classDescr.klass, ModelClass):
defaultValue = True
fieldName = 'showWorkflowFor%s' % className
- fieldType = Boolean(default=defaultValue, page='userInterface',
- group=groupName)
+ fieldType = gen.Boolean(default=defaultValue, page='userInterface',
+ group=groupName)
self.addField(fieldName, fieldType)
# Adds the boolean field for showing or not the field "enter comments".
fieldName = 'showWorkflowCommentFieldFor%s' % className
- fieldType = Boolean(default=defaultValue, page='userInterface',
- group=groupName)
+ fieldType = gen.Boolean(default=defaultValue, page='userInterface',
+ group=groupName)
self.addField(fieldName, fieldType)
# Adds the boolean field for showing all states in current state or not.
# If this boolean is True but the current phase counts only one state,
@@ -577,13 +578,12 @@ class ToolClassDescriptor(ClassDescriptor):
if len(classDescr.getPhases()) > 1:
defaultValue = True
fieldName = 'showAllStatesInPhaseFor%s' % className
- fieldType = Boolean(default=defaultValue, page='userInterface',
- group=groupName)
+ fieldType = gen.Boolean(default=defaultValue, page='userInterface',
+ group=groupName)
self.addField(fieldName, fieldType)
class UserClassDescriptor(ClassDescriptor):
- '''Represents an Archetypes-compliant class that corresponds to the User
- for the generated application.'''
+ '''Appy-specific class for representing a user.'''
def __init__(self, klass, generator):
ClassDescriptor.__init__(self,klass,klass._appy_attributes[:],generator)
self.modelClass = self.klass
@@ -649,8 +649,8 @@ class TranslationClassDescriptor(ClassDescriptor):
def addLabelField(self, messageId, page):
'''Adds a Computed field that will display, in the source language, the
content of the text to translate.'''
- field = Computed(method=self.modelClass.label, plainText=False,
- page=page, show=self.modelClass.show, layouts='f')
+ field = gen.Computed(method=self.modelClass.label, plainText=False,
+ page=page, show=self.modelClass.show, layouts='f')
self.addField('%s_label' % messageId, field)
def addMessageField(self, messageId, page, i18nFiles):
@@ -683,7 +683,7 @@ class TranslationClassDescriptor(ClassDescriptor):
params['width'] = width
else:
# This is a multi-line field, or a very-long-single-lined field
- params['format'] = String.TEXT
+ params['format'] = gen.String.TEXT
params['height'] = height
- self.addField(messageId, String(**params))
+ self.addField(messageId, gen.String(**params))
# ------------------------------------------------------------------------------
diff --git a/gen/generator.py b/gen/generator.py
index fd7c58d..8ca3c75 100644
--- a/gen/generator.py
+++ b/gen/generator.py
@@ -2,7 +2,7 @@
import os, os.path, re, sys, parser, symbol, token, types
import appy.pod, appy.pod.renderer
from appy.shared.utils import FolderDeleter
-#from appy.gen import *
+import appy.gen as gen
from po import PoMessage, PoFile, PoParser
from descriptors import *
from utils import produceNiceMessage, getClassName
@@ -140,7 +140,7 @@ class Generator:
self.user = None
self.workflows = []
self.initialize()
- self.config = Config.getDefault()
+ self.config = gen.Config.getDefault()
self.modulesWithTests = set()
self.totalNumberOfTests = 0
@@ -152,9 +152,9 @@ class Generator:
workflow.'''
res = 'none'
for attrValue in klass.__dict__.itervalues():
- if isinstance(attrValue, Type):
+ if isinstance(attrValue, gen.Type):
res = 'class'
- elif isinstance(attrValue, State):
+ elif isinstance(attrValue, gen.State):
res = 'workflow'
if not res:
for baseClass in klass.__bases__:
@@ -219,13 +219,13 @@ class Generator:
attrs = astClasses[moduleElem.__name__].attributes
if appyType == 'class':
# Determine the class type (standard, tool, user...)
- if issubclass(moduleElem, Tool):
+ if issubclass(moduleElem, gen.Tool):
if not self.tool:
klass = self.descriptorClasses['tool']
self.tool = klass(moduleElem, attrs, self)
else:
self.tool.update(moduleElem, attrs)
- elif issubclass(moduleElem, User):
+ elif issubclass(moduleElem, gen.User):
if not self.user:
klass = self.descriptorClasses['user']
self.user = klass(moduleElem, attrs, self)
@@ -244,7 +244,7 @@ class Generator:
self.workflows.append(descriptor)
if self.containsTests(moduleElem):
self.modulesWithTests.add(moduleObj.__name__)
- elif isinstance(moduleElem, Config):
+ elif isinstance(moduleElem, gen.Config):
self.config = moduleElem
# Walk potential sub-modules
@@ -461,7 +461,6 @@ class ZopeGenerator(Generator):
self.generateTool()
self.generateInit()
self.generateTests()
- self.generateConfigureZcml()
# Create version.txt
f = open(os.path.join(self.outputFolder, 'version.txt'), 'w')
f.write(self.version)
@@ -536,13 +535,13 @@ class ZopeGenerator(Generator):
self.generateWrappers()
self.generateConfig()
- def getAllUsedRoles(self, plone=None, local=None, grantable=None):
+ def getAllUsedRoles(self, zope=None, local=None, grantable=None):
'''Produces a list of all the roles used within all workflows and
classes defined in this application.
- If p_plone is True, it keeps only Plone-standard roles; if p_plone
+ If p_zope is True, it keeps only Zope-standard roles; if p_zope
is False, it keeps only roles which are specific to this application;
- if p_plone is None it has no effect (so it keeps both roles).
+ if p_zope is None it has no effect (so it keeps both roles).
If p_local is True, it keeps only local roles (ie, roles that can
only be granted locally); if p_local is False, it keeps only "global"
@@ -557,8 +556,8 @@ class ZopeGenerator(Generator):
for wfDescr in self.workflows:
for attr in dir(wfDescr.klass):
attrValue = getattr(wfDescr.klass, attr)
- if isinstance(attrValue, State) or \
- isinstance(attrValue, Transition):
+ if isinstance(attrValue, gen.State) or \
+ isinstance(attrValue, gen.Transition):
for role in attrValue.getUsedRoles():
if role.name not in allRoles:
allRoles[role.name] = role
@@ -569,7 +568,7 @@ class ZopeGenerator(Generator):
allRoles[role.name] = role
res = allRoles.values()
# Filter the result according to parameters
- for p in ('plone', 'local', 'grantable'):
+ for p in ('zope', 'local', 'grantable'):
if eval(p) != None:
res = [r for r in res if eval('r.%s == %s' % (p, p))]
return res
@@ -613,17 +612,6 @@ class ZopeGenerator(Generator):
res = configClasses
return res
- def generateConfigureZcml(self):
- '''Generates file configure.zcml.'''
- repls = self.repls.copy()
- # Note every class as "deprecated".
- depr = ''
- for klass in self.getClasses(include='all'):
- depr += '\n' % \
- (klass.name, klass.name)
- repls['deprecated'] = depr
- self.copyFile('configure.zcml', repls)
-
def generateConfig(self):
repls = self.repls.copy()
# Get some lists of classes
@@ -677,9 +665,9 @@ class ZopeGenerator(Generator):
attributes.append('"%s":[%s]' % (classDescr.name, ','.join(qNames)))
repls['attributes'] = ',\n '.join(attributes)
# Compute list of used roles for registering them if needed
- specificRoles = self.getAllUsedRoles(plone=False)
+ specificRoles = self.getAllUsedRoles(zope=False)
repls['roles'] = ','.join(['"%s"' % r.name for r in specificRoles])
- globalRoles = self.getAllUsedRoles(plone=False, local=False)
+ globalRoles = self.getAllUsedRoles(zope=False, local=False)
repls['gRoles'] = ','.join(['"%s"' % r.name for r in globalRoles])
grantableRoles = self.getAllUsedRoles(local=False, grantable=True)
repls['grRoles'] = ','.join(['"%s"' % r.name for r in grantableRoles])
@@ -780,7 +768,7 @@ class ZopeGenerator(Generator):
self.copyFile('testAll.py', repls, destFolder='tests')
def generateTool(self):
- '''Generates the Plone tool that corresponds to this application.'''
+ '''Generates the tool that corresponds to this application.'''
Msg = PoMessage
# Create Tool-related i18n-related messages
msg = Msg(self.tool.name, '', Msg.CONFIG % self.applicationName)
@@ -874,7 +862,7 @@ class ZopeGenerator(Generator):
poMsg.produceNiceDefault()
if poMsg not in self.labels:
self.labels.append(poMsg)
- # Generate the resulting Archetypes class.
+ # Generate the resulting Zope class.
self.copyFile('Class.py', repls, destName=fileName)
def generateWorkflow(self, wfDescr):
@@ -886,14 +874,14 @@ class ZopeGenerator(Generator):
wfName = WorkflowDescriptor.getWorkflowName(wfDescr.klass)
# Add i18n messages for states
for name in dir(wfDescr.klass):
- if not isinstance(getattr(wfDescr.klass, name), State): continue
+ if not isinstance(getattr(wfDescr.klass, name), gen.State): continue
poMsg = PoMessage('%s_%s' % (wfName, name), '', name)
poMsg.produceNiceDefault()
self.labels.append(poMsg)
# Add i18n messages for transitions
for name in dir(wfDescr.klass):
transition = getattr(wfDescr.klass, name)
- if not isinstance(transition, Transition): continue
+ if not isinstance(transition, gen.Transition): continue
poMsg = PoMessage('%s_%s' % (wfName, name), '', name)
poMsg.produceNiceDefault()
self.labels.append(poMsg)
diff --git a/gen/installer.py b/gen/installer.py
index 3ade52e..d32db31 100644
--- a/gen/installer.py
+++ b/gen/installer.py
@@ -5,7 +5,7 @@
import os, os.path, time
import appy
import appy.version
-from appy.gen import Type, Ref, String, File
+import appy.gen as gen
from appy.gen.po import PoParser
from appy.gen.utils import updateRolesForPermission, createObject
from appy.shared.data import languages
@@ -110,7 +110,7 @@ class ZopeInstaller:
for name in files:
baseName, ext = os.path.splitext(name)
f = file(j(root, name))
- if ext in File.imageExts:
+ if ext in gen.File.imageExts:
zopeFolder.manage_addImage(name, f)
elif ext == '.pt':
manage_addPageTemplate(zopeFolder, baseName, '', f.read())
@@ -302,13 +302,11 @@ class ZopeInstaller:
# "po" file on disk.
appFolder = self.config.diskFolder
appName = self.config.PROJECTNAME
- dn = os.path.dirname
- jn = os.path.join
- i18nFolder = jn(jn(jn(dn(dn(dn(appFolder))),'Products'),appName),'i18n')
+ i18nFolder = os.path.join(appFolder, 'tr')
for translation in appyTool.translations:
# Get the "po" file
poName = '%s-%s.po' % (appName, translation.id)
- poFile = PoParser(jn(i18nFolder, poName)).parse()
+ poFile = PoParser(os.path.join(i18nFolder, poName)).parse()
for message in poFile.messages:
setattr(translation, message.id, message.getMessage())
appyTool.log('Translation "%s" updated from "%s".' % \
@@ -359,7 +357,7 @@ class ZopeInstaller:
wrapperClass = klass.wrapperClass
if not hasattr(wrapperClass, 'title'):
# Special field "type" is mandatory for every class.
- title = String(multiplicity=(1,1), show='edit', indexed=True)
+ title = gen.String(multiplicity=(1,1), show='edit',indexed=True)
title.init('title', None, 'appy')
setattr(wrapperClass, 'title', title)
names = self.config.attributes[wrapperClass.__name__[:-8]]
@@ -368,8 +366,8 @@ class ZopeInstaller:
for baseClass in klass.wrapperClass.__bases__:
if baseClass.__name__ == 'AbstractWrapper': continue
for name, appyType in baseClass.__dict__.iteritems():
- if not isinstance(appyType, Type) or \
- (isinstance(appyType, Ref) and appyType.isBack):
+ if not isinstance(appyType, gen.Type) or \
+ (isinstance(appyType, gen.Ref) and appyType.isBack):
continue # Back refs are initialised within fw refs
appyType.init(name, baseClass, appName)
diff --git a/gen/migrator.py b/gen/migrator.py
index a3db7b1..29d8386 100644
--- a/gen/migrator.py
+++ b/gen/migrator.py
@@ -9,8 +9,7 @@ class Migrator:
self.installer = installer
def migrateTo_0_7_1(self):
- '''Appy 0.7.1 has its own management of Ref fields and does not use
- Archetypes references and the reference catalog anymore. So we must
+ '''Appy 0.7.1 has its own management of Ref fields. So we must
update data structures that store Ref info on instances.'''
ins = self.installer
ins.info('Migrating to Appy 0.7.1...')
diff --git a/gen/mixins/TestMixin.py b/gen/mixins/TestMixin.py
index c46337e..cafc4a7 100644
--- a/gen/mixins/TestMixin.py
+++ b/gen/mixins/TestMixin.py
@@ -3,7 +3,7 @@ import os, os.path, sys
# ------------------------------------------------------------------------------
class TestMixin:
- '''This class is mixed in with any PloneTestCase.'''
+ '''This class is mixed in with any ZopeTestCase.'''
def createUser(self, userId, roles):
'''Creates a user with id p_userId with some p_roles.'''
self.acl_users.addMember(userId, 'password', [], [])
@@ -59,7 +59,7 @@ class TestMixin:
def beforeTest(test):
'''Is executed before every test.'''
g = test.globs
- g['tool'] = test.app.plone.get('portal_%s' % g['appName'].lower()).appy()
+ g['tool'] = test.app.config.appy()
cfg = g['tool'].o.getProductConfig()
g['appFolder'] = cfg.diskFolder
moduleOrClassName = g['test'].name # Not used yet.
diff --git a/gen/mixins/ToolMixin.py b/gen/mixins/ToolMixin.py
index 5d6f73e..86cef2a 100644
--- a/gen/mixins/ToolMixin.py
+++ b/gen/mixins/ToolMixin.py
@@ -6,9 +6,9 @@ from appy.shared.data import languages
import appy.gen
from appy.gen import Type, Search, Selection
from appy.gen.utils import SomeObjects, sequenceTypes, getClassName
-from appy.gen.plone25.mixins import BaseMixin
-from appy.gen.plone25.wrappers import AbstractWrapper
-from appy.gen.plone25.descriptors import ClassDescriptor
+from appy.gen.mixins import BaseMixin
+from appy.gen.wrappers import AbstractWrapper
+from appy.gen.descriptors import ClassDescriptor
try:
from AccessControl.ZopeSecurityPolicy import _noroles
except ImportError:
@@ -411,7 +411,7 @@ class ToolMixin(BaseMixin):
def getCreateMeans(self, contentTypeOrAppyClass):
'''Gets the different ways objects of p_contentTypeOrAppyClass (which
- can be a Plone content type or a Appy class) can be created
+ can be a Zope content type or a Appy class) can be created
(via a web form, by importing external data, etc). Result is a
dict whose keys are strings (ie "form", "import"...) and whose
values are additional data bout the particular mean.'''
@@ -810,7 +810,7 @@ class ToolMixin(BaseMixin):
9: 'month_sep', 10: 'month_oct', 11: 'month_nov', 12: 'month_dec'}
def getMonthName(self, monthNumber):
'''Gets the translated month name of month numbered p_monthNumber.'''
- return self.translate(self.monthsIds[int(monthNumber)], domain='plone')
+ return self.translate(self.monthsIds[int(monthNumber)])
# --------------------------------------------------------------------------
# Authentication-related methods
@@ -824,7 +824,7 @@ class ToolMixin(BaseMixin):
if jsEnabled and not cookiesEnabled:
msg = self.translate(u'You must enable cookies before you can ' \
- 'log in.', domain='plone')
+ 'log in.')
return self.goto(urlBack, msg.encode('utf-8'))
# Perform the Zope-level authentication
login = rq.get('__ac_name', '')
@@ -835,11 +835,10 @@ class ToolMixin(BaseMixin):
user = self.acl_users.validate(rq)
if self.userIsAnon():
rq.RESPONSE.expireCookie('__ac', path='/')
- msg = self.translate(u'Login failed', domain='plone')
+ msg = self.translate(u'Login failed')
logMsg = 'Authentication failed (tried with login "%s")' % login
else:
- msg = self.translate(u'Welcome! You are now logged in.',
- domain='plone')
+ msg = self.translate(u'Welcome! You are now logged in.')
logMsg = 'User "%s" has been logged in.' % login
msg = msg.encode('utf-8')
self.log(logMsg)
@@ -865,7 +864,7 @@ class ToolMixin(BaseMixin):
session.invalidate()
self.log('User "%s" has been logged out.' % userId)
# Remove user from variable "loggedUsers"
- from appy.gen.plone25.installer import loggedUsers
+ from appy.gen.installer import loggedUsers
if loggedUsers.has_key(userId): del loggedUsers[userId]
return self.goto(self.getApp().absolute_url())
diff --git a/gen/mixins/__init__.py b/gen/mixins/__init__.py
index e1528b2..9dbee23 100644
--- a/gen/mixins/__init__.py
+++ b/gen/mixins/__init__.py
@@ -1,17 +1,14 @@
'''This package contains mixin classes that are mixed in with generated classes:
- - mixins/BaseMixin is mixed in with Standard Archetypes classes;
+ - mixins/BaseMixin is mixed in with standard Zope classes;
- mixins/ToolMixin is mixed in with the generated application Tool class.'''
# ------------------------------------------------------------------------------
import os, os.path, sys, types, mimetypes, urllib, cgi
from appy import Object
-import appy.gen
-from appy.gen import Type, String, Selection, Role, No, WorkflowAnonymous, \
- Transition, Permission
+import appy.gen as gen
from appy.gen.utils import *
from appy.gen.layout import Table, defaultPageLayouts
-from appy.gen.descriptors import WorkflowDescriptor
-from appy.gen.plone25.descriptors import ClassDescriptor
+from appy.gen.descriptors import WorkflowDescriptor, ClassDescriptor
# ------------------------------------------------------------------------------
class BaseMixin:
@@ -187,8 +184,7 @@ class BaseMixin:
fields in the database.'''
rq = self.REQUEST
tool = self.getTool()
- errorMessage = self.translate(
- 'Please correct the indicated errors.', domain='plone')
+ errorMessage = self.translate('Please correct the indicated errors.')
isNew = rq.get('is_new') == 'True'
# If this object is created from an initiator, get info about him.
initiator = None
@@ -209,7 +205,7 @@ class BaseMixin:
urlBack = tool.getSiteUrl()
else:
urlBack = self.getUrl()
- self.say(self.translate('Changes canceled.', domain='plone'))
+ self.say(self.translate('Changes canceled.'))
return self.goto(urlBack)
# Object for storing validation errors
@@ -245,7 +241,7 @@ class BaseMixin:
obj, msg = self.createOrUpdate(isNew, values, initiator, initiatorField)
# Redirect the user to the appropriate page
- if not msg: msg = obj.translate('Changes saved.', domain='plone')
+ if not msg: msg = obj.translate('Changes saved.')
# If the object has already been deleted (ie, it is a kind of transient
# object like a one-shot form and has already been deleted in method
# onEdit), redirect to the main site page.
@@ -711,7 +707,7 @@ class BaseMixin:
if not includeFake:
includeIt = mayTrigger
else:
- includeIt = mayTrigger or isinstance(mayTrigger, No)
+ includeIt = mayTrigger or isinstance(mayTrigger, gen.No)
if not includeNotShowable:
includeIt = includeIt and transition.isShowable(wf, self)
if not includeIt: continue
@@ -864,7 +860,7 @@ class BaseMixin:
# Get the initial workflow state
initialState = self.State(name=False)
# Create a Transition instance representing the initial transition.
- initialTransition = Transition((initialState, initialState))
+ initialTransition = gen.Transition((initialState, initialState))
initialTransition.trigger('_init_', self, wf, '')
def getWorkflow(self, name=False, className=None):
@@ -875,7 +871,7 @@ class BaseMixin:
else:
appyClass = self.getTool().getAppyClass(className)
if hasattr(appyClass, 'workflow'): wf = appyClass.workflow
- else: wf = WorkflowAnonymous
+ else: wf = gen.WorkflowAnonymous
if not name: return wf
return WorkflowDescriptor.getWorkflowName(wf)
diff --git a/gen/model.py b/gen/model.py
index a42045c..0fafbc6 100644
--- a/gen/model.py
+++ b/gen/model.py
@@ -1,14 +1,10 @@
'''This file contains basic classes that will be added into any user
application for creating the basic structure of the application "Tool" which
- is the set of web pages used for configuring the application. The "Tool" is
- available to administrators under the standard Plone link "site setup". Plone
- itself is shipped with several tools used for conguring the various parts of
- Plone (content types, catalogs, workflows, etc.)'''
+ is the set of web pages used for configuring the application.'''
# ------------------------------------------------------------------------------
import types
-from appy.gen import *
-Grp=Group # Avoid name clash between appy.gen.Group and class Group below
+import appy.gen as gen
# Prototypical instances of every type -----------------------------------------
class Protos:
@@ -73,7 +69,7 @@ class ModelClass:
value = appyType.getInputLayouts()
elif isinstance(value, basestring):
value = '"%s"' % value
- elif isinstance(value, Ref):
+ elif isinstance(value, gen.Ref):
if not value.isBack: continue
value = klass._appy_getTypeBody(value, wrapperName)
elif type(value) == type(ModelClass):
@@ -82,11 +78,11 @@ class ModelClass:
value = value.__name__
else:
value = '%s.%s' % (moduleName, value.__name__)
- elif isinstance(value, Selection):
+ elif isinstance(value, gen.Selection):
value = 'Selection("%s")' % value.methodName
- elif isinstance(value, Grp):
+ elif isinstance(value, gen.Group):
value = 'Grp("%s")' % value.name
- elif isinstance(value, Page):
+ elif isinstance(value, gen.Page):
value = 'pages["%s"]' % value.name
elif callable(value):
value = '%s.%s' % (wrapperName, value.__name__)
@@ -135,20 +131,22 @@ class User(ModelClass):
_appy_attributes = ['title', 'name', 'firstName', 'login', 'password1',
'password2', 'roles']
# All methods defined below are fake. Real versions are in the wrapper.
- title = String(show=False, indexed=True)
+ title = gen.String(show=False, indexed=True)
gm = {'group': 'main', 'multiplicity': (1,1), 'width': 25}
- name = String(**gm)
- firstName = String(**gm)
+ name = gen.String(**gm)
+ firstName = gen.String(**gm)
def showLogin(self): pass
def validateLogin(self): pass
- login = String(show=showLogin, validator=validateLogin, indexed=True, **gm)
+ login = gen.String(show=showLogin, validator=validateLogin,
+ indexed=True, **gm)
def showPassword(self): pass
def validatePassword(self): pass
- password1 = String(format=String.PASSWORD, show=showPassword,
- validator=validatePassword, **gm)
- password2 = String(format=String.PASSWORD, show=showPassword, **gm)
+ password1 = gen.String(format=gen.String.PASSWORD, show=showPassword,
+ validator=validatePassword, **gm)
+ password2 = gen.String(format=gen.String.PASSWORD, show=showPassword, **gm)
gm['multiplicity'] = (0, None)
- roles = String(validator=Selection('getGrantableRoles'), indexed=True, **gm)
+ roles = gen.String(validator=gen.Selection('getGrantableRoles'),
+ indexed=True, **gm)
# The Group class --------------------------------------------------------------
class Group(ModelClass):
@@ -156,25 +154,25 @@ class Group(ModelClass):
_appy_attributes = ['title', 'login', 'roles', 'users']
# All methods defined below are fake. Real versions are in the wrapper.
m = {'group': 'main', 'width': 25, 'indexed': True}
- title = String(multiplicity=(1,1), **m)
+ title = gen.String(multiplicity=(1,1), **m)
def showLogin(self): pass
def validateLogin(self): pass
- login = String(show=showLogin, validator=validateLogin,
- multiplicity=(1,1), **m)
- roles = String(validator=Selection('getGrantableRoles'),
- multiplicity=(0,None), **m)
- users = Ref(User, multiplicity=(0,None), add=False, link=True,
- back=Ref(attribute='groups', show=True),
- showHeaders=True, shownInfo=('title', 'login'))
+ login = gen.String(show=showLogin, validator=validateLogin,
+ multiplicity=(1,1), **m)
+ roles = gen.String(validator=gen.Selection('getGrantableRoles'),
+ multiplicity=(0,None), **m)
+ users = gen.Ref(User, multiplicity=(0,None), add=False, link=True,
+ back=gen.Ref(attribute='groups', show=True),
+ showHeaders=True, shownInfo=('title', 'login'))
# The Translation class --------------------------------------------------------
class Translation(ModelClass):
_appy_attributes = ['po', 'title']
# All methods defined below are fake. Real versions are in the wrapper.
def getPoFile(self): pass
- po = Action(action=getPoFile, page=Page('actions', show='view'),
- result='filetmp')
- title = String(show=False, indexed=True)
+ po = gen.Action(action=getPoFile, page=gen.Page('actions', show='view'),
+ result='filetmp')
+ title = gen.String(show=False, indexed=True)
def label(self): pass
def show(self, name): pass
@@ -195,30 +193,31 @@ class Tool(ModelClass):
# Tool attributes
def validPythonWithUno(self, value): pass # Real method in the wrapper
- unoEnabledPython = String(group="connectionToOpenOffice",
- validator=validPythonWithUno)
- openOfficePort = Integer(default=2002, group="connectionToOpenOffice")
- numberOfResultsPerPage = Integer(default=30, show=False)
- listBoxesMaximumWidth = Integer(default=100, show=False)
- appyVersion = String(show=False, layouts='f')
+ unoEnabledPython = gen.String(group="connectionToOpenOffice",
+ validator=validPythonWithUno)
+ openOfficePort = gen.Integer(default=2002, group="connectionToOpenOffice")
+ numberOfResultsPerPage = gen.Integer(default=30, show=False)
+ listBoxesMaximumWidth = gen.Integer(default=100, show=False)
+ appyVersion = gen.String(show=False, layouts='f')
def refreshSecurity(self): pass # Real method in the wrapper
- refreshSecurity = Action(action=refreshSecurity, confirm=True)
+ refreshSecurity = gen.Action(action=refreshSecurity, confirm=True)
# Ref(User) will maybe be transformed into Ref(CustomUserClass).
- users = Ref(User, multiplicity=(0,None), add=True, link=False,
- back=Ref(attribute='toTool', show=False),
- page=Page('users', show='view'),
- queryable=True, queryFields=('title', 'login'),
- showHeaders=True, shownInfo=('title', 'login', 'roles'))
- groups = Ref(Group, multiplicity=(0,None), add=True, link=False,
- back=Ref(attribute='toTool2', show=False),
- page=Page('groups', show='view'),
- queryable=True, queryFields=('title', 'login'),
- showHeaders=True, shownInfo=('title', 'login', 'roles'))
- translations = Ref(Translation, multiplicity=(0,None),add=False,link=False,
- back=Ref(attribute='trToTool', show=False), show='view',
- page=Page('translations', show='view'))
- enableNotifications = Boolean(default=True,
- page=Page('notifications', show=False))
+ users = gen.Ref(User, multiplicity=(0,None), add=True, link=False,
+ back=gen.Ref(attribute='toTool', show=False),
+ page=gen.Page('users', show='view'),
+ queryable=True, queryFields=('title', 'login'),
+ showHeaders=True, shownInfo=('title', 'login', 'roles'))
+ groups = gen.Ref(Group, multiplicity=(0,None), add=True, link=False,
+ back=gen.Ref(attribute='toTool2', show=False),
+ page=gen.Page('groups', show='view'),
+ queryable=True, queryFields=('title', 'login'),
+ showHeaders=True, shownInfo=('title', 'login', 'roles'))
+ translations = gen.Ref(Translation, multiplicity=(0,None), add=False,
+ link=False, show='view',
+ back=gen.Ref(attribute='trToTool', show=False),
+ page=gen.Page('translations', show='view'))
+ enableNotifications = gen.Boolean(default=True,
+ page=gen.Page('notifications', show=False))
@classmethod
def _appy_clean(klass):
diff --git a/gen/notifier.py b/gen/notifier.py
index f5e2990..cdc273f 100644
--- a/gen/notifier.py
+++ b/gen/notifier.py
@@ -41,8 +41,8 @@ def sendMail(obj, transition, transitionName, workflow):
'''Sends mail about p_transition that has been triggered on p_obj that is
controlled by p_workflow.'''
wfName = WorkflowDescriptor.getWorkflowName(workflow.__class__)
- ploneObj = obj.o
- portal = ploneObj.portal_url.getPortalObject()
+ zopeObj = obj.o
+ tool = zopeObj.getTool()
mailInfo = transition.notify(workflow, obj)
if not mailInfo[0]: return # Send a mail to nobody.
# mailInfo may be one of the following:
@@ -54,15 +54,15 @@ def sendMail(obj, transition, transitionName, workflow):
# address or one role) or sequences of strings.
# Determine mail subject and body.
if len(mailInfo) <= 2:
- # The user didn't mention mail body and subject. We will use
- # those defined from i18n labels.
- wfHistory = ploneObj.getWorkflowHistory()
+ # The user didn't mention mail body and subject. We will use those
+ # defined from i18n labels.
+ wfHistory = zopeObj.getHistory()
labelPrefix = '%s_%s' % (wfName, transitionName)
tName = obj.translate(labelPrefix)
- keys = {'siteUrl': portal.absolute_url(),
- 'siteTitle': portal.Title(),
- 'objectUrl': ploneObj.absolute_url(),
- 'objectTitle': ploneObj.Title(),
+ keys = {'siteUrl': tool.getPath('/').absolute_url(),
+ 'siteTitle': tool.getAppName(),
+ 'objectUrl': zopeObj.absolute_url(),
+ 'objectTitle': zopeObj.Title(),
'transitionName': tName,
'transitionComment': wfHistory[0]['comments']}
mailSubject = obj.translate(labelPrefix + '_mail_subject', keys)
diff --git a/gen/odt/__init__.py b/gen/odt/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/gen/odt/generator.py b/gen/odt/generator.py
deleted file mode 100644
index b4b4d89..0000000
--- a/gen/odt/generator.py
+++ /dev/null
@@ -1,54 +0,0 @@
-'''This file contains the main Generator class used for generating an
- ODT file from an Appy application.'''
-
-# ------------------------------------------------------------------------------
-import os, os.path
-from appy.gen import Page
-from appy.gen.utils import produceNiceMessage
-from appy.gen.generator import Generator as AbstractGenerator
-
-# ------------------------------------------------------------------------------
-class Generator(AbstractGenerator):
- '''This generator generates ODT files from an Appy application.'''
-
- def __init__(self, *args, **kwargs):
- AbstractGenerator.__init__(self, *args, **kwargs)
- self.repls = {'generator': self}
-
- def finalize(self):
- pass
-
- def getOdtFieldLabel(self, fieldName):
- '''Given a p_fieldName, this method creates the label as it will appear
- in the ODT file.'''
- return '%s' % \
- (fieldName, produceNiceMessage(fieldName))
-
- def generateClass(self, classDescr):
- '''Is called each time an Appy class is found in the application.'''
- repls = self.repls.copy()
- repls['classDescr'] = classDescr
- self.copyFile('basic.odt', repls,
- destName='%sEdit.odt' % classDescr.klass.__name__, isPod=True)
-
- def fieldIsStaticallyInvisible(self, field):
- '''This method determines if p_field is always invisible. It can be
- verified for example if field.type.show is the boolean value False or
- if the page where the field must be displayed has a boolean attribute
- "show" having the boolean value False.'''
- if (type(field.show) == bool) and not field.show: return True
- if (type(field.page.show) == bool) and not field.page.show: return True
- return False
-
- undumpable = ('Ref', 'Action', 'File', 'Computed')
- def getRelevantAttributes(self, classDescr):
- '''Some fields, like computed fields or actions, should not be dumped
- into the ODT file. This method returns the list of "dumpable"
- fields.'''
- res = []
- for fieldName, field, klass in classDescr.getOrderedAppyAttributes():
- if (field.type not in self.undumpable) and \
- (not self.fieldIsStaticallyInvisible(field)):
- res.append((fieldName, field))
- return res
-# ------------------------------------------------------------------------------
diff --git a/gen/odt/templates/basic.odt b/gen/odt/templates/basic.odt
deleted file mode 100644
index 7f3816a..0000000
Binary files a/gen/odt/templates/basic.odt and /dev/null differ
diff --git a/gen/plone25/__init__.py b/gen/plone25/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/gen/templates/Class.py b/gen/templates/Class.py
index 2ec361c..38dec98 100644
--- a/gen/templates/Class.py
+++ b/gen/templates/Class.py
@@ -4,8 +4,8 @@ from OFS.Folder import Folder
from appy.gen.utils import createObject
from AccessControl import ClassSecurityInfo
import Products..config as cfg
-from appy.gen.plone25.mixins import BaseMixin
-from appy.gen.plone25.mixins.ToolMixin import ToolMixin
+from appy.gen.mixins import BaseMixin
+from appy.gen.mixins.ToolMixin import ToolMixin
from wrappers import _Wrapper as Wrapper
def manage_add(self, id, title='', REQUEST=None):
diff --git a/gen/templates/Styles.css.dtml b/gen/templates/Styles.css.dtml
deleted file mode 100644
index 70f4dd9..0000000
--- a/gen/templates/Styles.css.dtml
+++ /dev/null
@@ -1,90 +0,0 @@
-#importedElem { color: grey; font-style: italic; }
-.appyPod { float:right; }
-.appyFocus { color: #900101; }
-
-.appyChanges th {
- font-style: italic;
- background-color: transparent;
- border: 0 none transparent;
- padding: 0.1em 0.1em 0.1em 0.1em;
-}
-
-.appyChanges td {
- padding: 0.1em 0.2em 0.1em 0.2em !important;
- border-top: 1px dashed #8CACBB !important;
- border-right: 0 none transparent !important;
- border-left: 0 none transparent !important;
- border-bottom: 0 none transparent !important;
-}
-
-/* Tooltip */
-a.tooltip span {
- display:none;
- padding:2px 3px;
- margin-top: 25px;
-}
-a.rtip span { margin-left:3px; }
-a.ltip span { margin-left:-150px }
-a.tooltip:hover span {
- display: inline;
- position: absolute;
- border: 1px solid grey;
- background-color: white;
- color: #dd;
-}
-
-/* Table styles */
-fieldset {
- line-height: 1em;
- border: 2px solid #8CACBB;
- margin: 0.5em 0em 0.5em 0em;
- padding: 0 0.7em 0.5em;
-}
-
-.noPadding {
- padding-right: 0em !important;
- padding-left: 0em !important;
- padding-top: 0em !important;
- padding-bottom: 0em !important;
-}
-
-.appyButton {
- background: &dtml-globalBackgroundColor; url(&dtml-portal_url;/linkOpaque.gif) 5px 1px no-repeat;
- cursor: pointer;
- font-size: &dtml-fontSmallSize;;
- padding: 1px 1px 1px 12px;
- text-transform: &dtml-textTransform;;
- /* overflow: visible; IE produces ugly results with this */
-}
-
-.fakeButton {
- background: #ffd5c0 url(&dtml-portal_url;/ui/fakeTransition.gif) 5px 1px no-repeat;
- padding: 3px 4px 3px 12px;
-}
-
-/* Portlet elements */
-.portletHeader {
- text-transform: none;
- padding: 1px 0.5em;
-}
-.portletSearch {
- padding: 0 0 0 0.6em;
- font-style: normal;
- font-size: 95%;
-}
-.portletGroup {
- font-variant: small-caps;
- font-weight: bold;
- font-style: normal;
-}
-
-.portletGroupItem { padding-left: 0.8em; font-style: italic; }
-.portletMenu { margin-bottom: 0.4em; }
-
-/* image-right, but without border */
-.image-right {
- border:0px solid Black;
- clear:both;
- float:right;
- margin:0.5em;
-}
diff --git a/gen/templates/__init__.py b/gen/templates/__init__.py
index 4d20f53..3452a0f 100644
--- a/gen/templates/__init__.py
+++ b/gen/templates/__init__.py
@@ -1,7 +1,7 @@
# Test coverage-related stuff --------------------------------------------------
import sys
-from appy.gen.plone25.mixins.TestMixin import TestMixin
+from appy.gen.mixins.TestMixin import TestMixin
covFolder = TestMixin.getCovFolder()
# The previous method checks in sys.argv whether Zope was lauched for performing
# coverage tests or not.
@@ -26,7 +26,7 @@ def countTest():
# ------------------------------------------------------------------------------
import config
-from appy.gen.plone25.installer import ZopeInstaller
+from appy.gen.installer import ZopeInstaller
# Zope-level installation of the generated product. ----------------------------
def initialize(context):
diff --git a/gen/templates/config.py b/gen/templates/config.py
index 4d56cc9..b640024 100644
--- a/gen/templates/config.py
+++ b/gen/templates/config.py
@@ -5,9 +5,7 @@ import wrappers
# The following imports are here for allowing mixin classes to access those
-# elements without being statically dependent on Plone/Zope packages. Indeed,
-# every Archetype instance has a method "getProductConfig" that returns this
-# module.
+# elements without being statically dependent on Zope packages.
from persistent.list import PersistentList
from zExceptions import BadRequest
from ZPublisher.HTTPRequest import BaseRequest
diff --git a/gen/templates/configure.zcml b/gen/templates/configure.zcml
deleted file mode 100644
index be6e398..0000000
--- a/gen/templates/configure.zcml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
diff --git a/gen/templates/testAll.py b/gen/templates/testAll.py
index 4edff9f..0e34d74 100644
--- a/gen/templates/testAll.py
+++ b/gen/templates/testAll.py
@@ -3,17 +3,13 @@
from unittest import TestSuite
from Testing import ZopeTestCase
from Testing.ZopeTestCase import ZopeDocTestSuite
-from Products.PloneTestCase import PloneTestCase
-from appy.gen.plone25.mixins.TestMixin import TestMixin, beforeTest, afterTest
+from appy.gen.mixins.TestMixin import TestMixin, beforeTest, afterTest
-# Initialize Zope & Plone test systems -----------------------------------------
-ZopeTestCase.installProduct('PloneLanguageTool')
+# Initialize the Zope test system ----------------------------------------------
ZopeTestCase.installProduct('')
-PloneTestCase.setupPloneSite(products=['PloneLanguageTool',
- ''])
-class Test(PloneTestCase.PloneTestCase, TestMixin):
+class Test(ZopeTestCase.ZopeTestCase, TestMixin):
'''Base test class for test cases.'''
# Data needed for defining the tests -------------------------------------------
diff --git a/gen/templates/wrappers.py b/gen/templates/wrappers.py
index 9149b7f..92f85b7 100644
--- a/gen/templates/wrappers.py
+++ b/gen/templates/wrappers.py
@@ -1,11 +1,11 @@
# ------------------------------------------------------------------------------
from appy.gen import *
Grp = Group # Avoid name clashes with the Group class below and appy.gen.Group
-from appy.gen.plone25.wrappers import AbstractWrapper
-from appy.gen.plone25.wrappers.ToolWrapper import ToolWrapper as WTool
-from appy.gen.plone25.wrappers.UserWrapper import UserWrapper as WUser
-from appy.gen.plone25.wrappers.GroupWrapper import GroupWrapper as WGroup
-from appy.gen.plone25.wrappers.TranslationWrapper import TranslationWrapper as WT
+from appy.gen.wrappers import AbstractWrapper
+from appy.gen.wrappers.ToolWrapper import ToolWrapper as WTool
+from appy.gen.wrappers.UserWrapper import UserWrapper as WUser
+from appy.gen.wrappers.GroupWrapper import GroupWrapper as WGroup
+from appy.gen.wrappers.TranslationWrapper import TranslationWrapper as WT
from Globals import InitializeClass
from AccessControl import ClassSecurityInfo
tfw = {"edit":"f","cell":"f","view":"f"} # Layout for Translation fields
diff --git a/gen/ui/import.pt b/gen/ui/import.pt
index 500956b..6f34d2c 100644
--- a/gen/ui/import.pt
+++ b/gen/ui/import.pt
@@ -1,23 +1,9 @@
-
-
-Disable standard Plone green tabs
-
-
-
-
-
-Fill main slot of Plone main_template
-
-
+
+
+ Form for importing several meetings at once.
diff --git a/gen/utils.py b/gen/utils.py
index 94872fd..5389cfd 100644
--- a/gen/utils.py
+++ b/gen/utils.py
@@ -247,30 +247,30 @@ CONVERSION_ERROR = 'An error occurred while executing command "%s". %s'
class FileWrapper:
'''When you get, from an appy object, the value of a File attribute, you
get an instance of this class.'''
- def __init__(self, atFile):
+ def __init__(self, zopeFile):
'''This constructor is only used by Appy to create a nice File instance
- from a Plone/Zope corresponding instance (p_atFile). If you need to
+ from a Zope corresponding instance (p_zopeFile). If you need to
create a new file and assign it to a File attribute, use the
attribute setter, do not create yourself an instance of this
class.'''
d = self.__dict__
- d['_atFile'] = atFile # Not for you!
- d['name'] = atFile.filename
- d['content'] = atFile.data
- d['mimeType'] = atFile.content_type
- d['size'] = atFile.size # In bytes
+ d['_zopeFile'] = zopeFile # Not for you!
+ d['name'] = zopeFile.filename
+ d['content'] = zopeFile.data
+ d['mimeType'] = zopeFile.content_type
+ d['size'] = zopeFile.size # In bytes
def __setattr__(self, name, v):
d = self.__dict__
if name == 'name':
- self._atFile.filename = v
+ self._zopeFile.filename = v
d['name'] = v
elif name == 'content':
- self._atFile.update_data(v, self.mimeType, len(v))
+ self._zopeFile.update_data(v, self.mimeType, len(v))
d['content'] = v
d['size'] = len(v)
elif name == 'mimeType':
- self._atFile.content_type = self.mimeType = v
+ self._zopeFile.content_type = self.mimeType = v
else:
raise 'Impossible to set attribute %s. "Settable" attributes ' \
'are "name", "content" and "mimeType".' % name
@@ -326,8 +326,7 @@ def getClassName(klass, appName=None):
Zope class. For some classes, name p_appName is required: it is
part of the class name.'''
moduleName = klass.__module__
- if (moduleName == 'appy.gen.plone25.model') or \
- moduleName.endswith('.wrappers'):
+ if (moduleName == 'appy.gen.model') or moduleName.endswith('.wrappers'):
# This is a model (generation time or run time)
res = appName + klass.__name__
elif klass.__bases__ and (klass.__bases__[-1].__module__ == 'appy.gen'):
diff --git a/gen/wrappers/GroupWrapper.py b/gen/wrappers/GroupWrapper.py
index 32bd3f8..47c2ee7 100644
--- a/gen/wrappers/GroupWrapper.py
+++ b/gen/wrappers/GroupWrapper.py
@@ -1,5 +1,5 @@
# ------------------------------------------------------------------------------
-from appy.gen.plone25.wrappers import AbstractWrapper
+from appy.gen.wrappers import AbstractWrapper
# ------------------------------------------------------------------------------
class GroupWrapper(AbstractWrapper):
diff --git a/gen/wrappers/ToolWrapper.py b/gen/wrappers/ToolWrapper.py
index 949bab2..c240fe8 100644
--- a/gen/wrappers/ToolWrapper.py
+++ b/gen/wrappers/ToolWrapper.py
@@ -2,7 +2,7 @@
import os.path
import appy
from appy.shared.utils import executeCommand
-from appy.gen.plone25.wrappers import AbstractWrapper
+from appy.gen.wrappers import AbstractWrapper
# ------------------------------------------------------------------------------
_PY = 'Please specify a file corresponding to a Python interpreter ' \
diff --git a/gen/wrappers/TranslationWrapper.py b/gen/wrappers/TranslationWrapper.py
index 3a91233..d1ed616 100644
--- a/gen/wrappers/TranslationWrapper.py
+++ b/gen/wrappers/TranslationWrapper.py
@@ -1,6 +1,6 @@
# ------------------------------------------------------------------------------
import os.path
-from appy.gen.plone25.wrappers import AbstractWrapper
+from appy.gen.wrappers import AbstractWrapper
from appy.gen.po import PoFile, PoMessage
from appy.shared.utils import getOsTempFolder
diff --git a/gen/wrappers/UserWrapper.py b/gen/wrappers/UserWrapper.py
index 1d6c310..8c53709 100644
--- a/gen/wrappers/UserWrapper.py
+++ b/gen/wrappers/UserWrapper.py
@@ -1,5 +1,5 @@
# ------------------------------------------------------------------------------
-from appy.gen.plone25.wrappers import AbstractWrapper
+from appy.gen.wrappers import AbstractWrapper
# ------------------------------------------------------------------------------
class UserWrapper(AbstractWrapper):