add python3 suppport based on 2to3 script
This commit is contained in:
parent
caef0e85d0
commit
4f91a30fec
31
__init__.py
31
__init__.py
|
@ -22,26 +22,27 @@ class Object:
|
||||||
'''At every place we need an object, but without any requirement on its
|
'''At every place we need an object, but without any requirement on its
|
||||||
class (methods, attributes,...) we will use this minimalist class.'''
|
class (methods, attributes,...) we will use this minimalist class.'''
|
||||||
def __init__(self, **fields):
|
def __init__(self, **fields):
|
||||||
for k, v in fields.iteritems():
|
for k, v in fields.items():
|
||||||
setattr(self, k, v)
|
setattr(self, k, v)
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
res = u'<Object '
|
res = '<Object '
|
||||||
for attrName, attrValue in self.__dict__.iteritems():
|
for attrName, attrValue in self.__dict__.items():
|
||||||
v = attrValue
|
v = attrValue
|
||||||
if hasattr(v, '__repr__'):
|
if hasattr(v, '__repr__'):
|
||||||
v = v.__repr__()
|
v = v.__repr__()
|
||||||
try:
|
try:
|
||||||
res += u'%s=%s ' % (attrName, v)
|
res += '%s=%s ' % (attrName, v)
|
||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
res += u'%s=<encoding problem> ' % attrName
|
res += '%s=<encoding problem> ' % attrName
|
||||||
res = res.strip() + '>'
|
res = res.strip() + '>'
|
||||||
return res.encode('utf-8')
|
return res.encode('utf-8')
|
||||||
def __nonzero__(self): return bool(self.__dict__)
|
def __bool__(self):
|
||||||
|
return bool(self.__dict__)
|
||||||
def get(self, name, default=None): return getattr(self, name, default)
|
def get(self, name, default=None): return getattr(self, name, default)
|
||||||
def __getitem__(self, k): return getattr(self, k)
|
def __getitem__(self, k): return getattr(self, k)
|
||||||
def update(self, other):
|
def update(self, other):
|
||||||
'''Includes information from p_other into p_self'''
|
'''Includes information from p_other into p_self.'''
|
||||||
for k, v in other.__dict__.iteritems():
|
for k, v in other.__dict__.items():
|
||||||
setattr(self, k, v)
|
setattr(self, k, v)
|
||||||
def clone(self):
|
def clone(self):
|
||||||
res = Object()
|
res = Object()
|
||||||
|
@ -59,11 +60,11 @@ class Hack:
|
||||||
"_base_<initial_method_name>_". In the patched method, one may use
|
"_base_<initial_method_name>_". In the patched method, one may use
|
||||||
Hack.base to call the base method. If p_method is static, you must
|
Hack.base to call the base method. If p_method is static, you must
|
||||||
specify its class in p_klass.'''
|
specify its class in p_klass.'''
|
||||||
# Get the class on which the surgery will take place
|
# Get the class on which the surgery will take place.
|
||||||
isStatic = klass
|
isStatic = klass
|
||||||
klass = klass or method.im_class
|
klass = klass or method.__self__.__class__
|
||||||
# On this class, store m_method under its "base" name
|
# On this class, store m_method under its "base" name.
|
||||||
name = isStatic and method.func_name or method.im_func.__name__
|
name = isStatic and method.__name__ or method.__func__.__name__
|
||||||
baseName = '_base_%s_' % name
|
baseName = '_base_%s_' % name
|
||||||
if isStatic:
|
if isStatic:
|
||||||
# If "staticmethod" isn't called hereafter, the static functions
|
# If "staticmethod" isn't called hereafter, the static functions
|
||||||
|
@ -78,8 +79,8 @@ class Hack:
|
||||||
'''Allows to call the base (replaced) method. If p_method is static,
|
'''Allows to call the base (replaced) method. If p_method is static,
|
||||||
you must specify its p_klass.'''
|
you must specify its p_klass.'''
|
||||||
isStatic = klass
|
isStatic = klass
|
||||||
klass = klass or method.im_class
|
klass = klass or method.__self__.__class__
|
||||||
name = isStatic and method.func_name or method.im_func.__name__
|
name = isStatic and method.__name__ or method.__func__.__name__
|
||||||
return getattr(klass, '_base_%s_' % name)
|
return getattr(klass, '_base_%s_' % name)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -87,7 +88,7 @@ class Hack:
|
||||||
'''Injects any method or attribute from p_patchClass into klass.'''
|
'''Injects any method or attribute from p_patchClass into klass.'''
|
||||||
patched = []
|
patched = []
|
||||||
added = []
|
added = []
|
||||||
for name, attr in patchClass.__dict__.items():
|
for name, attr in patchClass.__dict__.iteritems():
|
||||||
if name.startswith('__'): continue # Ignore special methods
|
if name.startswith('__'): continue # Ignore special methods
|
||||||
# Unwrap functions from static methods
|
# Unwrap functions from static methods
|
||||||
if attr.__class__.__name__ == 'staticmethod':
|
if attr.__class__.__name__ == 'staticmethod':
|
||||||
|
|
|
@ -73,10 +73,10 @@ class AskSap:
|
||||||
# Return info about a given function.
|
# Return info about a given function.
|
||||||
info = sap.getFunctionInfo(sapElement)
|
info = sap.getFunctionInfo(sapElement)
|
||||||
prefix = 'Function'
|
prefix = 'Function'
|
||||||
print('%s: %s' % (prefix, sapElement))
|
print(('%s: %s' % (prefix, sapElement)))
|
||||||
print(info)
|
print(info)
|
||||||
sap.disconnect()
|
sap.disconnect()
|
||||||
except SapError, se:
|
except SapError as se:
|
||||||
sys.stderr.write(str(se))
|
sys.stderr.write(str(se))
|
||||||
sys.stderr.write('\n')
|
sys.stderr.write('\n')
|
||||||
sys.exit(ERROR_CODE)
|
sys.exit(ERROR_CODE)
|
||||||
|
|
|
@ -4,7 +4,7 @@ from optparse import OptionParser
|
||||||
import ZODB.FileStorage
|
import ZODB.FileStorage
|
||||||
import ZODB.serialize
|
import ZODB.serialize
|
||||||
from DateTime import DateTime
|
from DateTime import DateTime
|
||||||
from StringIO import StringIO
|
from io import StringIO
|
||||||
folderName = os.path.dirname(__file__)
|
folderName = os.path.dirname(__file__)
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
@ -87,9 +87,9 @@ class ZodbBackuper:
|
||||||
w('Try to create backup folder for logs "%s"...' % \
|
w('Try to create backup folder for logs "%s"...' % \
|
||||||
self.logsBackupFolder)
|
self.logsBackupFolder)
|
||||||
os.mkdir(self.logsBackupFolder)
|
os.mkdir(self.logsBackupFolder)
|
||||||
except IOError, ioe:
|
except IOError as ioe:
|
||||||
w(folderCreateError % str(ioe))
|
w(folderCreateError % str(ioe))
|
||||||
except OSError, oe:
|
except OSError as oe:
|
||||||
w(folderCreateError % str(oe))
|
w(folderCreateError % str(oe))
|
||||||
if os.path.exists(self.logsBackupFolder):
|
if os.path.exists(self.logsBackupFolder):
|
||||||
# Ok, we can make the backup of the log files.
|
# Ok, we can make the backup of the log files.
|
||||||
|
@ -175,7 +175,7 @@ class ZodbBackuper:
|
||||||
except smtplib.SMTPException, sme:
|
except smtplib.SMTPException, sme:
|
||||||
w('Error while contacting SMTP server %s (%s).' % \
|
w('Error while contacting SMTP server %s (%s).' % \
|
||||||
(self.options.smtpServer, str(se)))
|
(self.options.smtpServer, str(se)))
|
||||||
except socket.error, se:
|
except socket.error as se:
|
||||||
w('Could not connect to SMTP server %s (%s).' % \
|
w('Could not connect to SMTP server %s (%s).' % \
|
||||||
(self.options.smtpServer, str(se)))
|
(self.options.smtpServer, str(se)))
|
||||||
|
|
||||||
|
@ -191,12 +191,12 @@ class ZodbBackuper:
|
||||||
for fileName in os.listdir(self.tempFolder):
|
for fileName in os.listdir(self.tempFolder):
|
||||||
ext = os.path.splitext(fileName)[1]
|
ext = os.path.splitext(fileName)[1]
|
||||||
if ext in self.toRemoveExts:
|
if ext in self.toRemoveExts:
|
||||||
exec '%sCount += 1' % ext[1:]
|
exec('%sCount += 1' % ext[1:])
|
||||||
fullFileName = os.path.join(self.tempFolder, fileName)
|
fullFileName = os.path.join(self.tempFolder, fileName)
|
||||||
#w('Removing "%s"...' % fullFileName)
|
#w('Removing "%s"...' % fullFileName)
|
||||||
try:
|
try:
|
||||||
os.remove(fullFileName)
|
os.remove(fullFileName)
|
||||||
except OSError, oe:
|
except OSError as oe:
|
||||||
w('Could not remove "%s" (%s).' % (fullFileName, str(oe)))
|
w('Could not remove "%s" (%s).' % (fullFileName, str(oe)))
|
||||||
w('%d .pdf, %d .doc, %d .rtf and %d .odt file(s) removed.' % \
|
w('%d .pdf, %d .doc, %d .rtf and %d .odt file(s) removed.' % \
|
||||||
(pdfCount, docCount, rtfCount, odtCount))
|
(pdfCount, docCount, rtfCount, odtCount))
|
||||||
|
@ -268,7 +268,7 @@ class ZodbBackuper:
|
||||||
if self.emails:
|
if self.emails:
|
||||||
self.sendEmails()
|
self.sendEmails()
|
||||||
self.logFile.close()
|
self.logFile.close()
|
||||||
print(self.logMem.getvalue())
|
print((self.logMem.getvalue()))
|
||||||
self.logMem.close()
|
self.logMem.close()
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
@ -302,7 +302,7 @@ class ZodbBackupScript:
|
||||||
f.write('Hello.')
|
f.write('Hello.')
|
||||||
f.close()
|
f.close()
|
||||||
os.remove(fileName)
|
os.remove(fileName)
|
||||||
except OSError, oe:
|
except OSError as oe:
|
||||||
raise BackupError('I do not have the right to write in ' \
|
raise BackupError('I do not have the right to write in ' \
|
||||||
'folder "%s".' % args[1])
|
'folder "%s".' % args[1])
|
||||||
# Check temp folder
|
# Check temp folder
|
||||||
|
@ -401,7 +401,7 @@ class ZodbBackupScript:
|
||||||
self.checkArgs(options, args)
|
self.checkArgs(options, args)
|
||||||
backuper = ZodbBackuper(args[0], args[1], options)
|
backuper = ZodbBackuper(args[0], args[1], options)
|
||||||
backuper.run()
|
backuper.run()
|
||||||
except BackupError, be:
|
except BackupError as be:
|
||||||
sys.stderr.write(str(be) + '\nRun the script without any ' \
|
sys.stderr.write(str(be) + '\nRun the script without any ' \
|
||||||
'argument for getting help.\n')
|
'argument for getting help.\n')
|
||||||
sys.exit(ERROR_CODE)
|
sys.exit(ERROR_CODE)
|
||||||
|
|
|
@ -21,7 +21,7 @@ class LdapTester:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# Get params from shell args.
|
# Get params from shell args.
|
||||||
if len(sys.argv) != 8:
|
if len(sys.argv) != 8:
|
||||||
print(LdapTester.__doc__)
|
print((LdapTester.__doc__))
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
s = self
|
s = self
|
||||||
s.uri,s.login,s.password,s.base,s.attrs,s.filter,s.scope = sys.argv[1:]
|
s.uri,s.login,s.password,s.base,s.attrs,s.filter,s.scope = sys.argv[1:]
|
||||||
|
@ -33,15 +33,15 @@ class LdapTester:
|
||||||
|
|
||||||
def test(self):
|
def test(self):
|
||||||
# Connect the the LDAP
|
# Connect the the LDAP
|
||||||
print('Connecting to... %s' % self.uri)
|
print(('Connecting to... %s' % self.uri))
|
||||||
connector = LdapConnector(self.uri)
|
connector = LdapConnector(self.uri)
|
||||||
success, msg = connector.connect(self.login, self.password)
|
success, msg = connector.connect(self.login, self.password)
|
||||||
if not success: return
|
if not success: return
|
||||||
# Perform the query.
|
# Perform the query.
|
||||||
print ('Querying %s...' % self.base)
|
print(('Querying %s...' % self.base))
|
||||||
res = connector.search(self.base, self.scope, self.filter,
|
res = connector.search(self.base, self.scope, self.filter,
|
||||||
self.attributes)
|
self.attributes)
|
||||||
print('Got %d results' % len(res))
|
print(('Got %d results' % len(res)))
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
if __name__ == '__main__': LdapTester().test()
|
if __name__ == '__main__': LdapTester().test()
|
||||||
|
|
|
@ -110,12 +110,12 @@ class EggifyScript:
|
||||||
eggFullName = j(self.eggFolder, self.eggName)
|
eggFullName = j(self.eggFolder, self.eggName)
|
||||||
if os.path.exists(eggFullName):
|
if os.path.exists(eggFullName):
|
||||||
os.remove(eggFullName)
|
os.remove(eggFullName)
|
||||||
print('Existing "%s" was removed.' % eggFullName)
|
print(('Existing "%s" was removed.' % eggFullName))
|
||||||
# Create a temp folder where to store the egg
|
# Create a temp folder where to store the egg
|
||||||
eggTempFolder = os.path.splitext(eggFullName)[0]
|
eggTempFolder = os.path.splitext(eggFullName)[0]
|
||||||
if os.path.exists(eggTempFolder):
|
if os.path.exists(eggTempFolder):
|
||||||
FolderDeleter.delete(eggTempFolder)
|
FolderDeleter.delete(eggTempFolder)
|
||||||
print('Removed "%s" that was in my way.' % eggTempFolder)
|
print(('Removed "%s" that was in my way.' % eggTempFolder))
|
||||||
os.mkdir(eggTempFolder)
|
os.mkdir(eggTempFolder)
|
||||||
# Create the "Products" sub-folder if we must wrap the package in this
|
# Create the "Products" sub-folder if we must wrap the package in this
|
||||||
# namespace
|
# namespace
|
||||||
|
@ -170,7 +170,7 @@ class EggifyScript:
|
||||||
try:
|
try:
|
||||||
self.checkArgs(options, args)
|
self.checkArgs(options, args)
|
||||||
self.eggify()
|
self.eggify()
|
||||||
except EggifierError, ee:
|
except EggifierError as ee:
|
||||||
sys.stderr.write(str(ee) + '\nRun eggify.py -h for getting help.\n')
|
sys.stderr.write(str(ee) + '\nRun eggify.py -h for getting help.\n')
|
||||||
sys.exit(ERROR_CODE)
|
sys.exit(ERROR_CODE)
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ class GeneratorScript:
|
||||||
sys.exit(ERROR_CODE)
|
sys.exit(ERROR_CODE)
|
||||||
# Check existence of application
|
# Check existence of application
|
||||||
if not os.path.exists(args[0]):
|
if not os.path.exists(args[0]):
|
||||||
print(APP_NOT_FOUND % args[0])
|
print((APP_NOT_FOUND % args[0]))
|
||||||
sys.exit(ERROR_CODE)
|
sys.exit(ERROR_CODE)
|
||||||
# Convert app path to an absolute path
|
# Convert app path to an absolute path
|
||||||
args[0] = os.path.abspath(args[0])
|
args[0] = os.path.abspath(args[0])
|
||||||
|
@ -55,8 +55,8 @@ class GeneratorScript:
|
||||||
(options, args) = optParser.parse_args()
|
(options, args) = optParser.parse_args()
|
||||||
try:
|
try:
|
||||||
self.manageArgs(optParser, options, args)
|
self.manageArgs(optParser, options, args)
|
||||||
print('Appy version: %s' % appy.version.verbose)
|
print(('Appy version: %s' % appy.version.verbose))
|
||||||
print('Generating Zope product in %s/zope...' % args[0])
|
print(('Generating Zope product in %s/zope...' % args[0]))
|
||||||
ZopeGenerator(args[0], options).run()
|
ZopeGenerator(args[0], options).run()
|
||||||
# Give the user some statistics about its code
|
# Give the user some statistics about its code
|
||||||
LinesCounter(args[0], excludes=['%szope' % os.sep]).run()
|
LinesCounter(args[0], excludes=['%szope' % os.sep]).run()
|
||||||
|
@ -71,7 +71,7 @@ class GeneratorScript:
|
||||||
f.close()
|
f.close()
|
||||||
version = version[:version.find('build')-1]
|
version = version[:version.find('build')-1]
|
||||||
Debianizer(app, appDir, appVersion=version).run()
|
Debianizer(app, appDir, appVersion=version).run()
|
||||||
except GeneratorError, ge:
|
except GeneratorError as ge:
|
||||||
sys.stderr.write(str(ge))
|
sys.stderr.write(str(ge))
|
||||||
sys.stderr.write('\n')
|
sys.stderr.write('\n')
|
||||||
optParser.print_help()
|
optParser.print_help()
|
||||||
|
|
|
@ -82,6 +82,6 @@ else:
|
||||||
targetObject = getattr(targetObject, elem)
|
targetObject = getattr(targetObject, elem)
|
||||||
# Execute the method on the target object
|
# Execute the method on the target object
|
||||||
if args: args = args.split('*')
|
if args: args = args.split('*')
|
||||||
exec 'targetObject.%s(*args)' % toolMethod
|
exec('targetObject.%s(*args)' % toolMethod)
|
||||||
transaction.commit()
|
transaction.commit()
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
18
bin/new.py
18
bin/new.py
|
@ -106,17 +106,17 @@ class ZopeInstanceCreator:
|
||||||
f = file('bin/zopectl', 'w')
|
f = file('bin/zopectl', 'w')
|
||||||
f.write(zopeCtl % self.instancePath)
|
f.write(zopeCtl % self.instancePath)
|
||||||
f.close()
|
f.close()
|
||||||
os.chmod('bin/zopectl', 0744) # Make it executable by owner.
|
os.chmod('bin/zopectl', 0o744) # Make it executable by owner.
|
||||||
# Create bin/runzope
|
# Create bin/runzope
|
||||||
f = file('bin/runzope', 'w')
|
f = file('bin/runzope', 'w')
|
||||||
f.write(runZope % self.instancePath)
|
f.write(runZope % self.instancePath)
|
||||||
f.close()
|
f.close()
|
||||||
os.chmod('bin/runzope', 0744) # Make it executable by owner.
|
os.chmod('bin/runzope', 0o744) # Make it executable by owner.
|
||||||
# Create bin/startoo
|
# Create bin/startoo
|
||||||
f = file('bin/startoo', 'w')
|
f = file('bin/startoo', 'w')
|
||||||
f.write(ooStart)
|
f.write(ooStart)
|
||||||
f.close()
|
f.close()
|
||||||
os.chmod('bin/startoo', 0744) # Make it executable by owner.
|
os.chmod('bin/startoo', 0o744) # Make it executable by owner.
|
||||||
# Create etc/zope.conf
|
# Create etc/zope.conf
|
||||||
os.mkdir('etc')
|
os.mkdir('etc')
|
||||||
f = file('etc/zope.conf', 'w')
|
f = file('etc/zope.conf', 'w')
|
||||||
|
@ -138,10 +138,10 @@ class ZopeInstanceCreator:
|
||||||
password = binascii.b2a_base64(sha('admin').digest())[:-1]
|
password = binascii.b2a_base64(sha('admin').digest())[:-1]
|
||||||
f.write('admin:{SHA}%s\n' % password)
|
f.write('admin:{SHA}%s\n' % password)
|
||||||
f.close()
|
f.close()
|
||||||
os.chmod('inituser', 0644)
|
os.chmod('inituser', 0o644)
|
||||||
# User "zope" must own this instance
|
# User "zope" must own this instance
|
||||||
os.system('chown -R zope %s' % self.instancePath)
|
os.system('chown -R zope %s' % self.instancePath)
|
||||||
print('Zope instance created in %s.' % self.instancePath)
|
print(('Zope instance created in %s.' % self.instancePath))
|
||||||
os.chdir(curdir)
|
os.chdir(curdir)
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
@ -229,7 +229,7 @@ class NewScript:
|
||||||
j = os.path.join
|
j = os.path.join
|
||||||
# As eggs have been deleted, versions of components are lost. Reify
|
# As eggs have been deleted, versions of components are lost. Reify
|
||||||
# them from p_versions.
|
# them from p_versions.
|
||||||
dVersions = ['"%s":"%s"' % (n, v) for n, v in versions.iteritems()]
|
dVersions = ['"%s":"%s"' % (n, v) for n, v in versions.items()]
|
||||||
sVersions = 'appyVersions = {' + ','.join(dVersions) + '}'
|
sVersions = 'appyVersions = {' + ','.join(dVersions) + '}'
|
||||||
codeFile = "%s/pkg_resources.py" % self.libFolder
|
codeFile = "%s/pkg_resources.py" % self.libFolder
|
||||||
f = file(codeFile)
|
f = file(codeFile)
|
||||||
|
@ -326,7 +326,7 @@ class NewScript:
|
||||||
action = 'Copying'
|
action = 'Copying'
|
||||||
if linksForProducts:
|
if linksForProducts:
|
||||||
action = 'Symlinking'
|
action = 'Symlinking'
|
||||||
print('%s Plone stuff in the Zope instance...' % action)
|
print(('%s Plone stuff in the Zope instance...' % action))
|
||||||
if self.ploneVersion in ('plone25', 'plone30'):
|
if self.ploneVersion in ('plone25', 'plone30'):
|
||||||
self.installPlone25or30Stuff(linksForProducts)
|
self.installPlone25or30Stuff(linksForProducts)
|
||||||
elif self.ploneVersion in ('plone3x', 'plone4'):
|
elif self.ploneVersion in ('plone3x', 'plone4'):
|
||||||
|
@ -379,11 +379,11 @@ class NewScript:
|
||||||
try:
|
try:
|
||||||
self.manageArgs(args)
|
self.manageArgs(args)
|
||||||
if self.ploneVersion != 'zope':
|
if self.ploneVersion != 'zope':
|
||||||
print('Creating new %s instance...' % self.ploneVersion)
|
print(('Creating new %s instance...' % self.ploneVersion))
|
||||||
self.createInstance(linksForProducts)
|
self.createInstance(linksForProducts)
|
||||||
else:
|
else:
|
||||||
ZopeInstanceCreator(self.instancePath).run()
|
ZopeInstanceCreator(self.instancePath).run()
|
||||||
except NewError, ne:
|
except NewError as ne:
|
||||||
optParser.print_help()
|
optParser.print_help()
|
||||||
sys.stderr.write(str(ne))
|
sys.stderr.write(str(ne))
|
||||||
sys.stderr.write('\n')
|
sys.stderr.write('\n')
|
||||||
|
|
|
@ -52,7 +52,7 @@ class OdfGrep:
|
||||||
# Run "grep" in this folder
|
# Run "grep" in this folder
|
||||||
match = self.callGrep(tempFolder)
|
match = self.callGrep(tempFolder)
|
||||||
if match:
|
if match:
|
||||||
print('Found in %s' % fileName)
|
print(('Found in %s' % fileName))
|
||||||
FolderDeleter.delete(tempFolder)
|
FolderDeleter.delete(tempFolder)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
@ -65,7 +65,7 @@ class OdfGrep:
|
||||||
if os.path.splitext(name)[1] in self.toUnzip:
|
if os.path.splitext(name)[1] in self.toUnzip:
|
||||||
self.grepFile(os.path.join(dir, name))
|
self.grepFile(os.path.join(dir, name))
|
||||||
else:
|
else:
|
||||||
print('%s does not exist.' % self.fileOrFolder)
|
print(('%s does not exist.' % self.fileOrFolder))
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -85,8 +85,8 @@ class FtpFolder:
|
||||||
def clean(self, site):
|
def clean(self, site):
|
||||||
'''Cleans this folder'''
|
'''Cleans this folder'''
|
||||||
# First, clean subFolders if they exist
|
# First, clean subFolders if they exist
|
||||||
print('Cleaning %s %d subFolders' % \
|
print(('Cleaning %s %d subFolders' % \
|
||||||
(self.getFullName(), len(self.subFolders)))
|
(self.getFullName(), len(self.subFolders))))
|
||||||
for subFolder in self.subFolders:
|
for subFolder in self.subFolders:
|
||||||
subFolder.clean(site)
|
subFolder.clean(site)
|
||||||
# Remove the subFolder
|
# Remove the subFolder
|
||||||
|
@ -95,7 +95,7 @@ class FtpFolder:
|
||||||
for f in self.files:
|
for f in self.files:
|
||||||
fileName = '%s/%s' % (self.getFullName(), f)
|
fileName = '%s/%s' % (self.getFullName(), f)
|
||||||
site.delete(fileName)
|
site.delete(fileName)
|
||||||
print('%s removed.' % fileName)
|
print(('%s removed.' % fileName))
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
class AppySite:
|
class AppySite:
|
||||||
|
@ -148,11 +148,11 @@ class AppySite:
|
||||||
fileExt = os.path.splitext(fileName)[1]
|
fileExt = os.path.splitext(fileName)[1]
|
||||||
if fileExt in self.textExtensions:
|
if fileExt in self.textExtensions:
|
||||||
# Make a transfer in text mode
|
# Make a transfer in text mode
|
||||||
print('Transfer file %s (text mode)' % fileName)
|
print(('Transfer file %s (text mode)' % fileName))
|
||||||
self.site.storlines(cmd, localFile)
|
self.site.storlines(cmd, localFile)
|
||||||
else:
|
else:
|
||||||
# Make a transfer in binary mode
|
# Make a transfer in binary mode
|
||||||
print('Transfer file %s (binary mode)' % fileName)
|
print(('Transfer file %s (binary mode)' % fileName))
|
||||||
self.site.storbinary(cmd, localFile)
|
self.site.storbinary(cmd, localFile)
|
||||||
|
|
||||||
def publish(self):
|
def publish(self):
|
||||||
|
@ -257,7 +257,7 @@ class Publisher:
|
||||||
yesNo = '[Y/n]'
|
yesNo = '[Y/n]'
|
||||||
else:
|
else:
|
||||||
yesNo = '[y/N]'
|
yesNo = '[y/N]'
|
||||||
print(question + ' ' + yesNo + ' ')
|
print((question + ' ' + yesNo + ' '))
|
||||||
response = sys.stdin.readline().strip().lower()
|
response = sys.stdin.readline().strip().lower()
|
||||||
res = False
|
res = False
|
||||||
if response in ('y', 'yes'):
|
if response in ('y', 'yes'):
|
||||||
|
@ -274,7 +274,7 @@ class Publisher:
|
||||||
|
|
||||||
def executeCommand(self, cmd):
|
def executeCommand(self, cmd):
|
||||||
'''Executes the system command p_cmd.'''
|
'''Executes the system command p_cmd.'''
|
||||||
print('Executing %s...' % cmd)
|
print(('Executing %s...' % cmd))
|
||||||
os.system(cmd)
|
os.system(cmd)
|
||||||
|
|
||||||
distExcluded = ('appy/doc', 'appy/temp', 'appy/versions', 'appy/gen/test')
|
distExcluded = ('appy/doc', 'appy/temp', 'appy/versions', 'appy/gen/test')
|
||||||
|
@ -340,7 +340,7 @@ class Publisher:
|
||||||
newZipRelease, default='yes'):
|
newZipRelease, default='yes'):
|
||||||
print('Publication canceled.')
|
print('Publication canceled.')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
print('Removing obsolete %s...' % newZipRelease)
|
print(('Removing obsolete %s...' % newZipRelease))
|
||||||
os.remove(newZipRelease)
|
os.remove(newZipRelease)
|
||||||
zipFile = zipfile.ZipFile(newZipRelease, 'w', zipfile.ZIP_DEFLATED)
|
zipFile = zipfile.ZipFile(newZipRelease, 'w', zipfile.ZIP_DEFLATED)
|
||||||
curdir = os.getcwd()
|
curdir = os.getcwd()
|
||||||
|
@ -474,7 +474,7 @@ class Publisher:
|
||||||
if minimalist:
|
if minimalist:
|
||||||
FolderDeleter.delete('%s/pod/test' % genSrcFolder)
|
FolderDeleter.delete('%s/pod/test' % genSrcFolder)
|
||||||
# Write the appy version into the code itself (in appy/version.py)'''
|
# Write the appy version into the code itself (in appy/version.py)'''
|
||||||
print('Publishing version %s...' % self.versionShort)
|
print(('Publishing version %s...' % self.versionShort))
|
||||||
# Dump version info in appy/version.py
|
# Dump version info in appy/version.py
|
||||||
f = file('%s/version.py' % genSrcFolder, 'w')
|
f = file('%s/version.py' % genSrcFolder, 'w')
|
||||||
f.write('short = "%s"\n' % self.versionShort)
|
f.write('short = "%s"\n' % self.versionShort)
|
||||||
|
@ -495,7 +495,7 @@ class Publisher:
|
||||||
Cleaner().run(verbose=False)
|
Cleaner().run(verbose=False)
|
||||||
# Perform a small analysis on the Appy code
|
# Perform a small analysis on the Appy code
|
||||||
LinesCounter(appy).run()
|
LinesCounter(appy).run()
|
||||||
print('Generating site in %s...' % self.genFolder)
|
print(('Generating site in %s...' % self.genFolder))
|
||||||
minimalist = self.askQuestion('Minimalist (shipped without tests)?',
|
minimalist = self.askQuestion('Minimalist (shipped without tests)?',
|
||||||
default='no')
|
default='no')
|
||||||
self.prepareGenFolder(minimalist)
|
self.prepareGenFolder(minimalist)
|
||||||
|
|
|
@ -21,10 +21,10 @@ class ZodbRestorer:
|
||||||
datePart = '-D %s' % self.restoreDate
|
datePart = '-D %s' % self.restoreDate
|
||||||
repozoCmd = '%s %s -Rv -r %s %s -o %s' % (self.python,
|
repozoCmd = '%s %s -Rv -r %s %s -o %s' % (self.python,
|
||||||
self.repozo, self.backupFolder, datePart, self.storageLocation)
|
self.repozo, self.backupFolder, datePart, self.storageLocation)
|
||||||
print('Executing %s...' % repozoCmd)
|
print(('Executing %s...' % repozoCmd))
|
||||||
os.system(repozoCmd)
|
os.system(repozoCmd)
|
||||||
stopTime = time.time()
|
stopTime = time.time()
|
||||||
print('Done in %d minute(s).' % ((stopTime-startTime)/60))
|
print(('Done in %d minute(s).' % ((stopTime-startTime)/60)))
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
class ZodbRestoreScript:
|
class ZodbRestoreScript:
|
||||||
|
@ -56,7 +56,7 @@ class ZodbRestoreScript:
|
||||||
f.write('Hello.')
|
f.write('Hello.')
|
||||||
f.close()
|
f.close()
|
||||||
os.remove(args[0])
|
os.remove(args[0])
|
||||||
except OSError, oe:
|
except OSError as oe:
|
||||||
raise RestoreError('I do not have the right to write file ' \
|
raise RestoreError('I do not have the right to write file ' \
|
||||||
'"%s".' % args[0])
|
'"%s".' % args[0])
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ class ZodbRestoreScript:
|
||||||
self.checkArgs(options, args)
|
self.checkArgs(options, args)
|
||||||
backuper = ZodbRestorer(args[0], args[1], options)
|
backuper = ZodbRestorer(args[0], args[1], options)
|
||||||
backuper.run()
|
backuper.run()
|
||||||
except RestoreError, be:
|
except RestoreError as be:
|
||||||
sys.stderr.write(str(be))
|
sys.stderr.write(str(be))
|
||||||
sys.stderr.write('\n')
|
sys.stderr.write('\n')
|
||||||
optParser.print_help()
|
optParser.print_help()
|
||||||
|
|
12
bin/zip.py
12
bin/zip.py
|
@ -8,29 +8,29 @@ class Zipper:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.zipFileName = '%s/Desktop/appy.zip' % os.environ['HOME']
|
self.zipFileName = '%s/Desktop/appy.zip' % os.environ['HOME']
|
||||||
def createZipFile(self):
|
def createZipFile(self):
|
||||||
print('Creating %s...' % self.zipFileName)
|
print(('Creating %s...' % self.zipFileName))
|
||||||
zipFile = zipfile.ZipFile(self.zipFileName, 'w', zipfile.ZIP_DEFLATED)
|
zipFile = zipfile.ZipFile(self.zipFileName, 'w', zipfile.ZIP_DEFLATED)
|
||||||
for dir, dirnames, filenames in os.walk(appyPath):
|
for dir, dirnames, filenames in os.walk(appyPath):
|
||||||
for f in filenames:
|
for f in filenames:
|
||||||
fileName = os.path.join(dir, f)
|
fileName = os.path.join(dir, f)
|
||||||
arcName = fileName[fileName.find('appy/'):]
|
arcName = fileName[fileName.find('appy/'):]
|
||||||
print('Adding %s' % fileName)
|
print(('Adding %s' % fileName))
|
||||||
zipFile.write(fileName, arcName)
|
zipFile.write(fileName, arcName)
|
||||||
zipFile.close()
|
zipFile.close()
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
# Where to put the zip file ?
|
# Where to put the zip file ?
|
||||||
print("Where do you want to put appy.zip ? [Default is %s] " % \
|
print(("Where do you want to put appy.zip ? [Default is %s] " % \
|
||||||
os.path.dirname(self.zipFileName))
|
os.path.dirname(self.zipFileName)))
|
||||||
response = sys.stdin.readline().strip()
|
response = sys.stdin.readline().strip()
|
||||||
if response:
|
if response:
|
||||||
if os.path.exists(response) and os.path.isdir(response):
|
if os.path.exists(response) and os.path.isdir(response):
|
||||||
self.zipFileName = '%s/appy.zip' % response
|
self.zipFileName = '%s/appy.zip' % response
|
||||||
else:
|
else:
|
||||||
print('%s is not a folder.' % response)
|
print(('%s is not a folder.' % response))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
if os.path.exists(self.zipFileName):
|
if os.path.exists(self.zipFileName):
|
||||||
print('Removing existing %s...' % self.zipFileName)
|
print(('Removing existing %s...' % self.zipFileName))
|
||||||
os.remove(self.zipFileName)
|
os.remove(self.zipFileName)
|
||||||
Cleaner().run(verbose=False)
|
Cleaner().run(verbose=False)
|
||||||
self.createZipFile()
|
self.createZipFile()
|
||||||
|
|
|
@ -21,9 +21,9 @@ from appy.gen.layout import Table, defaultFieldLayouts
|
||||||
from appy.gen import utils as gutils
|
from appy.gen import utils as gutils
|
||||||
from appy.px import Px
|
from appy.px import Px
|
||||||
from appy.shared import utils as sutils
|
from appy.shared import utils as sutils
|
||||||
from group import Group
|
from .group import Group
|
||||||
from search import Search
|
from .page import Page
|
||||||
from page import Page
|
import collections
|
||||||
|
|
||||||
# In this file, names "list" and "dict" refer to sub-modules. To use Python
|
# In this file, names "list" and "dict" refer to sub-modules. To use Python
|
||||||
# builtin types, use __builtins__['list'] and __builtins__['dict']
|
# builtin types, use __builtins__['list'] and __builtins__['dict']
|
||||||
|
@ -370,7 +370,7 @@ class Field:
|
||||||
labelName = name
|
labelName = name
|
||||||
trPrefix = None
|
trPrefix = None
|
||||||
if self.label:
|
if self.label:
|
||||||
if isinstance(self.label, basestring): trPrefix = self.label
|
if isinstance(self.label, str): trPrefix = self.label
|
||||||
else: # It is a tuple (trPrefix, name)
|
else: # It is a tuple (trPrefix, name)
|
||||||
if self.label[1]: labelName = self.label[1]
|
if self.label[1]: labelName = self.label[1]
|
||||||
if self.label[0]: trPrefix = self.label[0]
|
if self.label[0]: trPrefix = self.label[0]
|
||||||
|
@ -382,16 +382,16 @@ class Field:
|
||||||
self.helpId = self.labelId + '_help'
|
self.helpId = self.labelId + '_help'
|
||||||
# Determine read and write permissions for this field
|
# Determine read and write permissions for this field
|
||||||
rp = self.specificReadPermission
|
rp = self.specificReadPermission
|
||||||
if rp and not isinstance(rp, basestring):
|
if rp and not isinstance(rp, str):
|
||||||
self.readPermission = '%s: Read %s %s' % (appName, prefix, name)
|
self.readPermission = '%s: Read %s %s' % (appName, prefix, name)
|
||||||
elif rp and isinstance(rp, basestring):
|
elif rp and isinstance(rp, str):
|
||||||
self.readPermission = rp
|
self.readPermission = rp
|
||||||
else:
|
else:
|
||||||
self.readPermission = 'read'
|
self.readPermission = 'read'
|
||||||
wp = self.specificWritePermission
|
wp = self.specificWritePermission
|
||||||
if wp and not isinstance(wp, basestring):
|
if wp and not isinstance(wp, str):
|
||||||
self.writePermission = '%s: Write %s %s' % (appName, prefix, name)
|
self.writePermission = '%s: Write %s %s' % (appName, prefix, name)
|
||||||
elif wp and isinstance(wp, basestring):
|
elif wp and isinstance(wp, str):
|
||||||
self.writePermission = wp
|
self.writePermission = wp
|
||||||
else:
|
else:
|
||||||
self.writePermission = 'write'
|
self.writePermission = 'write'
|
||||||
|
@ -442,7 +442,7 @@ class Field:
|
||||||
self.readPermission
|
self.readPermission
|
||||||
if not obj.allows(perm): return
|
if not obj.allows(perm): return
|
||||||
# Evaluate self.show
|
# Evaluate self.show
|
||||||
if callable(self.show):
|
if isinstance(self.show, collections.Callable):
|
||||||
res = self.callMethod(obj, self.show)
|
res = self.callMethod(obj, self.show)
|
||||||
else:
|
else:
|
||||||
res = self.show
|
res = self.show
|
||||||
|
@ -480,7 +480,7 @@ class Field:
|
||||||
if not masterData: return True
|
if not masterData: return True
|
||||||
else:
|
else:
|
||||||
master, masterValue = masterData
|
master, masterValue = masterData
|
||||||
if masterValue and callable(masterValue): return True
|
if masterValue and isinstance(masterValue, collections.Callable): return True
|
||||||
reqValue = master.getRequestValue(obj)
|
reqValue = master.getRequestValue(obj)
|
||||||
# reqValue can be a list or not
|
# reqValue can be a list or not
|
||||||
if type(reqValue) not in sutils.sequenceTypes:
|
if type(reqValue) not in sutils.sequenceTypes:
|
||||||
|
@ -496,8 +496,8 @@ class Field:
|
||||||
if isinstance(mapping, __builtins__['dict']):
|
if isinstance(mapping, __builtins__['dict']):
|
||||||
# Is it a dict like {'label':..., 'descr':...}, or is it directly a
|
# Is it a dict like {'label':..., 'descr':...}, or is it directly a
|
||||||
# dict with a mapping?
|
# dict with a mapping?
|
||||||
for k, v in mapping.iteritems():
|
for k, v in mapping.items():
|
||||||
if (k not in self.labelTypes) or isinstance(v, basestring):
|
if (k not in self.labelTypes) or isinstance(v, str):
|
||||||
# It is already a mapping
|
# It is already a mapping
|
||||||
return {'label':mapping, 'descr':mapping, 'help':mapping}
|
return {'label':mapping, 'descr':mapping, 'help':mapping}
|
||||||
# If we are here, we have {'label':..., 'descr':...}. Complete
|
# If we are here, we have {'label':..., 'descr':...}. Complete
|
||||||
|
@ -520,7 +520,7 @@ class Field:
|
||||||
areDefault = True
|
areDefault = True
|
||||||
layouts = self.computeDefaultLayouts()
|
layouts = self.computeDefaultLayouts()
|
||||||
else:
|
else:
|
||||||
if isinstance(layouts, basestring):
|
if isinstance(layouts, str):
|
||||||
# The user specified a single layoutString (the "edit" one)
|
# The user specified a single layoutString (the "edit" one)
|
||||||
layouts = {'edit': layouts}
|
layouts = {'edit': layouts}
|
||||||
elif isinstance(layouts, Table):
|
elif isinstance(layouts, Table):
|
||||||
|
@ -541,8 +541,8 @@ class Field:
|
||||||
# We have now a dict of layouts in p_layouts. Ensure now that a Table
|
# We have now a dict of layouts in p_layouts. Ensure now that a Table
|
||||||
# instance is created for every layout (=value from the dict). Indeed,
|
# instance is created for every layout (=value from the dict). Indeed,
|
||||||
# a layout could have been expressed as a simple layout string.
|
# a layout could have been expressed as a simple layout string.
|
||||||
for layoutType in layouts.iterkeys():
|
for layoutType in layouts.keys():
|
||||||
if isinstance(layouts[layoutType], basestring):
|
if isinstance(layouts[layoutType], str):
|
||||||
layouts[layoutType] = Table(layouts[layoutType])
|
layouts[layoutType] = Table(layouts[layoutType])
|
||||||
# Derive "view", "search" and "cell" layouts from the "edit" layout
|
# Derive "view", "search" and "cell" layouts from the "edit" layout
|
||||||
# when relevant.
|
# when relevant.
|
||||||
|
@ -566,11 +566,11 @@ class Field:
|
||||||
if areDefault and not self.group and \
|
if areDefault and not self.group and \
|
||||||
not ((self.type == 'String') and (self.format == self.XHTML)) and \
|
not ((self.type == 'String') and (self.format == self.XHTML)) and \
|
||||||
not (self.type == 'Ref'):
|
not (self.type == 'Ref'):
|
||||||
for layoutType in layouts.iterkeys():
|
for layoutType in layouts.keys():
|
||||||
layouts[layoutType].width = ''
|
layouts[layoutType].width = ''
|
||||||
# Remove letters "r" from the layouts if the field is not required.
|
# Remove letters "r" from the layouts if the field is not required.
|
||||||
if not self.required:
|
if not self.required:
|
||||||
for layoutType in layouts.iterkeys():
|
for layoutType in layouts.keys():
|
||||||
layouts[layoutType].removeElement('r')
|
layouts[layoutType].removeElement('r')
|
||||||
# Derive some boolean values from the layouts.
|
# Derive some boolean values from the layouts.
|
||||||
self.hasLabel = self.hasLayoutElement('l', layouts)
|
self.hasLabel = self.hasLayoutElement('l', layouts)
|
||||||
|
@ -597,7 +597,7 @@ class Field:
|
||||||
def hasLayoutElement(self, element, layouts):
|
def hasLayoutElement(self, element, layouts):
|
||||||
'''This method returns True if the given layout p_element can be found
|
'''This method returns True if the given layout p_element can be found
|
||||||
at least once among the various p_layouts defined for this field.'''
|
at least once among the various p_layouts defined for this field.'''
|
||||||
for layout in layouts.itervalues():
|
for layout in layouts.values():
|
||||||
if element in layout.layoutString: return True
|
if element in layout.layoutString: return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -610,7 +610,7 @@ class Field:
|
||||||
'''Gets, as a string, the layouts as could have been specified as input
|
'''Gets, as a string, the layouts as could have been specified as input
|
||||||
value for the Field constructor.'''
|
value for the Field constructor.'''
|
||||||
res = '{'
|
res = '{'
|
||||||
for k, v in self.layouts.iteritems():
|
for k, v in self.layouts.items():
|
||||||
res += '"%s":"%s",' % (k, v.layoutString)
|
res += '"%s":"%s",' % (k, v.layoutString)
|
||||||
res += '}'
|
res += '}'
|
||||||
return res
|
return res
|
||||||
|
@ -650,7 +650,7 @@ class Field:
|
||||||
if self.isEmptyValue(obj, value):
|
if self.isEmptyValue(obj, value):
|
||||||
# If there is no value, get the default value if any: return
|
# If there is no value, get the default value if any: return
|
||||||
# self.default, of self.default() if it is a method.
|
# self.default, of self.default() if it is a method.
|
||||||
if callable(self.default):
|
if isinstance(self.default, collections.Callable):
|
||||||
try:
|
try:
|
||||||
# Caching a default value can lead to problems. For example,
|
# Caching a default value can lead to problems. For example,
|
||||||
# the process of creating an object from another one, or
|
# the process of creating an object from another one, or
|
||||||
|
@ -660,7 +660,7 @@ class Field:
|
||||||
# but it they depend on values set at (b), and are cached
|
# but it they depend on values set at (b), and are cached
|
||||||
# and indexed, (c) will get the wrong, cached value.
|
# and indexed, (c) will get the wrong, cached value.
|
||||||
return self.callMethod(obj, self.default, cache=False)
|
return self.callMethod(obj, self.default, cache=False)
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
# Already logged. Here I do not raise the exception,
|
# Already logged. Here I do not raise the exception,
|
||||||
# because it can be raised as the result of reindexing
|
# because it can be raised as the result of reindexing
|
||||||
# the object in situations that are not foreseen by
|
# the object in situations that are not foreseen by
|
||||||
|
@ -723,12 +723,13 @@ class Field:
|
||||||
# Start by getting the field value on p_obj
|
# Start by getting the field value on p_obj
|
||||||
res = self.getValue(obj)
|
res = self.getValue(obj)
|
||||||
# Zope catalog does not like unicode strings
|
# Zope catalog does not like unicode strings
|
||||||
if isinstance(res, unicode): res = res.encode('utf-8')
|
if isinstance(value, str):
|
||||||
|
res = value.encode('utf-8')
|
||||||
if forSearch and (res != None):
|
if forSearch and (res != None):
|
||||||
if type(res) in sutils.sequenceTypes:
|
if type(res) in sutils.sequenceTypes:
|
||||||
vals = []
|
vals = []
|
||||||
for v in res:
|
for v in res:
|
||||||
if isinstance(v, unicode): vals.append(v.encode('utf-8'))
|
if isinstance(v, str): vals.append(v.encode('utf-8'))
|
||||||
else: vals.append(str(v))
|
else: vals.append(str(v))
|
||||||
res = ' '.join(vals)
|
res = ' '.join(vals)
|
||||||
else:
|
else:
|
||||||
|
@ -824,7 +825,7 @@ class Field:
|
||||||
this field is the slave of another field.'''
|
this field is the slave of another field.'''
|
||||||
if not self.master: return ''
|
if not self.master: return ''
|
||||||
res = 'slave*%s*' % self.masterName
|
res = 'slave*%s*' % self.masterName
|
||||||
if not callable(self.masterValue):
|
if not isinstance(self.masterValue, collections.Callable):
|
||||||
res += '*'.join(self.masterValue)
|
res += '*'.join(self.masterValue)
|
||||||
else:
|
else:
|
||||||
res += '+'
|
res += '+'
|
||||||
|
@ -866,7 +867,7 @@ class Field:
|
||||||
def securityCheck(self, obj, value):
|
def securityCheck(self, obj, value):
|
||||||
'''This method performs some security checks on the p_value that
|
'''This method performs some security checks on the p_value that
|
||||||
represents user input.'''
|
represents user input.'''
|
||||||
if not isinstance(value, basestring): return
|
if not isinstance(value, str): return
|
||||||
# Search Javascript code in the value (prevent XSS attacks).
|
# Search Javascript code in the value (prevent XSS attacks).
|
||||||
if '<script' in value:
|
if '<script' in value:
|
||||||
obj.log('Detected Javascript in user input.', type='error')
|
obj.log('Detected Javascript in user input.', type='error')
|
||||||
|
@ -900,14 +901,14 @@ class Field:
|
||||||
# It is a custom function: execute it
|
# It is a custom function: execute it
|
||||||
try:
|
try:
|
||||||
validValue = self.validator(obj, value)
|
validValue = self.validator(obj, value)
|
||||||
if isinstance(validValue, basestring) and validValue:
|
if isinstance(validValue, str) and validValue:
|
||||||
# Validation failed; and p_validValue contains an error
|
# Validation failed; and p_validValue contains an error
|
||||||
# message.
|
# message.
|
||||||
return validValue
|
return validValue
|
||||||
else:
|
else:
|
||||||
if not validValue:
|
if not validValue:
|
||||||
return obj.translate('field_invalid')
|
return obj.translate('field_invalid')
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
return str(e)
|
return str(e)
|
||||||
except:
|
except:
|
||||||
return obj.translate('field_invalid')
|
return obj.translate('field_invalid')
|
||||||
|
@ -931,7 +932,7 @@ class Field:
|
||||||
obj = obj.appy()
|
obj = obj.appy()
|
||||||
try:
|
try:
|
||||||
return gutils.callMethod(obj, method, cache=cache)
|
return gutils.callMethod(obj, method, cache=cache)
|
||||||
except TypeError, te:
|
except TypeError as te:
|
||||||
# Try a version of the method that would accept self as an
|
# Try a version of the method that would accept self as an
|
||||||
# additional parameter. In this case, we do not try to cache the
|
# additional parameter. In this case, we do not try to cache the
|
||||||
# value (we do not call gutils.callMethod), because the value may
|
# value (we do not call gutils.callMethod), because the value may
|
||||||
|
@ -939,11 +940,11 @@ class Field:
|
||||||
tb = sutils.Traceback.get()
|
tb = sutils.Traceback.get()
|
||||||
try:
|
try:
|
||||||
return method(obj, self)
|
return method(obj, self)
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
obj.log(tb, type='error')
|
obj.log(tb, type='error')
|
||||||
# Raise the initial error.
|
# Raise the initial error.
|
||||||
raise te
|
raise te
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
obj.log(sutils.Traceback.get(), type='error')
|
obj.log(sutils.Traceback.get(), type='error')
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
|
@ -951,7 +952,7 @@ class Field:
|
||||||
'''Gets the value of attribue p_name on p_self, which can be a simple
|
'''Gets the value of attribue p_name on p_self, which can be a simple
|
||||||
value or the result of a method call on p_obj.'''
|
value or the result of a method call on p_obj.'''
|
||||||
res = getattr(self, name)
|
res = getattr(self, name)
|
||||||
if not callable(res): return res
|
if not isinstance(res, collections.Callable): return res
|
||||||
return self.callMethod(obj, res)
|
return self.callMethod(obj, res)
|
||||||
|
|
||||||
def process(self, obj):
|
def process(self, obj):
|
||||||
|
|
|
@ -123,7 +123,7 @@ class Boolean(Field):
|
||||||
|
|
||||||
def getStorableValue(self, obj, value):
|
def getStorableValue(self, obj, value):
|
||||||
if not self.isEmptyValue(obj, value):
|
if not self.isEmptyValue(obj, value):
|
||||||
exec 'res = %s' % value
|
exec('res = %s' % value)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def isTrue(self, obj, dbValue):
|
def isTrue(self, obj, dbValue):
|
||||||
|
@ -131,7 +131,7 @@ class Boolean(Field):
|
||||||
not?'''
|
not?'''
|
||||||
rq = obj.REQUEST
|
rq = obj.REQUEST
|
||||||
# Get the value we must compare (from request or from database)
|
# Get the value we must compare (from request or from database)
|
||||||
if rq.has_key(self.name):
|
if self.name in rq:
|
||||||
return rq.get(self.name) in ('True', 1, '1')
|
return rq.get(self.name) in ('True', 1, '1')
|
||||||
return dbValue
|
return dbValue
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -1263,20 +1263,20 @@ class Calendar(Field):
|
||||||
maxDay = (maxYear, maxDate.month(), maxDate.day())
|
maxDay = (maxYear, maxDate.month(), maxDate.day())
|
||||||
# Browse years
|
# Browse years
|
||||||
years = getattr(obj, self.name)
|
years = getattr(obj, self.name)
|
||||||
for year in years.keys():
|
for year in list(years.keys()):
|
||||||
# Don't take this year into account if outside interval
|
# Don't take this year into account if outside interval
|
||||||
if minDate and (year < minYear): continue
|
if minDate and (year < minYear): continue
|
||||||
if maxDate and (year > maxYear): continue
|
if maxDate and (year > maxYear): continue
|
||||||
months = years[year]
|
months = years[year]
|
||||||
# Browse this year's months
|
# Browse this year's months
|
||||||
for month in months.keys():
|
for month in list(months.keys()):
|
||||||
# Don't take this month into account if outside interval
|
# Don't take this month into account if outside interval
|
||||||
thisMonth = (year, month)
|
thisMonth = (year, month)
|
||||||
if minDate and (thisMonth < minMonth): continue
|
if minDate and (thisMonth < minMonth): continue
|
||||||
if maxDate and (thisMonth > maxMonth): continue
|
if maxDate and (thisMonth > maxMonth): continue
|
||||||
days = months[month]
|
days = months[month]
|
||||||
# Browse this month's days
|
# Browse this month's days
|
||||||
for day in days.keys():
|
for day in list(days.keys()):
|
||||||
# Don't take this day into account if outside interval
|
# Don't take this day into account if outside interval
|
||||||
thisDay = (year, month, day)
|
thisDay = (year, month, day)
|
||||||
if minDate and (thisDay < minDay): continue
|
if minDate and (thisDay < minDay): continue
|
||||||
|
|
|
@ -47,7 +47,7 @@ class Computed(Field):
|
||||||
# the user interface while m_method computes the value stored in the
|
# the user interface while m_method computes the value stored in the
|
||||||
# catalog.
|
# catalog.
|
||||||
self.formatMethod = formatMethod
|
self.formatMethod = formatMethod
|
||||||
if isinstance(self.method, basestring):
|
if isinstance(self.method, str):
|
||||||
# A legacy macro identifier. Raise an exception
|
# A legacy macro identifier. Raise an exception
|
||||||
raise Exception(self.WRONG_METHOD % self.method)
|
raise Exception(self.WRONG_METHOD % self.method)
|
||||||
# Does field computation produce plain text or XHTML?
|
# Does field computation produce plain text or XHTML?
|
||||||
|
@ -99,6 +99,6 @@ class Computed(Field):
|
||||||
res = self.formatMethod(obj, value)
|
res = self.formatMethod(obj, value)
|
||||||
else:
|
else:
|
||||||
res = value
|
res = value
|
||||||
if not isinstance(res, basestring): res = str(res)
|
if not isinstance(res, str): res = str(res)
|
||||||
return res
|
return res
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -219,7 +219,7 @@ class Date(Field):
|
||||||
|
|
||||||
def getSelectableYears(self):
|
def getSelectableYears(self):
|
||||||
'''Gets the list of years one may select for this field.'''
|
'''Gets the list of years one may select for this field.'''
|
||||||
res = range(self.startYear, self.endYear + 1)
|
res = list(range(self.startYear, self.endYear + 1))
|
||||||
if self.reverseYears: res.reverse()
|
if self.reverseYears: res.reverse()
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
@ -227,7 +227,7 @@ class Date(Field):
|
||||||
DateTime = obj.getProductConfig().DateTime
|
DateTime = obj.getProductConfig().DateTime
|
||||||
try:
|
try:
|
||||||
value = DateTime(value)
|
value = DateTime(value)
|
||||||
except DateTime.DateError, ValueError:
|
except DateTime.DateError as ValueError:
|
||||||
return obj.translate('bad_date')
|
return obj.translate('bad_date')
|
||||||
|
|
||||||
def getFormattedValue(self, obj, value, layoutType='view',
|
def getFormattedValue(self, obj, value, layoutType='view',
|
||||||
|
@ -278,7 +278,7 @@ class Date(Field):
|
||||||
# Get the value we must compare (from request or from database)
|
# Get the value we must compare (from request or from database)
|
||||||
rq = obj.REQUEST
|
rq = obj.REQUEST
|
||||||
partName = '%s_%s' % (self.name, fieldPart)
|
partName = '%s_%s' % (self.name, fieldPart)
|
||||||
if rq.has_key(partName):
|
if partName in rq:
|
||||||
compValue = rq.get(partName)
|
compValue = rq.get(partName)
|
||||||
if compValue.isdigit():
|
if compValue.isdigit():
|
||||||
compValue = int(compValue)
|
compValue = int(compValue)
|
||||||
|
|
|
@ -108,7 +108,7 @@ class FileInfo:
|
||||||
'''Removes the file from the filesystem.'''
|
'''Removes the file from the filesystem.'''
|
||||||
try:
|
try:
|
||||||
os.remove(osPathJoin(dbFolder, self.fsPath, self.fsName))
|
os.remove(osPathJoin(dbFolder, self.fsPath, self.fsName))
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
# If the current ZODB transaction is re-triggered, the file may
|
# If the current ZODB transaction is re-triggered, the file may
|
||||||
# already have been deleted.
|
# already have been deleted.
|
||||||
pass
|
pass
|
||||||
|
@ -207,10 +207,10 @@ class FileInfo:
|
||||||
if fileObj.data.__class__.__name__ == 'Pdata':
|
if fileObj.data.__class__.__name__ == 'Pdata':
|
||||||
# The file content is splitted in several chunks
|
# The file content is splitted in several chunks
|
||||||
f.write(fileObj.data.data)
|
f.write(fileObj.data.data)
|
||||||
nextPart = fileObj.data.next
|
nextPart = fileObj.data.__next__
|
||||||
while nextPart:
|
while nextPart:
|
||||||
f.write(nextPart.data)
|
f.write(nextPart.data)
|
||||||
nextPart = nextPart.next
|
nextPart = nextPart.__next__
|
||||||
else:
|
else:
|
||||||
# Only one chunk
|
# Only one chunk
|
||||||
f.write(fileObj.data)
|
f.write(fileObj.data)
|
||||||
|
@ -393,7 +393,7 @@ class File(Field):
|
||||||
def validateValue(self, obj, value):
|
def validateValue(self, obj, value):
|
||||||
form = obj.REQUEST.form
|
form = obj.REQUEST.form
|
||||||
action = '%s_delete' % self.name
|
action = '%s_delete' % self.name
|
||||||
if (not value or not value.filename) and form.has_key(action) and \
|
if (not value or not value.filename) and action in form and \
|
||||||
not form[action]:
|
not form[action]:
|
||||||
# If this key is present but empty, it means that the user selected
|
# If this key is present but empty, it means that the user selected
|
||||||
# "replace the file with a new one". So in this case he must provide
|
# "replace the file with a new one". So in this case he must provide
|
||||||
|
@ -450,7 +450,7 @@ class File(Field):
|
||||||
# Case c
|
# Case c
|
||||||
fileInfo = (value.name, value.content, value.mimeType)
|
fileInfo = (value.name, value.content, value.mimeType)
|
||||||
info.writeFile(self.name, fileInfo, dbFolder)
|
info.writeFile(self.name, fileInfo, dbFolder)
|
||||||
elif isinstance(value, basestring):
|
elif isinstance(value, str):
|
||||||
# Case d
|
# Case d
|
||||||
info.copyFile(self.name, value, dbFolder)
|
info.copyFile(self.name, value, dbFolder)
|
||||||
elif isinstance(value, FileInfo):
|
elif isinstance(value, FileInfo):
|
||||||
|
|
|
@ -40,7 +40,7 @@ class Group:
|
||||||
# which will be used for HTML param "width".
|
# which will be used for HTML param "width".
|
||||||
if wide == True:
|
if wide == True:
|
||||||
self.wide = '100%'
|
self.wide = '100%'
|
||||||
elif isinstance(wide, basestring):
|
elif isinstance(wide, str):
|
||||||
self.wide = wide
|
self.wide = wide
|
||||||
else:
|
else:
|
||||||
self.wide = ''
|
self.wide = ''
|
||||||
|
@ -106,7 +106,7 @@ class Group:
|
||||||
can be a string or a Group instance; this method returns always a
|
can be a string or a Group instance; this method returns always a
|
||||||
Group instance.'''
|
Group instance.'''
|
||||||
res = groupData
|
res = groupData
|
||||||
if res and isinstance(res, basestring):
|
if res and isinstance(res, str):
|
||||||
# Group data is given as a string. 2 more possibilities:
|
# Group data is given as a string. 2 more possibilities:
|
||||||
# (a) groupData is simply the name of the group;
|
# (a) groupData is simply the name of the group;
|
||||||
# (b) groupData is of the form <groupName>_<numberOfColumns>.
|
# (b) groupData is of the form <groupName>_<numberOfColumns>.
|
||||||
|
@ -336,7 +336,7 @@ class UiGroup:
|
||||||
# All p_group attributes become self attributes. This is required
|
# All p_group attributes become self attributes. This is required
|
||||||
# because a UiGroup, in some PXs, must behave like a Field (ie, have
|
# because a UiGroup, in some PXs, must behave like a Field (ie, have
|
||||||
# the same attributes, like "master".
|
# the same attributes, like "master".
|
||||||
for name, value in group.__dict__.iteritems():
|
for name, value in group.__dict__.items():
|
||||||
if not name.startswith('_'):
|
if not name.startswith('_'):
|
||||||
setattr(self, name, value)
|
setattr(self, name, value)
|
||||||
self.group = group
|
self.group = group
|
||||||
|
@ -346,7 +346,7 @@ class UiGroup:
|
||||||
labelName = self.name
|
labelName = self.name
|
||||||
prefix = className
|
prefix = className
|
||||||
if group.label:
|
if group.label:
|
||||||
if isinstance(group.label, basestring): prefix = group.label
|
if isinstance(group.label, str): prefix = group.label
|
||||||
else: # It is a tuple (className, name)
|
else: # It is a tuple (className, name)
|
||||||
if group.label[1]: labelName = group.label[1]
|
if group.label[1]: labelName = group.label[1]
|
||||||
if group.label[0]: prefix = group.label[0]
|
if group.label[0]: prefix = group.label[0]
|
||||||
|
|
|
@ -60,7 +60,7 @@ class Integer(Field):
|
||||||
height, maxChars, colspan, master, masterValue, focus,
|
height, maxChars, colspan, master, masterValue, focus,
|
||||||
historized, mapping, label, sdefault, scolspan, swidth,
|
historized, mapping, label, sdefault, scolspan, swidth,
|
||||||
sheight, persist, view, xml)
|
sheight, persist, view, xml)
|
||||||
self.pythonType = long
|
self.pythonType = int
|
||||||
|
|
||||||
def validateValue(self, obj, value):
|
def validateValue(self, obj, value):
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -132,7 +132,7 @@ class List(Field):
|
||||||
name = requestName or self.name # A List may be into another List (?)
|
name = requestName or self.name # A List may be into another List (?)
|
||||||
prefix = name + '*' + self.fields[0][0] + '*'
|
prefix = name + '*' + self.fields[0][0] + '*'
|
||||||
res = {}
|
res = {}
|
||||||
for key in request.keys():
|
for key in list(request.keys()):
|
||||||
if not key.startswith(prefix): continue
|
if not key.startswith(prefix): continue
|
||||||
# I have found a row. Gets its index.
|
# I have found a row. Gets its index.
|
||||||
row = Object()
|
row = Object()
|
||||||
|
@ -145,7 +145,7 @@ class List(Field):
|
||||||
setattr(row, subName, v)
|
setattr(row, subName, v)
|
||||||
res[rowIndex] = row
|
res[rowIndex] = row
|
||||||
# Produce a sorted list
|
# Produce a sorted list
|
||||||
keys = res.keys()
|
keys = list(res.keys())
|
||||||
keys.sort()
|
keys.sort()
|
||||||
res = [res[key] for key in keys]
|
res = [res[key] for key in keys]
|
||||||
# I store in the request this computed value. This way, when individual
|
# I store in the request this computed value. This way, when individual
|
||||||
|
|
|
@ -83,13 +83,13 @@ class Ogone(Field):
|
||||||
# Create a new dict by removing p_keysToIgnore from p_values, and by
|
# Create a new dict by removing p_keysToIgnore from p_values, and by
|
||||||
# upperizing all keys.
|
# upperizing all keys.
|
||||||
shaRes = {}
|
shaRes = {}
|
||||||
for k, v in values.iteritems():
|
for k, v in values.items():
|
||||||
if k in keysToIgnore: continue
|
if k in keysToIgnore: continue
|
||||||
# Ogone: we must not include empty values.
|
# Ogone: we must not include empty values.
|
||||||
if (v == None) or (v == ''): continue
|
if (v == None) or (v == ''): continue
|
||||||
shaRes[k.upper()] = v
|
shaRes[k.upper()] = v
|
||||||
# Create a sorted list of keys
|
# Create a sorted list of keys
|
||||||
keys = shaRes.keys()
|
keys = list(shaRes.keys())
|
||||||
keys.sort()
|
keys.sort()
|
||||||
shaList = []
|
shaList = []
|
||||||
for k in keys:
|
for k in keys:
|
||||||
|
@ -127,7 +127,7 @@ class Ogone(Field):
|
||||||
# Ogone's response.
|
# Ogone's response.
|
||||||
res['paramplus'] = 'name=%s' % self.name
|
res['paramplus'] = 'name=%s' % self.name
|
||||||
# Ensure every value is a str
|
# Ensure every value is a str
|
||||||
for k in res.iterkeys():
|
for k in res.keys():
|
||||||
if not isinstance(res[k], str):
|
if not isinstance(res[k], str):
|
||||||
res[k] = str(res[k])
|
res[k] = str(res[k])
|
||||||
# Compute a SHA-1 key as required by Ogone and add it to the res
|
# Compute a SHA-1 key as required by Ogone and add it to the res
|
||||||
|
@ -154,7 +154,7 @@ class Ogone(Field):
|
||||||
'administrator has been contacted.')
|
'administrator has been contacted.')
|
||||||
# Create a nice object from the form.
|
# Create a nice object from the form.
|
||||||
response = Object()
|
response = Object()
|
||||||
for k, v in obj.REQUEST.form.iteritems():
|
for k, v in obj.REQUEST.form.items():
|
||||||
setattr(response, k, v)
|
setattr(response, k, v)
|
||||||
# Call the field method that handles the response received from Ogone.
|
# Call the field method that handles the response received from Ogone.
|
||||||
url = self.responseMethod(obj.appy(), response)
|
url = self.responseMethod(obj.appy(), response)
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
from appy import Object
|
from appy import Object
|
||||||
|
import collections
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
class Page:
|
class Page:
|
||||||
|
@ -53,7 +54,7 @@ class Page:
|
||||||
(c) a Page instance.
|
(c) a Page instance.
|
||||||
This method returns always a Page instance.'''
|
This method returns always a Page instance.'''
|
||||||
res = pageData
|
res = pageData
|
||||||
if res and isinstance(res, basestring):
|
if res and isinstance(res, str):
|
||||||
# Page data is given as a string.
|
# Page data is given as a string.
|
||||||
pageElems = pageData.rsplit('_', 1)
|
pageElems = pageData.rsplit('_', 1)
|
||||||
if len(pageElems) == 1: # We have case (a)
|
if len(pageElems) == 1: # We have case (a)
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
import time, os, os.path
|
import time, os, os.path
|
||||||
from file import FileInfo
|
from .file import FileInfo
|
||||||
from appy import Object
|
from appy import Object
|
||||||
from appy.fields import Field
|
from appy.fields import Field
|
||||||
from appy.px import Px
|
from appy.px import Px
|
||||||
|
@ -25,6 +25,7 @@ from appy.gen import utils as gutils
|
||||||
from appy.pod import PodError
|
from appy.pod import PodError
|
||||||
from appy.pod.renderer import Renderer
|
from appy.pod.renderer import Renderer
|
||||||
from appy.shared import utils as sutils
|
from appy.shared import utils as sutils
|
||||||
|
import collections
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
class Mailing:
|
class Mailing:
|
||||||
|
@ -170,7 +171,7 @@ class Pod(Field):
|
||||||
# of your app will be referred as "Test.odt" in self.template. If it is
|
# of your app will be referred as "Test.odt" in self.template. If it is
|
||||||
# stored within sub-folder "pod", it will be referred as "pod/Test.odt".
|
# stored within sub-folder "pod", it will be referred as "pod/Test.odt".
|
||||||
if not template: raise Exception(Pod.NO_TEMPLATE)
|
if not template: raise Exception(Pod.NO_TEMPLATE)
|
||||||
if isinstance(template, basestring):
|
if isinstance(template, str):
|
||||||
self.template = [template]
|
self.template = [template]
|
||||||
elif isinstance(template, tuple):
|
elif isinstance(template, tuple):
|
||||||
self.template = list(template)
|
self.template = list(template)
|
||||||
|
@ -396,7 +397,7 @@ class Pod(Field):
|
||||||
formats = self.showTemplate(obj, template)
|
formats = self.showTemplate(obj, template)
|
||||||
if not formats: continue
|
if not formats: continue
|
||||||
elif isinstance(formats, bool): formats = self.formats
|
elif isinstance(formats, bool): formats = self.formats
|
||||||
elif isinstance(formats, basestring): formats = (formats,)
|
elif isinstance(formats, str): formats = (formats,)
|
||||||
res.append(Object(template=template, formats=formats,
|
res.append(Object(template=template, formats=formats,
|
||||||
freezeFormats=self.getFreezeFormats(obj, template)))
|
freezeFormats=self.getFreezeFormats(obj, template)))
|
||||||
return res
|
return res
|
||||||
|
@ -525,7 +526,7 @@ class Pod(Field):
|
||||||
templatePath = self.getTemplatePath(diskFolder, template)
|
templatePath = self.getTemplatePath(diskFolder, template)
|
||||||
# Get or compute the specific POD context
|
# Get or compute the specific POD context
|
||||||
specificContext = None
|
specificContext = None
|
||||||
if callable(self.context):
|
if isinstance(self.context, collections.Callable):
|
||||||
specificContext = self.callMethod(obj, self.context)
|
specificContext = self.callMethod(obj, self.context)
|
||||||
else:
|
else:
|
||||||
specificContext = self.context
|
specificContext = self.context
|
||||||
|
@ -544,7 +545,7 @@ class Pod(Field):
|
||||||
# Retrieve query params
|
# Retrieve query params
|
||||||
cmd = ', '.join(Pod.queryParams)
|
cmd = ', '.join(Pod.queryParams)
|
||||||
cmd += " = queryData.split(';')"
|
cmd += " = queryData.split(';')"
|
||||||
exec cmd
|
exec(cmd)
|
||||||
# (re-)execute the query, but without any limit on the number of
|
# (re-)execute the query, but without any limit on the number of
|
||||||
# results; return Appy objects.
|
# results; return Appy objects.
|
||||||
objs = tool.o.executeQuery(obj.o.portal_type, searchName=search,
|
objs = tool.o.executeQuery(obj.o.portal_type, searchName=search,
|
||||||
|
@ -559,7 +560,7 @@ class Pod(Field):
|
||||||
# when generating frozen documents).
|
# when generating frozen documents).
|
||||||
if '_checked' not in podContext: podContext['_checked'] = Object()
|
if '_checked' not in podContext: podContext['_checked'] = Object()
|
||||||
# Define a potential global styles mapping
|
# Define a potential global styles mapping
|
||||||
if callable(self.stylesMapping):
|
if isinstance(self.stylesMapping, collections.Callable):
|
||||||
stylesMapping = self.callMethod(obj, self.stylesMapping)
|
stylesMapping = self.callMethod(obj, self.stylesMapping)
|
||||||
else:
|
else:
|
||||||
stylesMapping = self.stylesMapping
|
stylesMapping = self.stylesMapping
|
||||||
|
@ -575,7 +576,7 @@ class Pod(Field):
|
||||||
try:
|
try:
|
||||||
renderer = Renderer(**rendererParams)
|
renderer = Renderer(**rendererParams)
|
||||||
renderer.run()
|
renderer.run()
|
||||||
except PodError, pe:
|
except PodError as pe:
|
||||||
if not os.path.exists(result):
|
if not os.path.exists(result):
|
||||||
# In some (most?) cases, when OO returns an error, the result is
|
# In some (most?) cases, when OO returns an error, the result is
|
||||||
# nevertheless generated.
|
# nevertheless generated.
|
||||||
|
@ -643,7 +644,7 @@ class Pod(Field):
|
||||||
# Generate the document
|
# Generate the document
|
||||||
doc = self.getValue(obj, template=template, format=format,
|
doc = self.getValue(obj, template=template, format=format,
|
||||||
result=result)
|
result=result)
|
||||||
if isinstance(doc, basestring):
|
if isinstance(doc, str):
|
||||||
# An error occurred, the document was not generated.
|
# An error occurred, the document was not generated.
|
||||||
obj.log(self.FREEZE_ERROR % (format, self.name, doc),
|
obj.log(self.FREEZE_ERROR % (format, self.name, doc),
|
||||||
type='error')
|
type='error')
|
||||||
|
@ -658,7 +659,7 @@ class Pod(Field):
|
||||||
obj.log('freeze: overwriting %s...' % result)
|
obj.log('freeze: overwriting %s...' % result)
|
||||||
doc = self.getValue(obj, template=template, format='odt',
|
doc = self.getValue(obj, template=template, format='odt',
|
||||||
result=result)
|
result=result)
|
||||||
if isinstance(doc, basestring):
|
if isinstance(doc, str):
|
||||||
self.log(self.FREEZE_ERROR % ('odt', self.name, doc),
|
self.log(self.FREEZE_ERROR % ('odt', self.name, doc),
|
||||||
type='error')
|
type='error')
|
||||||
raise Exception(self.FREEZE_FATAL_ERROR)
|
raise Exception(self.FREEZE_FATAL_ERROR)
|
||||||
|
@ -762,7 +763,7 @@ class Pod(Field):
|
||||||
res = self.getValue(obj, template=template, format=format,
|
res = self.getValue(obj, template=template, format=format,
|
||||||
queryData=rq.get('queryData'),
|
queryData=rq.get('queryData'),
|
||||||
customContext=self.getCustomContext(obj, rq))
|
customContext=self.getCustomContext(obj, rq))
|
||||||
if isinstance(res, basestring):
|
if isinstance(res, str):
|
||||||
# An error has occurred, and p_res contains the error message
|
# An error has occurred, and p_res contains the error message
|
||||||
obj.say(res)
|
obj.say(res)
|
||||||
return tool.goto(rq.get('HTTP_REFERER'))
|
return tool.goto(rq.get('HTTP_REFERER'))
|
||||||
|
|
|
@ -23,6 +23,7 @@ from appy.px import Px
|
||||||
from appy.gen.layout import Table
|
from appy.gen.layout import Table
|
||||||
from appy.gen import utils as gutils
|
from appy.gen import utils as gutils
|
||||||
from appy.shared import utils as sutils
|
from appy.shared import utils as sutils
|
||||||
|
import collections
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
class Ref(Field):
|
class Ref(Field):
|
||||||
|
@ -826,7 +827,7 @@ class Ref(Field):
|
||||||
# If this field is an ajax-updatable slave, no need to compute
|
# If this field is an ajax-updatable slave, no need to compute
|
||||||
# possible values: it will be overridden by method self.masterValue
|
# possible values: it will be overridden by method self.masterValue
|
||||||
# by a subsequent ajax request (=the "if" statement above).
|
# by a subsequent ajax request (=the "if" statement above).
|
||||||
if self.masterValue and callable(self.masterValue):
|
if self.masterValue and isinstance(self.masterValue, collections.Callable):
|
||||||
objects = []
|
objects = []
|
||||||
else:
|
else:
|
||||||
if not self.select:
|
if not self.select:
|
||||||
|
@ -921,7 +922,7 @@ class Ref(Field):
|
||||||
res = self.getAttribute(obj, 'numbered')
|
res = self.getAttribute(obj, 'numbered')
|
||||||
if not res: return res
|
if not res: return res
|
||||||
# Returns the column width.
|
# Returns the column width.
|
||||||
if not isinstance(res, basestring): return '15px'
|
if not isinstance(res, str): return '15px'
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def getMenuUrl(self, zobj, tied):
|
def getMenuUrl(self, zobj, tied):
|
||||||
|
@ -996,14 +997,14 @@ class Ref(Field):
|
||||||
# Also ensure that multiplicities are enforced.
|
# Also ensure that multiplicities are enforced.
|
||||||
if not value:
|
if not value:
|
||||||
nbOfRefs = 0
|
nbOfRefs = 0
|
||||||
elif isinstance(value, basestring):
|
elif isinstance(value, str):
|
||||||
nbOfRefs = 1
|
nbOfRefs = 1
|
||||||
else:
|
else:
|
||||||
nbOfRefs = len(value)
|
nbOfRefs = len(value)
|
||||||
minRef = self.multiplicity[0]
|
minRef = self.multiplicity[0]
|
||||||
maxRef = self.multiplicity[1]
|
maxRef = self.multiplicity[1]
|
||||||
if maxRef == None:
|
if maxRef == None:
|
||||||
maxRef = sys.maxint
|
maxRef = sys.maxsize
|
||||||
if nbOfRefs < minRef:
|
if nbOfRefs < minRef:
|
||||||
return obj.translate('min_ref_violated')
|
return obj.translate('min_ref_violated')
|
||||||
elif nbOfRefs > maxRef:
|
elif nbOfRefs > maxRef:
|
||||||
|
@ -1119,7 +1120,7 @@ class Ref(Field):
|
||||||
if type(objects) not in sutils.sequenceTypes: objects = [objects]
|
if type(objects) not in sutils.sequenceTypes: objects = [objects]
|
||||||
tool = obj.getTool()
|
tool = obj.getTool()
|
||||||
for i in range(len(objects)):
|
for i in range(len(objects)):
|
||||||
if isinstance(objects[i], basestring):
|
if isinstance(objects[i], str):
|
||||||
# We have an UID here
|
# We have an UID here
|
||||||
objects[i] = tool.getObject(objects[i], appy=True)
|
objects[i] = tool.getObject(objects[i], appy=True)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -19,7 +19,7 @@ from appy.px import Px
|
||||||
from appy.gen import utils as gutils
|
from appy.gen import utils as gutils
|
||||||
from appy.gen.indexer import defaultIndexes
|
from appy.gen.indexer import defaultIndexes
|
||||||
from appy.shared import utils as sutils
|
from appy.shared import utils as sutils
|
||||||
from group import Group
|
from .group import Group
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
class Search:
|
class Search:
|
||||||
|
@ -85,12 +85,12 @@ class Search:
|
||||||
(fieldName == 'SearchableText'):
|
(fieldName == 'SearchableText'):
|
||||||
# For TextIndex indexes. We must split p_fieldValue into keywords.
|
# For TextIndex indexes. We must split p_fieldValue into keywords.
|
||||||
res = gutils.Keywords(fieldValue).get()
|
res = gutils.Keywords(fieldValue).get()
|
||||||
elif isinstance(fieldValue, basestring) and fieldValue.endswith('*'):
|
elif isinstance(fieldValue, str) and fieldValue.endswith('*'):
|
||||||
v = fieldValue[:-1]
|
v = fieldValue[:-1]
|
||||||
# Warning: 'z' is higher than 'Z'!
|
# Warning: 'z' is higher than 'Z'!
|
||||||
res = {'query':(v,v+'z'), 'range':'min:max'}
|
res = {'query':(v,v+'z'), 'range':'min:max'}
|
||||||
elif type(fieldValue) in sutils.sequenceTypes:
|
elif type(fieldValue) in sutils.sequenceTypes:
|
||||||
if fieldValue and isinstance(fieldValue[0], basestring):
|
if fieldValue and isinstance(fieldValue[0], str):
|
||||||
# We have a list of string values (ie: we need to
|
# We have a list of string values (ie: we need to
|
||||||
# search v1 or v2 or...)
|
# search v1 or v2 or...)
|
||||||
res = fieldValue
|
res = fieldValue
|
||||||
|
@ -118,7 +118,7 @@ class Search:
|
||||||
sortBy and sortOrder (and not "resolve" them to Zope's sort_on and
|
sortBy and sortOrder (and not "resolve" them to Zope's sort_on and
|
||||||
sort_order).'''
|
sort_order).'''
|
||||||
# Put search criteria in p_criteria
|
# Put search criteria in p_criteria
|
||||||
for name, value in self.fields.iteritems():
|
for name, value in self.fields.items():
|
||||||
# Management of searches restricted to objects linked through a
|
# Management of searches restricted to objects linked through a
|
||||||
# Ref field: not implemented yet.
|
# Ref field: not implemented yet.
|
||||||
if name == '_ref': continue
|
if name == '_ref': continue
|
||||||
|
|
|
@ -25,6 +25,7 @@ from appy.shared.data import countries
|
||||||
from appy.shared.xml_parser import XhtmlCleaner
|
from appy.shared.xml_parser import XhtmlCleaner
|
||||||
from appy.shared.diff import HtmlDiff
|
from appy.shared.diff import HtmlDiff
|
||||||
from appy.shared import utils as sutils
|
from appy.shared import utils as sutils
|
||||||
|
import collections
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
digit = re.compile('[0-9]')
|
digit = re.compile('[0-9]')
|
||||||
|
@ -471,7 +472,7 @@ class String(Field):
|
||||||
res = True
|
res = True
|
||||||
if type(self.validator) in (list, tuple):
|
if type(self.validator) in (list, tuple):
|
||||||
for elem in self.validator:
|
for elem in self.validator:
|
||||||
if not isinstance(elem, basestring):
|
if not isinstance(elem, str):
|
||||||
res = False
|
res = False
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
|
@ -533,7 +534,7 @@ class String(Field):
|
||||||
if not value:
|
if not value:
|
||||||
if self.isMultiValued(): return emptyTuple
|
if self.isMultiValued(): return emptyTuple
|
||||||
else: return value
|
else: return value
|
||||||
if isinstance(value, basestring) and self.isMultiValued():
|
if isinstance(value, str) and self.isMultiValued():
|
||||||
value = [value]
|
value = [value]
|
||||||
elif isinstance(value, tuple):
|
elif isinstance(value, tuple):
|
||||||
value = list(value)
|
value = list(value)
|
||||||
|
@ -602,8 +603,7 @@ class String(Field):
|
||||||
identifies the language-specific part we will work on.'''
|
identifies the language-specific part we will work on.'''
|
||||||
res = None
|
res = None
|
||||||
lastEvent = None
|
lastEvent = None
|
||||||
name = language and ('%s-%s' % (self.name, language)) or self.name
|
for event in obj.workflow_history.values()[0]:
|
||||||
for event in obj.workflow_history['appy']:
|
|
||||||
if event['action'] != '_datachange_': continue
|
if event['action'] != '_datachange_': continue
|
||||||
if name not in event['changes']: continue
|
if name not in event['changes']: continue
|
||||||
if res == None:
|
if res == None:
|
||||||
|
@ -660,7 +660,7 @@ class String(Field):
|
||||||
res = obj.formatText(res, format='html')
|
res = obj.formatText(res, format='html')
|
||||||
# If value starts with a carriage return, add a space; else, it will
|
# If value starts with a carriage return, add a space; else, it will
|
||||||
# be ignored.
|
# be ignored.
|
||||||
if isinstance(res, basestring) and \
|
if isinstance(res, str) and \
|
||||||
(res.startswith('\n') or res.startswith('\r\n')): res = ' ' + res
|
(res.startswith('\n') or res.startswith('\r\n')): res = ' ' + res
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
@ -774,7 +774,7 @@ class String(Field):
|
||||||
# If this field is an ajax-updatable slave, no need to compute
|
# If this field is an ajax-updatable slave, no need to compute
|
||||||
# possible values: it will be overridden by method self.masterValue
|
# possible values: it will be overridden by method self.masterValue
|
||||||
# by a subsequent ajax request (=the "if" statement above).
|
# by a subsequent ajax request (=the "if" statement above).
|
||||||
if self.masterValue and callable(self.masterValue) and \
|
if self.masterValue and isinstance(self.masterValue, collections.Callable) and \
|
||||||
not ignoreMasterValues: return []
|
not ignoreMasterValues: return []
|
||||||
if isinstance(self.validator, Selection):
|
if isinstance(self.validator, Selection):
|
||||||
# We need to call self.methodName for getting the (dynamic)
|
# We need to call self.methodName for getting the (dynamic)
|
||||||
|
@ -808,9 +808,9 @@ class String(Field):
|
||||||
obj = brains[0].getObject()
|
obj = brains[0].getObject()
|
||||||
# Do we need to call the method on the object or on the wrapper?
|
# Do we need to call the method on the object or on the wrapper?
|
||||||
if methodName.startswith('_appy_'):
|
if methodName.startswith('_appy_'):
|
||||||
exec 'res = obj.%s(*args)' % methodName
|
exec('res = obj.%s(*args)' % methodName)
|
||||||
else:
|
else:
|
||||||
exec 'res = obj.appy().%s(*args)' % methodName
|
exec('res = obj.appy().%s(*args)' % methodName)
|
||||||
if not withTranslations: res = [v[0] for v in res]
|
if not withTranslations: res = [v[0] for v in res]
|
||||||
elif isinstance(res, list): res = res[:]
|
elif isinstance(res, list): res = res[:]
|
||||||
else:
|
else:
|
||||||
|
@ -847,7 +847,7 @@ class String(Field):
|
||||||
elif self.isSelect:
|
elif self.isSelect:
|
||||||
# Check that the value is among possible values
|
# Check that the value is among possible values
|
||||||
possibleValues = self.getPossibleValues(obj,ignoreMasterValues=True)
|
possibleValues = self.getPossibleValues(obj,ignoreMasterValues=True)
|
||||||
if isinstance(value, basestring):
|
if isinstance(value, str):
|
||||||
error = value not in possibleValues
|
error = value not in possibleValues
|
||||||
else:
|
else:
|
||||||
error = False
|
error = False
|
||||||
|
@ -872,7 +872,7 @@ class String(Field):
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def getUnilingualStorableValue(self, obj, value):
|
def getUnilingualStorableValue(self, obj, value):
|
||||||
isString = isinstance(value, basestring)
|
isString = isinstance(value, str)
|
||||||
isEmpty = Field.isEmptyValue(self, obj, value)
|
isEmpty = Field.isEmptyValue(self, obj, value)
|
||||||
# Apply transform if required
|
# Apply transform if required
|
||||||
if isString and not isEmpty and (self.transform != 'none'):
|
if isString and not isEmpty and (self.transform != 'none'):
|
||||||
|
@ -1021,7 +1021,7 @@ class String(Field):
|
||||||
if self.allowImageUpload:
|
if self.allowImageUpload:
|
||||||
ckAttrs['filebrowserUploadUrl'] = '%s/upload' % obj.absolute_url()
|
ckAttrs['filebrowserUploadUrl'] = '%s/upload' % obj.absolute_url()
|
||||||
ck = []
|
ck = []
|
||||||
for k, v in ckAttrs.iteritems():
|
for k, v in ckAttrs.items():
|
||||||
if isinstance(v, int): sv = str(v)
|
if isinstance(v, int): sv = str(v)
|
||||||
if isinstance(v, bool): sv = str(v).lower()
|
if isinstance(v, bool): sv = str(v).lower()
|
||||||
else: sv = '"%s"' % v
|
else: sv = '"%s"' % v
|
||||||
|
@ -1059,7 +1059,7 @@ class String(Field):
|
||||||
name containing a row number from a field within a list field.'''
|
name containing a row number from a field within a list field.'''
|
||||||
rq = obj.REQUEST
|
rq = obj.REQUEST
|
||||||
# Get the value we must compare (from request or from database)
|
# Get the value we must compare (from request or from database)
|
||||||
if rq.has_key(fieldName):
|
if fieldName in rq:
|
||||||
compValue = rq.get(fieldName)
|
compValue = rq.get(fieldName)
|
||||||
else:
|
else:
|
||||||
compValue = dbValue
|
compValue = dbValue
|
||||||
|
|
|
@ -14,10 +14,12 @@
|
||||||
# You should have received a copy of the GNU General Public License along with
|
# You should have received a copy of the GNU General Public License along with
|
||||||
# Appy. If not, see <http://www.gnu.org/licenses/>.
|
# Appy. If not, see <http://www.gnu.org/licenses/>.
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
import types, string
|
import types
|
||||||
from group import Group
|
import .string
|
||||||
|
from .group import Group
|
||||||
from appy.px import Px
|
from appy.px import Px
|
||||||
from appy.gen.utils import User
|
from appy.gen.utils import User
|
||||||
|
import collections
|
||||||
|
|
||||||
# Default Appy permissions -----------------------------------------------------
|
# Default Appy permissions -----------------------------------------------------
|
||||||
r, w, d = ('read', 'write', 'delete')
|
r, w, d = ('read', 'write', 'delete')
|
||||||
|
@ -73,7 +75,7 @@ class State:
|
||||||
exists, or creates a Role instance, puts it in self.usedRoles and
|
exists, or creates a Role instance, puts it in self.usedRoles and
|
||||||
returns it else. If it is a Role instance, the method stores it in
|
returns it else. If it is a Role instance, the method stores it in
|
||||||
self.usedRoles if it is not in it yet and returns it.'''
|
self.usedRoles if it is not in it yet and returns it.'''
|
||||||
if isinstance(role, basestring):
|
if isinstance(role, str):
|
||||||
if role in self.usedRoles:
|
if role in self.usedRoles:
|
||||||
return self.usedRoles[role]
|
return self.usedRoles[role]
|
||||||
else:
|
else:
|
||||||
|
@ -88,24 +90,24 @@ class State:
|
||||||
def standardizeRoles(self):
|
def standardizeRoles(self):
|
||||||
'''This method converts, within self.permissions, every role to a
|
'''This method converts, within self.permissions, every role to a
|
||||||
Role instance. Every used role is stored in self.usedRoles.'''
|
Role instance. Every used role is stored in self.usedRoles.'''
|
||||||
for permission, roles in self.permissions.iteritems():
|
for permission, roles in self.permissions.items():
|
||||||
if not roles: continue # Nobody may have this permission
|
if not roles: continue # Nobody may have this permission
|
||||||
if isinstance(roles, basestring) or isinstance(roles, Role):
|
if isinstance(roles, str) or isinstance(roles, Role):
|
||||||
self.permissions[permission] = [self.getRole(roles)]
|
self.permissions[permission] = [self.getRole(roles)]
|
||||||
elif isinstance(roles, list):
|
elif isinstance(roles, list):
|
||||||
for i in range(len(roles)): roles[i] = self.getRole(roles[i])
|
for i in range(len(roles)): roles[i] = self.getRole(roles[i])
|
||||||
else: # A tuple
|
else: # A tuple
|
||||||
self.permissions[permission] = [self.getRole(r) for r in roles]
|
self.permissions[permission] = [self.getRole(r) for r in roles]
|
||||||
|
|
||||||
def getUsedRoles(self): return self.usedRoles.values()
|
def getUsedRoles(self): return list(self.usedRoles.values())
|
||||||
|
|
||||||
def addRoles(self, roleNames, permissions=()):
|
def addRoles(self, roleNames, permissions=()):
|
||||||
'''Adds p_roleNames in self.permissions. If p_permissions is specified,
|
'''Adds p_roleNames in self.permissions. If p_permissions is specified,
|
||||||
roles are added to those permissions only. Else, roles are added for
|
roles are added to those permissions only. Else, roles are added for
|
||||||
every permission within self.permissions.'''
|
every permission within self.permissions.'''
|
||||||
if isinstance(roleNames, basestring): roleNames = (roleNames,)
|
if isinstance(roleNames, str): roleNames = (roleNames,)
|
||||||
if isinstance(permissions, basestring): permissions = (permissions,)
|
if isinstance(permissions, str): permissions = (permissions,)
|
||||||
for perm, roles in self.permissions.iteritems():
|
for perm, roles in self.permissions.items():
|
||||||
if permissions and (perm not in permissions): continue
|
if permissions and (perm not in permissions): continue
|
||||||
for roleName in roleNames:
|
for roleName in roleNames:
|
||||||
# Do nothing if p_roleName is already almong roles.
|
# Do nothing if p_roleName is already almong roles.
|
||||||
|
@ -124,9 +126,9 @@ class State:
|
||||||
'''Removes p_roleNames within dict self.permissions. If p_permissions is
|
'''Removes p_roleNames within dict self.permissions. If p_permissions is
|
||||||
specified, removal is restricted to those permissions. Else, removal
|
specified, removal is restricted to those permissions. Else, removal
|
||||||
occurs throughout the whole dict self.permissions.'''
|
occurs throughout the whole dict self.permissions.'''
|
||||||
if isinstance(roleNames, basestring): roleNames = (roleNames,)
|
if isinstance(roleNames, str): roleNames = (roleNames,)
|
||||||
if isinstance(permissions, basestring): permissions = (permissions,)
|
if isinstance(permissions, str): permissions = (permissions,)
|
||||||
for perm, roles in self.permissions.iteritems():
|
for perm, roles in self.permissions.items():
|
||||||
if permissions and (perm not in permissions): continue
|
if permissions and (perm not in permissions): continue
|
||||||
for roleName in roleNames:
|
for roleName in roleNames:
|
||||||
# Remove this role if present in roles for this permission.
|
# Remove this role if present in roles for this permission.
|
||||||
|
@ -138,9 +140,9 @@ class State:
|
||||||
def setRoles(self, roleNames, permissions=()):
|
def setRoles(self, roleNames, permissions=()):
|
||||||
'''Sets p_rolesNames for p_permissions if not empty, for every
|
'''Sets p_rolesNames for p_permissions if not empty, for every
|
||||||
permission in self.permissions else.'''
|
permission in self.permissions else.'''
|
||||||
if isinstance(roleNames, basestring): roleNames = (roleNames,)
|
if isinstance(roleNames, str): roleNames = (roleNames,)
|
||||||
if isinstance(permissions, basestring): permissions = (permissions,)
|
if isinstance(permissions, str): permissions = (permissions,)
|
||||||
for perm in self.permissions.iterkeys():
|
for perm in self.permissions.keys():
|
||||||
if permissions and (perm not in permissions): continue
|
if permissions and (perm not in permissions): continue
|
||||||
roles = self.permissions[perm] = []
|
roles = self.permissions[perm] = []
|
||||||
for roleName in roleNames:
|
for roleName in roleNames:
|
||||||
|
@ -150,8 +152,8 @@ class State:
|
||||||
'''Replaces p_oldRoleName by p_newRoleName. If p_permissions is
|
'''Replaces p_oldRoleName by p_newRoleName. If p_permissions is
|
||||||
specified, the replacement is restricted to those permissions. Else,
|
specified, the replacement is restricted to those permissions. Else,
|
||||||
replacements apply to the whole dict self.permissions.'''
|
replacements apply to the whole dict self.permissions.'''
|
||||||
if isinstance(permissions, basestring): permissions = (permissions,)
|
if isinstance(permissions, str): permissions = (permissions,)
|
||||||
for perm, roles in self.permissions.iteritems():
|
for perm, roles in self.permissions.items():
|
||||||
if permissions and (perm not in permissions): continue
|
if permissions and (perm not in permissions): continue
|
||||||
# Find and delete p_oldRoleName
|
# Find and delete p_oldRoleName
|
||||||
for role in roles:
|
for role in roles:
|
||||||
|
@ -170,7 +172,7 @@ class State:
|
||||||
worklflow, this method will always return True (I mean: in this case,
|
worklflow, this method will always return True (I mean: in this case,
|
||||||
having an isolated state does not mean the state has been
|
having an isolated state does not mean the state has been
|
||||||
deactivated).'''
|
deactivated).'''
|
||||||
for tr in wf.__dict__.itervalues():
|
for tr in wf.__dict__.values():
|
||||||
if not isinstance(tr, Transition): continue
|
if not isinstance(tr, Transition): continue
|
||||||
if not tr.hasState(self, True): continue
|
if not tr.hasState(self, True): continue
|
||||||
# Transition "tr" has this state as start state. If the end state is
|
# Transition "tr" has this state as start state. If the end state is
|
||||||
|
@ -200,7 +202,7 @@ class Transition:
|
||||||
# be useful for "undo" transitions, for example.
|
# be useful for "undo" transitions, for example.
|
||||||
self.states = self.standardiseStates(states)
|
self.states = self.standardiseStates(states)
|
||||||
self.condition = condition
|
self.condition = condition
|
||||||
if isinstance(condition, basestring):
|
if isinstance(condition, str):
|
||||||
# The condition specifies the name of a role.
|
# The condition specifies the name of a role.
|
||||||
self.condition = Role(condition)
|
self.condition = Role(condition)
|
||||||
self.action = action
|
self.action = action
|
||||||
|
@ -276,7 +278,7 @@ class Transition:
|
||||||
|
|
||||||
def isShowable(self, workflow, obj):
|
def isShowable(self, workflow, obj):
|
||||||
'''Is this transition showable?'''
|
'''Is this transition showable?'''
|
||||||
if callable(self.show):
|
if isinstance(self.show, collections.Callable):
|
||||||
return self.show(workflow, obj.appy())
|
return self.show(workflow, obj.appy())
|
||||||
else:
|
else:
|
||||||
return self.show
|
return self.show
|
||||||
|
@ -330,7 +332,7 @@ class Transition:
|
||||||
for condition in self.condition:
|
for condition in self.condition:
|
||||||
# "Unwrap" role names from Role instances
|
# "Unwrap" role names from Role instances
|
||||||
if isinstance(condition, Role): condition = condition.name
|
if isinstance(condition, Role): condition = condition.name
|
||||||
if isinstance(condition, basestring): # It is a role
|
if isinstance(condition, str): # It is a role
|
||||||
if hasRole == None:
|
if hasRole == None:
|
||||||
hasRole = False
|
hasRole = False
|
||||||
if user.has_role(condition, obj):
|
if user.has_role(condition, obj):
|
||||||
|
@ -450,7 +452,7 @@ class Transition:
|
||||||
transition = getattr(workflow, transition)
|
transition = getattr(workflow, transition)
|
||||||
# Browse all transitions and find the one starting at p_transition's end
|
# Browse all transitions and find the one starting at p_transition's end
|
||||||
# state and coming back to p_transition's start state.
|
# state and coming back to p_transition's start state.
|
||||||
for trName, tr in workflow.__dict__.iteritems():
|
for trName, tr in workflow.__dict__.items():
|
||||||
if not isinstance(tr, Transition) or (tr == transition): continue
|
if not isinstance(tr, Transition) or (tr == transition): continue
|
||||||
if transition.isSingle():
|
if transition.isSingle():
|
||||||
if tr.hasState(transition.states[1], True) and \
|
if tr.hasState(transition.states[1], True) and \
|
||||||
|
|
|
@ -5,9 +5,9 @@
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
import types, copy
|
import types, copy
|
||||||
import appy.gen as gen
|
import appy.gen as gen
|
||||||
import po
|
from . import po
|
||||||
from model import ModelClass
|
from .model import ModelClass
|
||||||
from utils import produceNiceMessage, getClassName
|
from .utils import produceNiceMessage, getClassName
|
||||||
TABS = 4 # Number of blanks in a Python indentation.
|
TABS = 4 # Number of blanks in a Python indentation.
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
@ -130,7 +130,7 @@ class ClassDescriptor(Descriptor):
|
||||||
def isAbstract(self):
|
def isAbstract(self):
|
||||||
'''Is self.klass abstract?'''
|
'''Is self.klass abstract?'''
|
||||||
res = False
|
res = False
|
||||||
if self.klass.__dict__.has_key('abstract'):
|
if 'abstract' in self.klass.__dict__:
|
||||||
res = self.klass.__dict__['abstract']
|
res = self.klass.__dict__['abstract']
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ class ClassDescriptor(Descriptor):
|
||||||
concept into the application. For example, creating instances
|
concept into the application. For example, creating instances
|
||||||
of such classes will be easy from the user interface.'''
|
of such classes will be easy from the user interface.'''
|
||||||
res = False
|
res = False
|
||||||
if self.klass.__dict__.has_key('root'):
|
if 'root' in self.klass.__dict__:
|
||||||
res = self.klass.__dict__['root']
|
res = self.klass.__dict__['root']
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ class ClassDescriptor(Descriptor):
|
||||||
theClass = self.klass
|
theClass = self.klass
|
||||||
if klass:
|
if klass:
|
||||||
theClass = klass
|
theClass = klass
|
||||||
if theClass.__dict__.has_key('folder'):
|
if 'folder' in theClass.__dict__:
|
||||||
res = theClass.__dict__['folder']
|
res = theClass.__dict__['folder']
|
||||||
else:
|
else:
|
||||||
if theClass.__bases__:
|
if theClass.__bases__:
|
||||||
|
@ -176,14 +176,14 @@ class ClassDescriptor(Descriptor):
|
||||||
def getCreateMean(self, type='Import'):
|
def getCreateMean(self, type='Import'):
|
||||||
'''Returns the mean for this class that corresponds to p_type, or
|
'''Returns the mean for this class that corresponds to p_type, or
|
||||||
None if the class does not support this create mean.'''
|
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:
|
else:
|
||||||
means = self.klass.create
|
means = self.klass.create
|
||||||
if not means: return
|
if not means: return
|
||||||
if not isinstance(means, tuple) and not isinstance(means, list):
|
if not isinstance(means, tuple) and not isinstance(means, list):
|
||||||
means = [means]
|
means = [means]
|
||||||
for mean in means:
|
for mean in means:
|
||||||
exec 'found = isinstance(mean, %s)' % type
|
exec('found = isinstance(mean, %s)' % type)
|
||||||
if found: return mean
|
if found: return mean
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -192,7 +192,7 @@ class ClassDescriptor(Descriptor):
|
||||||
p_tool is given, we are at execution time (not a generation time),
|
p_tool is given, we are at execution time (not a generation time),
|
||||||
and we may potentially execute search.show methods that allow to
|
and we may potentially execute search.show methods that allow to
|
||||||
conditionnaly include a search or not.'''
|
conditionnaly include a search or not.'''
|
||||||
if klass.__dict__.has_key('search'):
|
if 'search' in klass.__dict__:
|
||||||
searches = klass.__dict__['search']
|
searches = klass.__dict__['search']
|
||||||
if not tool: return searches
|
if not tool: return searches
|
||||||
# Evaluate attributes "show" for every search.
|
# Evaluate attributes "show" for every search.
|
||||||
|
@ -229,10 +229,10 @@ class ClassDescriptor(Descriptor):
|
||||||
|
|
||||||
def addField(self, fieldName, fieldType):
|
def addField(self, fieldName, fieldType):
|
||||||
'''Adds a new field to the Tool.'''
|
'''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:
|
if fieldName in self.modelClass._appy_attributes:
|
||||||
print('Warning, field "%s" is already existing on class "%s"' % \
|
print(('Warning, field "%s" is already existing on class "%s"' % \
|
||||||
(fieldName, self.modelClass.__name__))
|
(fieldName, self.modelClass.__name__)))
|
||||||
return
|
return
|
||||||
self.modelClass._appy_attributes.append(fieldName)
|
self.modelClass._appy_attributes.append(fieldName)
|
||||||
self.orderedAttributes.append(fieldName)
|
self.orderedAttributes.append(fieldName)
|
||||||
|
@ -488,9 +488,9 @@ class TranslationClassDescriptor(ClassDescriptor):
|
||||||
maxLine = 100 # We suppose a line is 100 characters long.
|
maxLine = 100 # We suppose a line is 100 characters long.
|
||||||
width = 0
|
width = 0
|
||||||
height = 0
|
height = 0
|
||||||
for fileName, poFile in i18nFiles.iteritems():
|
for fileName, poFile in i18nFiles.items():
|
||||||
if not fileName.startswith('%s-' % appName) or \
|
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
|
# In this case this is not one of our Appy-managed translation
|
||||||
# files.
|
# files.
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -3,10 +3,11 @@ import os, os.path, re, sys, parser, symbol, token, types
|
||||||
import appy, appy.pod.renderer
|
import appy, appy.pod.renderer
|
||||||
from appy.shared.utils import FolderDeleter
|
from appy.shared.utils import FolderDeleter
|
||||||
import appy.gen as gen
|
import appy.gen as gen
|
||||||
import po
|
from . import po
|
||||||
from descriptors import *
|
from .descriptors import *
|
||||||
from utils import getClassName
|
from .utils import getClassName
|
||||||
from model import ModelClass, User, Group, Tool, Translation, Page
|
from .model import ModelClass, User, Group, Tool, Translation, Page
|
||||||
|
import collections
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
class GeneratorError(Exception): pass
|
class GeneratorError(Exception): pass
|
||||||
|
@ -160,7 +161,7 @@ class Generator:
|
||||||
appy.fields.Field, it will be considered a gen-class. If p_klass
|
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,
|
declares at least one static attribute that is a appy.gen.State,
|
||||||
it will be considered a gen-workflow.'''
|
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'
|
if isinstance(attr, gen.Field): return 'class'
|
||||||
elif isinstance(attr, gen.State): return 'workflow'
|
elif isinstance(attr, gen.State): return 'workflow'
|
||||||
|
|
||||||
|
@ -173,11 +174,11 @@ class Generator:
|
||||||
self.totalNumberOfTests += 1
|
self.totalNumberOfTests += 1
|
||||||
res = True
|
res = True
|
||||||
# Count also docstring in methods
|
# Count also docstring in methods
|
||||||
if type(moduleOrClass) == types.ClassType:
|
if type(moduleOrClass) == type:
|
||||||
for name, elem in moduleOrClass.__dict__.iteritems():
|
for name, elem in moduleOrClass.__dict__.items():
|
||||||
if type(elem) in (staticmethod, classmethod):
|
if type(elem) in (staticmethod, classmethod):
|
||||||
elem = elem.__get__(name)
|
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 \
|
hasattr(elem, '__doc__') and elem.__doc__ and \
|
||||||
(elem.__doc__.find('>>>') != -1):
|
(elem.__doc__.find('>>>') != -1):
|
||||||
res = True
|
res = True
|
||||||
|
@ -198,8 +199,8 @@ class Generator:
|
||||||
self.modulesWithTests.add(module.__name__)
|
self.modulesWithTests.add(module.__name__)
|
||||||
classType = type(Generator)
|
classType = type(Generator)
|
||||||
# Find all classes in this module
|
# Find all classes in this module
|
||||||
for name in module.__dict__.keys():
|
for name in list(module.__dict__.keys()):
|
||||||
exec 'moduleElem = module.%s' % name
|
exec('moduleElem = module.%s' % name)
|
||||||
# Ignore non-classes module elements or classes that were imported
|
# Ignore non-classes module elements or classes that were imported
|
||||||
# from other modules.
|
# from other modules.
|
||||||
if (type(moduleElem) != classType) or \
|
if (type(moduleElem) != classType) or \
|
||||||
|
@ -213,7 +214,7 @@ class Generator:
|
||||||
# Collect non-parsable attrs = back references added
|
# Collect non-parsable attrs = back references added
|
||||||
# programmatically
|
# programmatically
|
||||||
moreAttrs = []
|
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):
|
if isinstance(eValue, gen.Field) and (eName not in attrs):
|
||||||
moreAttrs.append(eName)
|
moreAttrs.append(eName)
|
||||||
# Sort them in alphabetical order: else, order would be random
|
# Sort them in alphabetical order: else, order would be random
|
||||||
|
@ -257,7 +258,7 @@ class Generator:
|
||||||
# What is the name of the application ?
|
# What is the name of the application ?
|
||||||
appName = os.path.basename(self.application)
|
appName = os.path.basename(self.application)
|
||||||
# Get the app-specific config if any
|
# Get the app-specific config if any
|
||||||
exec 'import %s as appModule' % appName
|
exec('import %s as appModule' % appName)
|
||||||
if hasattr (appModule, 'Config'):
|
if hasattr (appModule, 'Config'):
|
||||||
self.config = appModule.Config
|
self.config = appModule.Config
|
||||||
if not issubclass(self.config, gen.Config):
|
if not issubclass(self.config, gen.Config):
|
||||||
|
@ -273,7 +274,7 @@ class Generator:
|
||||||
# Ignore non Python files
|
# Ignore non Python files
|
||||||
if not fileName.endswith('.py'): continue
|
if not fileName.endswith('.py'): continue
|
||||||
moduleName = '%s.%s' % (appName, os.path.splitext(fileName)[0])
|
moduleName = '%s.%s' % (appName, os.path.splitext(fileName)[0])
|
||||||
exec 'import %s' % moduleName
|
exec('import %s' % moduleName)
|
||||||
modules.append(eval(moduleName))
|
modules.append(eval(moduleName))
|
||||||
# Parse imported modules
|
# Parse imported modules
|
||||||
for module in modules:
|
for module in modules:
|
||||||
|
@ -321,7 +322,7 @@ class Generator:
|
||||||
fileContent = f.read()
|
fileContent = f.read()
|
||||||
f.close()
|
f.close()
|
||||||
if not fileName.endswith('.png'):
|
if not fileName.endswith('.png'):
|
||||||
for rKey, rValue in replacements.iteritems():
|
for rKey, rValue in replacements.items():
|
||||||
fileContent = fileContent.replace(
|
fileContent = fileContent.replace(
|
||||||
'<!%s!>' % rKey, str(rValue))
|
'<!%s!>' % rKey, str(rValue))
|
||||||
f = file(resultPath, 'w')
|
f = file(resultPath, 'w')
|
||||||
|
@ -343,7 +344,7 @@ class Generator:
|
||||||
msg = ''
|
msg = ''
|
||||||
if self.totalNumberOfTests:
|
if self.totalNumberOfTests:
|
||||||
msg = ' (number of tests found: %d)' % self.totalNumberOfTests
|
msg = ' (number of tests found: %d)' % self.totalNumberOfTests
|
||||||
print('Done%s.' % msg)
|
print(('Done%s.' % msg))
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
class ZopeGenerator(Generator):
|
class ZopeGenerator(Generator):
|
||||||
|
@ -413,7 +414,7 @@ class ZopeGenerator(Generator):
|
||||||
f.close()
|
f.close()
|
||||||
# Generate i18n pot file
|
# Generate i18n pot file
|
||||||
potFileName = '%s.pot' % self.applicationName
|
potFileName = '%s.pot' % self.applicationName
|
||||||
if self.i18nFiles.has_key(potFileName):
|
if potFileName in self.i18nFiles:
|
||||||
potFile = self.i18nFiles[potFileName]
|
potFile = self.i18nFiles[potFileName]
|
||||||
else:
|
else:
|
||||||
fullName = os.path.join(self.application, 'tr', potFileName)
|
fullName = os.path.join(self.application, 'tr', potFileName)
|
||||||
|
@ -427,14 +428,14 @@ class ZopeGenerator(Generator):
|
||||||
self.options.i18nClean, keepExistingOrder=False)
|
self.options.i18nClean, keepExistingOrder=False)
|
||||||
potFile.generate()
|
potFile.generate()
|
||||||
if removedLabels:
|
if removedLabels:
|
||||||
print('Warning: %d messages were removed from translation ' \
|
print(('Warning: %d messages were removed from translation ' \
|
||||||
'files: %s' % (len(removedLabels), str(removedLabels)))
|
'files: %s' % (len(removedLabels), str(removedLabels))))
|
||||||
# Generate i18n po files
|
# Generate i18n po files
|
||||||
for language in self.config.languages:
|
for language in self.config.languages:
|
||||||
# I must generate (or update) a po file for the language(s)
|
# I must generate (or update) a po file for the language(s)
|
||||||
# specified in the configuration.
|
# specified in the configuration.
|
||||||
poFileName = potFile.getPoFileName(language)
|
poFileName = potFile.getPoFileName(language)
|
||||||
if self.i18nFiles.has_key(poFileName):
|
if poFileName in self.i18nFiles:
|
||||||
poFile = self.i18nFiles[poFileName]
|
poFile = self.i18nFiles[poFileName]
|
||||||
else:
|
else:
|
||||||
fullName = os.path.join(self.application, 'tr', poFileName)
|
fullName = os.path.join(self.application, 'tr', poFileName)
|
||||||
|
@ -501,7 +502,7 @@ class ZopeGenerator(Generator):
|
||||||
for role in creators:
|
for role in creators:
|
||||||
if role.name not in allRoles:
|
if role.name not in allRoles:
|
||||||
allRoles[role.name] = role
|
allRoles[role.name] = role
|
||||||
res = allRoles.values()
|
res = list(allRoles.values())
|
||||||
# Filter the result according to parameters
|
# Filter the result according to parameters
|
||||||
for p in ('appy', 'local', 'grantable'):
|
for p in ('appy', 'local', 'grantable'):
|
||||||
if eval(p) != None:
|
if eval(p) != None:
|
||||||
|
@ -621,12 +622,12 @@ class ZopeGenerator(Generator):
|
||||||
else:
|
else:
|
||||||
# If a child of this class is already present, we must insert
|
# If a child of this class is already present, we must insert
|
||||||
# this klass before it.
|
# this klass before it.
|
||||||
lowestChildIndex = sys.maxint
|
lowestChildIndex = sys.maxsize
|
||||||
for resClass in resClasses:
|
for resClass in resClasses:
|
||||||
if klass in resClass.__bases__:
|
if klass in resClass.__bases__:
|
||||||
lowestChildIndex = min(lowestChildIndex,
|
lowestChildIndex = min(lowestChildIndex,
|
||||||
resClasses.index(resClass))
|
resClasses.index(resClass))
|
||||||
if lowestChildIndex != sys.maxint:
|
if lowestChildIndex != sys.maxsize:
|
||||||
res.insert(lowestChildIndex, classDescr)
|
res.insert(lowestChildIndex, classDescr)
|
||||||
resClasses.insert(lowestChildIndex, klass)
|
resClasses.insert(lowestChildIndex, klass)
|
||||||
else:
|
else:
|
||||||
|
@ -745,7 +746,7 @@ class ZopeGenerator(Generator):
|
||||||
'''Is called each time an Appy class is found in the application, for
|
'''Is called each time an Appy class is found in the application, for
|
||||||
generating the corresponding Archetype class.'''
|
generating the corresponding Archetype class.'''
|
||||||
k = classDescr.klass
|
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
|
# Determine base Zope class
|
||||||
isFolder = classDescr.isFolder()
|
isFolder = classDescr.isFolder()
|
||||||
baseClass = isFolder and 'Folder' or 'SimpleItem'
|
baseClass = isFolder and 'Folder' or 'SimpleItem'
|
||||||
|
@ -772,7 +773,7 @@ class ZopeGenerator(Generator):
|
||||||
'''This method creates the i18n labels related to the workflow described
|
'''This method creates the i18n labels related to the workflow described
|
||||||
by p_wfDescr.'''
|
by p_wfDescr.'''
|
||||||
k = wfDescr.klass
|
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
|
# Identify workflow name
|
||||||
wfName = WorkflowDescriptor.getWorkflowName(wfDescr.klass)
|
wfName = WorkflowDescriptor.getWorkflowName(wfDescr.klass)
|
||||||
# Add i18n messages for states
|
# Add i18n messages for states
|
||||||
|
|
|
@ -33,7 +33,7 @@ def updateIndexes(installer, indexInfo):
|
||||||
'''This function updates the indexes defined in the catalog.'''
|
'''This function updates the indexes defined in the catalog.'''
|
||||||
catalog = installer.app.catalog
|
catalog = installer.app.catalog
|
||||||
logger = installer.logger
|
logger = installer.logger
|
||||||
for indexName, indexType in indexInfo.iteritems():
|
for indexName, indexType in indexInfo.items():
|
||||||
indexRealType = indexType
|
indexRealType = indexType
|
||||||
if indexType in ('XhtmlIndex', 'TextIndex', 'ListIndex'):
|
if indexType in ('XhtmlIndex', 'TextIndex', 'ListIndex'):
|
||||||
indexRealType = 'ZCTextIndex'
|
indexRealType = 'ZCTextIndex'
|
||||||
|
|
|
@ -43,7 +43,7 @@ class FakeZCatalog:
|
||||||
def onDelSession(sessionObject, container):
|
def onDelSession(sessionObject, container):
|
||||||
'''This function is called when a session expires.'''
|
'''This function is called when a session expires.'''
|
||||||
rq = container.REQUEST
|
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):
|
(rq['_ZopeId'] == sessionObject.token):
|
||||||
# The request comes from a guy whose session has expired.
|
# The request comes from a guy whose session has expired.
|
||||||
resp = rq.RESPONSE
|
resp = rq.RESPONSE
|
||||||
|
@ -155,7 +155,7 @@ class ZopeInstaller:
|
||||||
# Create or update Appy-wide indexes and field-related indexes
|
# Create or update Appy-wide indexes and field-related indexes
|
||||||
indexInfo = defaultIndexes.copy()
|
indexInfo = defaultIndexes.copy()
|
||||||
tool = self.app.config
|
tool = self.app.config
|
||||||
for className in self.config.attributes.iterkeys():
|
for className in self.config.attributes.keys():
|
||||||
wrapperClass = tool.getAppyClass(className, wrapper=True)
|
wrapperClass = tool.getAppyClass(className, wrapper=True)
|
||||||
indexInfo.update(wrapperClass.getIndexes(includeDefaults=False))
|
indexInfo.update(wrapperClass.getIndexes(includeDefaults=False))
|
||||||
updateIndexes(self, indexInfo)
|
updateIndexes(self, indexInfo)
|
||||||
|
@ -196,7 +196,7 @@ class ZopeInstaller:
|
||||||
if hasattr(appyTool, 'beforeInstall'): appyTool.beforeInstall()
|
if hasattr(appyTool, 'beforeInstall'): appyTool.beforeInstall()
|
||||||
|
|
||||||
# Create the default users if they do not exist.
|
# 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):
|
if not appyTool.count('User', noSecurity=True, login=login):
|
||||||
appyTool.create('users', noSecurity=True, id=login, login=login,
|
appyTool.create('users', noSecurity=True, id=login, login=login,
|
||||||
password3=login, password4=login,
|
password3=login, password4=login,
|
||||||
|
@ -277,7 +277,7 @@ class ZopeInstaller:
|
||||||
name = klass.__name__
|
name = klass.__name__
|
||||||
module = klass.__module__
|
module = klass.__module__
|
||||||
wrapper = klass.wrapperClass
|
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,
|
self.zopeContext.registerClass(meta_type=name,
|
||||||
constructors = (ctor,), permission = None)
|
constructors = (ctor,), permission = None)
|
||||||
# Create workflow prototypical instances in __instance__ attributes
|
# Create workflow prototypical instances in __instance__ attributes
|
||||||
|
@ -316,7 +316,7 @@ class ZopeInstaller:
|
||||||
# Post-initialise every Appy type
|
# Post-initialise every Appy type
|
||||||
for baseClass in klass.wrapperClass.__bases__:
|
for baseClass in klass.wrapperClass.__bases__:
|
||||||
if baseClass.__name__ == 'AbstractWrapper': continue
|
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 \
|
if not isinstance(appyType, gen.Field) or \
|
||||||
(isinstance(appyType, gen.Ref) and appyType.isBack):
|
(isinstance(appyType, gen.Ref) and appyType.isBack):
|
||||||
continue # Back refs are initialised within fw refs
|
continue # Back refs are initialised within fw refs
|
||||||
|
|
|
@ -39,9 +39,9 @@
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
rowDelimiters = {'-':'middle', '=':'top', '_':'bottom'}
|
rowDelimiters = {'-':'middle', '=':'top', '_':'bottom'}
|
||||||
rowDelms = ''.join(rowDelimiters.keys())
|
rowDelms = ''.join(list(rowDelimiters.keys()))
|
||||||
cellDelimiters = {'|': 'center', ';': 'left', '!': 'right'}
|
cellDelimiters = {'|': 'center', ';': 'left', '!': 'right'}
|
||||||
cellDelms = ''.join(cellDelimiters.keys())
|
cellDelms = ''.join(list(cellDelimiters.keys()))
|
||||||
|
|
||||||
pxDict = {
|
pxDict = {
|
||||||
# Page-related elements
|
# Page-related elements
|
||||||
|
@ -138,7 +138,7 @@ class Table:
|
||||||
# Initialise simple params, either from the true params, either from
|
# Initialise simple params, either from the true params, either from
|
||||||
# the p_other Table instance.
|
# the p_other Table instance.
|
||||||
for param in Table.simpleParams:
|
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
|
# The following attribute will store a special Row instance used for
|
||||||
# defining column properties.
|
# defining column properties.
|
||||||
self.headerRow = None
|
self.headerRow = None
|
||||||
|
|
|
@ -120,10 +120,10 @@ def sendMail(config, to, subject, body, attachments=None, log=None):
|
||||||
if res and log:
|
if res and log:
|
||||||
log('could not send mail to some recipients. %s' % str(res),
|
log('could not send mail to some recipients. %s' % str(res),
|
||||||
type='warning')
|
type='warning')
|
||||||
except smtplib.SMTPException, e:
|
except smtplib.SMTPException as e:
|
||||||
if log:
|
if log:
|
||||||
log('%s: mail sending failed (%s)' % (config, str(e)), type='error')
|
log('%s: mail sending failed (%s)' % (config, str(e)), type='error')
|
||||||
except socket.error, se:
|
except socket.error as se:
|
||||||
if log:
|
if log:
|
||||||
log('%s: mail sending failed (%s)' % (config, str(se)),type='error')
|
log('%s: mail sending failed (%s)' % (config, str(se)),type='error')
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -38,10 +38,10 @@ class Migrator:
|
||||||
if frozen.data.__class__.__name__ == 'Pdata':
|
if frozen.data.__class__.__name__ == 'Pdata':
|
||||||
# The file content is splitted in several chunks.
|
# The file content is splitted in several chunks.
|
||||||
f.write(frozen.data.data)
|
f.write(frozen.data.data)
|
||||||
nextPart = frozen.data.next
|
nextPart = frozen.data.__next__
|
||||||
while nextPart:
|
while nextPart:
|
||||||
f.write(nextPart.data)
|
f.write(nextPart.data)
|
||||||
nextPart = nextPart.next
|
nextPart = nextPart.__next__
|
||||||
else:
|
else:
|
||||||
# Only one chunk
|
# Only one chunk
|
||||||
f.write(frozen.data)
|
f.write(frozen.data)
|
||||||
|
|
|
@ -13,18 +13,18 @@ class TestMixin:
|
||||||
'''Returns the list of sub-modules of p_app that are non-empty.'''
|
'''Returns the list of sub-modules of p_app that are non-empty.'''
|
||||||
res = []
|
res = []
|
||||||
try:
|
try:
|
||||||
exec 'import %s' % moduleName
|
exec('import %s' % moduleName)
|
||||||
exec 'moduleObj = %s' % moduleName
|
exec('moduleObj = %s' % moduleName)
|
||||||
moduleFile = moduleObj.__file__
|
moduleFile = moduleObj.__file__
|
||||||
if moduleFile.endswith('.pyc'):
|
if moduleFile.endswith('.pyc'):
|
||||||
moduleFile = moduleFile[:-1]
|
moduleFile = moduleFile[:-1]
|
||||||
except ImportError, ie:
|
except ImportError as ie:
|
||||||
return res
|
return res
|
||||||
except SyntaxError, se:
|
except SyntaxError as se:
|
||||||
return res
|
return res
|
||||||
# Include the module if not empty. "Emptyness" is determined by the
|
# Include the module if not empty. "Emptyness" is determined by the
|
||||||
# absence of names beginning with other chars than "__".
|
# absence of names beginning with other chars than "__".
|
||||||
for elem in moduleObj.__dict__.iterkeys():
|
for elem in moduleObj.__dict__.keys():
|
||||||
if not elem.startswith('__'):
|
if not elem.startswith('__'):
|
||||||
res.append(moduleObj)
|
res.append(moduleObj)
|
||||||
break
|
break
|
||||||
|
@ -66,10 +66,10 @@ def afterTest(test):
|
||||||
'''Is executed after every test.'''
|
'''Is executed after every test.'''
|
||||||
g = test.globs
|
g = test.globs
|
||||||
appName = g['tool'].o.getAppName()
|
appName = g['tool'].o.getAppName()
|
||||||
exec 'from Products.%s import cov, covFolder, totalNumberOfTests, ' \
|
exec('from Products.%s import cov, covFolder, totalNumberOfTests, ' \
|
||||||
'countTest' % appName
|
'countTest' % appName)
|
||||||
countTest()
|
countTest()
|
||||||
exec 'from Products.%s import numberOfExecutedTests' % appName
|
exec('from Products.%s import numberOfExecutedTests' % appName)
|
||||||
if cov and (numberOfExecutedTests == totalNumberOfTests):
|
if cov and (numberOfExecutedTests == totalNumberOfTests):
|
||||||
cov.stop()
|
cov.stop()
|
||||||
appModules = test.getNonEmptySubModules(appName)
|
appModules = test.getNonEmptySubModules(appName)
|
||||||
|
|
|
@ -13,6 +13,7 @@ from appy.shared import mimeTypes
|
||||||
from appy.shared import utils as sutils
|
from appy.shared import utils as sutils
|
||||||
from appy.shared.data import languages
|
from appy.shared.data import languages
|
||||||
from appy.shared.ldap_connector import LdapConnector
|
from appy.shared.ldap_connector import LdapConnector
|
||||||
|
import collections
|
||||||
try:
|
try:
|
||||||
from AccessControl.ZopeSecurityPolicy import _noroles
|
from AccessControl.ZopeSecurityPolicy import _noroles
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
@ -36,7 +37,7 @@ class ToolMixin(BaseMixin):
|
||||||
p_metaTypeOrAppyType.'''
|
p_metaTypeOrAppyType.'''
|
||||||
appName = self.getProductConfig().PROJECTNAME
|
appName = self.getProductConfig().PROJECTNAME
|
||||||
res = metaTypeOrAppyClass
|
res = metaTypeOrAppyClass
|
||||||
if not isinstance(metaTypeOrAppyClass, basestring):
|
if not isinstance(metaTypeOrAppyClass, str):
|
||||||
res = gutils.getClassName(metaTypeOrAppyClass, appName)
|
res = gutils.getClassName(metaTypeOrAppyClass, appName)
|
||||||
if res.find('_wrappers') != -1:
|
if res.find('_wrappers') != -1:
|
||||||
elems = res.split('_')
|
elems = res.split('_')
|
||||||
|
@ -439,7 +440,7 @@ class ToolMixin(BaseMixin):
|
||||||
|
|
||||||
def quote(self, s, escapeWithEntity=True):
|
def quote(self, s, escapeWithEntity=True):
|
||||||
'''Returns the quoted version of p_s.'''
|
'''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 "\\'"
|
repl = escapeWithEntity and ''' or "\\'"
|
||||||
s = s.replace('\r\n', '').replace('\n', '').replace("'", repl)
|
s = s.replace('\r\n', '').replace('\n', '').replace("'", repl)
|
||||||
return "'%s'" % s
|
return "'%s'" % s
|
||||||
|
@ -452,7 +453,7 @@ class ToolMixin(BaseMixin):
|
||||||
|
|
||||||
def getZopeClass(self, name):
|
def getZopeClass(self, name):
|
||||||
'''Returns the Zope class whose name is p_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
|
return C
|
||||||
|
|
||||||
def getAppyClass(self, zopeName, wrapper=False):
|
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:
|
'''Gets the different ways objects of p_klass can be created (currently:
|
||||||
via a web form or programmatically only). Result is a list.'''
|
via a web form or programmatically only). Result is a list.'''
|
||||||
res = []
|
res = []
|
||||||
if not klass.__dict__.has_key('create'):
|
if 'create' not in klass.__dict__:
|
||||||
return ['form']
|
return ['form']
|
||||||
else:
|
else:
|
||||||
means = klass.create
|
means = klass.create
|
||||||
if means:
|
if means:
|
||||||
if isinstance(means, basestring): res = [means]
|
if isinstance(means, str): res = [means]
|
||||||
else: res = means
|
else: res = means
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
@ -511,7 +512,7 @@ class ToolMixin(BaseMixin):
|
||||||
else:
|
else:
|
||||||
creators = self.getProductConfig().appConfig.defaultCreators
|
creators = self.getProductConfig().appConfig.defaultCreators
|
||||||
# Resolve case (3): if "creators" is a method, execute it.
|
# 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)
|
# Resolve case (2)
|
||||||
if isinstance(creators, bool) or not creators: return creators
|
if isinstance(creators, bool) or not creators: return creators
|
||||||
# Resolve case (1): checks whether the user has at least one of the
|
# Resolve case (1): checks whether the user has at least one of the
|
||||||
|
@ -595,7 +596,7 @@ class ToolMixin(BaseMixin):
|
||||||
rq = self.REQUEST
|
rq = self.REQUEST
|
||||||
# Store the search criteria in the session
|
# Store the search criteria in the session
|
||||||
criteria = self._getDefaultSearchCriteria()
|
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):
|
if name.startswith('w_') and not self._searchValueIsEmpty(name):
|
||||||
hasStar = name.find('*') != -1
|
hasStar = name.find('*') != -1
|
||||||
fieldName = not hasStar and name[2:] or name[2:name.find('*')]
|
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 "*".
|
# The type of the value is encoded after char "*".
|
||||||
name, type = name.split('*')
|
name, type = name.split('*')
|
||||||
if type == 'bool':
|
if type == 'bool':
|
||||||
exec 'value = %s' % value
|
exec('value = %s' % value)
|
||||||
elif type in ('int', 'float'):
|
elif type in ('int', 'float'):
|
||||||
# Get the "from" value
|
# Get the "from" value
|
||||||
if not value: value = None
|
if not value: value = None
|
||||||
else:
|
else:
|
||||||
exec 'value = %s(value)' % type
|
exec('value = %s(value)' % type)
|
||||||
# Get the "to" value
|
# Get the "to" value
|
||||||
toValue = rq.form['%s_to' % name[2:]].strip()
|
toValue = rq.form['%s_to' % name[2:]].strip()
|
||||||
if not toValue: toValue = None
|
if not toValue: toValue = None
|
||||||
else:
|
else:
|
||||||
exec 'toValue = %s(toValue)' % type
|
exec('toValue = %s(toValue)' % type)
|
||||||
value = (value, toValue)
|
value = (value, toValue)
|
||||||
elif type == 'date':
|
elif type == 'date':
|
||||||
prefix = name[2:]
|
prefix = name[2:]
|
||||||
|
@ -640,8 +641,8 @@ class ToolMixin(BaseMixin):
|
||||||
if len(type) > 6:
|
if len(type) > 6:
|
||||||
transform = type.split('-')[1]
|
transform = type.split('-')[1]
|
||||||
if (transform != 'none') and value:
|
if (transform != 'none') and value:
|
||||||
exec 'value = value.%s()' % \
|
exec('value = value.%s()' % \
|
||||||
self.transformMethods[transform]
|
self.transformMethods[transform])
|
||||||
if isinstance(value, list):
|
if isinstance(value, list):
|
||||||
# It is a list of values. Check if we have an operator for
|
# 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
|
# 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.'''
|
it among search criteria in the session.'''
|
||||||
if not refInfo and (self.REQUEST.get('search', None) == 'customSearch'):
|
if not refInfo and (self.REQUEST.get('search', None) == 'customSearch'):
|
||||||
criteria = self.REQUEST.SESSION.get('searchCriteria', None)
|
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
|
if not refInfo: return None, None
|
||||||
objectUid, fieldName = refInfo.split(':')
|
objectUid, fieldName = refInfo.split(':')
|
||||||
obj = self.getObject(objectUid)
|
obj = self.getObject(objectUid)
|
||||||
|
@ -856,7 +857,7 @@ class ToolMixin(BaseMixin):
|
||||||
try:
|
try:
|
||||||
creds = creds.split(' ')[-1]
|
creds = creds.split(' ')[-1]
|
||||||
login, password = base64.decodestring(creds).split(':', 1)
|
login, password = base64.decodestring(creds).split(':', 1)
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
pass
|
pass
|
||||||
# b. Identify the user from the authentication cookie.
|
# b. Identify the user from the authentication cookie.
|
||||||
if not login:
|
if not login:
|
||||||
|
@ -968,7 +969,7 @@ class ToolMixin(BaseMixin):
|
||||||
# Invalidate the user session.
|
# Invalidate the user session.
|
||||||
try:
|
try:
|
||||||
sdm = self.session_data_manager
|
sdm = self.session_data_manager
|
||||||
except AttributeError, ae:
|
except AttributeError as ae:
|
||||||
# When ran in test mode, session_data_manager is not there.
|
# When ran in test mode, session_data_manager is not there.
|
||||||
sdm = None
|
sdm = None
|
||||||
if sdm:
|
if sdm:
|
||||||
|
@ -977,7 +978,7 @@ class ToolMixin(BaseMixin):
|
||||||
session.invalidate()
|
session.invalidate()
|
||||||
self.log('logged out.')
|
self.log('logged out.')
|
||||||
# Remove user from variable "loggedUsers"
|
# 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())
|
return self.goto(self.getApp().absolute_url())
|
||||||
|
|
||||||
# This dict stores, for every logged user, the date/time of its last access
|
# 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'):
|
if hasattr(klass, 'popup'):
|
||||||
res.target = 'appyIFrame'
|
res.target = 'appyIFrame'
|
||||||
d = klass.popup
|
d = klass.popup
|
||||||
if isinstance(d, basestring):
|
if isinstance(d, str):
|
||||||
# Width only
|
# Width only
|
||||||
params = d[:-2]
|
params = d[:-2]
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
- mixins/ToolMixin is mixed in with the generated application Tool class.'''
|
- 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 import Object
|
||||||
from appy.px import Px
|
from appy.px import Px
|
||||||
from appy.fields.workflow import UiTransition
|
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.data import rtlLanguages
|
||||||
from appy.shared.xml_parser import XmlMarshaller, XmlUnmarshaller
|
from appy.shared.xml_parser import XmlMarshaller, XmlUnmarshaller
|
||||||
from appy.shared.diff import HtmlDiff
|
from appy.shared.diff import HtmlDiff
|
||||||
|
import collections
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
NUMBERED_ID = re.compile('.+\d{4}$')
|
NUMBERED_ID = re.compile('.+\d{4}$')
|
||||||
|
@ -371,9 +372,9 @@ class BaseMixin:
|
||||||
# p_errors object. Within this object, for every error message that is
|
# 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
|
# not a string, we replace it with the standard validation error for the
|
||||||
# corresponding field.
|
# corresponding field.
|
||||||
for key, value in errors.__dict__.iteritems():
|
for key, value in errors.__dict__.items():
|
||||||
resValue = value
|
resValue = value
|
||||||
if not isinstance(resValue, basestring):
|
if not isinstance(resValue, str):
|
||||||
resValue = self.translate('field_invalid')
|
resValue = self.translate('field_invalid')
|
||||||
setattr(errors, key, resValue)
|
setattr(errors, key, resValue)
|
||||||
return msg
|
return msg
|
||||||
|
@ -419,7 +420,7 @@ class BaseMixin:
|
||||||
# Trigger field-specific validation
|
# Trigger field-specific validation
|
||||||
self.intraFieldValidation(errors, values)
|
self.intraFieldValidation(errors, values)
|
||||||
if errors.__dict__:
|
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)
|
self.say(errorMessage)
|
||||||
return self.gotoEdit()
|
return self.gotoEdit()
|
||||||
|
|
||||||
|
@ -427,7 +428,7 @@ class BaseMixin:
|
||||||
msg = self.interFieldValidation(errors, values)
|
msg = self.interFieldValidation(errors, values)
|
||||||
if not msg: msg = errorMessage
|
if not msg: msg = errorMessage
|
||||||
if errors.__dict__:
|
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)
|
self.say(msg)
|
||||||
return self.gotoEdit()
|
return self.gotoEdit()
|
||||||
|
|
||||||
|
@ -506,7 +507,7 @@ class BaseMixin:
|
||||||
# Get the list of indexes that apply on this object. Else, Zope
|
# Get the list of indexes that apply on this object. Else, Zope
|
||||||
# will reindex all indexes defined in the catalog, and through
|
# will reindex all indexes defined in the catalog, and through
|
||||||
# acquisition, wrong methods can be called on wrong objects.
|
# 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)
|
catalog.catalog_object(self, path, idxs=iNames)
|
||||||
|
|
||||||
def xml(self, action=None):
|
def xml(self, action=None):
|
||||||
|
@ -529,14 +530,14 @@ class BaseMixin:
|
||||||
elif isinstance(methodRes, file):
|
elif isinstance(methodRes, file):
|
||||||
res = methodRes.read()
|
res = methodRes.read()
|
||||||
methodRes.close()
|
methodRes.close()
|
||||||
elif isinstance(methodRes, basestring) and \
|
elif isinstance(methodRes, str) and \
|
||||||
methodRes.startswith('<?xml'): # Already XML
|
methodRes.startswith('<?xml'): # Already XML
|
||||||
return methodRes
|
return methodRes
|
||||||
else:
|
else:
|
||||||
marshaller = XmlMarshaller()
|
marshaller = XmlMarshaller()
|
||||||
oType = isinstance(methodRes, Object) and 'popo' or 'appy'
|
oType = isinstance(methodRes, Object) and 'popo' or 'appy'
|
||||||
res = marshaller.marshall(methodRes, objectType=oType)
|
res = marshaller.marshall(methodRes, objectType=oType)
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
tb = sutils.Traceback.get()
|
tb = sutils.Traceback.get()
|
||||||
res = XmlMarshaller(rootTag='exception').marshall(tb)
|
res = XmlMarshaller(rootTag='exception').marshall(tb)
|
||||||
self.log(tb, type='error')
|
self.log(tb, type='error')
|
||||||
|
@ -548,7 +549,7 @@ class BaseMixin:
|
||||||
'''Prints a p_msg in the user interface. p_logLevel may be "info",
|
'''Prints a p_msg in the user interface. p_logLevel may be "info",
|
||||||
"warning" or "error".'''
|
"warning" or "error".'''
|
||||||
rq = self.REQUEST
|
rq = self.REQUEST
|
||||||
if 'messages' not in rq.SESSION.keys():
|
if 'messages' not in list(rq.SESSION.keys()):
|
||||||
plist = self.getProductConfig().PersistentList
|
plist = self.getProductConfig().PersistentList
|
||||||
messages = rq.SESSION['messages'] = plist()
|
messages = rq.SESSION['messages'] = plist()
|
||||||
else:
|
else:
|
||||||
|
@ -619,7 +620,7 @@ class BaseMixin:
|
||||||
For a multilingual string field, p_changes can contain a key for
|
For a multilingual string field, p_changes can contain a key for
|
||||||
every language, of the form <field name>-<language>.'''
|
every language, of the form <field name>-<language>.'''
|
||||||
# Add to the p_changes dict the field labels
|
# 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.
|
# "name" can contain the language for multilingual fields.
|
||||||
if '-' in name:
|
if '-' in name:
|
||||||
fieldName, lg = name.split('-')
|
fieldName, lg = name.split('-')
|
||||||
|
@ -646,7 +647,7 @@ class BaseMixin:
|
||||||
historized fields, while p_self already contains the (potentially)
|
historized fields, while p_self already contains the (potentially)
|
||||||
modified values.'''
|
modified values.'''
|
||||||
# Remove from previousData all values that were not changed
|
# Remove from previousData all values that were not changed
|
||||||
for name in previousData.keys():
|
for name in list(previousData.keys()):
|
||||||
field = self.getAppyType(name)
|
field = self.getAppyType(name)
|
||||||
prev = previousData[name]
|
prev = previousData[name]
|
||||||
curr = field.getValue(self)
|
curr = field.getValue(self)
|
||||||
|
@ -655,7 +656,7 @@ class BaseMixin:
|
||||||
((prev == '') and (curr == None)):
|
((prev == '') and (curr == None)):
|
||||||
del previousData[name]
|
del previousData[name]
|
||||||
continue
|
continue
|
||||||
except UnicodeDecodeError, ude:
|
except UnicodeDecodeError as ude:
|
||||||
# The string comparisons above may imply silent encoding-related
|
# The string comparisons above may imply silent encoding-related
|
||||||
# conversions that may produce this exception.
|
# conversions that may produce this exception.
|
||||||
continue
|
continue
|
||||||
|
@ -743,15 +744,15 @@ class BaseMixin:
|
||||||
else:
|
else:
|
||||||
klass = self.appy().klass
|
klass = self.appy().klass
|
||||||
moduleName = klass.__module__
|
moduleName = klass.__module__
|
||||||
exec 'import %s' % moduleName
|
exec('import %s' % moduleName)
|
||||||
exec 'reload(%s)' % moduleName
|
exec('reload(%s)' % moduleName)
|
||||||
exec 'res = %s.%s' % (moduleName, klass.__name__)
|
exec('res = %s.%s' % (moduleName, klass.__name__))
|
||||||
# More manipulations may have occurred in m_update
|
# More manipulations may have occurred in m_update
|
||||||
if hasattr(res, 'update'):
|
if hasattr(res, 'update'):
|
||||||
parentName= res.__bases__[-1].__name__
|
parentName= res.__bases__[-1].__name__
|
||||||
moduleName= 'Products.%s.wrappers' % self.getTool().getAppName()
|
moduleName= 'Products.%s.wrappers' % self.getTool().getAppName()
|
||||||
exec 'import %s' % moduleName
|
exec('import %s' % moduleName)
|
||||||
exec 'parent = %s.%s' % (moduleName, parentName)
|
exec('parent = %s.%s' % (moduleName, parentName))
|
||||||
res.update(parent)
|
res.update(parent)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
@ -839,15 +840,15 @@ class BaseMixin:
|
||||||
req = self.REQUEST
|
req = self.REQUEST
|
||||||
for field in self.getAllAppyTypes():
|
for field in self.getAllAppyTypes():
|
||||||
if field.page.name != pageName: continue
|
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.
|
# We have a slave field that is updated via ajax requests.
|
||||||
name = field.name
|
name = field.name
|
||||||
# Remember the request value for this field if present.
|
# 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]
|
requestValues[name] = req[name]
|
||||||
# Remember the validation error for this field if present.
|
# Remember the validation error for this field if present.
|
||||||
errorKey = '%s_error' % name
|
errorKey = '%s_error' % name
|
||||||
if req.has_key(errorKey):
|
if errorKey in req:
|
||||||
errors[name] = req[errorKey]
|
errors[name] = req[errorKey]
|
||||||
return sutils.getStringDict(requestValues), sutils.getStringDict(errors)
|
return sutils.getStringDict(requestValues), sutils.getStringDict(errors)
|
||||||
|
|
||||||
|
@ -899,7 +900,7 @@ class BaseMixin:
|
||||||
del phases[res[i].name]
|
del phases[res[i].name]
|
||||||
del res[i]
|
del res[i]
|
||||||
# Compute next/previous phases of every phase
|
# Compute next/previous phases of every phase
|
||||||
for ph in phases.itervalues():
|
for ph in phases.values():
|
||||||
ph.computeNextPrevious(res)
|
ph.computeNextPrevious(res)
|
||||||
ph.totalNbOfPhases = len(res)
|
ph.totalNbOfPhases = len(res)
|
||||||
# Restrict the result to the current phase if required
|
# Restrict the result to the current phase if required
|
||||||
|
@ -1208,7 +1209,7 @@ class BaseMixin:
|
||||||
# fields' old values by their formatted counterparts.
|
# fields' old values by their formatted counterparts.
|
||||||
event = history[i].copy()
|
event = history[i].copy()
|
||||||
event['changes'] = {}
|
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
|
# "name" can specify a language-specific part in a
|
||||||
# multilingual field. "oldValue" is a tuple
|
# multilingual field. "oldValue" is a tuple
|
||||||
# (value, fieldName).
|
# (value, fieldName).
|
||||||
|
@ -1455,7 +1456,7 @@ class BaseMixin:
|
||||||
# Add users or groups having, locally, this role on this object.
|
# Add users or groups having, locally, this role on this object.
|
||||||
localRoles = getattr(self.aq_base, '__ac_local_roles__', None)
|
localRoles = getattr(self.aq_base, '__ac_local_roles__', None)
|
||||||
if not localRoles: return res
|
if not localRoles: return res
|
||||||
for id, roles in localRoles.iteritems():
|
for id, roles in localRoles.items():
|
||||||
for role in roles:
|
for role in roles:
|
||||||
if role in res:
|
if role in res:
|
||||||
usr = 'user:%s' % id
|
usr = 'user:%s' % id
|
||||||
|
@ -1465,7 +1466,7 @@ class BaseMixin:
|
||||||
def showState(self):
|
def showState(self):
|
||||||
'''Must I show self's current state ?'''
|
'''Must I show self's current state ?'''
|
||||||
stateShow = self.State(name=False).show
|
stateShow = self.State(name=False).show
|
||||||
if callable(stateShow):
|
if isinstance(stateShow, collections.Callable):
|
||||||
return stateShow(self.getWorkflow(), self.appy())
|
return stateShow(self.getWorkflow(), self.appy())
|
||||||
return stateShow
|
return stateShow
|
||||||
|
|
||||||
|
@ -1479,7 +1480,7 @@ class BaseMixin:
|
||||||
if not hasattr(klass, 'showTransitions'): return (layoutType=='view')
|
if not hasattr(klass, 'showTransitions'): return (layoutType=='view')
|
||||||
showValue = klass.showTransitions
|
showValue = klass.showTransitions
|
||||||
# This value can be a single value or a tuple/list of values.
|
# 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
|
return layoutType in showValue
|
||||||
|
|
||||||
getUrlDefaults = {'page':True, 'nav':True}
|
getUrlDefaults = {'page':True, 'nav':True}
|
||||||
|
@ -1524,8 +1525,8 @@ class BaseMixin:
|
||||||
if 'nav' not in kwargs: kwargs['nav'] = True
|
if 'nav' not in kwargs: kwargs['nav'] = True
|
||||||
# Create URL parameters from kwargs
|
# Create URL parameters from kwargs
|
||||||
params = []
|
params = []
|
||||||
for name, value in kwargs.iteritems():
|
for name, value in kwargs.items():
|
||||||
if isinstance(value, basestring):
|
if isinstance(value, str):
|
||||||
params.append('%s=%s' % (name, value))
|
params.append('%s=%s' % (name, value))
|
||||||
elif self.REQUEST.get(name, ''):
|
elif self.REQUEST.get(name, ''):
|
||||||
params.append('%s=%s' % (name, self.REQUEST[name]))
|
params.append('%s=%s' % (name, self.REQUEST[name]))
|
||||||
|
@ -1601,7 +1602,7 @@ class BaseMixin:
|
||||||
# Find the name of the method to call.
|
# Find the name of the method to call.
|
||||||
methodName = rq.QUERY_STRING.split('=')[1]
|
methodName = rq.QUERY_STRING.split('=')[1]
|
||||||
return self.xml(action=methodName)
|
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
|
# The user wants to call a method on this object and get its result
|
||||||
# as XML.
|
# as XML.
|
||||||
return self.xml(action=rq['do'])
|
return self.xml(action=rq['do'])
|
||||||
|
@ -1672,7 +1673,7 @@ class BaseMixin:
|
||||||
if field.type != 'group':
|
if field.type != 'group':
|
||||||
fieldMapping = field.mapping[label]
|
fieldMapping = field.mapping[label]
|
||||||
if fieldMapping:
|
if fieldMapping:
|
||||||
if callable(fieldMapping):
|
if isinstance(fieldMapping, collections.Callable):
|
||||||
fieldMapping = field.callMethod(self, fieldMapping)
|
fieldMapping = field.callMethod(self, fieldMapping)
|
||||||
mapping.update(fieldMapping)
|
mapping.update(fieldMapping)
|
||||||
label = getattr(field, '%sId' % label)
|
label = getattr(field, '%sId' % label)
|
||||||
|
@ -1697,15 +1698,15 @@ class BaseMixin:
|
||||||
# Perform replacements, according to p_format.
|
# Perform replacements, according to p_format.
|
||||||
res = self.formatText(res, format)
|
res = self.formatText(res, format)
|
||||||
# Perform variable replacements
|
# Perform variable replacements
|
||||||
for name, repl in mapping.iteritems():
|
for name, repl in mapping.items():
|
||||||
if not isinstance(repl, basestring): repl = str(repl)
|
if not isinstance(repl, str): repl = str(repl)
|
||||||
res = res.replace('${%s}' % name, repl)
|
res = res.replace('${%s}' % name, repl)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def getPageLayout(self, layoutType):
|
def getPageLayout(self, layoutType):
|
||||||
'''Returns the layout corresponding to p_layoutType for p_self.'''
|
'''Returns the layout corresponding to p_layoutType for p_self.'''
|
||||||
res = self.wrapperClass.getPageLayouts()[layoutType]
|
res = self.wrapperClass.getPageLayouts()[layoutType]
|
||||||
if isinstance(res, basestring): res = Table(res)
|
if isinstance(res, str): res = Table(res)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def download(self, name=None):
|
def download(self, name=None):
|
||||||
|
|
21
gen/model.py
21
gen/model.py
|
@ -5,6 +5,7 @@
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
import types
|
import types
|
||||||
import appy.gen as gen
|
import appy.gen as gen
|
||||||
|
import collections
|
||||||
|
|
||||||
# Prototypical instances of every type -----------------------------------------
|
# Prototypical instances of every type -----------------------------------------
|
||||||
class Protos:
|
class Protos:
|
||||||
|
@ -49,7 +50,7 @@ class ModelClass:
|
||||||
'''This method returns the code declaration for p_appyType.'''
|
'''This method returns the code declaration for p_appyType.'''
|
||||||
typeArgs = ''
|
typeArgs = ''
|
||||||
proto = Protos.get(appyType)
|
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
|
# Some attrs can't be given to the constructor
|
||||||
if name in Protos.notInit: continue
|
if name in Protos.notInit: continue
|
||||||
# If the given value corresponds to the default value, don't give it
|
# 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
|
# defined. So we initialize it to None. The post-init of the
|
||||||
# field must be done manually in wrappers.py.
|
# field must be done manually in wrappers.py.
|
||||||
value = 'None'
|
value = 'None'
|
||||||
elif isinstance(value, basestring):
|
elif isinstance(value, str):
|
||||||
value = '"%s"' % value
|
value = '"%s"' % value
|
||||||
elif isinstance(value, gen.Ref):
|
elif isinstance(value, gen.Ref):
|
||||||
if not value.isBack: continue
|
if not value.isBack: continue
|
||||||
|
@ -91,10 +92,10 @@ class ModelClass:
|
||||||
value = 'Grp("%s")' % value.name
|
value = 'Grp("%s")' % value.name
|
||||||
elif isinstance(value, gen.Page):
|
elif isinstance(value, gen.Page):
|
||||||
value = 'pges["%s"]' % value.name
|
value = 'pges["%s"]' % value.name
|
||||||
elif callable(value):
|
elif isinstance(value, collections.Callable):
|
||||||
className = wrapperName
|
className = wrapperName
|
||||||
if (appyType.type == 'Ref') and appyType.isBack:
|
if (appyType.type == 'Ref') and appyType.isBack:
|
||||||
className = value.im_class.__name__
|
className = value.__self__.__class__.__name__
|
||||||
value = '%s.%s' % (className, value.__name__)
|
value = '%s.%s' % (className, value.__name__)
|
||||||
typeArgs += '%s=%s,' % (name, value)
|
typeArgs += '%s=%s,' % (name, value)
|
||||||
return '%s(%s)' % (appyType.__class__.__name__, typeArgs)
|
return '%s(%s)' % (appyType.__class__.__name__, typeArgs)
|
||||||
|
@ -118,17 +119,17 @@ class ModelClass:
|
||||||
pages = {}
|
pages = {}
|
||||||
layouts = []
|
layouts = []
|
||||||
for name in klass._appy_attributes:
|
for name in klass._appy_attributes:
|
||||||
exec 'appyType = klass.%s' % name
|
exec('appyType = klass.%s' % name)
|
||||||
if appyType.page.name not in pages:
|
if appyType.page.name not in pages:
|
||||||
pages[appyType.page.name] = appyType.page
|
pages[appyType.page.name] = appyType.page
|
||||||
res += ' pges = {'
|
res += ' pges = {'
|
||||||
for page in pages.itervalues():
|
for page in pages.values():
|
||||||
# Determine page "show" attributes
|
# Determine page "show" attributes
|
||||||
pShow = ''
|
pShow = ''
|
||||||
for attr in ('',) + page.subElements:
|
for attr in ('',) + page.subElements:
|
||||||
attrName = 'show%s' % attr.capitalize()
|
attrName = 'show%s' % attr.capitalize()
|
||||||
pageShow = getattr(page, attrName)
|
pageShow = getattr(page, attrName)
|
||||||
if isinstance(pageShow, basestring): pageShow='"%s"' % pageShow
|
if isinstance(pageShow, str): pageShow='"%s"' % pageShow
|
||||||
elif callable(pageShow):
|
elif callable(pageShow):
|
||||||
pageShow = '%s.%s' % (wrapperName, pageShow.__name__)
|
pageShow = '%s.%s' % (wrapperName, pageShow.__name__)
|
||||||
if pageShow != True:
|
if pageShow != True:
|
||||||
|
@ -142,7 +143,7 @@ class ModelClass:
|
||||||
res += '}\n'
|
res += '}\n'
|
||||||
# Secondly, dump every (not Ref.isBack) attribute
|
# Secondly, dump every (not Ref.isBack) attribute
|
||||||
for name in klass._appy_attributes:
|
for name in klass._appy_attributes:
|
||||||
exec 'appyType = klass.%s' % name
|
exec('appyType = klass.%s' % name)
|
||||||
if (appyType.type == 'Ref') and appyType.isBack: continue
|
if (appyType.type == 'Ref') and appyType.isBack: continue
|
||||||
typeBody = klass._appy_getTypeBody(appyType, wrapperName)
|
typeBody = klass._appy_getTypeBody(appyType, wrapperName)
|
||||||
res += ' %s=%s\n' % (name, typeBody)
|
res += ' %s=%s\n' % (name, typeBody)
|
||||||
|
@ -305,12 +306,12 @@ class Tool(ModelClass):
|
||||||
@classmethod
|
@classmethod
|
||||||
def _appy_clean(klass):
|
def _appy_clean(klass):
|
||||||
toClean = []
|
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 not k.startswith('__') and (not k.startswith('_appy_')):
|
||||||
if k not in defaultToolFields:
|
if k not in defaultToolFields:
|
||||||
toClean.append(k)
|
toClean.append(k)
|
||||||
for k in toClean:
|
for k in toClean:
|
||||||
exec 'del klass.%s' % k
|
exec('del klass.%s' % k)
|
||||||
klass._appy_attributes = list(defaultToolFields)
|
klass._appy_attributes = list(defaultToolFields)
|
||||||
klass.folder = True
|
klass.folder = True
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
import os, re, time, copy
|
import os, re, time, copy
|
||||||
from utils import produceNiceMessage
|
from .utils import produceNiceMessage
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
poHeader = '''msgid ""
|
poHeader = '''msgid ""
|
||||||
|
@ -213,7 +213,7 @@ class PoFile:
|
||||||
if keepExistingOrder:
|
if keepExistingOrder:
|
||||||
# Update existing messages and add inexistent messages to the end.
|
# Update existing messages and add inexistent messages to the end.
|
||||||
for newMsg in newMessages:
|
for newMsg in newMessages:
|
||||||
if self.messagesDict.has_key(newMsg.id):
|
if newMsg.id in self.messagesDict:
|
||||||
msg = self.messagesDict[newMsg.id]
|
msg = self.messagesDict[newMsg.id]
|
||||||
else:
|
else:
|
||||||
msg = self.addMessage(newMsg)
|
msg = self.addMessage(newMsg)
|
||||||
|
@ -224,7 +224,7 @@ class PoFile:
|
||||||
notNewMessages = [m for m in self.messages if m.id not in newIds]
|
notNewMessages = [m for m in self.messages if m.id not in newIds]
|
||||||
del self.messages[:]
|
del self.messages[:]
|
||||||
for newMsg in newMessages:
|
for newMsg in newMessages:
|
||||||
if self.messagesDict.has_key(newMsg.id):
|
if newMsg.id in self.messagesDict:
|
||||||
msg = self.messagesDict[newMsg.id]
|
msg = self.messagesDict[newMsg.id]
|
||||||
self.messages.append(msg)
|
self.messages.append(msg)
|
||||||
else:
|
else:
|
||||||
|
@ -240,7 +240,7 @@ class PoFile:
|
||||||
fb = ''
|
fb = ''
|
||||||
if not self.isPot:
|
if not self.isPot:
|
||||||
# I must add fallbacks
|
# 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]
|
fb = '"X-is-fallback-for: %s\\n"' % fallbacks[self.language]
|
||||||
f.write(poHeader % (self.applicationName, creationTime,
|
f.write(poHeader % (self.applicationName, creationTime,
|
||||||
self.language, self.language, self.domain, fb))
|
self.language, self.language, self.domain, fb))
|
||||||
|
|
21
gen/utils.py
21
gen/utils.py
|
@ -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.px import Px
|
||||||
from appy.shared import utils as sutils
|
from appy.shared import utils as sutils
|
||||||
|
import collections
|
||||||
|
|
||||||
# Function for creating a Zope object ------------------------------------------
|
# Function for creating a Zope object ------------------------------------------
|
||||||
def createObject(folder, id, className, appName, wf=True, noSecurity=False):
|
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
|
creation of the config object), computing workflow-related info is not
|
||||||
possible at this time. This is why this function can be called with
|
possible at this time. This is why this function can be called with
|
||||||
p_wf=False.'''
|
p_wf=False.'''
|
||||||
exec 'from Products.%s.%s import %s as ZopeClass' % \
|
exec('from Products.%s.%s import %s as ZopeClass' % \
|
||||||
(appName, className, className)
|
(appName, className, className))
|
||||||
# Get the tool. It may not be present yet, maybe are we creating it now.
|
# Get the tool. It may not be present yet, maybe are we creating it now.
|
||||||
if folder.meta_type.endswith('Folder'):
|
if folder.meta_type.endswith('Folder'):
|
||||||
# p_folder is a standard Zope (temp) folder.
|
# p_folder is a standard Zope (temp) folder.
|
||||||
|
@ -178,7 +179,7 @@ def callMethod(obj, method, klass=None, cache=True):
|
||||||
if methodType == 'staticmethod':
|
if methodType == 'staticmethod':
|
||||||
method = method.__get__(klass)
|
method = method.__get__(klass)
|
||||||
elif methodType == 'instancemethod':
|
elif methodType == 'instancemethod':
|
||||||
method = method.im_func
|
method = method.__func__
|
||||||
# Call the method if cache is not needed
|
# Call the method if cache is not needed
|
||||||
if not cache: return method(obj)
|
if not cache: return method(obj)
|
||||||
# If first arg of method is named "tool" instead of the traditional "self",
|
# 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
|
# Every method call, even on different instances, will be cached in a unique
|
||||||
# key.
|
# key.
|
||||||
cheat = False
|
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__
|
prefix = obj.klass.__name__
|
||||||
obj = obj.tool
|
obj = obj.tool
|
||||||
cheat = True
|
cheat = True
|
||||||
|
@ -200,7 +201,7 @@ def callMethod(obj, method, klass=None, cache=True):
|
||||||
else:
|
else:
|
||||||
prefix = obj.uid
|
prefix = obj.uid
|
||||||
# Second part of the key: p_method name
|
# 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.
|
# Return the cached value if present in the method cache.
|
||||||
if key in rq.methodCache:
|
if key in rq.methodCache:
|
||||||
return rq.methodCache[key]
|
return rq.methodCache[key]
|
||||||
|
@ -216,20 +217,20 @@ def readCookie(request):
|
||||||
(None, None).'''
|
(None, None).'''
|
||||||
cookie = request.get('_appy_', None)
|
cookie = request.get('_appy_', None)
|
||||||
if not cookie: return None, 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(':')
|
if ':' in cookieValue: return cookieValue.split(':')
|
||||||
return None, None
|
return None, None
|
||||||
|
|
||||||
def writeCookie(login, password, request):
|
def writeCookie(login, password, request):
|
||||||
'''Encode p_login and p_password into the cookie set in the p_request.'''
|
'''Encode p_login and p_password into the cookie set in the p_request.'''
|
||||||
cookieValue = base64.encodestring('%s:%s' % (login, password)).rstrip()
|
cookieValue = base64.encodestring('%s:%s' % (login, password)).rstrip()
|
||||||
cookieValue = urllib.quote(cookieValue)
|
cookieValue = urllib.parse.quote(cookieValue)
|
||||||
request.RESPONSE.setCookie('_appy_', cookieValue, path='/')
|
request.RESPONSE.setCookie('_appy_', cookieValue, path='/')
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
def initMasterValue(v):
|
def initMasterValue(v):
|
||||||
'''Standardizes p_v as a list of strings, excepted if p_v is a method.'''
|
'''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 = []
|
if not isinstance(v, bool) and not v: res = []
|
||||||
elif type(v) not in sutils.sequenceTypes: res = [v]
|
elif type(v) not in sutils.sequenceTypes: res = [v]
|
||||||
else: res = v
|
else: res = v
|
||||||
|
@ -243,7 +244,7 @@ class No:
|
||||||
instead. When creating such an instance, you can specify an error
|
instead. When creating such an instance, you can specify an error
|
||||||
message.'''
|
message.'''
|
||||||
def __init__(self, msg): self.msg = msg
|
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
|
def __repr__(self): return '<No: %s>' % self.msg
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -424,7 +424,7 @@ class ToolWrapper(AbstractWrapper):
|
||||||
'<tr><th></th><th>%s</th></tr>' % \
|
'<tr><th></th><th>%s</th></tr>' % \
|
||||||
self.translate('last_user_access')
|
self.translate('last_user_access')
|
||||||
rows = []
|
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)
|
user = self.search1('User', noSecurity=True, login=userId)
|
||||||
if not user: continue # Could have been deleted in the meanwhile
|
if not user: continue # Could have been deleted in the meanwhile
|
||||||
fmt = '%s (%s)' % (self.dateFormat, self.hourFormat)
|
fmt = '%s (%s)' % (self.dateFormat, self.hourFormat)
|
||||||
|
@ -515,7 +515,7 @@ class ToolWrapper(AbstractWrapper):
|
||||||
failed += subFailed
|
failed += subFailed
|
||||||
try:
|
try:
|
||||||
startObject.reindex()
|
startObject.reindex()
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
failed.append(startObject)
|
failed.append(startObject)
|
||||||
return nb, failed
|
return nb, failed
|
||||||
|
|
||||||
|
|
|
@ -343,7 +343,7 @@ class UserWrapper(AbstractWrapper):
|
||||||
if not localRoles: return res
|
if not localRoles: return res
|
||||||
# Gets the logins of this user and all its groups.
|
# Gets the logins of this user and all its groups.
|
||||||
logins = self.getLogins()
|
logins = self.getLogins()
|
||||||
for login, roles in localRoles.iteritems():
|
for login, roles in localRoles.items():
|
||||||
# Ignore logins not corresponding to this user.
|
# Ignore logins not corresponding to this user.
|
||||||
if login not in logins: continue
|
if login not in logins: continue
|
||||||
for role in roles:
|
for role in roles:
|
||||||
|
@ -388,7 +388,7 @@ class UserWrapper(AbstractWrapper):
|
||||||
if not localRoles: return
|
if not localRoles: return
|
||||||
# Gets the logins of this user and all its groups.
|
# Gets the logins of this user and all its groups.
|
||||||
userLogins = self.getLogins()
|
userLogins = self.getLogins()
|
||||||
for login, roles in localRoles.iteritems():
|
for login, roles in localRoles.items():
|
||||||
# Ignore logins not corresponding to this user.
|
# Ignore logins not corresponding to this user.
|
||||||
if login not in userLogins: continue
|
if login not in userLogins: continue
|
||||||
for role in roles:
|
for role in roles:
|
||||||
|
|
|
@ -861,7 +861,7 @@ class AbstractWrapper(object):
|
||||||
if len(self.__class__.__bases__) > 1:
|
if len(self.__class__.__bases__) > 1:
|
||||||
# There is a custom user class
|
# There is a custom user class
|
||||||
custom = self.__class__.__bases__[-1]
|
custom = self.__class__.__bases__[-1]
|
||||||
if custom.__dict__.has_key(methodName):
|
if methodName in custom.__dict__:
|
||||||
return custom.__dict__[methodName]
|
return custom.__dict__[methodName]
|
||||||
|
|
||||||
def _callCustom(self, methodName, *args, **kwargs):
|
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
|
present, will not be called; any other defined method will not be
|
||||||
called neither (ie, Ref.insert, Ref.beforeLink, Ref.afterLink...).
|
called neither (ie, Ref.insert, Ref.beforeLink, Ref.afterLink...).
|
||||||
'''
|
'''
|
||||||
isField = isinstance(fieldNameOrClass, basestring)
|
isField = isinstance(fieldNameOrClass, str)
|
||||||
tool = self.tool.o
|
tool = self.tool.o
|
||||||
# Determine the class of the object to create
|
# Determine the class of the object to create
|
||||||
if isField:
|
if isField:
|
||||||
|
@ -984,7 +984,7 @@ class AbstractWrapper(object):
|
||||||
klass = fieldNameOrClass
|
klass = fieldNameOrClass
|
||||||
portalType = tool.getPortalType(klass)
|
portalType = tool.getPortalType(klass)
|
||||||
# Determine object id
|
# Determine object id
|
||||||
if kwargs.has_key('id'):
|
if 'id' in kwargs:
|
||||||
objId = kwargs['id']
|
objId = kwargs['id']
|
||||||
del kwargs['id']
|
del kwargs['id']
|
||||||
else:
|
else:
|
||||||
|
@ -1002,7 +1002,7 @@ class AbstractWrapper(object):
|
||||||
noSecurity=noSecurity)
|
noSecurity=noSecurity)
|
||||||
appyObj = zopeObj.appy()
|
appyObj = zopeObj.appy()
|
||||||
# Set object attributes
|
# Set object attributes
|
||||||
for attrName, attrValue in kwargs.iteritems():
|
for attrName, attrValue in kwargs.items():
|
||||||
try:
|
try:
|
||||||
setattr(appyObj, attrName, attrValue)
|
setattr(appyObj, attrName, attrValue)
|
||||||
except AttributeError, ae:
|
except AttributeError, ae:
|
||||||
|
@ -1183,8 +1183,8 @@ class AbstractWrapper(object):
|
||||||
# Get the Appy object from the brain
|
# Get the Appy object from the brain
|
||||||
if noSecurity: method = '_unrestrictedGetObject'
|
if noSecurity: method = '_unrestrictedGetObject'
|
||||||
else: method = 'getObject'
|
else: method = 'getObject'
|
||||||
exec 'obj = brain.%s().appy()' % method
|
exec('obj = brain.%s().appy()' % method)
|
||||||
exec expression
|
exec(expression)
|
||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
def reindex(self, fields=None, unindex=False):
|
def reindex(self, fields=None, unindex=False):
|
||||||
|
@ -1249,7 +1249,7 @@ class AbstractWrapper(object):
|
||||||
else:
|
else:
|
||||||
return xml
|
return xml
|
||||||
elif format == 'csv':
|
elif format == 'csv':
|
||||||
if isinstance(at, basestring):
|
if isinstance(at, str):
|
||||||
marshaller = CsvMarshaller(include=include, exclude=exclude)
|
marshaller = CsvMarshaller(include=include, exclude=exclude)
|
||||||
return marshaller.marshall(self)
|
return marshaller.marshall(self)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -101,7 +101,7 @@ class BufferAction:
|
||||||
try:
|
try:
|
||||||
res = self._evalExpr(expr, context)
|
res = self._evalExpr(expr, context)
|
||||||
error = False
|
error = False
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
res = None
|
res = None
|
||||||
errorMessage = EVAL_ERROR % (expr, self.getExceptionLine(e))
|
errorMessage = EVAL_ERROR % (expr, self.getExceptionLine(e))
|
||||||
self.manageError(result, context, errorMessage)
|
self.manageError(result, context, errorMessage)
|
||||||
|
@ -134,7 +134,7 @@ class BufferAction:
|
||||||
error = False
|
error = False
|
||||||
try:
|
try:
|
||||||
feRes = eval(self.fromExpr, context)
|
feRes = eval(self.fromExpr, context)
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
msg = FROM_EVAL_ERROR% (self.fromExpr, self.getExceptionLine(e))
|
msg = FROM_EVAL_ERROR% (self.fromExpr, self.getExceptionLine(e))
|
||||||
self.manageError(result, context, msg)
|
self.manageError(result, context, msg)
|
||||||
error = True
|
error = True
|
||||||
|
@ -240,7 +240,7 @@ class ForAction(BufferAction):
|
||||||
return
|
return
|
||||||
# Remember variable hidden by iter if any
|
# Remember variable hidden by iter if any
|
||||||
hasHiddenVariable = False
|
hasHiddenVariable = False
|
||||||
if context.has_key(self.iter):
|
if self.iter in context:
|
||||||
hiddenVariable = context[self.iter]
|
hiddenVariable = context[self.iter]
|
||||||
hasHiddenVariable = True
|
hasHiddenVariable = True
|
||||||
# In the case of cells, initialize some values
|
# In the case of cells, initialize some values
|
||||||
|
|
|
@ -80,15 +80,15 @@ NULL_ACTION_ERROR = 'There was a problem with this action. Possible causes: ' \
|
||||||
class BufferIterator:
|
class BufferIterator:
|
||||||
def __init__(self, buffer):
|
def __init__(self, buffer):
|
||||||
self.buffer = buffer
|
self.buffer = buffer
|
||||||
self.remainingSubBufferIndexes = self.buffer.subBuffers.keys()
|
self.remainingSubBufferIndexes = list(self.buffer.subBuffers.keys())
|
||||||
self.remainingElemIndexes = self.buffer.elements.keys()
|
self.remainingElemIndexes = list(self.buffer.elements.keys())
|
||||||
self.remainingSubBufferIndexes.sort()
|
self.remainingSubBufferIndexes.sort()
|
||||||
self.remainingElemIndexes.sort()
|
self.remainingElemIndexes.sort()
|
||||||
|
|
||||||
def hasNext(self):
|
def hasNext(self):
|
||||||
return self.remainingSubBufferIndexes or self.remainingElemIndexes
|
return self.remainingSubBufferIndexes or self.remainingElemIndexes
|
||||||
|
|
||||||
def next(self):
|
def __next__(self):
|
||||||
nextSubBufferIndex = None
|
nextSubBufferIndex = None
|
||||||
if self.remainingSubBufferIndexes:
|
if self.remainingSubBufferIndexes:
|
||||||
nextSubBufferIndex = self.remainingSubBufferIndexes[0]
|
nextSubBufferIndex = self.remainingSubBufferIndexes[0]
|
||||||
|
@ -131,7 +131,7 @@ class Buffer:
|
||||||
return subBuffer
|
return subBuffer
|
||||||
|
|
||||||
def removeLastSubBuffer(self):
|
def removeLastSubBuffer(self):
|
||||||
subBufferIndexes = self.subBuffers.keys()
|
subBufferIndexes = list(self.subBuffers.keys())
|
||||||
subBufferIndexes.sort()
|
subBufferIndexes.sort()
|
||||||
lastIndex = subBufferIndexes.pop()
|
lastIndex = subBufferIndexes.pop()
|
||||||
del self.subBuffers[lastIndex]
|
del self.subBuffers[lastIndex]
|
||||||
|
@ -176,7 +176,7 @@ class Buffer:
|
||||||
self.write('<%s' % elem)
|
self.write('<%s' % elem)
|
||||||
# Some table elements must be patched (pod only)
|
# Some table elements must be patched (pod only)
|
||||||
if self.pod: self.patchTableElement(elem, attrs)
|
if self.pod: self.patchTableElement(elem, attrs)
|
||||||
for name, value in attrs.items():
|
for name, value in list(attrs.items()):
|
||||||
if ignoreAttrs and (name in ignoreAttrs): continue
|
if ignoreAttrs and (name in ignoreAttrs): continue
|
||||||
if renamedAttrs and (name in renamedAttrs): name=renamedAttrs[name]
|
if renamedAttrs and (name in renamedAttrs): name=renamedAttrs[name]
|
||||||
# If the value begins with ':', it is a Python expression. Else,
|
# If the value begins with ':', it is a Python expression. Else,
|
||||||
|
@ -244,7 +244,7 @@ class FileBuffer(Buffer):
|
||||||
res, escape = expr.evaluate(self.env.context)
|
res, escape = expr.evaluate(self.env.context)
|
||||||
if escape: self.dumpContent(res)
|
if escape: self.dumpContent(res)
|
||||||
else: self.write(res)
|
else: self.write(res)
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
if not self.env.raiseOnError:
|
if not self.env.raiseOnError:
|
||||||
PodError.dump(self, EVAL_EXPR_ERROR % (expression, e),
|
PodError.dump(self, EVAL_EXPR_ERROR % (expression, e),
|
||||||
dumpTb=False)
|
dumpTb=False)
|
||||||
|
@ -271,7 +271,7 @@ class MemoryBuffer(Buffer):
|
||||||
|
|
||||||
def __init__(self, env, parent):
|
def __init__(self, env, parent):
|
||||||
Buffer.__init__(self, env, parent)
|
Buffer.__init__(self, env, parent)
|
||||||
self.content = u''
|
self.content = ''
|
||||||
self.elements = {}
|
self.elements = {}
|
||||||
self.action = None
|
self.action = None
|
||||||
|
|
||||||
|
@ -297,7 +297,7 @@ class MemoryBuffer(Buffer):
|
||||||
|
|
||||||
def getIndex(self, podElemName):
|
def getIndex(self, podElemName):
|
||||||
res = -1
|
res = -1
|
||||||
for index, podElem in self.elements.iteritems():
|
for index, podElem in self.elements.items():
|
||||||
if podElem.__class__.__name__.lower() == podElemName:
|
if podElem.__class__.__name__.lower() == podElemName:
|
||||||
if index > res:
|
if index > res:
|
||||||
res = index
|
res = index
|
||||||
|
@ -305,7 +305,7 @@ class MemoryBuffer(Buffer):
|
||||||
|
|
||||||
def getMainElement(self):
|
def getMainElement(self):
|
||||||
res = None
|
res = None
|
||||||
if self.elements.has_key(0):
|
if 0 in self.elements:
|
||||||
res = self.elements[0]
|
res = self.elements[0]
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
@ -317,7 +317,7 @@ class MemoryBuffer(Buffer):
|
||||||
if elem != mainElem: return
|
if elem != mainElem: return
|
||||||
# elem is the same as the main elem. But is it really the main elem, or
|
# elem is the same as the main elem. But is it really the main elem, or
|
||||||
# the same elem, found deeper in the buffer?
|
# the same elem, found deeper in the buffer?
|
||||||
for index, iElem in self.elements.iteritems():
|
for index, iElem in self.elements.items():
|
||||||
foundElem = None
|
foundElem = None
|
||||||
if hasattr(iElem, 'OD'):
|
if hasattr(iElem, 'OD'):
|
||||||
if iElem.OD:
|
if iElem.OD:
|
||||||
|
@ -331,7 +331,7 @@ class MemoryBuffer(Buffer):
|
||||||
def unreferenceElement(self, elem):
|
def unreferenceElement(self, elem):
|
||||||
# Find last occurrence of this element
|
# Find last occurrence of this element
|
||||||
elemIndex = -1
|
elemIndex = -1
|
||||||
for index, iElem in self.elements.iteritems():
|
for index, iElem in self.elements.items():
|
||||||
foundElem = None
|
foundElem = None
|
||||||
if hasattr(iElem, 'OD'):
|
if hasattr(iElem, 'OD'):
|
||||||
# A POD element
|
# A POD element
|
||||||
|
@ -347,7 +347,7 @@ class MemoryBuffer(Buffer):
|
||||||
def pushSubBuffer(self, subBuffer):
|
def pushSubBuffer(self, subBuffer):
|
||||||
'''Sets p_subBuffer at the very end of the buffer.'''
|
'''Sets p_subBuffer at the very end of the buffer.'''
|
||||||
subIndex = None
|
subIndex = None
|
||||||
for index, aSubBuffer in self.subBuffers.iteritems():
|
for index, aSubBuffer in self.subBuffers.items():
|
||||||
if aSubBuffer == subBuffer:
|
if aSubBuffer == subBuffer:
|
||||||
subIndex = index
|
subIndex = index
|
||||||
break
|
break
|
||||||
|
@ -356,7 +356,7 @@ class MemoryBuffer(Buffer):
|
||||||
# in the parent (if it is a temp buffer generated from a cut)
|
# in the parent (if it is a temp buffer generated from a cut)
|
||||||
del self.subBuffers[subIndex]
|
del self.subBuffers[subIndex]
|
||||||
self.subBuffers[self.getLength()] = subBuffer
|
self.subBuffers[self.getLength()] = subBuffer
|
||||||
self.content += u' '
|
self.content += ' '
|
||||||
|
|
||||||
def transferAllContent(self):
|
def transferAllContent(self):
|
||||||
'''Transfer all content to parent.'''
|
'''Transfer all content to parent.'''
|
||||||
|
@ -370,10 +370,10 @@ class MemoryBuffer(Buffer):
|
||||||
oldParentLength = self.parent.getLength()
|
oldParentLength = self.parent.getLength()
|
||||||
self.parent.write(self.content)
|
self.parent.write(self.content)
|
||||||
# Transfer elements
|
# Transfer elements
|
||||||
for index, podElem in self.elements.iteritems():
|
for index, podElem in self.elements.items():
|
||||||
self.parent.elements[oldParentLength + index] = podElem
|
self.parent.elements[oldParentLength + index] = podElem
|
||||||
# Transfer sub-buffers
|
# Transfer sub-buffers
|
||||||
for index, buf in self.subBuffers.iteritems():
|
for index, buf in self.subBuffers.items():
|
||||||
self.parent.subBuffers[oldParentLength + index] = buf
|
self.parent.subBuffers[oldParentLength + index] = buf
|
||||||
# Empty the buffer
|
# Empty the buffer
|
||||||
MemoryBuffer.__init__(self, self.env, self.parent)
|
MemoryBuffer.__init__(self, self.env, self.parent)
|
||||||
|
@ -391,7 +391,7 @@ class MemoryBuffer(Buffer):
|
||||||
elem.colIndex = elem.tableInfo.curColIndex
|
elem.colIndex = elem.tableInfo.curColIndex
|
||||||
if elem == 'x':
|
if elem == 'x':
|
||||||
# See comment on similar statement in the method below.
|
# See comment on similar statement in the method below.
|
||||||
self.content += u' '
|
self.content += ' '
|
||||||
|
|
||||||
def addExpression(self, expression, tiedHook=None):
|
def addExpression(self, expression, tiedHook=None):
|
||||||
# Create the POD expression
|
# Create the POD expression
|
||||||
|
@ -400,20 +400,20 @@ class MemoryBuffer(Buffer):
|
||||||
self.elements[self.getLength()] = expr
|
self.elements[self.getLength()] = expr
|
||||||
# To be sure that an expr and an elem can't be found at the same index
|
# To be sure that an expr and an elem can't be found at the same index
|
||||||
# in the buffer.
|
# in the buffer.
|
||||||
self.content += u' '
|
self.content += ' '
|
||||||
|
|
||||||
def addAttributes(self):
|
def addAttributes(self):
|
||||||
'''pod-only: adds an Attributes instance into this buffer.'''
|
'''pod-only: adds an Attributes instance into this buffer.'''
|
||||||
attrs = Attributes(self.env)
|
attrs = Attributes(self.env)
|
||||||
self.elements[self.getLength()] = attrs
|
self.elements[self.getLength()] = attrs
|
||||||
self.content += u' '
|
self.content += ' '
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
def addAttribute(self, name, expr):
|
def addAttribute(self, name, expr):
|
||||||
'''px-only: adds an Attribute instance into this buffer.'''
|
'''px-only: adds an Attribute instance into this buffer.'''
|
||||||
attr = Attribute(name, expr)
|
attr = Attribute(name, expr)
|
||||||
self.elements[self.getLength()] = attr
|
self.elements[self.getLength()] = attr
|
||||||
self.content += u' '
|
self.content += ' '
|
||||||
return attr
|
return attr
|
||||||
|
|
||||||
def _getVariables(self, expr):
|
def _getVariables(self, expr):
|
||||||
|
@ -453,7 +453,7 @@ class MemoryBuffer(Buffer):
|
||||||
raise ParsingError(
|
raise ParsingError(
|
||||||
ELEMENT_NOT_FOUND % (podElem, str([
|
ELEMENT_NOT_FOUND % (podElem, str([
|
||||||
e.__class__.__name__.lower() \
|
e.__class__.__name__.lower() \
|
||||||
for e in self.elements.values()])))
|
for e in list(self.elements.values())])))
|
||||||
podElem = self.elements[indexPodElem]
|
podElem = self.elements[indexPodElem]
|
||||||
# Check the 'from' clause
|
# Check the 'from' clause
|
||||||
fromClause = None
|
fromClause = None
|
||||||
|
@ -471,7 +471,7 @@ class MemoryBuffer(Buffer):
|
||||||
self.env.ifActions.append(self.action)
|
self.env.ifActions.append(self.action)
|
||||||
if self.action.name:
|
if self.action.name:
|
||||||
# We must register this action as a named action
|
# We must register this action as a named action
|
||||||
if self.env.namedIfActions.has_key(self.action.name):
|
if self.action.name in self.env.namedIfActions:
|
||||||
raise ParsingError(DUPLICATE_NAMED_IF)
|
raise ParsingError(DUPLICATE_NAMED_IF)
|
||||||
self.env.namedIfActions[self.action.name] = self.action
|
self.env.namedIfActions[self.action.name] = self.action
|
||||||
elif actionType == 'else':
|
elif actionType == 'else':
|
||||||
|
@ -480,7 +480,7 @@ class MemoryBuffer(Buffer):
|
||||||
# Does the "else" action reference a named "if" action?
|
# Does the "else" action reference a named "if" action?
|
||||||
ifReference = subExpr.strip()
|
ifReference = subExpr.strip()
|
||||||
if ifReference:
|
if ifReference:
|
||||||
if not self.env.namedIfActions.has_key(ifReference):
|
if ifReference not in self.env.namedIfActions:
|
||||||
raise ParsingError(ELSE_WITHOUT_NAMED_IF % ifReference)
|
raise ParsingError(ELSE_WITHOUT_NAMED_IF % ifReference)
|
||||||
linkedIfAction = self.env.namedIfActions[ifReference]
|
linkedIfAction = self.env.namedIfActions[ifReference]
|
||||||
# This "else" action "consumes" the "if" action: this way,
|
# This "else" action "consumes" the "if" action: this way,
|
||||||
|
@ -510,7 +510,7 @@ class MemoryBuffer(Buffer):
|
||||||
self.action = NullAction(statementName, self, None, podElem,
|
self.action = NullAction(statementName, self, None, podElem,
|
||||||
None, source, fromClause)
|
None, source, fromClause)
|
||||||
res = indexPodElem
|
res = indexPodElem
|
||||||
except ParsingError, ppe:
|
except ParsingError as ppe:
|
||||||
PodError.dump(self, ppe, removeFirstLine=True)
|
PodError.dump(self, ppe, removeFirstLine=True)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
@ -552,7 +552,7 @@ class MemoryBuffer(Buffer):
|
||||||
elementsToDelete = []
|
elementsToDelete = []
|
||||||
mustShift = False
|
mustShift = False
|
||||||
while iter.hasNext():
|
while iter.hasNext():
|
||||||
itemIndex, item = iter.next()
|
itemIndex, item = next(iter)
|
||||||
if keepFirstPart:
|
if keepFirstPart:
|
||||||
if itemIndex >= index:
|
if itemIndex >= index:
|
||||||
newIndex = itemIndex-index
|
newIndex = itemIndex-index
|
||||||
|
@ -580,11 +580,11 @@ class MemoryBuffer(Buffer):
|
||||||
del self.subBuffers[subIndex]
|
del self.subBuffers[subIndex]
|
||||||
if mustShift:
|
if mustShift:
|
||||||
elements = {}
|
elements = {}
|
||||||
for elemIndex, elem in self.elements.iteritems():
|
for elemIndex, elem in self.elements.items():
|
||||||
elements[elemIndex-index] = elem
|
elements[elemIndex-index] = elem
|
||||||
self.elements = elements
|
self.elements = elements
|
||||||
subBuffers = {}
|
subBuffers = {}
|
||||||
for subIndex, buf in self.subBuffers.iteritems():
|
for subIndex, buf in self.subBuffers.items():
|
||||||
subBuffers[subIndex-index] = buf
|
subBuffers[subIndex-index] = buf
|
||||||
self.subBuffers = subBuffers
|
self.subBuffers = subBuffers
|
||||||
# Manage content
|
# Manage content
|
||||||
|
@ -598,7 +598,7 @@ class MemoryBuffer(Buffer):
|
||||||
|
|
||||||
def getElementIndexes(self, expressions=True):
|
def getElementIndexes(self, expressions=True):
|
||||||
res = []
|
res = []
|
||||||
for index, elem in self.elements.iteritems():
|
for index, elem in self.elements.items():
|
||||||
condition = isinstance(elem, Expression) or \
|
condition = isinstance(elem, Expression) or \
|
||||||
isinstance(elem, Attributes)
|
isinstance(elem, Attributes)
|
||||||
if not expressions:
|
if not expressions:
|
||||||
|
@ -696,7 +696,7 @@ class MemoryBuffer(Buffer):
|
||||||
iter = BufferIterator(self)
|
iter = BufferIterator(self)
|
||||||
currentIndex = self.getStartIndex(removeMainElems)
|
currentIndex = self.getStartIndex(removeMainElems)
|
||||||
while iter.hasNext():
|
while iter.hasNext():
|
||||||
index, evalEntry = iter.next()
|
index, evalEntry = next(iter)
|
||||||
result.write(self.content[currentIndex:index])
|
result.write(self.content[currentIndex:index])
|
||||||
currentIndex = index + 1
|
currentIndex = index + 1
|
||||||
if isinstance(evalEntry, Expression):
|
if isinstance(evalEntry, Expression):
|
||||||
|
@ -708,7 +708,7 @@ class MemoryBuffer(Buffer):
|
||||||
# This exception has already been treated (see the
|
# This exception has already been treated (see the
|
||||||
# "except" block below). Simply re-raise it when needed.
|
# "except" block below). Simply re-raise it when needed.
|
||||||
if self.env.raiseOnError: raise e
|
if self.env.raiseOnError: raise e
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
if not self.env.raiseOnError:
|
if not self.env.raiseOnError:
|
||||||
PodError.dump(result, EVAL_EXPR_ERROR % (
|
PodError.dump(result, EVAL_EXPR_ERROR % (
|
||||||
evalEntry.expr, e))
|
evalEntry.expr, e))
|
||||||
|
@ -729,5 +729,5 @@ class MemoryBuffer(Buffer):
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
'''Cleans the buffer content.'''
|
'''Cleans the buffer content.'''
|
||||||
self.content = u''
|
self.content = ''
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -109,7 +109,7 @@ class Converter:
|
||||||
res = res[self.inputType]
|
res = res[self.inputType]
|
||||||
else:
|
else:
|
||||||
raise ConverterError(BAD_RESULT_TYPE % (self.resultType,
|
raise ConverterError(BAD_RESULT_TYPE % (self.resultType,
|
||||||
FILE_TYPES.keys()))
|
list(FILE_TYPES.keys())))
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def getResultUrl(self):
|
def getResultUrl(self):
|
||||||
|
@ -275,7 +275,7 @@ class ConverterScript:
|
||||||
' %s.\n' \
|
' %s.\n' \
|
||||||
' "python" should be a UNO-enabled Python interpreter (ie the ' \
|
' "python" should be a UNO-enabled Python interpreter (ie the ' \
|
||||||
' one which is included in the LibreOffice distribution).' % \
|
' one which is included in the LibreOffice distribution).' % \
|
||||||
str(FILE_TYPES.keys())
|
str(list(FILE_TYPES.keys()))
|
||||||
def run(self):
|
def run(self):
|
||||||
optParser = OptionParser(usage=ConverterScript.usage)
|
optParser = OptionParser(usage=ConverterScript.usage)
|
||||||
optParser.add_option("-p", "--port", dest="port",
|
optParser.add_option("-p", "--port", dest="port",
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,USA.
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,USA.
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
import os, os.path, time, shutil, struct, random, urlparse
|
import os, os.path, time, shutil, struct, random, urllib.parse
|
||||||
from appy.pod import PodError
|
from appy.pod import PodError
|
||||||
from appy.pod.odf_parser import OdfEnvironment
|
from appy.pod.odf_parser import OdfEnvironment
|
||||||
from appy.shared import mimeTypesExts
|
from appy.shared import mimeTypesExts
|
||||||
|
@ -53,7 +53,7 @@ class DocImporter:
|
||||||
if at and not at.startswith('http') and not os.path.isfile(at):
|
if at and not at.startswith('http') and not os.path.isfile(at):
|
||||||
raise PodError(FILE_NOT_FOUND % at)
|
raise PodError(FILE_NOT_FOUND % at)
|
||||||
self.format = format
|
self.format = format
|
||||||
self.res = u''
|
self.res = ''
|
||||||
self.renderer = renderer
|
self.renderer = renderer
|
||||||
self.ns = renderer.currentParser.env.namespaces
|
self.ns = renderer.currentParser.env.namespaces
|
||||||
# Unpack some useful namespaces
|
# Unpack some useful namespaces
|
||||||
|
@ -285,7 +285,7 @@ class ImageImporter(DocImporter):
|
||||||
def moveFile(self, at, importPath):
|
def moveFile(self, at, importPath):
|
||||||
'''Copies file at p_at into the ODT file at p_importPath.'''
|
'''Copies file at p_at into the ODT file at p_importPath.'''
|
||||||
# Has this image already been imported ?
|
# Has this image already been imported ?
|
||||||
for imagePath, imageAt in self.fileNames.iteritems():
|
for imagePath, imageAt in self.fileNames.items():
|
||||||
if imageAt == at:
|
if imageAt == at:
|
||||||
# Yes!
|
# Yes!
|
||||||
i = importPath.rfind(self.pictFolder) + 1
|
i = importPath.rfind(self.pictFolder) + 1
|
||||||
|
@ -327,7 +327,7 @@ class ImageImporter(DocImporter):
|
||||||
# The imageResolver is a Zope application. From it, we will
|
# The imageResolver is a Zope application. From it, we will
|
||||||
# retrieve the object on which the image is stored and get
|
# retrieve the object on which the image is stored and get
|
||||||
# the file to download.
|
# the file to download.
|
||||||
urlParts = urlparse.urlsplit(at)
|
urlParts = urllib.parse.urlsplit(at)
|
||||||
path = urlParts[2][1:].split('/')[:-1]
|
path = urlParts[2][1:].split('/')[:-1]
|
||||||
try:
|
try:
|
||||||
obj = imageResolver.unrestrictedTraverse(path)
|
obj = imageResolver.unrestrictedTraverse(path)
|
||||||
|
|
|
@ -148,7 +148,7 @@ class Expression(PodElement):
|
||||||
# pod/px result.
|
# pod/px result.
|
||||||
resultType = res.__class__.__name__
|
resultType = res.__class__.__name__
|
||||||
if resultType == 'NoneType':
|
if resultType == 'NoneType':
|
||||||
res = u''
|
res = ''
|
||||||
elif resultType == 'str':
|
elif resultType == 'str':
|
||||||
res = res.decode('utf-8')
|
res = res.decode('utf-8')
|
||||||
elif resultType == 'unicode':
|
elif resultType == 'unicode':
|
||||||
|
@ -160,7 +160,7 @@ class Expression(PodElement):
|
||||||
# Force escapeXml to False.
|
# Force escapeXml to False.
|
||||||
escapeXml = False
|
escapeXml = False
|
||||||
else:
|
else:
|
||||||
res = unicode(res)
|
res = str(res)
|
||||||
return res, escapeXml
|
return res, escapeXml
|
||||||
|
|
||||||
class Attributes(PodElement):
|
class Attributes(PodElement):
|
||||||
|
@ -199,7 +199,7 @@ class Attributes(PodElement):
|
||||||
try:
|
try:
|
||||||
self.tiedExpression.evaluate(context)
|
self.tiedExpression.evaluate(context)
|
||||||
self.tiedExpression.evaluated = True
|
self.tiedExpression.evaluated = True
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
# Don't set "evaluated" to True. This way, when the buffer will
|
# Don't set "evaluated" to True. This way, when the buffer will
|
||||||
# evaluate the expression directly, we will really evaluate it, so
|
# evaluate the expression directly, we will really evaluate it, so
|
||||||
# the error will be dumped into the pod result.
|
# the error will be dumped into the pod result.
|
||||||
|
@ -208,7 +208,7 @@ class Attributes(PodElement):
|
||||||
self.computeAttributes(self.tiedExpression)
|
self.computeAttributes(self.tiedExpression)
|
||||||
# Now, self.attrs has been populated. Transform it into a string.
|
# Now, self.attrs has been populated. Transform it into a string.
|
||||||
res = ''
|
res = ''
|
||||||
for name, value in self.attrs.iteritems():
|
for name, value in self.attrs.items():
|
||||||
res += ' %s=%s' % (name, quoteattr(value))
|
res += ' %s=%s' % (name, quoteattr(value))
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ class OdInsert:
|
||||||
def resolve(self, namespaces):
|
def resolve(self, namespaces):
|
||||||
'''Replaces all unresolved namespaces in p_odtChunk, thanks to the dict
|
'''Replaces all unresolved namespaces in p_odtChunk, thanks to the dict
|
||||||
of p_namespaces.'''
|
of p_namespaces.'''
|
||||||
for nsName, nsUri in self.nsUris.iteritems():
|
for nsName, nsUri in self.nsUris.items():
|
||||||
self.odtChunk = re.sub('@%s@' % nsName, namespaces[nsUri],
|
self.odtChunk = re.sub('@%s@' % nsName, namespaces[nsUri],
|
||||||
self.odtChunk)
|
self.odtChunk)
|
||||||
return self.odtChunk
|
return self.odtChunk
|
||||||
|
@ -126,14 +126,14 @@ class PodEnvironment(OdfEnvironment):
|
||||||
res = {}
|
res = {}
|
||||||
for insert in self.inserts:
|
for insert in self.inserts:
|
||||||
elemName = insert.elem.getFullName(self.namespaces)
|
elemName = insert.elem.getFullName(self.namespaces)
|
||||||
if not res.has_key(elemName):
|
if elemName not in res:
|
||||||
res[elemName] = insert
|
res[elemName] = insert
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def manageInserts(self):
|
def manageInserts(self):
|
||||||
'''We just dumped the start of an elem. Here we will insert any odt
|
'''We just dumped the start of an elem. Here we will insert any odt
|
||||||
chunk if needed.'''
|
chunk if needed.'''
|
||||||
if self.inserts.has_key(self.currentElem.elem):
|
if self.currentElem.elem in self.inserts:
|
||||||
insert = self.inserts[self.currentElem.elem]
|
insert = self.inserts[self.currentElem.elem]
|
||||||
self.currentBuffer.write(insert.resolve(self.namespaces))
|
self.currentBuffer.write(insert.resolve(self.namespaces))
|
||||||
# The insert is destroyed after single use
|
# The insert is destroyed after single use
|
||||||
|
@ -160,12 +160,12 @@ class PodEnvironment(OdfEnvironment):
|
||||||
elif elem == Cell.OD.elem:
|
elif elem == Cell.OD.elem:
|
||||||
colspan = 1
|
colspan = 1
|
||||||
attrSpan = self.tags['number-columns-spanned']
|
attrSpan = self.tags['number-columns-spanned']
|
||||||
if self.currentElem.attrs.has_key(attrSpan):
|
if attrSpan in self.currentElem.attrs:
|
||||||
colspan = int(self.currentElem.attrs[attrSpan])
|
colspan = int(self.currentElem.attrs[attrSpan])
|
||||||
self.getTable().curColIndex += colspan
|
self.getTable().curColIndex += colspan
|
||||||
elif elem == self.tags['table-column']:
|
elif elem == self.tags['table-column']:
|
||||||
attrs = self.currentElem.attrs
|
attrs = self.currentElem.attrs
|
||||||
if attrs.has_key(self.tags['number-columns-repeated']):
|
if self.tags['number-columns-repeated'] in attrs:
|
||||||
self.getTable().nbOfColumns += int(
|
self.getTable().nbOfColumns += int(
|
||||||
attrs[self.tags['number-columns-repeated']])
|
attrs[self.tags['number-columns-repeated']])
|
||||||
else:
|
else:
|
||||||
|
@ -254,8 +254,8 @@ class PodParser(OdfParser):
|
||||||
e.state = e.READING_EXPRESSION
|
e.state = e.READING_EXPRESSION
|
||||||
e.exprHasStyle = False
|
e.exprHasStyle = False
|
||||||
elif (elem == e.tags['table-cell']) and \
|
elif (elem == e.tags['table-cell']) and \
|
||||||
attrs.has_key(e.tags['formula']) and \
|
e.tags['formula'] in attrs and \
|
||||||
attrs.has_key(e.tags['value-type']) and \
|
e.tags['value-type'] in attrs and \
|
||||||
(attrs[e.tags['value-type']] == 'string') and \
|
(attrs[e.tags['value-type']] == 'string') and \
|
||||||
attrs[e.tags['formula']].startswith('of:="'):
|
attrs[e.tags['formula']].startswith('of:="'):
|
||||||
# In an ODS template, any cell containing a formula of type "string"
|
# In an ODS template, any cell containing a formula of type "string"
|
||||||
|
|
|
@ -18,7 +18,11 @@
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
import zipfile, shutil, xml.sax, os, os.path, re, mimetypes, time
|
import zipfile, shutil, xml.sax, os, os.path, re, mimetypes, time
|
||||||
|
#python3 compat
|
||||||
|
try:
|
||||||
from UserDict import UserDict
|
from UserDict import UserDict
|
||||||
|
except ImportError:
|
||||||
|
from collections import UserDict
|
||||||
import appy.pod
|
import appy.pod
|
||||||
from appy.pod import PodError
|
from appy.pod import PodError
|
||||||
from appy.shared import mimeTypes, mimeTypesExts
|
from appy.shared import mimeTypes, mimeTypesExts
|
||||||
|
@ -80,7 +84,7 @@ CONTENT_POD_FONTS = '<@style@:font-face @style@:name="PodStarSymbol" ' \
|
||||||
'@svg@:font-family="StarSymbol"/>'
|
'@svg@:font-family="StarSymbol"/>'
|
||||||
|
|
||||||
# Default text styles added by pod in styles.xml
|
# Default text styles added by pod in styles.xml
|
||||||
f = file('%s/styles.in.styles.xml' % os.path.dirname(appy.pod.__file__))
|
f = open('%s/styles.in.styles.xml' % os.path.dirname(appy.pod.__file__))
|
||||||
STYLES_POD_STYLES = f.read()
|
STYLES_POD_STYLES = f.read()
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
|
@ -263,7 +267,7 @@ class Renderer:
|
||||||
|
|
||||||
imageFormats = ('png', 'jpeg', 'jpg', 'gif', 'svg')
|
imageFormats = ('png', 'jpeg', 'jpg', 'gif', 'svg')
|
||||||
ooFormats = ('odt',)
|
ooFormats = ('odt',)
|
||||||
convertibleFormats = FILE_TYPES.keys()
|
convertibleFormats = list(FILE_TYPES.keys())
|
||||||
def importDocument(self, content=None, at=None, format=None,
|
def importDocument(self, content=None, at=None, format=None,
|
||||||
anchor='as-char', wrapInPara=True, size=None,
|
anchor='as-char', wrapInPara=True, size=None,
|
||||||
sizeUnit='cm', style=None,
|
sizeUnit='cm', style=None,
|
||||||
|
@ -309,7 +313,7 @@ class Renderer:
|
||||||
format = os.path.splitext(at)[1][1:]
|
format = os.path.splitext(at)[1][1:]
|
||||||
else:
|
else:
|
||||||
# If format is a mimeType, convert it to an extension
|
# If format is a mimeType, convert it to an extension
|
||||||
if mimeTypesExts.has_key(format):
|
if format in mimeTypesExts:
|
||||||
format = mimeTypesExts[format]
|
format = mimeTypesExts[format]
|
||||||
isImage = False
|
isImage = False
|
||||||
isOdt = False
|
isOdt = False
|
||||||
|
@ -370,9 +374,9 @@ class Renderer:
|
||||||
f = open(self.result, 'w')
|
f = open(self.result, 'w')
|
||||||
f.write('Hello')
|
f.write('Hello')
|
||||||
f.close()
|
f.close()
|
||||||
except OSError, oe:
|
except OSError as oe:
|
||||||
raise PodError(CANT_WRITE_RESULT % (self.result, oe))
|
raise PodError(CANT_WRITE_RESULT % (self.result, oe))
|
||||||
except IOError, ie:
|
except IOError as ie:
|
||||||
raise PodError(CANT_WRITE_RESULT % (self.result, ie))
|
raise PodError(CANT_WRITE_RESULT % (self.result, ie))
|
||||||
self.result = os.path.abspath(self.result)
|
self.result = os.path.abspath(self.result)
|
||||||
os.remove(self.result)
|
os.remove(self.result)
|
||||||
|
@ -381,7 +385,7 @@ class Renderer:
|
||||||
self.tempFolder = '%s.%f' % (absResult, time.time())
|
self.tempFolder = '%s.%f' % (absResult, time.time())
|
||||||
try:
|
try:
|
||||||
os.mkdir(self.tempFolder)
|
os.mkdir(self.tempFolder)
|
||||||
except OSError, oe:
|
except OSError as oe:
|
||||||
raise PodError(CANT_WRITE_TEMP_FOLDER % (self.result, oe))
|
raise PodError(CANT_WRITE_TEMP_FOLDER % (self.result, oe))
|
||||||
|
|
||||||
def patchManifest(self):
|
def patchManifest(self):
|
||||||
|
@ -390,7 +394,7 @@ class Renderer:
|
||||||
if self.fileNames:
|
if self.fileNames:
|
||||||
j = os.path.join
|
j = os.path.join
|
||||||
toInsert = ''
|
toInsert = ''
|
||||||
for fileName in self.fileNames.iterkeys():
|
for fileName in self.fileNames.keys():
|
||||||
if fileName.endswith('.svg'):
|
if fileName.endswith('.svg'):
|
||||||
fileName = os.path.splitext(fileName)[0] + '.png'
|
fileName = os.path.splitext(fileName)[0] + '.png'
|
||||||
mimeType = mimetypes.guess_type(fileName)[0]
|
mimeType = mimetypes.guess_type(fileName)[0]
|
||||||
|
@ -442,7 +446,7 @@ class Renderer:
|
||||||
if 'span[font-style=italic]' not in stylesMapping:
|
if 'span[font-style=italic]' not in stylesMapping:
|
||||||
stylesMapping['span[font-style=italic]'] = 'podItalic'
|
stylesMapping['span[font-style=italic]'] = 'podItalic'
|
||||||
self.stylesManager.stylesMapping = stylesMapping
|
self.stylesManager.stylesMapping = stylesMapping
|
||||||
except PodError, po:
|
except PodError as po:
|
||||||
self.contentParser.env.currentBuffer.content.close()
|
self.contentParser.env.currentBuffer.content.close()
|
||||||
self.stylesParser.env.currentBuffer.content.close()
|
self.stylesParser.env.currentBuffer.content.close()
|
||||||
if os.path.exists(self.tempFolder):
|
if os.path.exists(self.tempFolder):
|
||||||
|
@ -454,14 +458,14 @@ class Renderer:
|
||||||
loOutput = ''
|
loOutput = ''
|
||||||
try:
|
try:
|
||||||
if (not isinstance(self.ooPort, int)) and \
|
if (not isinstance(self.ooPort, int)) and \
|
||||||
(not isinstance(self.ooPort, long)):
|
(not isinstance(self.ooPort, int)):
|
||||||
raise PodError(BAD_OO_PORT % str(self.ooPort))
|
raise PodError(BAD_OO_PORT % str(self.ooPort))
|
||||||
try:
|
try:
|
||||||
from appy.pod.converter import Converter, ConverterError
|
from appy.pod.converter import Converter, ConverterError
|
||||||
try:
|
try:
|
||||||
Converter(resultName, resultType, self.ooPort,
|
Converter(resultName, resultType, self.ooPort,
|
||||||
self.stylesTemplate).run()
|
self.stylesTemplate).run()
|
||||||
except ConverterError, ce:
|
except ConverterError as ce:
|
||||||
raise PodError(CONVERT_ERROR % str(ce))
|
raise PodError(CONVERT_ERROR % str(ce))
|
||||||
except ImportError:
|
except ImportError:
|
||||||
# I do not have UNO. So try to launch a UNO-enabled Python
|
# I do not have UNO. So try to launch a UNO-enabled Python
|
||||||
|
@ -485,13 +489,13 @@ class Renderer:
|
||||||
self.ooPort)
|
self.ooPort)
|
||||||
if self.stylesTemplate: cmd += ' -t%s' % self.stylesTemplate
|
if self.stylesTemplate: cmd += ' -t%s' % self.stylesTemplate
|
||||||
loOutput = executeCommand(cmd)
|
loOutput = executeCommand(cmd)
|
||||||
except PodError, pe:
|
except PodError as pe:
|
||||||
# When trying to call LO in server mode for producing ODT or ODS
|
# When trying to call LO in server mode for producing ODT or ODS
|
||||||
# (=forceOoCall=True), if an error occurs we have nevertheless
|
# (=forceOoCall=True), if an error occurs we have nevertheless
|
||||||
# an ODT or ODS to return to the user. So we produce a warning
|
# an ODT or ODS to return to the user. So we produce a warning
|
||||||
# instead of raising an error.
|
# instead of raising an error.
|
||||||
if (resultType in self.templateTypes) and self.forceOoCall:
|
if (resultType in self.templateTypes) and self.forceOoCall:
|
||||||
print(WARNING_INCOMPLETE_OD % str(pe))
|
print((WARNING_INCOMPLETE_OD % str(pe)))
|
||||||
else:
|
else:
|
||||||
raise pe
|
raise pe
|
||||||
return loOutput
|
return loOutput
|
||||||
|
@ -501,7 +505,7 @@ class Renderer:
|
||||||
(ods or odt). If self.template is a string, it is a file name and we
|
(ods or odt). If self.template is a string, it is a file name and we
|
||||||
simply get its extension. Else, it is a binary file in a StringIO
|
simply get its extension. Else, it is a binary file in a StringIO
|
||||||
instance, and we seek the mime type from the first bytes.'''
|
instance, and we seek the mime type from the first bytes.'''
|
||||||
if isinstance(self.template, basestring):
|
if isinstance(self.template, str):
|
||||||
res = os.path.splitext(self.template)[1][1:]
|
res = os.path.splitext(self.template)[1][1:]
|
||||||
else:
|
else:
|
||||||
# A StringIO instance
|
# A StringIO instance
|
||||||
|
@ -534,8 +538,8 @@ class Renderer:
|
||||||
if self.finalizeFunction:
|
if self.finalizeFunction:
|
||||||
try:
|
try:
|
||||||
self.finalizeFunction(self.unzipFolder)
|
self.finalizeFunction(self.unzipFolder)
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
print(WARNING_FINALIZE_ERROR % str(e))
|
print((WARNING_FINALIZE_ERROR % str(e)))
|
||||||
# Re-zip the result, first as an OpenDocument file of the same type as
|
# Re-zip the result, first as an OpenDocument file of the same type as
|
||||||
# the POD template (odt, ods...)
|
# the POD template (odt, ods...)
|
||||||
resultExt = self.getTemplateType()
|
resultExt = self.getTemplateType()
|
||||||
|
|
|
@ -18,7 +18,12 @@
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
import re, os.path
|
import re, os.path
|
||||||
|
#python3 compat
|
||||||
|
try:
|
||||||
from UserDict import UserDict
|
from UserDict import UserDict
|
||||||
|
except ImportError:
|
||||||
|
from collections import UserDict
|
||||||
|
|
||||||
import appy.pod
|
import appy.pod
|
||||||
from appy.pod import *
|
from appy.pod import *
|
||||||
from appy.pod.odf_parser import OdfEnvironment, OdfParser
|
from appy.pod.odf_parser import OdfEnvironment, OdfParser
|
||||||
|
@ -93,7 +98,7 @@ class Styles(UserDict):
|
||||||
'''Tries to find a style which has level p_level. Returns None if no
|
'''Tries to find a style which has level p_level. Returns None if no
|
||||||
such style exists.'''
|
such style exists.'''
|
||||||
res = None
|
res = None
|
||||||
for style in self.itervalues():
|
for style in self.values():
|
||||||
if (style.family == 'paragraph') and (style.outlineLevel == level):
|
if (style.family == 'paragraph') and (style.outlineLevel == level):
|
||||||
res = style
|
res = style
|
||||||
break
|
break
|
||||||
|
@ -102,7 +107,7 @@ class Styles(UserDict):
|
||||||
'''Gets the style that has this p_displayName. Returns None if not
|
'''Gets the style that has this p_displayName. Returns None if not
|
||||||
found.'''
|
found.'''
|
||||||
res = None
|
res = None
|
||||||
for style in self.itervalues():
|
for style in self.values():
|
||||||
if style.displayName == displayName:
|
if style.displayName == displayName:
|
||||||
res = style
|
res = style
|
||||||
break
|
break
|
||||||
|
@ -111,9 +116,9 @@ class Styles(UserDict):
|
||||||
'''Returns a list of all the styles of the given p_stylesType.'''
|
'''Returns a list of all the styles of the given p_stylesType.'''
|
||||||
res = []
|
res = []
|
||||||
if stylesType == 'all':
|
if stylesType == 'all':
|
||||||
res = self.values()
|
res = list(self.values())
|
||||||
else:
|
else:
|
||||||
for style in self.itervalues():
|
for style in self.values():
|
||||||
if (style.family == stylesType) and style.displayName:
|
if (style.family == stylesType) and style.displayName:
|
||||||
res.append(style)
|
res.append(style)
|
||||||
return res
|
return res
|
||||||
|
@ -145,22 +150,22 @@ class StylesParser(OdfParser):
|
||||||
displayNameAttr = '%s:display-name' % e.ns(e.NS_STYLE)
|
displayNameAttr = '%s:display-name' % e.ns(e.NS_STYLE)
|
||||||
# Create the style
|
# Create the style
|
||||||
style = Style(name=attrs[nameAttr], family=attrs[familyAttr])
|
style = Style(name=attrs[nameAttr], family=attrs[familyAttr])
|
||||||
if attrs.has_key(classAttr):
|
if classAttr in attrs:
|
||||||
style.styleClass = attrs[classAttr]
|
style.styleClass = attrs[classAttr]
|
||||||
if attrs.has_key(displayNameAttr):
|
if displayNameAttr in attrs:
|
||||||
style.displayName = attrs[displayNameAttr]
|
style.displayName = attrs[displayNameAttr]
|
||||||
# Record this style in the environment
|
# Record this style in the environment
|
||||||
e.styles[style.name] = style
|
e.styles[style.name] = style
|
||||||
e.currentStyle = style
|
e.currentStyle = style
|
||||||
levelKey = '%s:default-outline-level' % e.ns(e.NS_STYLE)
|
levelKey = '%s:default-outline-level' % e.ns(e.NS_STYLE)
|
||||||
if attrs.has_key(levelKey) and attrs[levelKey].strip():
|
if levelKey in attrs and attrs[levelKey].strip():
|
||||||
style.outlineLevel = int(attrs[levelKey])
|
style.outlineLevel = int(attrs[levelKey])
|
||||||
else:
|
else:
|
||||||
if e.state == PARSING_STYLE:
|
if e.state == PARSING_STYLE:
|
||||||
# I am parsing tags within the style.
|
# I am parsing tags within the style.
|
||||||
if elem == ('%s:text-properties' % e.ns(e.NS_STYLE)):
|
if elem == ('%s:text-properties' % e.ns(e.NS_STYLE)):
|
||||||
fontSizeKey = '%s:font-size' % e.ns(e.NS_FO)
|
fontSizeKey = '%s:font-size' % e.ns(e.NS_FO)
|
||||||
if attrs.has_key(fontSizeKey):
|
if fontSizeKey in attrs:
|
||||||
e.currentStyle.setFontSize(attrs[fontSizeKey])
|
e.currentStyle.setFontSize(attrs[fontSizeKey])
|
||||||
def endElement(self, elem):
|
def endElement(self, elem):
|
||||||
e = OdfParser.endElement(self, elem)
|
e = OdfParser.endElement(self, elem)
|
||||||
|
@ -250,14 +255,14 @@ class StylesManager:
|
||||||
if not isinstance(stylesMapping, dict) and \
|
if not isinstance(stylesMapping, dict) and \
|
||||||
not isinstance(stylesMapping, UserDict):
|
not isinstance(stylesMapping, UserDict):
|
||||||
raise PodError(MAPPING_NOT_DICT)
|
raise PodError(MAPPING_NOT_DICT)
|
||||||
for xhtmlStyleName, odtStyleName in stylesMapping.iteritems():
|
for xhtmlStyleName, odtStyleName in stylesMapping.items():
|
||||||
if not isinstance(xhtmlStyleName, basestring):
|
if not isinstance(xhtmlStyleName, str):
|
||||||
raise PodError(MAPPING_ELEM_NOT_STRING)
|
raise PodError(MAPPING_ELEM_NOT_STRING)
|
||||||
if (xhtmlStyleName == 'h*') and \
|
if (xhtmlStyleName == 'h*') and \
|
||||||
not isinstance(odtStyleName, int):
|
not isinstance(odtStyleName, int):
|
||||||
raise PodError(MAPPING_OUTLINE_DELTA_NOT_INT)
|
raise PodError(MAPPING_OUTLINE_DELTA_NOT_INT)
|
||||||
if (xhtmlStyleName != 'h*') and \
|
if (xhtmlStyleName != 'h*') and \
|
||||||
not isinstance(odtStyleName, basestring):
|
not isinstance(odtStyleName, str):
|
||||||
raise PodError(MAPPING_ELEM_NOT_STRING)
|
raise PodError(MAPPING_ELEM_NOT_STRING)
|
||||||
if (xhtmlStyleName != 'h*') and \
|
if (xhtmlStyleName != 'h*') and \
|
||||||
((not xhtmlStyleName) or (not odtStyleName)):
|
((not xhtmlStyleName) or (not odtStyleName)):
|
||||||
|
@ -278,7 +283,7 @@ class StylesManager:
|
||||||
if xhtmlStyleName != 'h*':
|
if xhtmlStyleName != 'h*':
|
||||||
odtStyle = self.styles.getStyle(odtStyleName)
|
odtStyle = self.styles.getStyle(odtStyleName)
|
||||||
if not odtStyle:
|
if not odtStyle:
|
||||||
if self.podSpecificStyles.has_key(odtStyleName):
|
if odtStyleName in self.podSpecificStyles:
|
||||||
odtStyle = self.podSpecificStyles[odtStyleName]
|
odtStyle = self.podSpecificStyles[odtStyleName]
|
||||||
else:
|
else:
|
||||||
raise PodError(STYLE_NOT_FOUND % odtStyleName)
|
raise PodError(STYLE_NOT_FOUND % odtStyleName)
|
||||||
|
@ -311,7 +316,7 @@ class StylesManager:
|
||||||
This method returns True if p_attrs contains the winning (name,value)
|
This method returns True if p_attrs contains the winning (name,value)
|
||||||
pairs that match those in p_matchingAttrs. Note that ALL attrs in
|
pairs that match those in p_matchingAttrs. Note that ALL attrs in
|
||||||
p_matchingAttrs must be present in p_attrs.'''
|
p_matchingAttrs must be present in p_attrs.'''
|
||||||
for name, value in matchingAttrs.iteritems():
|
for name, value in matchingAttrs.items():
|
||||||
if name not in attrs: return
|
if name not in attrs: return
|
||||||
if value != attrs[name]: return
|
if value != attrs[name]: return
|
||||||
return True
|
return True
|
||||||
|
@ -356,29 +361,29 @@ class StylesManager:
|
||||||
'''
|
'''
|
||||||
res = None
|
res = None
|
||||||
cssStyleName = None
|
cssStyleName = None
|
||||||
if attrs and attrs.has_key('class'):
|
if attrs and 'class' in attrs:
|
||||||
cssStyleName = attrs['class']
|
cssStyleName = attrs['class']
|
||||||
if classValue:
|
if classValue:
|
||||||
cssStyleName = classValue
|
cssStyleName = classValue
|
||||||
# (1)
|
# (1)
|
||||||
if localStylesMapping.has_key(cssStyleName):
|
if cssStyleName in localStylesMapping:
|
||||||
res = localStylesMapping[cssStyleName]
|
res = localStylesMapping[cssStyleName]
|
||||||
# (2)
|
# (2)
|
||||||
if (not res) and localStylesMapping.has_key(elem):
|
if (not res) and elem in localStylesMapping:
|
||||||
styles = localStylesMapping[elem]
|
styles = localStylesMapping[elem]
|
||||||
res = self.getStyleFromMapping(elem, attrs, styles)
|
res = self.getStyleFromMapping(elem, attrs, styles)
|
||||||
# (3)
|
# (3)
|
||||||
if (not res) and self.stylesMapping.has_key(cssStyleName):
|
if (not res) and cssStyleName in self.stylesMapping:
|
||||||
res = self.stylesMapping[cssStyleName]
|
res = self.stylesMapping[cssStyleName]
|
||||||
# (4)
|
# (4)
|
||||||
if (not res) and self.stylesMapping.has_key(elem):
|
if (not res) and elem in self.stylesMapping:
|
||||||
styles = self.stylesMapping[elem]
|
styles = self.stylesMapping[elem]
|
||||||
res = self.getStyleFromMapping(elem, attrs, styles)
|
res = self.getStyleFromMapping(elem, attrs, styles)
|
||||||
# (5)
|
# (5)
|
||||||
if (not res) and self.styles.has_key(cssStyleName):
|
if (not res) and cssStyleName in self.styles:
|
||||||
res = self.styles[cssStyleName]
|
res = self.styles[cssStyleName]
|
||||||
# (6)
|
# (6)
|
||||||
if (not res) and self.podSpecificStyles.has_key(cssStyleName):
|
if (not res) and cssStyleName in self.podSpecificStyles:
|
||||||
res = self.podSpecificStyles[cssStyleName]
|
res = self.podSpecificStyles[cssStyleName]
|
||||||
# (7)
|
# (7)
|
||||||
if not res:
|
if not res:
|
||||||
|
@ -386,9 +391,9 @@ class StylesManager:
|
||||||
if elem in XHTML_HEADINGS:
|
if elem in XHTML_HEADINGS:
|
||||||
# Is there a delta that must be taken into account ?
|
# Is there a delta that must be taken into account ?
|
||||||
outlineDelta = 0
|
outlineDelta = 0
|
||||||
if localStylesMapping.has_key('h*'):
|
if 'h*' in localStylesMapping:
|
||||||
outlineDelta += localStylesMapping['h*']
|
outlineDelta += localStylesMapping['h*']
|
||||||
elif self.stylesMapping.has_key('h*'):
|
elif 'h*' in self.stylesMapping:
|
||||||
outlineDelta += self.stylesMapping['h*']
|
outlineDelta += self.stylesMapping['h*']
|
||||||
outlineLevel = int(elem[1]) + outlineDelta
|
outlineLevel = int(elem[1]) + outlineDelta
|
||||||
# Normalize the outline level
|
# Normalize the outline level
|
||||||
|
|
|
@ -38,7 +38,7 @@ class AnnotationsRemover(OdfParser):
|
||||||
machine-specific info, like absolute paths to the python files, etc.'''
|
machine-specific info, like absolute paths to the python files, etc.'''
|
||||||
def __init__(self, env, caller):
|
def __init__(self, env, caller):
|
||||||
OdfParser.__init__(self, env, caller)
|
OdfParser.__init__(self, env, caller)
|
||||||
self.res = u''
|
self.res = ''
|
||||||
self.inAnnotation = False # Are we parsing an annotation ?
|
self.inAnnotation = False # Are we parsing an annotation ?
|
||||||
self.textEncountered = False # Within an annotation, have we already
|
self.textEncountered = False # Within an annotation, have we already
|
||||||
# met a text ?
|
# met a text ?
|
||||||
|
@ -58,7 +58,7 @@ class AnnotationsRemover(OdfParser):
|
||||||
self.ignore = True
|
self.ignore = True
|
||||||
if not self.ignore:
|
if not self.ignore:
|
||||||
self.res += '<%s' % elem
|
self.res += '<%s' % elem
|
||||||
for attrName, attrValue in attrs.items():
|
for attrName, attrValue in list(attrs.items()):
|
||||||
self.res += ' %s="%s"' % (attrName, attrValue)
|
self.res += ' %s="%s"' % (attrName, attrValue)
|
||||||
self.res += '>'
|
self.res += '>'
|
||||||
def endElement(self, elem):
|
def endElement(self, elem):
|
||||||
|
@ -93,12 +93,12 @@ class Test(appy.shared.test.Test):
|
||||||
if not os.path.exists(contextPy):
|
if not os.path.exists(contextPy):
|
||||||
raise TesterError(CONTEXT_NOT_FOUND % contextPy)
|
raise TesterError(CONTEXT_NOT_FOUND % contextPy)
|
||||||
contextPkg = 'appy.pod.test.contexts.%s' % contextName
|
contextPkg = 'appy.pod.test.contexts.%s' % contextName
|
||||||
exec 'import %s' % contextPkg
|
exec('import %s' % contextPkg)
|
||||||
exec 'context = dir(%s)' % contextPkg
|
exec('context = dir(%s)' % contextPkg)
|
||||||
res = {}
|
res = {}
|
||||||
for elem in context:
|
for elem in context:
|
||||||
if not elem.startswith('__'):
|
if not elem.startswith('__'):
|
||||||
exec 'res[elem] = %s.%s' % (contextPkg, elem)
|
exec('res[elem] = %s.%s' % (contextPkg, elem))
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def do(self):
|
def do(self):
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
class Student:
|
class Student:
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
for k, v in kwargs.iteritems():
|
for k, v in kwargs.items():
|
||||||
setattr(self, k, v)
|
setattr(self, k, v)
|
||||||
|
|
||||||
students = [
|
students = [
|
||||||
|
|
|
@ -47,7 +47,7 @@ class HtmlElement:
|
||||||
# but for a strange reason those attrs are back to None (probably for
|
# but for a strange reason those attrs are back to None (probably for
|
||||||
# performance reasons they become inaccessible after a while).
|
# performance reasons they become inaccessible after a while).
|
||||||
self.classAttr = None
|
self.classAttr = None
|
||||||
if attrs.has_key('class'):
|
if 'class' in attrs:
|
||||||
self.classAttr = attrs['class']
|
self.classAttr = attrs['class']
|
||||||
self.tagsToReopen = [] # When the HTML element corresponding to self
|
self.tagsToReopen = [] # When the HTML element corresponding to self
|
||||||
# is completely dumped, if there was a problem related to tags
|
# is completely dumped, if there was a problem related to tags
|
||||||
|
@ -58,7 +58,7 @@ class HtmlElement:
|
||||||
# to self, we may need to close other tags (ie closing a paragraph
|
# to self, we may need to close other tags (ie closing a paragraph
|
||||||
# before closing a cell). This list contains HtmlElement instances.
|
# before closing a cell). This list contains HtmlElement instances.
|
||||||
self.elemType = self.elem
|
self.elemType = self.elem
|
||||||
if self.elemTypes.has_key(self.elem):
|
if self.elem in self.elemTypes:
|
||||||
self.elemType = self.elemTypes[self.elem]
|
self.elemType = self.elemTypes[self.elem]
|
||||||
# If a conflict occurs on this element, we will note it.
|
# If a conflict occurs on this element, we will note it.
|
||||||
self.isConflictual = False
|
self.isConflictual = False
|
||||||
|
@ -71,7 +71,7 @@ class HtmlElement:
|
||||||
def getOdfTag(self, env):
|
def getOdfTag(self, env):
|
||||||
'''Gets the raw ODF tag that corresponds to me'''
|
'''Gets the raw ODF tag that corresponds to me'''
|
||||||
res = ''
|
res = ''
|
||||||
if HTML_2_ODT.has_key(self.elem):
|
if self.elem in HTML_2_ODT:
|
||||||
res += '%s:%s' % (env.textNs, HTML_2_ODT[self.elem])
|
res += '%s:%s' % (env.textNs, HTML_2_ODT[self.elem])
|
||||||
elif self.elem == 'a':
|
elif self.elem == 'a':
|
||||||
res += '%s:a' % env.textNs
|
res += '%s:a' % env.textNs
|
||||||
|
@ -216,8 +216,8 @@ class HtmlTable:
|
||||||
elems = str(time.time()).split('.')
|
elems = str(time.time()).split('.')
|
||||||
self.name= 'AppyTable%s%s%d' % (elems[0],elems[1],random.randint(1,100))
|
self.name= 'AppyTable%s%s%d' % (elems[0],elems[1],random.randint(1,100))
|
||||||
self.styleNs = env.ns[OdfEnvironment.NS_STYLE]
|
self.styleNs = env.ns[OdfEnvironment.NS_STYLE]
|
||||||
self.res = u'' # The sub-buffer
|
self.res = '' # The sub-buffer
|
||||||
self.tempRes = u'' # The temporary sub-buffer, into which we will
|
self.tempRes = '' # The temporary sub-buffer, into which we will
|
||||||
# dump all table sub-elements, until we encounter the end of the first
|
# dump all table sub-elements, until we encounter the end of the first
|
||||||
# row. Then, we will know how much columns are defined in the table;
|
# row. Then, we will know how much columns are defined in the table;
|
||||||
# we will dump columns declarations into self.res and dump self.tempRes
|
# we will dump columns declarations into self.res and dump self.tempRes
|
||||||
|
@ -294,8 +294,8 @@ class XhtmlEnvironment(XmlEnvironment):
|
||||||
XmlEnvironment.__init__(self)
|
XmlEnvironment.__init__(self)
|
||||||
self.renderer = renderer
|
self.renderer = renderer
|
||||||
self.ns = renderer.currentParser.env.namespaces
|
self.ns = renderer.currentParser.env.namespaces
|
||||||
self.res = u''
|
self.res = ''
|
||||||
self.currentContent = u''
|
self.currentContent = ''
|
||||||
self.currentElements = [] # Stack of currently walked elements
|
self.currentElements = [] # Stack of currently walked elements
|
||||||
self.currentLists = [] # Stack of currently walked lists (ul or ol)
|
self.currentLists = [] # Stack of currently walked lists (ul or ol)
|
||||||
self.currentTables = [] # Stack of currently walked tables
|
self.currentTables = [] # Stack of currently walked tables
|
||||||
|
@ -349,7 +349,7 @@ class XhtmlEnvironment(XmlEnvironment):
|
||||||
# Dump and reinitialize the current content
|
# Dump and reinitialize the current content
|
||||||
contentSize = len(self.currentContent)
|
contentSize = len(self.currentContent)
|
||||||
self.dumpString(escapeXml(self.currentContent))
|
self.dumpString(escapeXml(self.currentContent))
|
||||||
self.currentContent = u''
|
self.currentContent = ''
|
||||||
# If we are within a table cell, update the total size of cell content
|
# If we are within a table cell, update the total size of cell content
|
||||||
if not contentSize: return
|
if not contentSize: return
|
||||||
if self.currentTables and self.currentTables[-1].inCell:
|
if self.currentTables and self.currentTables[-1].inCell:
|
||||||
|
@ -363,7 +363,7 @@ class XhtmlEnvironment(XmlEnvironment):
|
||||||
styleName = None
|
styleName = None
|
||||||
if odtStyle:
|
if odtStyle:
|
||||||
styleName = odtStyle.name
|
styleName = odtStyle.name
|
||||||
elif DEFAULT_ODT_STYLES.has_key(htmlElem.elem):
|
elif htmlElem.elem in DEFAULT_ODT_STYLES:
|
||||||
styleName = DEFAULT_ODT_STYLES[htmlElem.elem]
|
styleName = DEFAULT_ODT_STYLES[htmlElem.elem]
|
||||||
res = ''
|
res = ''
|
||||||
if styleName:
|
if styleName:
|
||||||
|
@ -458,7 +458,7 @@ class XhtmlEnvironment(XmlEnvironment):
|
||||||
elif elem in TABLE_CELL_TAGS:
|
elif elem in TABLE_CELL_TAGS:
|
||||||
# Determine colspan
|
# Determine colspan
|
||||||
colspan = 1
|
colspan = 1
|
||||||
if attrs.has_key('colspan'): colspan = int(attrs['colspan'])
|
if 'colspan' in attrs: colspan = int(attrs['colspan'])
|
||||||
table = self.currentTables[-1]
|
table = self.currentTables[-1]
|
||||||
table.inCell = colspan
|
table.inCell = colspan
|
||||||
table.cellIndex += colspan
|
table.cellIndex += colspan
|
||||||
|
@ -503,7 +503,7 @@ class XhtmlEnvironment(XmlEnvironment):
|
||||||
table.res+= '<%s:table-column %s:style-name="%s.%d"/>' % \
|
table.res+= '<%s:table-column %s:style-name="%s.%d"/>' % \
|
||||||
(self.tableNs, self.tableNs, table.name, i)
|
(self.tableNs, self.tableNs, table.name, i)
|
||||||
table.res += table.tempRes
|
table.res += table.tempRes
|
||||||
table.tempRes = u''
|
table.tempRes = ''
|
||||||
elif elem in TABLE_CELL_TAGS:
|
elif elem in TABLE_CELL_TAGS:
|
||||||
# Update attr "columnContentSizes" of the currently parsed table,
|
# Update attr "columnContentSizes" of the currently parsed table,
|
||||||
# excepted if the cell spans several columns.
|
# excepted if the cell spans several columns.
|
||||||
|
@ -535,7 +535,7 @@ class XhtmlParser(XmlParser):
|
||||||
resAttrs = attrs
|
resAttrs = attrs
|
||||||
if attrs:
|
if attrs:
|
||||||
resAttrs = {}
|
resAttrs = {}
|
||||||
for attrName in attrs.keys():
|
for attrName in list(attrs.keys()):
|
||||||
resAttrs[attrName.lower()] = attrs[attrName]
|
resAttrs[attrName.lower()] = attrs[attrName]
|
||||||
if attrs == None:
|
if attrs == None:
|
||||||
return resElem
|
return resElem
|
||||||
|
@ -548,11 +548,11 @@ class XhtmlParser(XmlParser):
|
||||||
currentElem = e.onElementStart(elem, attrs)
|
currentElem = e.onElementStart(elem, attrs)
|
||||||
odfTag = currentElem.getOdfTag(e)
|
odfTag = currentElem.getOdfTag(e)
|
||||||
|
|
||||||
if HTML_2_ODT.has_key(elem):
|
if elem in HTML_2_ODT:
|
||||||
e.dumpStyledElement(currentElem, odfTag, attrs)
|
e.dumpStyledElement(currentElem, odfTag, attrs)
|
||||||
elif elem == 'a':
|
elif elem == 'a':
|
||||||
e.dumpString('<%s %s:type="simple"' % (odfTag, e.linkNs))
|
e.dumpString('<%s %s:type="simple"' % (odfTag, e.linkNs))
|
||||||
if attrs.has_key('href'):
|
if 'href' in attrs:
|
||||||
e.dumpString(' %s:href="%s"' % (e.linkNs,
|
e.dumpString(' %s:href="%s"' % (e.linkNs,
|
||||||
escapeXml(attrs['href'])))
|
escapeXml(attrs['href'])))
|
||||||
e.dumpString('>')
|
e.dumpString('>')
|
||||||
|
@ -577,13 +577,13 @@ class XhtmlParser(XmlParser):
|
||||||
elif elem in TABLE_CELL_TAGS:
|
elif elem in TABLE_CELL_TAGS:
|
||||||
e.dumpString('<%s %s:style-name="%s"' % \
|
e.dumpString('<%s %s:style-name="%s"' % \
|
||||||
(odfTag, e.tableNs, DEFAULT_ODT_STYLES[elem]))
|
(odfTag, e.tableNs, DEFAULT_ODT_STYLES[elem]))
|
||||||
if attrs.has_key('colspan'):
|
if 'colspan' in attrs:
|
||||||
e.dumpString(' %s:number-columns-spanned="%s"' % \
|
e.dumpString(' %s:number-columns-spanned="%s"' % \
|
||||||
(e.tableNs, attrs['colspan']))
|
(e.tableNs, attrs['colspan']))
|
||||||
e.dumpString('>')
|
e.dumpString('>')
|
||||||
elif elem == 'img':
|
elif elem == 'img':
|
||||||
style = None
|
style = None
|
||||||
if attrs.has_key('style'): style = attrs['style']
|
if 'style' in attrs: style = attrs['style']
|
||||||
imgCode = e.renderer.importDocument(at=attrs['src'],
|
imgCode = e.renderer.importDocument(at=attrs['src'],
|
||||||
wrapInPara=False, style=style)
|
wrapInPara=False, style=style)
|
||||||
e.dumpString(imgCode)
|
e.dumpString(imgCode)
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
import xml.sax
|
import xml.sax
|
||||||
from px_parser import PxParser, PxEnvironment
|
from .px_parser import PxParser, PxEnvironment
|
||||||
from appy.pod.buffers import MemoryBuffer
|
from appy.pod.buffers import MemoryBuffer
|
||||||
from appy.shared.xml_parser import xmlPrologue, xhtmlPrologue
|
from appy.shared.xml_parser import xmlPrologue, xhtmlPrologue
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ class Px:
|
||||||
xhtmlPrologue = xhtmlPrologue
|
xhtmlPrologue = xhtmlPrologue
|
||||||
|
|
||||||
def __init__(self, content, isFileName=False, partial=True,
|
def __init__(self, content, isFileName=False, partial=True,
|
||||||
template=None, hook=None, prologue=None, unicode=True):
|
template=None, hook=None, prologue=None, str=True):
|
||||||
'''p_content is the PX code, as a string, or a file name if p_isFileName
|
'''p_content is the PX code, as a string, or a file name if p_isFileName
|
||||||
is True. If this code represents a complete XML file, p_partial is
|
is True. If this code represents a complete XML file, p_partial is
|
||||||
False. Else, we must surround p_content with a root tag to be able
|
False. Else, we must surround p_content with a root tag to be able
|
||||||
|
@ -49,7 +49,7 @@ class Px:
|
||||||
# Is there some (XML, XHTML...) prologue to dump?
|
# Is there some (XML, XHTML...) prologue to dump?
|
||||||
self.prologue = prologue
|
self.prologue = prologue
|
||||||
# Will the result be unicode or str?
|
# Will the result be unicode or str?
|
||||||
self.unicode = unicode
|
self.str = str
|
||||||
self.parse()
|
self.parse()
|
||||||
|
|
||||||
def parse(self):
|
def parse(self):
|
||||||
|
@ -64,7 +64,7 @@ class Px:
|
||||||
# produce a tree of memory buffers.
|
# produce a tree of memory buffers.
|
||||||
try:
|
try:
|
||||||
self.parser.parse(self.content)
|
self.parser.parse(self.content)
|
||||||
except xml.sax.SAXParseException, spe:
|
except xml.sax.SAXParseException as spe:
|
||||||
self.completeErrorMessage(spe)
|
self.completeErrorMessage(spe)
|
||||||
raise spe
|
raise spe
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ class Px:
|
||||||
res = result.content
|
res = result.content
|
||||||
if self.prologue:
|
if self.prologue:
|
||||||
res = self.prologue + res
|
res = self.prologue + res
|
||||||
if not self.unicode:
|
if not self.str:
|
||||||
res = res.encode('utf-8')
|
res = res.encode('utf-8')
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ class PxParser(XmlParser):
|
||||||
# See if we have a PX attribute among p_attrs.
|
# See if we have a PX attribute among p_attrs.
|
||||||
found = False
|
found = False
|
||||||
for name in self.pxAttributes:
|
for name in self.pxAttributes:
|
||||||
if attrs.has_key(name):
|
if name in attrs:
|
||||||
if not found:
|
if not found:
|
||||||
# This is the first PX attr we find.
|
# This is the first PX attr we find.
|
||||||
# Create a sub-buffer with an action.
|
# Create a sub-buffer with an action.
|
||||||
|
@ -87,7 +87,7 @@ class PxParser(XmlParser):
|
||||||
hook = None
|
hook = None
|
||||||
ignorableAttrs = self.pxAttributes
|
ignorableAttrs = self.pxAttributes
|
||||||
for name in self.noDumpTags:
|
for name in self.noDumpTags:
|
||||||
if attrs.has_key(name) and attrs[name].startswith(':'):
|
if name in attrs and attrs[name].startswith(':'):
|
||||||
hook = (name, attrs[name][1:])
|
hook = (name, attrs[name][1:])
|
||||||
ignorableAttrs += (name,)
|
ignorableAttrs += (name,)
|
||||||
break
|
break
|
||||||
|
|
|
@ -50,12 +50,12 @@ class UnicodeBuffer:
|
||||||
self.buffer = []
|
self.buffer = []
|
||||||
def write(self, s):
|
def write(self, s):
|
||||||
if s == None: return
|
if s == None: return
|
||||||
if isinstance(s, unicode):
|
if isinstance(s, str):
|
||||||
self.buffer.append(s)
|
self.buffer.append(s)
|
||||||
elif isinstance(s, str):
|
elif isinstance(s, str):
|
||||||
self.buffer.append(s.decode('utf-8'))
|
self.buffer.append(s.decode('utf-8'))
|
||||||
else:
|
else:
|
||||||
self.buffer.append(unicode(s))
|
self.buffer.append(str(s))
|
||||||
def getValue(self):
|
def getValue(self):
|
||||||
return u''.join(self.buffer)
|
return ''.join(self.buffer)
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -109,18 +109,18 @@ class CsvParser:
|
||||||
def convertValue(self, value, basicType):
|
def convertValue(self, value, basicType):
|
||||||
'''Converts the atomic p_value which is a string into some other atomic
|
'''Converts the atomic p_value which is a string into some other atomic
|
||||||
Python type specified in p_basicType (int, float, ...).'''
|
Python type specified in p_basicType (int, float, ...).'''
|
||||||
if (basicType != str) and (basicType != unicode):
|
if (basicType != str) and (basicType != str):
|
||||||
try:
|
try:
|
||||||
exec 'res = %s' % str(value)
|
exec('res = %s' % str(value))
|
||||||
except SyntaxError, se:
|
except SyntaxError as se:
|
||||||
res = None
|
res = None
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
exec 'res = """%s"""' % str(value)
|
exec('res = """%s"""' % str(value))
|
||||||
except SyntaxError, se:
|
except SyntaxError as se:
|
||||||
try:
|
try:
|
||||||
exec "res = '''%s'''" % str(value)
|
exec("res = '''%s'''" % str(value))
|
||||||
except SyntaxError, se:
|
except SyntaxError as se:
|
||||||
res = None
|
res = None
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
@ -183,7 +183,7 @@ class CsvParser:
|
||||||
self.res.append(lineObject)
|
self.res.append(lineObject)
|
||||||
f.close()
|
f.close()
|
||||||
# The second pass resolves the p_references if any
|
# The second pass resolves the p_references if any
|
||||||
for attrName, refInfo in self.references.iteritems():
|
for attrName, refInfo in self.references.items():
|
||||||
if attrName in self.attributes:
|
if attrName in self.attributes:
|
||||||
# Replace ID with real object from p_references
|
# Replace ID with real object from p_references
|
||||||
for obj in self.res:
|
for obj in self.res:
|
||||||
|
@ -228,7 +228,7 @@ class CsvMarshaller:
|
||||||
|
|
||||||
def marshallValue(self, field, value):
|
def marshallValue(self, field, value):
|
||||||
'''Produces a version of p_value that can be dumped in a CSV file.'''
|
'''Produces a version of p_value that can be dumped in a CSV file.'''
|
||||||
if isinstance(value, basestring):
|
if isinstance(value, str):
|
||||||
# Format the string as a one-line CSV-ready value
|
# Format the string as a one-line CSV-ready value
|
||||||
res = self.marshallString(value)
|
res = self.marshallString(value)
|
||||||
elif type(value) in sequenceTypes:
|
elif type(value) in sequenceTypes:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
import os, re, httplib, sys, stat, urlparse, time, socket, xml.sax
|
import os, re, http.client, sys, stat, urllib.parse, time, socket, xml.sax
|
||||||
import urllib
|
from urllib.parse import quote
|
||||||
from StringIO import StringIO
|
from StringIO import StringIO
|
||||||
from mimetypes import guess_type
|
from mimetypes import guess_type
|
||||||
from base64 import encodestring
|
from base64 import encodestring
|
||||||
|
@ -19,12 +19,12 @@ class FormDataEncoder:
|
||||||
|
|
||||||
def marshalValue(self, name, value):
|
def marshalValue(self, name, value):
|
||||||
if isinstance(value, basestring):
|
if isinstance(value, basestring):
|
||||||
return '%s=%s' % (name, urllib.quote(str(value)))
|
return '%s=%s' % (name, quote(str(value)))
|
||||||
elif isinstance(value, float):
|
elif isinstance(value, float):
|
||||||
return '%s:float=%s' % (name, value)
|
return '%s:float=%s' % (name, value)
|
||||||
elif isinstance(value, int):
|
elif isinstance(value, int):
|
||||||
return '%s:int=%s' % (name, value)
|
return '%s:int=%s' % (name, value)
|
||||||
elif isinstance(value, long):
|
elif isinstance(value, int):
|
||||||
res = '%s:long=%s' % (name, value)
|
res = '%s:long=%s' % (name, value)
|
||||||
if res[-1] == 'L':
|
if res[-1] == 'L':
|
||||||
res = res[:-1]
|
res = res[:-1]
|
||||||
|
@ -101,8 +101,8 @@ class HttpResponse:
|
||||||
redirect the user to if self.code is 302, or will unmarshall XML
|
redirect the user to if self.code is 302, or will unmarshall XML
|
||||||
data into Python objects.'''
|
data into Python objects.'''
|
||||||
if self.code == 302:
|
if self.code == 302:
|
||||||
return urlparse.urlparse(self.headers['location'])[2]
|
return urllib.parse.urlparse(self.headers['location'])[2]
|
||||||
elif self.headers.has_key('content-type'):
|
elif 'content-type' in self.headers:
|
||||||
contentType = self.extractContentType(self.headers['content-type'])
|
contentType = self.extractContentType(self.headers['content-type'])
|
||||||
for xmlHeader in self.xmlHeaders:
|
for xmlHeader in self.xmlHeaders:
|
||||||
if contentType.startswith(xmlHeader):
|
if contentType.startswith(xmlHeader):
|
||||||
|
@ -116,7 +116,7 @@ class HttpResponse:
|
||||||
raise ResourceError('Distant server exception: ' \
|
raise ResourceError('Distant server exception: ' \
|
||||||
'%s' % res)
|
'%s' % res)
|
||||||
return res
|
return res
|
||||||
except xml.sax.SAXParseException, se:
|
except xml.sax.SAXParseException as se:
|
||||||
raise ResourceError('Invalid XML response (%s)'%str(se))
|
raise ResourceError('Invalid XML response (%s)'%str(se))
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
@ -158,7 +158,7 @@ class Resource:
|
||||||
def updateHeaders(self, headers):
|
def updateHeaders(self, headers):
|
||||||
# Add credentials if present
|
# Add credentials if present
|
||||||
if not (self.username and self.password): return
|
if not (self.username and self.password): return
|
||||||
if headers.has_key('Authorization'): return
|
if 'Authorization' in headers: return
|
||||||
credentials = '%s:%s' % (self.username, self.password)
|
credentials = '%s:%s' % (self.username, self.password)
|
||||||
credentials = credentials.replace('\012', '')
|
credentials = credentials.replace('\012', '')
|
||||||
headers['Authorization'] = "Basic %s" % encodestring(credentials)
|
headers['Authorization'] = "Basic %s" % encodestring(credentials)
|
||||||
|
@ -170,19 +170,19 @@ class Resource:
|
||||||
|
|
||||||
def send(self, method, uri, body=None, headers={}, bodyType=None):
|
def send(self, method, uri, body=None, headers={}, bodyType=None):
|
||||||
'''Sends a HTTP request with p_method, for p_uri.'''
|
'''Sends a HTTP request with p_method, for p_uri.'''
|
||||||
conn = httplib.HTTPConnection(self.host, self.port)
|
conn = http.client.HTTPConnection(self.host, self.port)
|
||||||
try:
|
try:
|
||||||
conn.connect()
|
conn.connect()
|
||||||
except socket.gaierror, sge:
|
except socket.gaierror as sge:
|
||||||
raise ResourceError('Check your Internet connection (%s)'% str(sge))
|
raise ResourceError('Check your Internet connection (%s)'% str(sge))
|
||||||
except socket.error, se:
|
except socket.error as se:
|
||||||
raise ResourceError('Connection error (%s)' % str(se))
|
raise ResourceError('Connection error (%s)' % str(se))
|
||||||
# Tell what kind of HTTP request it will be.
|
# Tell what kind of HTTP request it will be.
|
||||||
conn.putrequest(method, uri, skip_host=True)
|
conn.putrequest(method, uri, skip_host=True)
|
||||||
# Add HTTP headers
|
# Add HTTP headers
|
||||||
self.updateHeaders(headers)
|
self.updateHeaders(headers)
|
||||||
if self.headers: headers.update(self.headers)
|
if self.headers: headers.update(self.headers)
|
||||||
for n, v in headers.items(): conn.putheader(n, v)
|
for n, v in list(headers.items()): conn.putheader(n, v)
|
||||||
conn.endheaders()
|
conn.endheaders()
|
||||||
# Add HTTP body
|
# Add HTTP body
|
||||||
if body:
|
if body:
|
||||||
|
|
|
@ -250,7 +250,7 @@ class HtmlDiff:
|
||||||
deleteStyle = 'color: red; text-decoration: line-through; cursor: help'
|
deleteStyle = 'color: red; text-decoration: line-through; cursor: help'
|
||||||
|
|
||||||
def __init__(self, old, new,
|
def __init__(self, old, new,
|
||||||
insertMsg=u'Inserted text', deleteMsg=u'Deleted text',
|
insertMsg='Inserted text', deleteMsg='Deleted text',
|
||||||
insertCss=None, deleteCss=None, insertName='insert',
|
insertCss=None, deleteCss=None, insertName='insert',
|
||||||
deleteName='delete', diffRatio=0.7):
|
deleteName='delete', diffRatio=0.7):
|
||||||
# p_old and p_new are strings containing chunks of HTML. If they are not
|
# p_old and p_new are strings containing chunks of HTML. If they are not
|
||||||
|
@ -306,24 +306,24 @@ class HtmlDiff:
|
||||||
else: tag = 'span'
|
else: tag = 'span'
|
||||||
# What message will it show in its 'title' attribute?
|
# What message will it show in its 'title' attribute?
|
||||||
if not msg:
|
if not msg:
|
||||||
exec 'msg = self.%sMsg' % type
|
exec('msg = self.%sMsg' % type)
|
||||||
# What CSS class (or, if none, tag-specific style) will be used ?
|
# What CSS class (or, if none, tag-specific style) will be used ?
|
||||||
exec 'cssClass = self.%sCss' % type
|
exec('cssClass = self.%sCss' % type)
|
||||||
if cssClass:
|
if cssClass:
|
||||||
style = 'class="%s"' % cssClass
|
style = 'class="%s"' % cssClass
|
||||||
else:
|
else:
|
||||||
exec 'style = self.%sStyle' % type
|
exec('style = self.%sStyle' % type)
|
||||||
style = 'style="%s"' % style
|
style = 'style="%s"' % style
|
||||||
# The 'name' attribute of the tag indicates the type of the update.
|
# The 'name' attribute of the tag indicates the type of the update.
|
||||||
exec 'tagName = self.%sName' % type
|
exec('tagName = self.%sName' % type)
|
||||||
# The idea is: if there are several lines, every line must be surrounded
|
# The idea is: if there are several lines, every line must be surrounded
|
||||||
# by a tag. This way, we know that a surrounding tag can't span several
|
# by a tag. This way, we know that a surrounding tag can't span several
|
||||||
# lines, which is a prerequisite for managing cumulative diffs.
|
# lines, which is a prerequisite for managing cumulative diffs.
|
||||||
if sep == ' ':
|
if sep == ' ':
|
||||||
if not isinstance(seq, basestring):
|
if not isinstance(seq, str):
|
||||||
seq = sep.join(seq)
|
seq = sep.join(seq)
|
||||||
sep = ''
|
sep = ''
|
||||||
if isinstance(seq, basestring):
|
if isinstance(seq, str):
|
||||||
return '%s<%s name="%s" %s title="%s">%s</%s>%s' % \
|
return '%s<%s name="%s" %s title="%s">%s</%s>%s' % \
|
||||||
(sep, tag, tagName, style, msg, seq, tag, sep)
|
(sep, tag, tagName, style, msg, seq, tag, sep)
|
||||||
else:
|
else:
|
||||||
|
@ -592,7 +592,7 @@ class HtmlDiff:
|
||||||
try:
|
try:
|
||||||
merger = Merger(lineA, add, previousDiffsA, self)
|
merger = Merger(lineA, add, previousDiffsA, self)
|
||||||
add = merger.merge()
|
add = merger.merge()
|
||||||
except Merger.MergeError, e:
|
except Merger.MergeError as e:
|
||||||
# The merge algorithm has made a burn out. Simplify and
|
# The merge algorithm has made a burn out. Simplify and
|
||||||
# consider lineA has having been completely deleted and
|
# consider lineA has having been completely deleted and
|
||||||
# lineB has completely inserted.
|
# lineB has completely inserted.
|
||||||
|
|
|
@ -239,14 +239,14 @@ class LdapConnector:
|
||||||
self.server = ldap.initialize(self.serverUri)
|
self.server = ldap.initialize(self.serverUri)
|
||||||
self.server.simple_bind_s(login, password)
|
self.server.simple_bind_s(login, password)
|
||||||
return True, None
|
return True, None
|
||||||
except AttributeError, ae:
|
except AttributeError as ae:
|
||||||
# When the ldap module is not there, trying to catch ldap.LDAPError
|
# When the ldap module is not there, trying to catch ldap.LDAPError
|
||||||
# will raise an error.
|
# will raise an error.
|
||||||
message = str(ae)
|
message = str(ae)
|
||||||
self.log('Ldap connect error with login %s (%s).' % \
|
self.log('Ldap connect error with login %s (%s).' % \
|
||||||
(login, message))
|
(login, message))
|
||||||
return False, message
|
return False, message
|
||||||
except ldap.LDAPError, le:
|
except ldap.LDAPError as le:
|
||||||
message = str(le)
|
message = str(le)
|
||||||
self.log('%s: connect error with login %s (%s).' % \
|
self.log('%s: connect error with login %s (%s).' % \
|
||||||
(self.serverUri, login, message))
|
(self.serverUri, login, message))
|
||||||
|
@ -275,7 +275,7 @@ class LdapConnector:
|
||||||
timeout=self.timeout)
|
timeout=self.timeout)
|
||||||
except ldap.TIMEOUT:
|
except ldap.TIMEOUT:
|
||||||
pass
|
pass
|
||||||
except ldap.LDAPError, le:
|
except ldap.LDAPError as le:
|
||||||
self.log('LDAP query error %s: %s' % \
|
self.log('LDAP query error %s: %s' % \
|
||||||
(le.__class__.__name__, str(le)))
|
(le.__class__.__name__, str(le)))
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -160,20 +160,20 @@ class Debianizer:
|
||||||
name = '%s/%sctl' % (binFolder, self.appNameLower)
|
name = '%s/%sctl' % (binFolder, self.appNameLower)
|
||||||
f = file(name, 'w')
|
f = file(name, 'w')
|
||||||
f.write(appCtl % self.appNameLower)
|
f.write(appCtl % self.appNameLower)
|
||||||
os.chmod(name, 0744) # Make it executable by owner.
|
os.chmod(name, 0o744) # Make it executable by owner.
|
||||||
f.close()
|
f.close()
|
||||||
# <app>run
|
# <app>run
|
||||||
name = '%s/%srun' % (binFolder, self.appNameLower)
|
name = '%s/%srun' % (binFolder, self.appNameLower)
|
||||||
f = file(name, 'w')
|
f = file(name, 'w')
|
||||||
f.write(appRun % self.appNameLower)
|
f.write(appRun % self.appNameLower)
|
||||||
os.chmod(name, 0744) # Make it executable by owner.
|
os.chmod(name, 0o744) # Make it executable by owner.
|
||||||
f.close()
|
f.close()
|
||||||
# startoo
|
# startoo
|
||||||
name = '%s/startoo' % binFolder
|
name = '%s/startoo' % binFolder
|
||||||
f = file(name, 'w')
|
f = file(name, 'w')
|
||||||
f.write(ooStart)
|
f.write(ooStart)
|
||||||
f.close()
|
f.close()
|
||||||
os.chmod(name, 0744) # Make it executable by owner.
|
os.chmod(name, 0o744) # Make it executable by owner.
|
||||||
# /var/lib/<app> (will store Data.fs, lock files, etc)
|
# /var/lib/<app> (will store Data.fs, lock files, etc)
|
||||||
varLibFolder = j(debFolder, 'var', 'lib', self.appNameLower)
|
varLibFolder = j(debFolder, 'var', 'lib', self.appNameLower)
|
||||||
os.makedirs(varLibFolder)
|
os.makedirs(varLibFolder)
|
||||||
|
@ -208,7 +208,7 @@ class Debianizer:
|
||||||
'application.' % n, '%sctl start' % n,
|
'application.' % n, '%sctl start' % n,
|
||||||
'%sctl restart' % n, '%sctl stop' % n))
|
'%sctl restart' % n, '%sctl stop' % n))
|
||||||
f.close()
|
f.close()
|
||||||
os.chmod(name, 0744) # Make it executable by owner.
|
os.chmod(name, 0o744) # Make it executable by owner.
|
||||||
# /etc/init.d/oo (start OpenOffice at boot time)
|
# /etc/init.d/oo (start OpenOffice at boot time)
|
||||||
name = '%s/oo' % initdFolder
|
name = '%s/oo' % initdFolder
|
||||||
f = file(name, 'w')
|
f = file(name, 'w')
|
||||||
|
@ -216,7 +216,7 @@ class Debianizer:
|
||||||
'startoo', 'startoo', "#Can't stop OO."))
|
'startoo', 'startoo', "#Can't stop OO."))
|
||||||
f.write('\n')
|
f.write('\n')
|
||||||
f.close()
|
f.close()
|
||||||
os.chmod(name, 0744) # Make it executable by owner.
|
os.chmod(name, 0o744) # Make it executable by owner.
|
||||||
# Get the size of the app, in Kb.
|
# Get the size of the app, in Kb.
|
||||||
os.chdir(tempFolder)
|
os.chdir(tempFolder)
|
||||||
cmd = subprocess.Popen(['du', '-b', '-s', 'debian'],
|
cmd = subprocess.Popen(['du', '-b', '-s', 'debian'],
|
||||||
|
|
|
@ -25,8 +25,8 @@
|
||||||
be strictly greater than 1.'''
|
be strictly greater than 1.'''
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
import re, sys, UserList, UserDict
|
import re, sys, collections, UserDict
|
||||||
from StringIO import StringIO
|
from io import StringIO
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
class ParserError(Exception): pass
|
class ParserError(Exception): pass
|
||||||
|
@ -69,7 +69,7 @@ LIST_VALUE_ERROR = 'Value "%s" is malformed: within it, %s. You should check ' \
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
class Type:
|
class Type:
|
||||||
basicTypes = {'f': float, 'i':int, 'g':long, 'b':bool}
|
basicTypes = {'f': float, 'i':int, 'g':int, 'b':bool}
|
||||||
separators = ['-', ';', ',', ':']
|
separators = ['-', ';', ',', ':']
|
||||||
def __init__(self, typeDecl):
|
def __init__(self, typeDecl):
|
||||||
self.basicType = None # The python basic type
|
self.basicType = None # The python basic type
|
||||||
|
@ -85,12 +85,12 @@ class Type:
|
||||||
self.listNumber += 1
|
self.listNumber += 1
|
||||||
else:
|
else:
|
||||||
# Get the basic type
|
# Get the basic type
|
||||||
if not (char in Type.basicTypes.keys()):
|
if not (char in list(Type.basicTypes.keys())):
|
||||||
raise TypeError(BASIC_TYPE_ERROR % char)
|
raise TypeError(BASIC_TYPE_ERROR % char)
|
||||||
self.basicType = Type.basicTypes[char]
|
self.basicType = Type.basicTypes[char]
|
||||||
break
|
break
|
||||||
if not self.basicType:
|
if not self.basicType:
|
||||||
self.basicType = unicode
|
self.basicType = str
|
||||||
def convertBasicValue(self, value):
|
def convertBasicValue(self, value):
|
||||||
try:
|
try:
|
||||||
return self.basicType(value.strip())
|
return self.basicType(value.strip())
|
||||||
|
@ -136,7 +136,7 @@ class Type:
|
||||||
elif not resIsComplete:
|
elif not resIsComplete:
|
||||||
try:
|
try:
|
||||||
res = self.convertListItem(value, separators)
|
res = self.convertListItem(value, separators)
|
||||||
except TypeError, te:
|
except TypeError as te:
|
||||||
raise TypeError(LIST_VALUE_ERROR % (value, te, self.name))
|
raise TypeError(LIST_VALUE_ERROR % (value, te, self.name))
|
||||||
return res
|
return res
|
||||||
def convertListItem(self, stringItem, remainingSeps):
|
def convertListItem(self, stringItem, remainingSeps):
|
||||||
|
@ -161,9 +161,9 @@ class Type:
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
class Table(UserList.UserList):
|
class Table(collections.UserList):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
UserList.UserList.__init__(self)
|
collections.UserList.__init__(self)
|
||||||
self.name = None
|
self.name = None
|
||||||
self.parent = None
|
self.parent = None
|
||||||
self.parentRow = None
|
self.parentRow = None
|
||||||
|
@ -213,7 +213,7 @@ class TableRow(UserDict.UserDict):
|
||||||
via the parent table self.table.'''
|
via the parent table self.table.'''
|
||||||
keyError = False
|
keyError = False
|
||||||
t = self.table
|
t = self.table
|
||||||
if self.has_key(key):
|
if key in self:
|
||||||
res = UserDict.UserDict.__getitem__(self, key)
|
res = UserDict.UserDict.__getitem__(self, key)
|
||||||
else:
|
else:
|
||||||
# Get the parent row
|
# Get the parent row
|
||||||
|
@ -259,9 +259,9 @@ class TableRow(UserDict.UserDict):
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
class NameResolver:
|
class NameResolver:
|
||||||
def resolveNames(self, tables):
|
def resolveNames(self, tables):
|
||||||
for tableName, table in tables.iteritems():
|
for tableName, table in tables.items():
|
||||||
if table.parent:
|
if table.parent:
|
||||||
if not tables.has_key(table.parent):
|
if table.parent not in tables:
|
||||||
raise ParserError(PARENT_NOT_FOUND %
|
raise ParserError(PARENT_NOT_FOUND %
|
||||||
(table.parent, table.name))
|
(table.parent, table.name))
|
||||||
table.parent = tables[table.parent]
|
table.parent = tables[table.parent]
|
||||||
|
@ -330,10 +330,10 @@ class TableParser:
|
||||||
def manageSpecialChar(self):
|
def manageSpecialChar(self):
|
||||||
specialChar = int(self.specialCharBuffer)
|
specialChar = int(self.specialCharBuffer)
|
||||||
self.specialCharBuffer = ''
|
self.specialCharBuffer = ''
|
||||||
if self.specialChars.has_key(specialChar):
|
if specialChar in self.specialChars:
|
||||||
self.contentBuffer.write(self.specialChars[specialChar])
|
self.contentBuffer.write(self.specialChars[specialChar])
|
||||||
else:
|
else:
|
||||||
print('Warning: char %d not known.' % specialChar)
|
print(('Warning: char %d not known.' % specialChar))
|
||||||
self.state = TableParser.READING_CONTENT
|
self.state = TableParser.READING_CONTENT
|
||||||
def bufferize(self, char):
|
def bufferize(self, char):
|
||||||
if self.state == TableParser.READING_CONTROL_WORD:
|
if self.state == TableParser.READING_CONTROL_WORD:
|
||||||
|
@ -403,7 +403,7 @@ class TableParser:
|
||||||
columnNames.append(name.strip())
|
columnNames.append(name.strip())
|
||||||
try:
|
try:
|
||||||
columnTypes.append(Type(typeDecl.strip()))
|
columnTypes.append(Type(typeDecl.strip()))
|
||||||
except TypeError, te:
|
except TypeError as te:
|
||||||
raise ParserError(TYPE_ERROR %
|
raise ParserError(TYPE_ERROR %
|
||||||
(header, self.currentTableName, te))
|
(header, self.currentTableName, te))
|
||||||
else:
|
else:
|
||||||
|
@ -449,7 +449,7 @@ class TableParser:
|
||||||
if columnType:
|
if columnType:
|
||||||
try:
|
try:
|
||||||
columnValue = columnType.convertValue(columnValue)
|
columnValue = columnType.convertValue(columnValue)
|
||||||
except TypeError, te:
|
except TypeError as te:
|
||||||
raise ParserError(VALUE_ERROR %
|
raise ParserError(VALUE_ERROR %
|
||||||
(columnName, self.currentTableName,
|
(columnName, self.currentTableName,
|
||||||
te))
|
te))
|
||||||
|
@ -496,7 +496,7 @@ class RtfTablesParser:
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
if __name__ =='__main__':
|
if __name__ =='__main__':
|
||||||
tables = RtfTablesParser("Tests.rtf").parse()
|
tables = RtfTablesParser("Tests.rtf").parse()
|
||||||
for key, item in tables.iteritems():
|
for key, item in tables.items():
|
||||||
print('Table %s' % key)
|
print(('Table %s' % key))
|
||||||
print(item)
|
print(item)
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
|
@ -74,7 +74,7 @@ class Sap:
|
||||||
try:
|
try:
|
||||||
self.sap = pysap.Rfc_connection(conn_string = params)
|
self.sap = pysap.Rfc_connection(conn_string = params)
|
||||||
self.sap.open()
|
self.sap.open()
|
||||||
except pysap.BaseSapRfcError, se:
|
except pysap.BaseSapRfcError as se:
|
||||||
# Put in the error message the connection string without the
|
# Put in the error message the connection string without the
|
||||||
# password.
|
# password.
|
||||||
connNoPasswd = params[:params.index('PASSWD')] + 'PASSWD=********'
|
connNoPasswd = params[:params.index('PASSWD')] + 'PASSWD=********'
|
||||||
|
@ -84,7 +84,7 @@ class Sap:
|
||||||
'''Create a struct corresponding to SAP/C structure definition
|
'''Create a struct corresponding to SAP/C structure definition
|
||||||
p_structDef and fills it with dict p_userData.'''
|
p_structDef and fills it with dict p_userData.'''
|
||||||
res = structDef()
|
res = structDef()
|
||||||
for name, value in userData.iteritems():
|
for name, value in userData.items():
|
||||||
if name not in structDef._sfield_names_:
|
if name not in structDef._sfield_names_:
|
||||||
raise SapError(SAP_STRUCT_ELEM_NOT_FOUND % (paramName, name))
|
raise SapError(SAP_STRUCT_ELEM_NOT_FOUND % (paramName, name))
|
||||||
sapType = structDef._sfield_sap_types_[name]
|
sapType = structDef._sfield_sap_types_[name]
|
||||||
|
@ -93,7 +93,7 @@ class Sap:
|
||||||
sType = '%s%d' % (sapType[0], sapType[1])
|
sType = '%s%d' % (sapType[0], sapType[1])
|
||||||
# "None" value is tolerated.
|
# "None" value is tolerated.
|
||||||
if value == None: value = ''
|
if value == None: value = ''
|
||||||
if not isinstance(value, basestring):
|
if not isinstance(value, str):
|
||||||
raise SapError(
|
raise SapError(
|
||||||
SAP_STRING_REQUIRED % (name, paramName, sType))
|
SAP_STRING_REQUIRED % (name, paramName, sType))
|
||||||
if len(value) > sapType[1]:
|
if len(value) > sapType[1]:
|
||||||
|
@ -113,7 +113,7 @@ class Sap:
|
||||||
functionName = self.functionName
|
functionName = self.functionName
|
||||||
function = self.sap.get_interface(functionName)
|
function = self.sap.get_interface(functionName)
|
||||||
# Specify the parameters
|
# Specify the parameters
|
||||||
for name, value in params.iteritems():
|
for name, value in params.items():
|
||||||
if type(value) == dict:
|
if type(value) == dict:
|
||||||
# The param corresponds to a SAP/C "struct"
|
# The param corresponds to a SAP/C "struct"
|
||||||
v = self.createStructure(
|
v = self.createStructure(
|
||||||
|
@ -140,7 +140,7 @@ class Sap:
|
||||||
function[name] = v
|
function[name] = v
|
||||||
# Call the function
|
# Call the function
|
||||||
function()
|
function()
|
||||||
except pysap.BaseSapRfcError, se:
|
except pysap.BaseSapRfcError as se:
|
||||||
raise SapError(SAP_FUNCTION_ERROR % (functionName, str(se)))
|
raise SapError(SAP_FUNCTION_ERROR % (functionName, str(se)))
|
||||||
return SapResult(function)
|
return SapResult(function)
|
||||||
|
|
||||||
|
@ -198,10 +198,10 @@ class Sap:
|
||||||
self.sap.get_structure(typeName)
|
self.sap.get_structure(typeName)
|
||||||
res += '%s\n%s\n\n' % \
|
res += '%s\n%s\n\n' % \
|
||||||
(typeName, self.getTypeInfo(typeName))
|
(typeName, self.getTypeInfo(typeName))
|
||||||
except pysap.BaseSapRfcError, ee:
|
except pysap.BaseSapRfcError as ee:
|
||||||
pass
|
pass
|
||||||
return res
|
return res
|
||||||
except pysap.BaseSapRfcError, se:
|
except pysap.BaseSapRfcError as se:
|
||||||
if se.value == 'FU_NOT_FOUND':
|
if se.value == 'FU_NOT_FOUND':
|
||||||
raise SapError(SAP_FUNCTION_NOT_FOUND % (functionName))
|
raise SapError(SAP_FUNCTION_NOT_FOUND % (functionName))
|
||||||
else:
|
else:
|
||||||
|
@ -229,6 +229,6 @@ class Sap:
|
||||||
'''Disconnects from SAP.'''
|
'''Disconnects from SAP.'''
|
||||||
try:
|
try:
|
||||||
self.sap.close()
|
self.sap.close()
|
||||||
except pysap.BaseSapRfcError, se:
|
except pysap.BaseSapRfcError as se:
|
||||||
raise SapError(SAP_DISCONNECT_ERROR % str(se))
|
raise SapError(SAP_DISCONNECT_ERROR % str(se))
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -177,7 +177,7 @@ class Tester:
|
||||||
(not isinstance(flavours, tuple)):
|
(not isinstance(flavours, tuple)):
|
||||||
raise TesterError(FLAVOURS_NOT_LIST)
|
raise TesterError(FLAVOURS_NOT_LIST)
|
||||||
for flavour in flavours:
|
for flavour in flavours:
|
||||||
if not isinstance(flavour, basestring):
|
if not isinstance(flavour, str):
|
||||||
raise TesterError(FLAVOUR_NOT_STRING)
|
raise TesterError(FLAVOUR_NOT_STRING)
|
||||||
self.flavours = flavours
|
self.flavours = flavours
|
||||||
self.flavour = None
|
self.flavour = None
|
||||||
|
@ -198,7 +198,7 @@ class Tester:
|
||||||
if self.flavour:
|
if self.flavour:
|
||||||
ext = '.%s' % self.flavour
|
ext = '.%s' % self.flavour
|
||||||
configTableName = 'Configuration%s' % ext
|
configTableName = 'Configuration%s' % ext
|
||||||
if self.tables.has_key(configTableName):
|
if configTableName in self.tables:
|
||||||
self.config = self.tables[configTableName].asDict()
|
self.config = self.tables[configTableName].asDict()
|
||||||
self.tempFolder = os.path.join(self.testFolder, 'temp')
|
self.tempFolder = os.path.join(self.testFolder, 'temp')
|
||||||
if os.path.exists(self.tempFolder):
|
if os.path.exists(self.tempFolder):
|
||||||
|
@ -249,11 +249,11 @@ class Tester:
|
||||||
self.report.say('Test successful.\n')
|
self.report.say('Test successful.\n')
|
||||||
self.nbOfSuccesses += 1
|
self.nbOfSuccesses += 1
|
||||||
def run(self):
|
def run(self):
|
||||||
assert self.tables.has_key('TestSuites'), \
|
assert 'TestSuites' in self.tables, \
|
||||||
TesterError(MAIN_TABLE_NOT_FOUND % self.testPlan)
|
TesterError(MAIN_TABLE_NOT_FOUND % self.testPlan)
|
||||||
for testSuite in self.tables['TestSuites']:
|
for testSuite in self.tables['TestSuites']:
|
||||||
if (not testSuite.has_key('Name')) or \
|
if ('Name' not in testSuite) or \
|
||||||
(not testSuite.has_key('Description')):
|
('Description' not in testSuite):
|
||||||
raise TesterError(MAIN_TABLE_MALFORMED)
|
raise TesterError(MAIN_TABLE_MALFORMED)
|
||||||
if testSuite['Name'].startswith('_'):
|
if testSuite['Name'].startswith('_'):
|
||||||
tsName = testSuite['Name'][1:]
|
tsName = testSuite['Name'][1:]
|
||||||
|
@ -261,8 +261,8 @@ class Tester:
|
||||||
else:
|
else:
|
||||||
tsName = testSuite['Name']
|
tsName = testSuite['Name']
|
||||||
tsIgnored = False
|
tsIgnored = False
|
||||||
assert self.tables.has_key('%s.descriptions' % tsName) \
|
assert '%s.descriptions' % tsName in self.tables \
|
||||||
and self.tables.has_key('%s.data' % tsName), \
|
and '%s.data' % tsName in self.tables, \
|
||||||
TesterError(TEST_SUITE_NOT_FOUND % (tsName, tsName))
|
TesterError(TEST_SUITE_NOT_FOUND % (tsName, tsName))
|
||||||
assert len(self.tables['%s.descriptions' % tsName]) == \
|
assert len(self.tables['%s.descriptions' % tsName]) == \
|
||||||
len(self.tables['%s.data' % tsName]), \
|
len(self.tables['%s.data' % tsName]), \
|
||||||
|
|
|
@ -44,7 +44,7 @@ class FolderDeleter:
|
||||||
dirName = os.path.dirname(dirName)
|
dirName = os.path.dirname(dirName)
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
except OSError, oe:
|
except OSError:
|
||||||
break
|
break
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
@ -53,7 +53,7 @@ def cleanFolder(folder, exts=extsToClean, folders=(), verbose=False):
|
||||||
'''This function allows to remove, in p_folder and subfolders, any file
|
'''This function allows to remove, in p_folder and subfolders, any file
|
||||||
whose extension is in p_exts, and any folder whose name is in
|
whose extension is in p_exts, and any folder whose name is in
|
||||||
p_folders.'''
|
p_folders.'''
|
||||||
if verbose: print('Cleaning folder %s...' % folder)
|
if verbose: print(('Cleaning folder %s...' % folder))
|
||||||
# Remove files with an extension listed in p_exts
|
# Remove files with an extension listed in p_exts
|
||||||
if exts:
|
if exts:
|
||||||
for root, dirs, files in os.walk(folder):
|
for root, dirs, files in os.walk(folder):
|
||||||
|
@ -61,7 +61,7 @@ def cleanFolder(folder, exts=extsToClean, folders=(), verbose=False):
|
||||||
ext = os.path.splitext(fileName)[1]
|
ext = os.path.splitext(fileName)[1]
|
||||||
if (ext in exts) or ext.endswith('~'):
|
if (ext in exts) or ext.endswith('~'):
|
||||||
fileToRemove = os.path.join(root, fileName)
|
fileToRemove = os.path.join(root, fileName)
|
||||||
if verbose: print('Removing file %s...' % fileToRemove)
|
if verbose: print(('Removing file %s...' % fileToRemove))
|
||||||
os.remove(fileToRemove)
|
os.remove(fileToRemove)
|
||||||
# Remove folders whose names are in p_folders.
|
# Remove folders whose names are in p_folders.
|
||||||
if folders:
|
if folders:
|
||||||
|
@ -69,7 +69,7 @@ def cleanFolder(folder, exts=extsToClean, folders=(), verbose=False):
|
||||||
for folderName in dirs:
|
for folderName in dirs:
|
||||||
if folderName in folders:
|
if folderName in folders:
|
||||||
toDelete = os.path.join(root, folderName)
|
toDelete = os.path.join(root, folderName)
|
||||||
if verbose: print('Removing folder %s...' % toDelete)
|
if verbose: print(('Removing folder %s...' % toDelete))
|
||||||
FolderDeleter.delete(toDelete)
|
FolderDeleter.delete(toDelete)
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
@ -142,14 +142,14 @@ def copyData(data, target, targetMethod, type='string', encoding=None,
|
||||||
dump(encodeData(chunk, encoding))
|
dump(encodeData(chunk, encoding))
|
||||||
elif type == 'zope':
|
elif type == 'zope':
|
||||||
# A OFS.Image.File instance can be split into several chunks
|
# A OFS.Image.File instance can be split into several chunks
|
||||||
if isinstance(data.data, basestring): # One chunk
|
if isinstance(data.data, str): # One chunk
|
||||||
dump(encodeData(data.data, encoding))
|
dump(encodeData(data.data, encoding))
|
||||||
else:
|
else:
|
||||||
# Several chunks
|
# Several chunks
|
||||||
data = data.data
|
data = data.data
|
||||||
while data is not None:
|
while data is not None:
|
||||||
dump(encodeData(data.data, encoding))
|
dump(encodeData(data.data, encoding))
|
||||||
data = data.next
|
data = data.__next__
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
def splitList(l, sub):
|
def splitList(l, sub):
|
||||||
|
@ -222,12 +222,12 @@ def getOsTempFolder():
|
||||||
tmp = '/tmp'
|
tmp = '/tmp'
|
||||||
if os.path.exists(tmp) and os.path.isdir(tmp):
|
if os.path.exists(tmp) and os.path.isdir(tmp):
|
||||||
res = tmp
|
res = tmp
|
||||||
elif os.environ.has_key('TMP'):
|
elif 'TMP' in os.environ:
|
||||||
res = os.environ['TMP']
|
res = os.environ['TMP']
|
||||||
elif os.environ.has_key('TEMP'):
|
elif 'TEMP' in os.environ:
|
||||||
res = os.environ['TEMP']
|
res = os.environ['TEMP']
|
||||||
else:
|
else:
|
||||||
raise "Sorry, I can't find a temp folder on your machine."
|
raise Exception("Sorry, I can't find a temp folder on your machine.")
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def getTempFileName(prefix='', extension=''):
|
def getTempFileName(prefix='', extension=''):
|
||||||
|
@ -273,10 +273,10 @@ def normalizeString(s, usage='fileName'):
|
||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
# Another encoding may be in use
|
# Another encoding may be in use
|
||||||
s = s.decode('latin-1')
|
s = s.decode('latin-1')
|
||||||
elif not isinstance(s, unicode): s = unicode(s)
|
elif not isinstance(s, str): s = str(s)
|
||||||
# For extracted text, replace any unwanted char with a blank
|
# For extracted text, replace any unwanted char with a blank
|
||||||
if usage == 'extractedText':
|
if usage == 'extractedText':
|
||||||
res = u''
|
res = ''
|
||||||
for char in s:
|
for char in s:
|
||||||
if char not in extractIgnore: res += char
|
if char not in extractIgnore: res += char
|
||||||
else: res += ' '
|
else: res += ' '
|
||||||
|
@ -291,7 +291,7 @@ def normalizeString(s, usage='fileName'):
|
||||||
for char in s:
|
for char in s:
|
||||||
if char not in fileNameIgnore: res += char
|
if char not in fileNameIgnore: res += char
|
||||||
elif usage.startswith('alpha'):
|
elif usage.startswith('alpha'):
|
||||||
exec 'rex = %sRex' % usage
|
exec('rex = %sRex' % usage)
|
||||||
res = ''
|
res = ''
|
||||||
for char in s:
|
for char in s:
|
||||||
if rex.match(char): res += char
|
if rex.match(char): res += char
|
||||||
|
@ -319,7 +319,7 @@ def keepDigits(s):
|
||||||
def getStringDict(d):
|
def getStringDict(d):
|
||||||
'''Gets the string literal corresponding to dict p_d.'''
|
'''Gets the string literal corresponding to dict p_d.'''
|
||||||
res = []
|
res = []
|
||||||
for k, v in d.iteritems():
|
for k, v in d.items():
|
||||||
if type(v) not in sequenceTypes:
|
if type(v) not in sequenceTypes:
|
||||||
if not isinstance(k, basestring): k = str(k)
|
if not isinstance(k, basestring): k = str(k)
|
||||||
if not isinstance(v, basestring): v = str(v)
|
if not isinstance(v, basestring): v = str(v)
|
||||||
|
@ -386,7 +386,7 @@ def formatNumber(n, sep=',', precision=2, tsep=' '):
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
def lower(s):
|
def lower(s):
|
||||||
'''French-accents-aware variant of string.lower.'''
|
'''French-accents-aware variant of string.lower.'''
|
||||||
isUnicode = isinstance(s, unicode)
|
isUnicode = isinstance(s, str)
|
||||||
if not isUnicode: s = s.decode('utf-8')
|
if not isUnicode: s = s.decode('utf-8')
|
||||||
res = s.lower()
|
res = s.lower()
|
||||||
if not isUnicode: res = res.encode('utf-8')
|
if not isUnicode: res = res.encode('utf-8')
|
||||||
|
@ -394,14 +394,14 @@ def lower(s):
|
||||||
|
|
||||||
def upper(s):
|
def upper(s):
|
||||||
'''French-accents-aware variant of string.upper.'''
|
'''French-accents-aware variant of string.upper.'''
|
||||||
isUnicode = isinstance(s, unicode)
|
isUnicode = isinstance(s, str)
|
||||||
if not isUnicode: s = s.decode('utf-8')
|
if not isUnicode: s = s.decode('utf-8')
|
||||||
res = s.upper()
|
res = s.upper()
|
||||||
if not isUnicode: res = res.encode('utf-8')
|
if not isUnicode: res = res.encode('utf-8')
|
||||||
return res
|
return res
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
typeLetters = {'b': bool, 'i': int, 'j': long, 'f':float, 's':str, 'u':unicode,
|
typeLetters = {'b': bool, 'i': int, 'j': int, 'f':float, 's':str, 'u':str,
|
||||||
'l': list, 'd': dict}
|
'l': list, 'd': dict}
|
||||||
caExts = {'py': ('.py', '.vpy', '.cpy'), 'xml': ('.pt', '.cpt', '.xml')}
|
caExts = {'py': ('.py', '.vpy', '.cpy'), 'xml': ('.pt', '.cpt', '.xml')}
|
||||||
|
|
||||||
|
@ -506,8 +506,8 @@ class CodeAnalysis:
|
||||||
if not lines: return
|
if not lines: return
|
||||||
commentRate = (self.commentLines / float(lines)) * 100.0
|
commentRate = (self.commentLines / float(lines)) * 100.0
|
||||||
blankRate = (self.emptyLines / float(lines)) * 100.0
|
blankRate = (self.emptyLines / float(lines)) * 100.0
|
||||||
print('%s: %d files, %d lines (%.0f%% comments, %.0f%% blank)' % \
|
print(('%s: %d files, %d lines (%.0f%% comments, %.0f%% blank)' % \
|
||||||
(self.name, self.numberOfFiles, lines, commentRate, blankRate))
|
(self.name, self.numberOfFiles, lines, commentRate, blankRate)))
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
class LinesCounter:
|
class LinesCounter:
|
||||||
|
@ -516,7 +516,7 @@ class LinesCounter:
|
||||||
'%stemp' % os.sep)
|
'%stemp' % os.sep)
|
||||||
|
|
||||||
def __init__(self, folderOrModule, excludes=None):
|
def __init__(self, folderOrModule, excludes=None):
|
||||||
if isinstance(folderOrModule, basestring):
|
if isinstance(folderOrModule, str):
|
||||||
# It is the path of some folder
|
# It is the path of some folder
|
||||||
self.folder = folderOrModule
|
self.folder = folderOrModule
|
||||||
else:
|
else:
|
||||||
|
@ -624,10 +624,10 @@ class FileWrapper:
|
||||||
if self.content.__class__.__name__ == 'Pdata':
|
if self.content.__class__.__name__ == 'Pdata':
|
||||||
# The file content is splitted in several chunks.
|
# The file content is splitted in several chunks.
|
||||||
f.write(self.content.data)
|
f.write(self.content.data)
|
||||||
nextPart = self.content.next
|
nextPart = self.content.__next__
|
||||||
while nextPart:
|
while nextPart:
|
||||||
f.write(nextPart.data)
|
f.write(nextPart.data)
|
||||||
nextPart = nextPart.next
|
nextPart = nextPart.__next__
|
||||||
else:
|
else:
|
||||||
# Only one chunk
|
# Only one chunk
|
||||||
f.write(self.content)
|
f.write(self.content)
|
||||||
|
|
|
@ -66,9 +66,9 @@ HTML_ENTITIES = {
|
||||||
'euro':'€', 'nbsp':' ', "rsquo":"'", "lsquo":"'", "ldquo":"'",
|
'euro':'€', 'nbsp':' ', "rsquo":"'", "lsquo":"'", "ldquo":"'",
|
||||||
"rdquo":"'", 'ndash': '—', 'mdash': '—', 'oelig':'oe', 'quot': "'",
|
"rdquo":"'", 'ndash': '—', 'mdash': '—', 'oelig':'oe', 'quot': "'",
|
||||||
'mu': 'µ'}
|
'mu': 'µ'}
|
||||||
import htmlentitydefs
|
import html.entities
|
||||||
for k, v in htmlentitydefs.entitydefs.iteritems():
|
for k, v in html.entities.entitydefs.items():
|
||||||
if not HTML_ENTITIES.has_key(k) and not XML_ENTITIES.has_key(k):
|
if k not in HTML_ENTITIES and k not in XML_ENTITIES:
|
||||||
HTML_ENTITIES[k] = ''
|
HTML_ENTITIES[k] = ''
|
||||||
|
|
||||||
def escapeXml(s, format='xml', nsText='text'):
|
def escapeXml(s, format='xml', nsText='text'):
|
||||||
|
@ -77,13 +77,13 @@ def escapeXml(s, format='xml', nsText='text'):
|
||||||
their ODF counterparts. In this case, it is needed to give the name of
|
their ODF counterparts. In this case, it is needed to give the name of
|
||||||
the "text" namespace (p_nsText) as defined in the ODF document where the
|
the "text" namespace (p_nsText) as defined in the ODF document where the
|
||||||
line breaks and tabs must be inserted.'''
|
line breaks and tabs must be inserted.'''
|
||||||
if isinstance(s, unicode):
|
if isinstance(s, str):
|
||||||
res = u''
|
res = ''
|
||||||
else:
|
else:
|
||||||
res = ''
|
res = ''
|
||||||
odf = format == 'odf'
|
odf = format == 'odf'
|
||||||
for c in s:
|
for c in s:
|
||||||
if XML_SPECIAL_CHARS_NO_APOS.has_key(c):
|
if c in XML_SPECIAL_CHARS_NO_APOS:
|
||||||
# We do not escape 'apos': there is no particular need for that.
|
# We do not escape 'apos': there is no particular need for that.
|
||||||
res += XML_SPECIAL_CHARS_NO_APOS[c]
|
res += XML_SPECIAL_CHARS_NO_APOS[c]
|
||||||
elif odf and (c == '\n'):
|
elif odf and (c == '\n'):
|
||||||
|
@ -99,12 +99,12 @@ def escapeXml(s, format='xml', nsText='text'):
|
||||||
def escapeXhtml(s):
|
def escapeXhtml(s):
|
||||||
'''Return p_s, whose XHTML special chars and carriage return chars have
|
'''Return p_s, whose XHTML special chars and carriage return chars have
|
||||||
been replaced with corresponding XHTML entities.'''
|
been replaced with corresponding XHTML entities.'''
|
||||||
if isinstance(s, unicode):
|
if isinstance(s, str):
|
||||||
res = u''
|
res = ''
|
||||||
else:
|
else:
|
||||||
res = ''
|
res = ''
|
||||||
for c in s:
|
for c in s:
|
||||||
if XML_SPECIAL_CHARS_NO_APOS.has_key(c):
|
if c in XML_SPECIAL_CHARS_NO_APOS:
|
||||||
res += XML_SPECIAL_CHARS_NO_APOS[c]
|
res += XML_SPECIAL_CHARS_NO_APOS[c]
|
||||||
elif c == '\n':
|
elif c == '\n':
|
||||||
res += '<br/>'
|
res += '<br/>'
|
||||||
|
@ -144,7 +144,7 @@ class XmlElement:
|
||||||
res = self.elem
|
res = self.elem
|
||||||
if self.attrs:
|
if self.attrs:
|
||||||
res += '('
|
res += '('
|
||||||
for attrName, attrValue in self.attrs.items():
|
for attrName, attrValue in list(self.attrs.items()):
|
||||||
res += '%s="%s"' % (attrName, attrValue)
|
res += '%s="%s"' % (attrName, attrValue)
|
||||||
res += ')'
|
res += ')'
|
||||||
return res
|
return res
|
||||||
|
@ -167,7 +167,7 @@ class XmlEnvironment:
|
||||||
self.parser = None
|
self.parser = None
|
||||||
def manageNamespaces(self, attrs):
|
def manageNamespaces(self, attrs):
|
||||||
'''Manages namespaces definitions encountered in p_attrs.'''
|
'''Manages namespaces definitions encountered in p_attrs.'''
|
||||||
for attrName, attrValue in attrs.items():
|
for attrName, attrValue in list(attrs.items()):
|
||||||
if attrName.startswith('xmlns:'):
|
if attrName.startswith('xmlns:'):
|
||||||
self.namespaces[attrValue] = attrName[6:]
|
self.namespaces[attrValue] = attrName[6:]
|
||||||
def ns(self, nsUri):
|
def ns(self, nsUri):
|
||||||
|
@ -221,7 +221,7 @@ class XmlParser(ContentHandler, ErrorHandler):
|
||||||
def skippedEntity(self, name):
|
def skippedEntity(self, name):
|
||||||
'''This method is called every time expat does not recognize an entity.
|
'''This method is called every time expat does not recognize an entity.
|
||||||
We provide here support for HTML entities.'''
|
We provide here support for HTML entities.'''
|
||||||
if HTML_ENTITIES.has_key(name):
|
if name in HTML_ENTITIES:
|
||||||
self.characters(HTML_ENTITIES[name].decode('utf-8'))
|
self.characters(HTML_ENTITIES[name].decode('utf-8'))
|
||||||
else:
|
else:
|
||||||
# Put a question mark instead of raising an exception.
|
# Put a question mark instead of raising an exception.
|
||||||
|
@ -230,10 +230,10 @@ class XmlParser(ContentHandler, ErrorHandler):
|
||||||
# ErrorHandler methods ---------------------------------------------------
|
# ErrorHandler methods ---------------------------------------------------
|
||||||
def error(self, error):
|
def error(self, error):
|
||||||
if self.raiseOnError: raise error
|
if self.raiseOnError: raise error
|
||||||
else: print('SAX error %s' % str(error))
|
else: print(('SAX error %s' % str(error)))
|
||||||
def fatalError(self, error):
|
def fatalError(self, error):
|
||||||
if self.raiseOnError: raise error
|
if self.raiseOnError: raise error
|
||||||
else: print('SAX fatal error %s' % str(error))
|
else: print(('SAX fatal error %s' % str(error)))
|
||||||
def warning(self, error): pass
|
def warning(self, error): pass
|
||||||
|
|
||||||
def parse(self, xml, source='string'):
|
def parse(self, xml, source='string'):
|
||||||
|
@ -246,9 +246,9 @@ class XmlParser(ContentHandler, ErrorHandler):
|
||||||
method will close it.
|
method will close it.
|
||||||
'''
|
'''
|
||||||
try:
|
try:
|
||||||
from cStringIO import StringIO
|
from io import StringIO
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from StringIO import StringIO
|
from io import StringIO
|
||||||
self._xml = xml
|
self._xml = xml
|
||||||
self.parser.setContentHandler(self)
|
self.parser.setContentHandler(self)
|
||||||
self.parser.setErrorHandler(self)
|
self.parser.setErrorHandler(self)
|
||||||
|
@ -333,7 +333,7 @@ class XmlUnmarshaller(XmlParser):
|
||||||
def convertAttrs(self, attrs):
|
def convertAttrs(self, attrs):
|
||||||
'''Converts XML attrs to a dict.'''
|
'''Converts XML attrs to a dict.'''
|
||||||
res = {}
|
res = {}
|
||||||
for k, v in attrs.items():
|
for k, v in list(attrs.items()):
|
||||||
if ':' in k: # An attr prefixed with a namespace. Remove this.
|
if ':' in k: # An attr prefixed with a namespace. Remove this.
|
||||||
k = k.split(':')[-1]
|
k = k.split(':')[-1]
|
||||||
res[str(k)] = self.encode(v)
|
res[str(k)] = self.encode(v)
|
||||||
|
@ -362,9 +362,9 @@ class XmlUnmarshaller(XmlParser):
|
||||||
e = XmlParser.startElement(self, elem, attrs)
|
e = XmlParser.startElement(self, elem, attrs)
|
||||||
# Determine the type of the element.
|
# Determine the type of the element.
|
||||||
elemType = 'unicode' # Default value
|
elemType = 'unicode' # Default value
|
||||||
if attrs.has_key('type'):
|
if 'type' in attrs:
|
||||||
elemType = attrs['type']
|
elemType = attrs['type']
|
||||||
elif self.tagTypes.has_key(elem):
|
elif elem in self.tagTypes:
|
||||||
elemType = self.tagTypes[elem]
|
elemType = self.tagTypes[elem]
|
||||||
if elemType in self.containerTags:
|
if elemType in self.containerTags:
|
||||||
# I must create a new container object.
|
# I must create a new container object.
|
||||||
|
@ -375,9 +375,9 @@ class XmlUnmarshaller(XmlParser):
|
||||||
elif elemType == 'dict': newObject = {}
|
elif elemType == 'dict': newObject = {}
|
||||||
elif elemType == 'file':
|
elif elemType == 'file':
|
||||||
newObject = UnmarshalledFile()
|
newObject = UnmarshalledFile()
|
||||||
if attrs.has_key('name'):
|
if 'name' in attrs:
|
||||||
newObject.name = self.encode(attrs['name'])
|
newObject.name = self.encode(attrs['name'])
|
||||||
if attrs.has_key('mimeType'):
|
if 'mimeType' in attrs:
|
||||||
newObject.mimeType = self.encode(attrs['mimeType'])
|
newObject.mimeType = self.encode(attrs['mimeType'])
|
||||||
else: newObject = Object(**self.convertAttrs(attrs))
|
else: newObject = Object(**self.convertAttrs(attrs))
|
||||||
# Store the value on the last container, or on the root object.
|
# Store the value on the last container, or on the root object.
|
||||||
|
@ -454,17 +454,17 @@ class XmlUnmarshaller(XmlParser):
|
||||||
if not value: value = None
|
if not value: value = None
|
||||||
else:
|
else:
|
||||||
# If we have a custom converter for values of this type, use it.
|
# If we have a custom converter for values of this type, use it.
|
||||||
if self.conversionFunctions.has_key(e.currentBasicType):
|
if e.currentBasicType in self.conversionFunctions:
|
||||||
try:
|
try:
|
||||||
value = self.conversionFunctions[e.currentBasicType](
|
value = self.conversionFunctions[e.currentBasicType](
|
||||||
value)
|
value)
|
||||||
except Exception, err:
|
except Exception as err:
|
||||||
raise AppyError(CUSTOM_CONVERSION_ERROR % (
|
raise AppyError(CUSTOM_CONVERSION_ERROR % (
|
||||||
e.currentBasicType, value, str(err)))
|
e.currentBasicType, value, str(err)))
|
||||||
# If not, try a standard conversion
|
# If not, try a standard conversion
|
||||||
elif e.currentBasicType in self.numericTypes:
|
elif e.currentBasicType in self.numericTypes:
|
||||||
try:
|
try:
|
||||||
exec 'value = %s' % value
|
exec('value = %s' % value)
|
||||||
except SyntaxError:
|
except SyntaxError:
|
||||||
raise AppyError(CONVERSION_ERROR % (
|
raise AppyError(CONVERSION_ERROR % (
|
||||||
e.currentBasicType, value))
|
e.currentBasicType, value))
|
||||||
|
@ -578,7 +578,7 @@ class XmlMarshaller:
|
||||||
tagName = self.getTagName(self.rootElementName)
|
tagName = self.getTagName(self.rootElementName)
|
||||||
res.write('<'); res.write(tagName)
|
res.write('<'); res.write(tagName)
|
||||||
# Dumps namespace definitions if any
|
# Dumps namespace definitions if any
|
||||||
for prefix, url in self.namespaces.iteritems():
|
for prefix, url in self.namespaces.items():
|
||||||
if not prefix:
|
if not prefix:
|
||||||
pre = 'xmlns' # The default namespace
|
pre = 'xmlns' # The default namespace
|
||||||
else:
|
else:
|
||||||
|
@ -597,7 +597,7 @@ class XmlMarshaller:
|
||||||
s = s.decode('utf-8')
|
s = s.decode('utf-8')
|
||||||
# Replace special chars by XML entities
|
# Replace special chars by XML entities
|
||||||
for c in s:
|
for c in s:
|
||||||
if self.xmlEntities.has_key(c):
|
if c in self.xmlEntities:
|
||||||
res.write(self.xmlEntities[c])
|
res.write(self.xmlEntities[c])
|
||||||
else:
|
else:
|
||||||
res.write(c)
|
res.write(c)
|
||||||
|
@ -617,13 +617,13 @@ class XmlMarshaller:
|
||||||
# There will be several parts.
|
# There will be several parts.
|
||||||
w(v.data.data.encode('base64'))
|
w(v.data.data.encode('base64'))
|
||||||
# Write subsequent parts
|
# Write subsequent parts
|
||||||
nextPart = v.data.next
|
nextPart = v.data.__next__
|
||||||
nextPartNb = 2
|
nextPartNb = 2
|
||||||
while nextPart:
|
while nextPart:
|
||||||
w('</%s>' % partTag) # Close the previous part
|
w('</%s>' % partTag) # Close the previous part
|
||||||
w('<%s type="base64" number="%d">' % (partTag, nextPartNb))
|
w('<%s type="base64" number="%d">' % (partTag, nextPartNb))
|
||||||
w(nextPart.data.encode('base64'))
|
w(nextPart.data.encode('base64'))
|
||||||
nextPart = nextPart.next
|
nextPart = nextPart.__next__
|
||||||
nextPartNb += 1
|
nextPartNb += 1
|
||||||
else:
|
else:
|
||||||
w(v.data.encode('base64'))
|
w(v.data.encode('base64'))
|
||||||
|
@ -654,7 +654,7 @@ class XmlMarshaller:
|
||||||
|
|
||||||
def dumpDict(self, res, v):
|
def dumpDict(self, res, v):
|
||||||
'''Dumps the XML version of dict p_v.'''
|
'''Dumps the XML version of dict p_v.'''
|
||||||
for key, value in v.iteritems():
|
for key, value in v.items():
|
||||||
res.write('<entry type="object">')
|
res.write('<entry type="object">')
|
||||||
self.dumpField(res, 'k', key)
|
self.dumpField(res, 'k', key)
|
||||||
self.dumpField(res, 'v', value)
|
self.dumpField(res, 'v', value)
|
||||||
|
@ -681,7 +681,7 @@ class XmlMarshaller:
|
||||||
# The previous condition must be checked before this one because
|
# The previous condition must be checked before this one because
|
||||||
# referred objects may be stored in lists or tuples, too.
|
# referred objects may be stored in lists or tuples, too.
|
||||||
for elem in value: self.dumpField(res, 'e', elem)
|
for elem in value: self.dumpField(res, 'e', elem)
|
||||||
elif isinstance(value, basestring): self.dumpString(res, value)
|
elif isinstance(value, str): self.dumpString(res, value)
|
||||||
elif isinstance(value, bool): res.write(self.trueFalse[value])
|
elif isinstance(value, bool): res.write(self.trueFalse[value])
|
||||||
elif fieldType == 'object':
|
elif fieldType == 'object':
|
||||||
if hasattr(value, 'absolute_url'):
|
if hasattr(value, 'absolute_url'):
|
||||||
|
@ -689,7 +689,7 @@ class XmlMarshaller:
|
||||||
res.write(value.absolute_url())
|
res.write(value.absolute_url())
|
||||||
else:
|
else:
|
||||||
# Dump the entire object content
|
# Dump the entire object content
|
||||||
for k, v in value.__dict__.iteritems():
|
for k, v in value.__dict__.items():
|
||||||
if not k.startswith('__'):
|
if not k.startswith('__'):
|
||||||
self.dumpField(res, k, v)
|
self.dumpField(res, k, v)
|
||||||
# Maybe we could add a parameter to the marshaller to know how
|
# Maybe we could add a parameter to the marshaller to know how
|
||||||
|
@ -771,7 +771,7 @@ class XmlMarshaller:
|
||||||
rootTagName = self.dumpRootTag(res, instance)
|
rootTagName = self.dumpRootTag(res, instance)
|
||||||
# Dump the fields of this root object
|
# Dump the fields of this root object
|
||||||
if objectType == 'popo':
|
if objectType == 'popo':
|
||||||
for fieldName, fieldValue in instance.__dict__.iteritems():
|
for fieldName, fieldValue in instance.__dict__.items():
|
||||||
mustDump = False
|
mustDump = False
|
||||||
if fieldName in self.fieldsToExclude:
|
if fieldName in self.fieldsToExclude:
|
||||||
mustDump = False
|
mustDump = False
|
||||||
|
@ -823,11 +823,11 @@ class XmlMarshaller:
|
||||||
histTag = self.getTagName('history')
|
histTag = self.getTagName('history')
|
||||||
eventTag = self.getTagName('event')
|
eventTag = self.getTagName('event')
|
||||||
res.write('<%s type="list">' % histTag)
|
res.write('<%s type="list">' % histTag)
|
||||||
key = instance.workflow_history.keys()[0]
|
key = list(instance.workflow_history.keys())[0]
|
||||||
history = instance.workflow_history[key]
|
history = instance.workflow_history[key]
|
||||||
for event in history:
|
for event in history:
|
||||||
res.write('<%s type="object">' % eventTag)
|
res.write('<%s type="object">' % eventTag)
|
||||||
for k, v in event.iteritems():
|
for k, v in event.items():
|
||||||
self.dumpField(res, k, v)
|
self.dumpField(res, k, v)
|
||||||
res.write('</%s>' % eventTag)
|
res.write('</%s>' % eventTag)
|
||||||
res.write('</%s>' % histTag)
|
res.write('</%s>' % histTag)
|
||||||
|
@ -856,7 +856,7 @@ class XmlHandler(ContentHandler):
|
||||||
(like dates) from a file that need to be compared to another file.'''
|
(like dates) from a file that need to be compared to another file.'''
|
||||||
def __init__(self, xmlTagsToIgnore, xmlAttrsToIgnore):
|
def __init__(self, xmlTagsToIgnore, xmlAttrsToIgnore):
|
||||||
ContentHandler.__init__(self)
|
ContentHandler.__init__(self)
|
||||||
self.res = unicode(xmlPrologue)
|
self.res = str(xmlPrologue)
|
||||||
self.namespaces = {} # ~{s_namespaceUri:s_namespaceName}~
|
self.namespaces = {} # ~{s_namespaceUri:s_namespaceName}~
|
||||||
self.indentLevel = -1
|
self.indentLevel = -1
|
||||||
self.tabWidth = 3
|
self.tabWidth = 3
|
||||||
|
@ -891,7 +891,7 @@ class XmlHandler(ContentHandler):
|
||||||
self.res += '\n' + (' ' * self.indentLevel * self.tabWidth)
|
self.res += '\n' + (' ' * self.indentLevel * self.tabWidth)
|
||||||
def manageNamespaces(self, attrs):
|
def manageNamespaces(self, attrs):
|
||||||
'''Manage namespaces definitions encountered in attrs'''
|
'''Manage namespaces definitions encountered in attrs'''
|
||||||
for attrName, attrValue in attrs.items():
|
for attrName, attrValue in list(attrs.items()):
|
||||||
if attrName.startswith('xmlns:'):
|
if attrName.startswith('xmlns:'):
|
||||||
self.namespaces[attrValue] = attrName[6:]
|
self.namespaces[attrValue] = attrName[6:]
|
||||||
def ns(self, nsUri):
|
def ns(self, nsUri):
|
||||||
|
@ -906,7 +906,7 @@ class XmlHandler(ContentHandler):
|
||||||
self.indentLevel += 1
|
self.indentLevel += 1
|
||||||
self.dumpSpaces()
|
self.dumpSpaces()
|
||||||
self.res += '<%s' % elem
|
self.res += '<%s' % elem
|
||||||
attrsNames = attrs.keys()
|
attrsNames = list(attrs.keys())
|
||||||
attrsNames.sort()
|
attrsNames.sort()
|
||||||
for attrToIgnore in self.attrsToIgnore:
|
for attrToIgnore in self.attrsToIgnore:
|
||||||
if attrToIgnore in attrsNames:
|
if attrToIgnore in attrsNames:
|
||||||
|
@ -986,7 +986,7 @@ class XmlComparator:
|
||||||
else: print(line)
|
else: print(line)
|
||||||
else:
|
else:
|
||||||
if report: report.say(line[:-1], encoding=encoding)
|
if report: report.say(line[:-1], encoding=encoding)
|
||||||
else: print(line[:-1])
|
else: print((line[:-1]))
|
||||||
lastLinePrinted = True
|
lastLinePrinted = True
|
||||||
else:
|
else:
|
||||||
lastLinePrinted = False
|
lastLinePrinted = False
|
||||||
|
@ -1061,7 +1061,7 @@ class XhtmlCleaner(XmlParser):
|
||||||
self.env.ignoreContent = False
|
self.env.ignoreContent = False
|
||||||
try:
|
try:
|
||||||
res = self.parse('<x>%s</x>' % s).encode('utf-8')
|
res = self.parse('<x>%s</x>' % s).encode('utf-8')
|
||||||
except SAXParseException, e:
|
except SAXParseException as e:
|
||||||
raise self.Error(str(e))
|
raise self.Error(str(e))
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
@ -1106,7 +1106,7 @@ class XhtmlCleaner(XmlParser):
|
||||||
prefix = ''
|
prefix = ''
|
||||||
res = '%s<%s' % (prefix, elem)
|
res = '%s<%s' % (prefix, elem)
|
||||||
# Include the found attributes, excepted those that must be ignored.
|
# Include the found attributes, excepted those that must be ignored.
|
||||||
for name, value in attrs.items():
|
for name, value in list(attrs.items()):
|
||||||
if not self.keepStyles:
|
if not self.keepStyles:
|
||||||
if name in self.attrsToIgnore: continue
|
if name in self.attrsToIgnore: continue
|
||||||
elif name == 'style':
|
elif name == 'style':
|
||||||
|
@ -1115,7 +1115,7 @@ class XhtmlCleaner(XmlParser):
|
||||||
res += ' %s="%s"' % (name, value)
|
res += ' %s="%s"' % (name, value)
|
||||||
# Include additional attributes if required.
|
# Include additional attributes if required.
|
||||||
if elem in self.attrsToAdd:
|
if elem in self.attrsToAdd:
|
||||||
for name, value in self.attrsToAdd[elem].iteritems():
|
for name, value in self.attrsToAdd[elem].items():
|
||||||
res += ' %s="%s"' % (name, value)
|
res += ' %s="%s"' % (name, value)
|
||||||
# Close the tag if it is a no-end tag
|
# Close the tag if it is a no-end tag
|
||||||
if elem in self.noEndTags:
|
if elem in self.noEndTags:
|
||||||
|
@ -1163,7 +1163,7 @@ class XhtmlCleaner(XmlParser):
|
||||||
# I give here to lstrip an explicit list of what is to be considered
|
# I give here to lstrip an explicit list of what is to be considered
|
||||||
# as blank chars, because I do not want unicode NBSP chars to be in
|
# as blank chars, because I do not want unicode NBSP chars to be in
|
||||||
# this list.
|
# this list.
|
||||||
toAdd = content.lstrip(u' \n\r\t')
|
toAdd = content.lstrip(' \n\r\t')
|
||||||
else:
|
else:
|
||||||
toAdd = content
|
toAdd = content
|
||||||
# Re-transform XML special chars to entities.
|
# Re-transform XML special chars to entities.
|
||||||
|
|
Loading…
Reference in a new issue