add python3 suppport based on 2to3 script

This commit is contained in:
Stefan Klug 2015-10-27 21:10:24 +01:00
parent caef0e85d0
commit 4f91a30fec
68 changed files with 597 additions and 576 deletions

View file

@ -5,9 +5,9 @@
# ------------------------------------------------------------------------------
import types, copy
import appy.gen as gen
import po
from model import ModelClass
from utils import produceNiceMessage, getClassName
from . import po
from .model import ModelClass
from .utils import produceNiceMessage, getClassName
TABS = 4 # Number of blanks in a Python indentation.
# ------------------------------------------------------------------------------
@ -130,7 +130,7 @@ class ClassDescriptor(Descriptor):
def isAbstract(self):
'''Is self.klass abstract?'''
res = False
if self.klass.__dict__.has_key('abstract'):
if 'abstract' in self.klass.__dict__:
res = self.klass.__dict__['abstract']
return res
@ -139,7 +139,7 @@ class ClassDescriptor(Descriptor):
concept into the application. For example, creating instances
of such classes will be easy from the user interface.'''
res = False
if self.klass.__dict__.has_key('root'):
if 'root' in self.klass.__dict__:
res = self.klass.__dict__['root']
return res
@ -150,7 +150,7 @@ class ClassDescriptor(Descriptor):
theClass = self.klass
if klass:
theClass = klass
if theClass.__dict__.has_key('folder'):
if 'folder' in theClass.__dict__:
res = theClass.__dict__['folder']
else:
if theClass.__bases__:
@ -176,14 +176,14 @@ class ClassDescriptor(Descriptor):
def getCreateMean(self, type='Import'):
'''Returns the mean for this class that corresponds to p_type, or
None if the class does not support this create mean.'''
if not self.klass.__dict__.has_key('create'): return
if 'create' not in self.klass.__dict__: return
else:
means = self.klass.create
if not means: return
if not isinstance(means, tuple) and not isinstance(means, list):
means = [means]
for mean in means:
exec 'found = isinstance(mean, %s)' % type
exec('found = isinstance(mean, %s)' % type)
if found: return mean
@staticmethod
@ -192,7 +192,7 @@ class ClassDescriptor(Descriptor):
p_tool is given, we are at execution time (not a generation time),
and we may potentially execute search.show methods that allow to
conditionnaly include a search or not.'''
if klass.__dict__.has_key('search'):
if 'search' in klass.__dict__:
searches = klass.__dict__['search']
if not tool: return searches
# Evaluate attributes "show" for every search.
@ -229,10 +229,10 @@ class ClassDescriptor(Descriptor):
def addField(self, fieldName, fieldType):
'''Adds a new field to the Tool.'''
exec "self.modelClass.%s = fieldType" % fieldName
exec("self.modelClass.%s = fieldType" % fieldName)
if fieldName in self.modelClass._appy_attributes:
print('Warning, field "%s" is already existing on class "%s"' % \
(fieldName, self.modelClass.__name__))
print(('Warning, field "%s" is already existing on class "%s"' % \
(fieldName, self.modelClass.__name__)))
return
self.modelClass._appy_attributes.append(fieldName)
self.orderedAttributes.append(fieldName)
@ -488,9 +488,9 @@ class TranslationClassDescriptor(ClassDescriptor):
maxLine = 100 # We suppose a line is 100 characters long.
width = 0
height = 0
for fileName, poFile in i18nFiles.iteritems():
for fileName, poFile in i18nFiles.items():
if not fileName.startswith('%s-' % appName) or \
not i18nFiles[fileName].messagesDict.has_key(messageId):
messageId not in i18nFiles[fileName].messagesDict:
# In this case this is not one of our Appy-managed translation
# files.
continue

View file

@ -3,10 +3,11 @@ import os, os.path, re, sys, parser, symbol, token, types
import appy, appy.pod.renderer
from appy.shared.utils import FolderDeleter
import appy.gen as gen
import po
from descriptors import *
from utils import getClassName
from model import ModelClass, User, Group, Tool, Translation, Page
from . import po
from .descriptors import *
from .utils import getClassName
from .model import ModelClass, User, Group, Tool, Translation, Page
import collections
# ------------------------------------------------------------------------------
class GeneratorError(Exception): pass
@ -160,7 +161,7 @@ class Generator:
appy.fields.Field, it will be considered a gen-class. If p_klass
declares at least one static attribute that is a appy.gen.State,
it will be considered a gen-workflow.'''
for attr in klass.__dict__.itervalues():
for attr in klass.__dict__.values():
if isinstance(attr, gen.Field): return 'class'
elif isinstance(attr, gen.State): return 'workflow'
@ -173,11 +174,11 @@ class Generator:
self.totalNumberOfTests += 1
res = True
# Count also docstring in methods
if type(moduleOrClass) == types.ClassType:
for name, elem in moduleOrClass.__dict__.iteritems():
if type(moduleOrClass) == type:
for name, elem in moduleOrClass.__dict__.items():
if type(elem) in (staticmethod, classmethod):
elem = elem.__get__(name)
if callable(elem) and (type(elem) != types.ClassType) and \
if isinstance(elem, collections.Callable) and (type(elem) != type) and \
hasattr(elem, '__doc__') and elem.__doc__ and \
(elem.__doc__.find('>>>') != -1):
res = True
@ -198,8 +199,8 @@ class Generator:
self.modulesWithTests.add(module.__name__)
classType = type(Generator)
# Find all classes in this module
for name in module.__dict__.keys():
exec 'moduleElem = module.%s' % name
for name in list(module.__dict__.keys()):
exec('moduleElem = module.%s' % name)
# Ignore non-classes module elements or classes that were imported
# from other modules.
if (type(moduleElem) != classType) or \
@ -213,7 +214,7 @@ class Generator:
# Collect non-parsable attrs = back references added
# programmatically
moreAttrs = []
for eName, eValue in moduleElem.__dict__.iteritems():
for eName, eValue in moduleElem.__dict__.items():
if isinstance(eValue, gen.Field) and (eName not in attrs):
moreAttrs.append(eName)
# Sort them in alphabetical order: else, order would be random
@ -257,7 +258,7 @@ class Generator:
# What is the name of the application ?
appName = os.path.basename(self.application)
# Get the app-specific config if any
exec 'import %s as appModule' % appName
exec('import %s as appModule' % appName)
if hasattr (appModule, 'Config'):
self.config = appModule.Config
if not issubclass(self.config, gen.Config):
@ -273,7 +274,7 @@ class Generator:
# Ignore non Python files
if not fileName.endswith('.py'): continue
moduleName = '%s.%s' % (appName, os.path.splitext(fileName)[0])
exec 'import %s' % moduleName
exec('import %s' % moduleName)
modules.append(eval(moduleName))
# Parse imported modules
for module in modules:
@ -321,7 +322,7 @@ class Generator:
fileContent = f.read()
f.close()
if not fileName.endswith('.png'):
for rKey, rValue in replacements.iteritems():
for rKey, rValue in replacements.items():
fileContent = fileContent.replace(
'<!%s!>' % rKey, str(rValue))
f = file(resultPath, 'w')
@ -343,7 +344,7 @@ class Generator:
msg = ''
if self.totalNumberOfTests:
msg = ' (number of tests found: %d)' % self.totalNumberOfTests
print('Done%s.' % msg)
print(('Done%s.' % msg))
# ------------------------------------------------------------------------------
class ZopeGenerator(Generator):
@ -413,7 +414,7 @@ class ZopeGenerator(Generator):
f.close()
# Generate i18n pot file
potFileName = '%s.pot' % self.applicationName
if self.i18nFiles.has_key(potFileName):
if potFileName in self.i18nFiles:
potFile = self.i18nFiles[potFileName]
else:
fullName = os.path.join(self.application, 'tr', potFileName)
@ -427,14 +428,14 @@ class ZopeGenerator(Generator):
self.options.i18nClean, keepExistingOrder=False)
potFile.generate()
if removedLabels:
print('Warning: %d messages were removed from translation ' \
'files: %s' % (len(removedLabels), str(removedLabels)))
print(('Warning: %d messages were removed from translation ' \
'files: %s' % (len(removedLabels), str(removedLabels))))
# Generate i18n po files
for language in self.config.languages:
# I must generate (or update) a po file for the language(s)
# specified in the configuration.
poFileName = potFile.getPoFileName(language)
if self.i18nFiles.has_key(poFileName):
if poFileName in self.i18nFiles:
poFile = self.i18nFiles[poFileName]
else:
fullName = os.path.join(self.application, 'tr', poFileName)
@ -501,7 +502,7 @@ class ZopeGenerator(Generator):
for role in creators:
if role.name not in allRoles:
allRoles[role.name] = role
res = allRoles.values()
res = list(allRoles.values())
# Filter the result according to parameters
for p in ('appy', 'local', 'grantable'):
if eval(p) != None:
@ -621,12 +622,12 @@ class ZopeGenerator(Generator):
else:
# If a child of this class is already present, we must insert
# this klass before it.
lowestChildIndex = sys.maxint
lowestChildIndex = sys.maxsize
for resClass in resClasses:
if klass in resClass.__bases__:
lowestChildIndex = min(lowestChildIndex,
resClasses.index(resClass))
if lowestChildIndex != sys.maxint:
if lowestChildIndex != sys.maxsize:
res.insert(lowestChildIndex, classDescr)
resClasses.insert(lowestChildIndex, klass)
else:
@ -745,7 +746,7 @@ class ZopeGenerator(Generator):
'''Is called each time an Appy class is found in the application, for
generating the corresponding Archetype class.'''
k = classDescr.klass
print('Generating %s.%s (gen-class)...' % (k.__module__, k.__name__))
print(('Generating %s.%s (gen-class)...' % (k.__module__, k.__name__)))
# Determine base Zope class
isFolder = classDescr.isFolder()
baseClass = isFolder and 'Folder' or 'SimpleItem'
@ -772,7 +773,7 @@ class ZopeGenerator(Generator):
'''This method creates the i18n labels related to the workflow described
by p_wfDescr.'''
k = wfDescr.klass
print('Generating %s.%s (gen-workflow)...' % (k.__module__, k.__name__))
print(('Generating %s.%s (gen-workflow)...' % (k.__module__, k.__name__)))
# Identify workflow name
wfName = WorkflowDescriptor.getWorkflowName(wfDescr.klass)
# Add i18n messages for states

View file

@ -33,7 +33,7 @@ def updateIndexes(installer, indexInfo):
'''This function updates the indexes defined in the catalog.'''
catalog = installer.app.catalog
logger = installer.logger
for indexName, indexType in indexInfo.iteritems():
for indexName, indexType in indexInfo.items():
indexRealType = indexType
if indexType in ('XhtmlIndex', 'TextIndex', 'ListIndex'):
indexRealType = 'ZCTextIndex'

View file

@ -43,7 +43,7 @@ class FakeZCatalog:
def onDelSession(sessionObject, container):
'''This function is called when a session expires.'''
rq = container.REQUEST
if rq.cookies.has_key('_appy_') and rq.cookies.has_key('_ZopeId') and \
if '_appy_' in rq.cookies and '_ZopeId' in rq.cookies and \
(rq['_ZopeId'] == sessionObject.token):
# The request comes from a guy whose session has expired.
resp = rq.RESPONSE
@ -155,7 +155,7 @@ class ZopeInstaller:
# Create or update Appy-wide indexes and field-related indexes
indexInfo = defaultIndexes.copy()
tool = self.app.config
for className in self.config.attributes.iterkeys():
for className in self.config.attributes.keys():
wrapperClass = tool.getAppyClass(className, wrapper=True)
indexInfo.update(wrapperClass.getIndexes(includeDefaults=False))
updateIndexes(self, indexInfo)
@ -196,7 +196,7 @@ class ZopeInstaller:
if hasattr(appyTool, 'beforeInstall'): appyTool.beforeInstall()
# Create the default users if they do not exist.
for login, roles in self.defaultUsers.iteritems():
for login, roles in self.defaultUsers.items():
if not appyTool.count('User', noSecurity=True, login=login):
appyTool.create('users', noSecurity=True, id=login, login=login,
password3=login, password4=login,
@ -277,7 +277,7 @@ class ZopeInstaller:
name = klass.__name__
module = klass.__module__
wrapper = klass.wrapperClass
exec 'from %s import manage_add%s as ctor' % (module, name)
exec('from %s import manage_add%s as ctor' % (module, name))
self.zopeContext.registerClass(meta_type=name,
constructors = (ctor,), permission = None)
# Create workflow prototypical instances in __instance__ attributes
@ -316,7 +316,7 @@ class ZopeInstaller:
# Post-initialise every Appy type
for baseClass in klass.wrapperClass.__bases__:
if baseClass.__name__ == 'AbstractWrapper': continue
for name, appyType in baseClass.__dict__.iteritems():
for name, appyType in baseClass.__dict__.items():
if not isinstance(appyType, gen.Field) or \
(isinstance(appyType, gen.Ref) and appyType.isBack):
continue # Back refs are initialised within fw refs

View file

@ -39,9 +39,9 @@
# ------------------------------------------------------------------------------
rowDelimiters = {'-':'middle', '=':'top', '_':'bottom'}
rowDelms = ''.join(rowDelimiters.keys())
rowDelms = ''.join(list(rowDelimiters.keys()))
cellDelimiters = {'|': 'center', ';': 'left', '!': 'right'}
cellDelms = ''.join(cellDelimiters.keys())
cellDelms = ''.join(list(cellDelimiters.keys()))
pxDict = {
# Page-related elements
@ -138,7 +138,7 @@ class Table:
# Initialise simple params, either from the true params, either from
# the p_other Table instance.
for param in Table.simpleParams:
exec 'self.%s = %s%s' % (param, source, param)
exec('self.%s = %s%s' % (param, source, param))
# The following attribute will store a special Row instance used for
# defining column properties.
self.headerRow = None

View file

@ -120,10 +120,10 @@ def sendMail(config, to, subject, body, attachments=None, log=None):
if res and log:
log('could not send mail to some recipients. %s' % str(res),
type='warning')
except smtplib.SMTPException, e:
except smtplib.SMTPException as e:
if log:
log('%s: mail sending failed (%s)' % (config, str(e)), type='error')
except socket.error, se:
except socket.error as se:
if log:
log('%s: mail sending failed (%s)' % (config, str(se)),type='error')
# ------------------------------------------------------------------------------

View file

@ -38,10 +38,10 @@ class Migrator:
if frozen.data.__class__.__name__ == 'Pdata':
# The file content is splitted in several chunks.
f.write(frozen.data.data)
nextPart = frozen.data.next
nextPart = frozen.data.__next__
while nextPart:
f.write(nextPart.data)
nextPart = nextPart.next
nextPart = nextPart.__next__
else:
# Only one chunk
f.write(frozen.data)

View file

@ -13,18 +13,18 @@ class TestMixin:
'''Returns the list of sub-modules of p_app that are non-empty.'''
res = []
try:
exec 'import %s' % moduleName
exec 'moduleObj = %s' % moduleName
exec('import %s' % moduleName)
exec('moduleObj = %s' % moduleName)
moduleFile = moduleObj.__file__
if moduleFile.endswith('.pyc'):
moduleFile = moduleFile[:-1]
except ImportError, ie:
except ImportError as ie:
return res
except SyntaxError, se:
except SyntaxError as se:
return res
# Include the module if not empty. "Emptyness" is determined by the
# absence of names beginning with other chars than "__".
for elem in moduleObj.__dict__.iterkeys():
for elem in moduleObj.__dict__.keys():
if not elem.startswith('__'):
res.append(moduleObj)
break
@ -66,10 +66,10 @@ def afterTest(test):
'''Is executed after every test.'''
g = test.globs
appName = g['tool'].o.getAppName()
exec 'from Products.%s import cov, covFolder, totalNumberOfTests, ' \
'countTest' % appName
exec('from Products.%s import cov, covFolder, totalNumberOfTests, ' \
'countTest' % appName)
countTest()
exec 'from Products.%s import numberOfExecutedTests' % appName
exec('from Products.%s import numberOfExecutedTests' % appName)
if cov and (numberOfExecutedTests == totalNumberOfTests):
cov.stop()
appModules = test.getNonEmptySubModules(appName)

View file

@ -13,6 +13,7 @@ from appy.shared import mimeTypes
from appy.shared import utils as sutils
from appy.shared.data import languages
from appy.shared.ldap_connector import LdapConnector
import collections
try:
from AccessControl.ZopeSecurityPolicy import _noroles
except ImportError:
@ -36,7 +37,7 @@ class ToolMixin(BaseMixin):
p_metaTypeOrAppyType.'''
appName = self.getProductConfig().PROJECTNAME
res = metaTypeOrAppyClass
if not isinstance(metaTypeOrAppyClass, basestring):
if not isinstance(metaTypeOrAppyClass, str):
res = gutils.getClassName(metaTypeOrAppyClass, appName)
if res.find('_wrappers') != -1:
elems = res.split('_')
@ -439,7 +440,7 @@ class ToolMixin(BaseMixin):
def quote(self, s, escapeWithEntity=True):
'''Returns the quoted version of p_s.'''
if not isinstance(s, basestring): s = str(s)
if not isinstance(s, str): s = str(s)
repl = escapeWithEntity and '&apos;' or "\\'"
s = s.replace('\r\n', '').replace('\n', '').replace("'", repl)
return "'%s'" % s
@ -452,7 +453,7 @@ class ToolMixin(BaseMixin):
def getZopeClass(self, name):
'''Returns the Zope class whose name is p_name.'''
exec 'from Products.%s.%s import %s as C'% (self.getAppName(),name,name)
exec('from Products.%s.%s import %s as C'% (self.getAppName(),name,name))
return C
def getAppyClass(self, zopeName, wrapper=False):
@ -476,12 +477,12 @@ class ToolMixin(BaseMixin):
'''Gets the different ways objects of p_klass can be created (currently:
via a web form or programmatically only). Result is a list.'''
res = []
if not klass.__dict__.has_key('create'):
if 'create' not in klass.__dict__:
return ['form']
else:
means = klass.create
if means:
if isinstance(means, basestring): res = [means]
if isinstance(means, str): res = [means]
else: res = means
return res
@ -511,7 +512,7 @@ class ToolMixin(BaseMixin):
else:
creators = self.getProductConfig().appConfig.defaultCreators
# Resolve case (3): if "creators" is a method, execute it.
if callable(creators): creators = creators(self.appy())
if isinstance(creators, collections.Callable): creators = creators(self.appy())
# Resolve case (2)
if isinstance(creators, bool) or not creators: return creators
# Resolve case (1): checks whether the user has at least one of the
@ -595,7 +596,7 @@ class ToolMixin(BaseMixin):
rq = self.REQUEST
# Store the search criteria in the session
criteria = self._getDefaultSearchCriteria()
for name in rq.form.keys():
for name in list(rq.form.keys()):
if name.startswith('w_') and not self._searchValueIsEmpty(name):
hasStar = name.find('*') != -1
fieldName = not hasStar and name[2:] or name[2:name.find('*')]
@ -609,17 +610,17 @@ class ToolMixin(BaseMixin):
# The type of the value is encoded after char "*".
name, type = name.split('*')
if type == 'bool':
exec 'value = %s' % value
exec('value = %s' % value)
elif type in ('int', 'float'):
# Get the "from" value
if not value: value = None
else:
exec 'value = %s(value)' % type
exec('value = %s(value)' % type)
# Get the "to" value
toValue = rq.form['%s_to' % name[2:]].strip()
if not toValue: toValue = None
else:
exec 'toValue = %s(toValue)' % type
exec('toValue = %s(toValue)' % type)
value = (value, toValue)
elif type == 'date':
prefix = name[2:]
@ -640,8 +641,8 @@ class ToolMixin(BaseMixin):
if len(type) > 6:
transform = type.split('-')[1]
if (transform != 'none') and value:
exec 'value = value.%s()' % \
self.transformMethods[transform]
exec('value = value.%s()' % \
self.transformMethods[transform])
if isinstance(value, list):
# It is a list of values. Check if we have an operator for
# the field, to see if we make an "and" or "or" for all
@ -697,7 +698,7 @@ class ToolMixin(BaseMixin):
it among search criteria in the session.'''
if not refInfo and (self.REQUEST.get('search', None) == 'customSearch'):
criteria = self.REQUEST.SESSION.get('searchCriteria', None)
if criteria and criteria.has_key('_ref'): refInfo = criteria['_ref']
if criteria and '_ref' in criteria: refInfo = criteria['_ref']
if not refInfo: return None, None
objectUid, fieldName = refInfo.split(':')
obj = self.getObject(objectUid)
@ -856,7 +857,7 @@ class ToolMixin(BaseMixin):
try:
creds = creds.split(' ')[-1]
login, password = base64.decodestring(creds).split(':', 1)
except Exception, e:
except Exception as e:
pass
# b. Identify the user from the authentication cookie.
if not login:
@ -968,7 +969,7 @@ class ToolMixin(BaseMixin):
# Invalidate the user session.
try:
sdm = self.session_data_manager
except AttributeError, ae:
except AttributeError as ae:
# When ran in test mode, session_data_manager is not there.
sdm = None
if sdm:
@ -977,7 +978,7 @@ class ToolMixin(BaseMixin):
session.invalidate()
self.log('logged out.')
# Remove user from variable "loggedUsers"
if self.loggedUsers.has_key(userId): del self.loggedUsers[userId]
if userId in self.loggedUsers: del self.loggedUsers[userId]
return self.goto(self.getApp().absolute_url())
# This dict stores, for every logged user, the date/time of its last access
@ -1247,7 +1248,7 @@ class ToolMixin(BaseMixin):
if hasattr(klass, 'popup'):
res.target = 'appyIFrame'
d = klass.popup
if isinstance(d, basestring):
if isinstance(d, str):
# Width only
params = d[:-2]
else:

View file

@ -3,7 +3,7 @@
- mixins/ToolMixin is mixed in with the generated application Tool class.'''
# ------------------------------------------------------------------------------
import os, os.path, re, sys, types, urllib, cgi
import os, os.path, re, sys, types, urllib.request, urllib.parse, urllib.error, cgi
from appy import Object
from appy.px import Px
from appy.fields.workflow import UiTransition
@ -15,6 +15,7 @@ from appy.shared import utils as sutils
from appy.shared.data import rtlLanguages
from appy.shared.xml_parser import XmlMarshaller, XmlUnmarshaller
from appy.shared.diff import HtmlDiff
import collections
# ------------------------------------------------------------------------------
NUMBERED_ID = re.compile('.+\d{4}$')
@ -371,9 +372,9 @@ class BaseMixin:
# p_errors object. Within this object, for every error message that is
# not a string, we replace it with the standard validation error for the
# corresponding field.
for key, value in errors.__dict__.iteritems():
for key, value in errors.__dict__.items():
resValue = value
if not isinstance(resValue, basestring):
if not isinstance(resValue, str):
resValue = self.translate('field_invalid')
setattr(errors, key, resValue)
return msg
@ -419,7 +420,7 @@ class BaseMixin:
# Trigger field-specific validation
self.intraFieldValidation(errors, values)
if errors.__dict__:
for k,v in errors.__dict__.iteritems(): rq.set('%s_error' % k, v)
for k,v in errors.__dict__.items(): rq.set('%s_error' % k, v)
self.say(errorMessage)
return self.gotoEdit()
@ -427,7 +428,7 @@ class BaseMixin:
msg = self.interFieldValidation(errors, values)
if not msg: msg = errorMessage
if errors.__dict__:
for k,v in errors.__dict__.iteritems(): rq.set('%s_error' % k, v)
for k,v in errors.__dict__.items(): rq.set('%s_error' % k, v)
self.say(msg)
return self.gotoEdit()
@ -506,7 +507,7 @@ class BaseMixin:
# Get the list of indexes that apply on this object. Else, Zope
# will reindex all indexes defined in the catalog, and through
# acquisition, wrong methods can be called on wrong objects.
iNames = self.wrapperClass.getIndexes().keys()
iNames = list(self.wrapperClass.getIndexes().keys())
catalog.catalog_object(self, path, idxs=iNames)
def xml(self, action=None):
@ -529,14 +530,14 @@ class BaseMixin:
elif isinstance(methodRes, file):
res = methodRes.read()
methodRes.close()
elif isinstance(methodRes, basestring) and \
elif isinstance(methodRes, str) and \
methodRes.startswith('<?xml'): # Already XML
return methodRes
else:
marshaller = XmlMarshaller()
oType = isinstance(methodRes, Object) and 'popo' or 'appy'
res = marshaller.marshall(methodRes, objectType=oType)
except Exception, e:
except Exception as e:
tb = sutils.Traceback.get()
res = XmlMarshaller(rootTag='exception').marshall(tb)
self.log(tb, type='error')
@ -548,7 +549,7 @@ class BaseMixin:
'''Prints a p_msg in the user interface. p_logLevel may be "info",
"warning" or "error".'''
rq = self.REQUEST
if 'messages' not in rq.SESSION.keys():
if 'messages' not in list(rq.SESSION.keys()):
plist = self.getProductConfig().PersistentList
messages = rq.SESSION['messages'] = plist()
else:
@ -619,7 +620,7 @@ class BaseMixin:
For a multilingual string field, p_changes can contain a key for
every language, of the form <field name>-<language>.'''
# Add to the p_changes dict the field labels
for name in changes.keys():
for name in list(changes.keys()):
# "name" can contain the language for multilingual fields.
if '-' in name:
fieldName, lg = name.split('-')
@ -646,7 +647,7 @@ class BaseMixin:
historized fields, while p_self already contains the (potentially)
modified values.'''
# Remove from previousData all values that were not changed
for name in previousData.keys():
for name in list(previousData.keys()):
field = self.getAppyType(name)
prev = previousData[name]
curr = field.getValue(self)
@ -655,7 +656,7 @@ class BaseMixin:
((prev == '') and (curr == None)):
del previousData[name]
continue
except UnicodeDecodeError, ude:
except UnicodeDecodeError as ude:
# The string comparisons above may imply silent encoding-related
# conversions that may produce this exception.
continue
@ -743,15 +744,15 @@ class BaseMixin:
else:
klass = self.appy().klass
moduleName = klass.__module__
exec 'import %s' % moduleName
exec 'reload(%s)' % moduleName
exec 'res = %s.%s' % (moduleName, klass.__name__)
exec('import %s' % moduleName)
exec('reload(%s)' % moduleName)
exec('res = %s.%s' % (moduleName, klass.__name__))
# More manipulations may have occurred in m_update
if hasattr(res, 'update'):
parentName= res.__bases__[-1].__name__
moduleName= 'Products.%s.wrappers' % self.getTool().getAppName()
exec 'import %s' % moduleName
exec 'parent = %s.%s' % (moduleName, parentName)
exec('import %s' % moduleName)
exec('parent = %s.%s' % (moduleName, parentName))
res.update(parent)
return res
@ -839,15 +840,15 @@ class BaseMixin:
req = self.REQUEST
for field in self.getAllAppyTypes():
if field.page.name != pageName: continue
if field.masterValue and callable(field.masterValue):
if field.masterValue and isinstance(field.masterValue, collections.Callable):
# We have a slave field that is updated via ajax requests.
name = field.name
# Remember the request value for this field if present.
if req.has_key(name) and req[name]:
if name in req and req[name]:
requestValues[name] = req[name]
# Remember the validation error for this field if present.
errorKey = '%s_error' % name
if req.has_key(errorKey):
if errorKey in req:
errors[name] = req[errorKey]
return sutils.getStringDict(requestValues), sutils.getStringDict(errors)
@ -899,7 +900,7 @@ class BaseMixin:
del phases[res[i].name]
del res[i]
# Compute next/previous phases of every phase
for ph in phases.itervalues():
for ph in phases.values():
ph.computeNextPrevious(res)
ph.totalNbOfPhases = len(res)
# Restrict the result to the current phase if required
@ -1208,7 +1209,7 @@ class BaseMixin:
# fields' old values by their formatted counterparts.
event = history[i].copy()
event['changes'] = {}
for name, oldValue in history[i]['changes'].iteritems():
for name, oldValue in history[i]['changes'].items():
# "name" can specify a language-specific part in a
# multilingual field. "oldValue" is a tuple
# (value, fieldName).
@ -1455,7 +1456,7 @@ class BaseMixin:
# Add users or groups having, locally, this role on this object.
localRoles = getattr(self.aq_base, '__ac_local_roles__', None)
if not localRoles: return res
for id, roles in localRoles.iteritems():
for id, roles in localRoles.items():
for role in roles:
if role in res:
usr = 'user:%s' % id
@ -1465,7 +1466,7 @@ class BaseMixin:
def showState(self):
'''Must I show self's current state ?'''
stateShow = self.State(name=False).show
if callable(stateShow):
if isinstance(stateShow, collections.Callable):
return stateShow(self.getWorkflow(), self.appy())
return stateShow
@ -1479,7 +1480,7 @@ class BaseMixin:
if not hasattr(klass, 'showTransitions'): return (layoutType=='view')
showValue = klass.showTransitions
# This value can be a single value or a tuple/list of values.
if isinstance(showValue, basestring): return layoutType == showValue
if isinstance(showValue, str): return layoutType == showValue
return layoutType in showValue
getUrlDefaults = {'page':True, 'nav':True}
@ -1524,8 +1525,8 @@ class BaseMixin:
if 'nav' not in kwargs: kwargs['nav'] = True
# Create URL parameters from kwargs
params = []
for name, value in kwargs.iteritems():
if isinstance(value, basestring):
for name, value in kwargs.items():
if isinstance(value, str):
params.append('%s=%s' % (name, value))
elif self.REQUEST.get(name, ''):
params.append('%s=%s' % (name, self.REQUEST[name]))
@ -1601,7 +1602,7 @@ class BaseMixin:
# Find the name of the method to call.
methodName = rq.QUERY_STRING.split('=')[1]
return self.xml(action=methodName)
elif rq.has_key('do'):
elif 'do' in rq:
# The user wants to call a method on this object and get its result
# as XML.
return self.xml(action=rq['do'])
@ -1672,7 +1673,7 @@ class BaseMixin:
if field.type != 'group':
fieldMapping = field.mapping[label]
if fieldMapping:
if callable(fieldMapping):
if isinstance(fieldMapping, collections.Callable):
fieldMapping = field.callMethod(self, fieldMapping)
mapping.update(fieldMapping)
label = getattr(field, '%sId' % label)
@ -1697,15 +1698,15 @@ class BaseMixin:
# Perform replacements, according to p_format.
res = self.formatText(res, format)
# Perform variable replacements
for name, repl in mapping.iteritems():
if not isinstance(repl, basestring): repl = str(repl)
for name, repl in mapping.items():
if not isinstance(repl, str): repl = str(repl)
res = res.replace('${%s}' % name, repl)
return res
def getPageLayout(self, layoutType):
'''Returns the layout corresponding to p_layoutType for p_self.'''
res = self.wrapperClass.getPageLayouts()[layoutType]
if isinstance(res, basestring): res = Table(res)
if isinstance(res, str): res = Table(res)
return res
def download(self, name=None):

View file

@ -5,6 +5,7 @@
# ------------------------------------------------------------------------------
import types
import appy.gen as gen
import collections
# Prototypical instances of every type -----------------------------------------
class Protos:
@ -49,7 +50,7 @@ class ModelClass:
'''This method returns the code declaration for p_appyType.'''
typeArgs = ''
proto = Protos.get(appyType)
for name, value in appyType.__dict__.iteritems():
for name, value in appyType.__dict__.items():
# Some attrs can't be given to the constructor
if name in Protos.notInit: continue
# If the given value corresponds to the default value, don't give it
@ -74,7 +75,7 @@ class ModelClass:
# defined. So we initialize it to None. The post-init of the
# field must be done manually in wrappers.py.
value = 'None'
elif isinstance(value, basestring):
elif isinstance(value, str):
value = '"%s"' % value
elif isinstance(value, gen.Ref):
if not value.isBack: continue
@ -91,10 +92,10 @@ class ModelClass:
value = 'Grp("%s")' % value.name
elif isinstance(value, gen.Page):
value = 'pges["%s"]' % value.name
elif callable(value):
elif isinstance(value, collections.Callable):
className = wrapperName
if (appyType.type == 'Ref') and appyType.isBack:
className = value.im_class.__name__
className = value.__self__.__class__.__name__
value = '%s.%s' % (className, value.__name__)
typeArgs += '%s=%s,' % (name, value)
return '%s(%s)' % (appyType.__class__.__name__, typeArgs)
@ -118,17 +119,17 @@ class ModelClass:
pages = {}
layouts = []
for name in klass._appy_attributes:
exec 'appyType = klass.%s' % name
exec('appyType = klass.%s' % name)
if appyType.page.name not in pages:
pages[appyType.page.name] = appyType.page
res += ' pges = {'
for page in pages.itervalues():
for page in pages.values():
# Determine page "show" attributes
pShow = ''
for attr in ('',) + page.subElements:
attrName = 'show%s' % attr.capitalize()
pageShow = getattr(page, attrName)
if isinstance(pageShow, basestring): pageShow='"%s"' % pageShow
if isinstance(pageShow, str): pageShow='"%s"' % pageShow
elif callable(pageShow):
pageShow = '%s.%s' % (wrapperName, pageShow.__name__)
if pageShow != True:
@ -142,7 +143,7 @@ class ModelClass:
res += '}\n'
# Secondly, dump every (not Ref.isBack) attribute
for name in klass._appy_attributes:
exec 'appyType = klass.%s' % name
exec('appyType = klass.%s' % name)
if (appyType.type == 'Ref') and appyType.isBack: continue
typeBody = klass._appy_getTypeBody(appyType, wrapperName)
res += ' %s=%s\n' % (name, typeBody)
@ -305,12 +306,12 @@ class Tool(ModelClass):
@classmethod
def _appy_clean(klass):
toClean = []
for k, v in klass.__dict__.iteritems():
for k, v in klass.__dict__.items():
if not k.startswith('__') and (not k.startswith('_appy_')):
if k not in defaultToolFields:
toClean.append(k)
for k in toClean:
exec 'del klass.%s' % k
exec('del klass.%s' % k)
klass._appy_attributes = list(defaultToolFields)
klass.folder = True
# ------------------------------------------------------------------------------

View file

@ -1,6 +1,6 @@
# ------------------------------------------------------------------------------
import os, re, time, copy
from utils import produceNiceMessage
from .utils import produceNiceMessage
# ------------------------------------------------------------------------------
poHeader = '''msgid ""
@ -213,7 +213,7 @@ class PoFile:
if keepExistingOrder:
# Update existing messages and add inexistent messages to the end.
for newMsg in newMessages:
if self.messagesDict.has_key(newMsg.id):
if newMsg.id in self.messagesDict:
msg = self.messagesDict[newMsg.id]
else:
msg = self.addMessage(newMsg)
@ -224,7 +224,7 @@ class PoFile:
notNewMessages = [m for m in self.messages if m.id not in newIds]
del self.messages[:]
for newMsg in newMessages:
if self.messagesDict.has_key(newMsg.id):
if newMsg.id in self.messagesDict:
msg = self.messagesDict[newMsg.id]
self.messages.append(msg)
else:
@ -240,7 +240,7 @@ class PoFile:
fb = ''
if not self.isPot:
# I must add fallbacks
if fallbacks.has_key(self.language):
if self.language in fallbacks:
fb = '"X-is-fallback-for: %s\\n"' % fallbacks[self.language]
f.write(poHeader % (self.applicationName, creationTime,
self.language, self.language, self.domain, fb))

View file

@ -1,7 +1,8 @@
# ------------------------------------------------------------------------------
import re, os, os.path, base64, urllib
import re, os, os.path, base64, urllib.request, urllib.parse, urllib.error
from appy.px import Px
from appy.shared import utils as sutils
import collections
# Function for creating a Zope object ------------------------------------------
def createObject(folder, id, className, appName, wf=True, noSecurity=False):
@ -10,8 +11,8 @@ def createObject(folder, id, className, appName, wf=True, noSecurity=False):
creation of the config object), computing workflow-related info is not
possible at this time. This is why this function can be called with
p_wf=False.'''
exec 'from Products.%s.%s import %s as ZopeClass' % \
(appName, className, className)
exec('from Products.%s.%s import %s as ZopeClass' % \
(appName, className, className))
# Get the tool. It may not be present yet, maybe are we creating it now.
if folder.meta_type.endswith('Folder'):
# p_folder is a standard Zope (temp) folder.
@ -178,7 +179,7 @@ def callMethod(obj, method, klass=None, cache=True):
if methodType == 'staticmethod':
method = method.__get__(klass)
elif methodType == 'instancemethod':
method = method.im_func
method = method.__func__
# Call the method if cache is not needed
if not cache: return method(obj)
# If first arg of method is named "tool" instead of the traditional "self",
@ -187,7 +188,7 @@ def callMethod(obj, method, klass=None, cache=True):
# Every method call, even on different instances, will be cached in a unique
# key.
cheat = False
if not klass and (method.func_code.co_varnames[0] == 'tool'):
if not klass and (method.__code__.co_varnames[0] == 'tool'):
prefix = obj.klass.__name__
obj = obj.tool
cheat = True
@ -200,7 +201,7 @@ def callMethod(obj, method, klass=None, cache=True):
else:
prefix = obj.uid
# Second part of the key: p_method name
key = '%s:%s' % (prefix, method.func_name)
key = '%s:%s' % (prefix, method.__name__)
# Return the cached value if present in the method cache.
if key in rq.methodCache:
return rq.methodCache[key]
@ -216,20 +217,20 @@ def readCookie(request):
(None, None).'''
cookie = request.get('_appy_', None)
if not cookie: return None, None
cookieValue = base64.decodestring(urllib.unquote(cookie))
cookieValue = base64.decodestring(urllib.parse.unquote(cookie))
if ':' in cookieValue: return cookieValue.split(':')
return None, None
def writeCookie(login, password, request):
'''Encode p_login and p_password into the cookie set in the p_request.'''
cookieValue = base64.encodestring('%s:%s' % (login, password)).rstrip()
cookieValue = urllib.quote(cookieValue)
cookieValue = urllib.parse.quote(cookieValue)
request.RESPONSE.setCookie('_appy_', cookieValue, path='/')
# ------------------------------------------------------------------------------
def initMasterValue(v):
'''Standardizes p_v as a list of strings, excepted if p_v is a method.'''
if callable(v): return v
if isinstance(v, collections.Callable): return v
if not isinstance(v, bool) and not v: res = []
elif type(v) not in sutils.sequenceTypes: res = [v]
else: res = v
@ -243,7 +244,7 @@ class No:
instead. When creating such an instance, you can specify an error
message.'''
def __init__(self, msg): self.msg = msg
def __nonzero__(self): return False
def __bool__(self): return False
def __repr__(self): return '<No: %s>' % self.msg
# ------------------------------------------------------------------------------

View file

@ -424,7 +424,7 @@ class ToolWrapper(AbstractWrapper):
'<tr><th></th><th>%s</th></tr>' % \
self.translate('last_user_access')
rows = []
for userId, lastAccess in self.o.loggedUsers.items():
for userId, lastAccess in list(self.o.loggedUsers.items()):
user = self.search1('User', noSecurity=True, login=userId)
if not user: continue # Could have been deleted in the meanwhile
fmt = '%s (%s)' % (self.dateFormat, self.hourFormat)
@ -515,7 +515,7 @@ class ToolWrapper(AbstractWrapper):
failed += subFailed
try:
startObject.reindex()
except Exception, e:
except Exception as e:
failed.append(startObject)
return nb, failed

View file

@ -343,7 +343,7 @@ class UserWrapper(AbstractWrapper):
if not localRoles: return res
# Gets the logins of this user and all its groups.
logins = self.getLogins()
for login, roles in localRoles.iteritems():
for login, roles in localRoles.items():
# Ignore logins not corresponding to this user.
if login not in logins: continue
for role in roles:
@ -388,7 +388,7 @@ class UserWrapper(AbstractWrapper):
if not localRoles: return
# Gets the logins of this user and all its groups.
userLogins = self.getLogins()
for login, roles in localRoles.iteritems():
for login, roles in localRoles.items():
# Ignore logins not corresponding to this user.
if login not in userLogins: continue
for role in roles:

View file

@ -861,7 +861,7 @@ class AbstractWrapper(object):
if len(self.__class__.__bases__) > 1:
# There is a custom user class
custom = self.__class__.__bases__[-1]
if custom.__dict__.has_key(methodName):
if methodName in custom.__dict__:
return custom.__dict__[methodName]
def _callCustom(self, methodName, *args, **kwargs):
@ -973,7 +973,7 @@ class AbstractWrapper(object):
present, will not be called; any other defined method will not be
called neither (ie, Ref.insert, Ref.beforeLink, Ref.afterLink...).
'''
isField = isinstance(fieldNameOrClass, basestring)
isField = isinstance(fieldNameOrClass, str)
tool = self.tool.o
# Determine the class of the object to create
if isField:
@ -984,7 +984,7 @@ class AbstractWrapper(object):
klass = fieldNameOrClass
portalType = tool.getPortalType(klass)
# Determine object id
if kwargs.has_key('id'):
if 'id' in kwargs:
objId = kwargs['id']
del kwargs['id']
else:
@ -1002,7 +1002,7 @@ class AbstractWrapper(object):
noSecurity=noSecurity)
appyObj = zopeObj.appy()
# Set object attributes
for attrName, attrValue in kwargs.iteritems():
for attrName, attrValue in kwargs.items():
try:
setattr(appyObj, attrName, attrValue)
except AttributeError, ae:
@ -1183,8 +1183,8 @@ class AbstractWrapper(object):
# Get the Appy object from the brain
if noSecurity: method = '_unrestrictedGetObject'
else: method = 'getObject'
exec 'obj = brain.%s().appy()' % method
exec expression
exec('obj = brain.%s().appy()' % method)
exec(expression)
return ctx
def reindex(self, fields=None, unindex=False):
@ -1249,7 +1249,7 @@ class AbstractWrapper(object):
else:
return xml
elif format == 'csv':
if isinstance(at, basestring):
if isinstance(at, str):
marshaller = CsvMarshaller(include=include, exclude=exclude)
return marshaller.marshall(self)
else: