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

@ -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 ''' 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):