Updated new.py for installing Plone 4 without buildout and added an alternative way to insert POD expressions in POD templates via fields (track-changed text still works).
This commit is contained in:
parent
feca97bda3
commit
50c8a139fc
338
bin/new.py
338
bin/new.py
|
@ -1,9 +1,9 @@
|
||||||
'''This script allows to create a brand new read-to-use Plone/Zone instance.
|
'''This script allows to create a brand new ready-to-use Plone/Zone instance.
|
||||||
As prerequisite, you must have installed Plone through the Unifier installer
|
As prerequisite, you must have installed Plone through the Unifier installer
|
||||||
available at http://plone.org.'''
|
available at http://plone.org.'''
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
import os, os.path, sys, shutil
|
import os, os.path, sys, shutil, re
|
||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
from appy.shared.utils import cleanFolder, copyFolder
|
from appy.shared.utils import cleanFolder, copyFolder
|
||||||
|
|
||||||
|
@ -22,12 +22,34 @@ MKZOPE_NOT_FOUND = 'Script mkzopeinstance.py not found in "%s and ' \
|
||||||
WRONG_INSTANCE_PATH = '"%s" must be an existing folder for creating the ' \
|
WRONG_INSTANCE_PATH = '"%s" must be an existing folder for creating the ' \
|
||||||
'instance in it.'
|
'instance in it.'
|
||||||
|
|
||||||
|
zopeCtl = '''#!/bin/sh
|
||||||
|
PYTHON="%s"
|
||||||
|
INSTANCE_HOME="%s"
|
||||||
|
CONFIG_FILE="$INSTANCE_HOME/etc/zope.conf"
|
||||||
|
PYTHONPATH="$INSTANCE_HOME/lib/python"
|
||||||
|
ZDCTL="%s/Zope2/Startup/zopectl.py"
|
||||||
|
export INSTANCE_HOME
|
||||||
|
export PYTHON
|
||||||
|
export PYTHONPATH
|
||||||
|
exec "$PYTHON" "$ZDCTL" -C "$CONFIG_FILE" "$@"
|
||||||
|
'''
|
||||||
|
runZope = '''#! /bin/sh
|
||||||
|
PYTHON="%s"
|
||||||
|
INSTANCE_HOME="%s"
|
||||||
|
CONFIG_FILE="$INSTANCE_HOME/etc/zope.conf"
|
||||||
|
PYTHONPATH="$INSTANCE_HOME/lib/python"
|
||||||
|
ZOPE_RUN="%s/Zope2/Startup/run.py"
|
||||||
|
export INSTANCE_HOME
|
||||||
|
export PYTHON
|
||||||
|
export PYTHONPATH
|
||||||
|
exec "$PYTHON" "$ZOPE_RUN" -C "$CONFIG_FILE" "$@"
|
||||||
|
'''
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
class NewScript:
|
class NewScript:
|
||||||
'''usage: %prog ploneVersion plonePath instancePath
|
'''usage: %prog ploneVersion plonePath instancePath
|
||||||
|
|
||||||
"ploneVersion" can be plone25, plone30, or plone3x
|
"ploneVersion" can be plone25, plone30, plone3x or plone4
|
||||||
(plone3x can be Plone 3.2.x, Plone 3.3.5...)
|
(plone3x represents Plone 3.2.x, Plone 3.3.5...)
|
||||||
|
|
||||||
"plonePath" is the (absolute) path to you plone installation.
|
"plonePath" is the (absolute) path to you plone installation.
|
||||||
Plone 2.5 and 3.0 are typically installed in
|
Plone 2.5 and 3.0 are typically installed in
|
||||||
|
@ -35,48 +57,7 @@ class NewScript:
|
||||||
installed in in /usr/local/Plone.
|
installed in in /usr/local/Plone.
|
||||||
"instancePath" is the (absolute) path where you want to create your
|
"instancePath" is the (absolute) path where you want to create your
|
||||||
instance (should not already exist).'''
|
instance (should not already exist).'''
|
||||||
ploneVersions = ('plone25', 'plone30', 'plone3x')
|
ploneVersions = ('plone25', 'plone30', 'plone3x', 'plone4')
|
||||||
|
|
||||||
def createInstance(self, linksForProducts):
|
|
||||||
'''Calls the Zope script that allows to create a Zope instance and copy
|
|
||||||
into it all the Plone packages and products.'''
|
|
||||||
# Find the Python interpreter running Zope
|
|
||||||
for elem in os.listdir(self.plonePath):
|
|
||||||
pythonPath = None
|
|
||||||
elemPath = os.path.join(self.plonePath, elem)
|
|
||||||
if elem.startswith('Python-') and os.path.isdir(elemPath):
|
|
||||||
pythonPath = elemPath + '/bin/python'
|
|
||||||
if not os.path.exists(pythonPath):
|
|
||||||
raise NewError(PYTHON_EXE_NOT_FOUND % pythonPath)
|
|
||||||
break
|
|
||||||
if not pythonPath:
|
|
||||||
raise NewError(PYTHON_NOT_FOUND % self.plonePath)
|
|
||||||
# Find the Zope script mkzopeinstance.py
|
|
||||||
makeInstancePath = None
|
|
||||||
for dirname, dirs, files in os.walk(self.plonePath):
|
|
||||||
# Do not browse the buildout-cache
|
|
||||||
for fileName in files:
|
|
||||||
if (fileName == 'mkzopeinstance.py') and \
|
|
||||||
('/buildout-cache/' not in dirname):
|
|
||||||
makeInstancePath = os.path.join(dirname, fileName)
|
|
||||||
if not makeInstancePath:
|
|
||||||
raise NewError(MKZOPE_NOT_FOUND % self.plonePath)
|
|
||||||
# Execute mkzopeinstance.py with the right Python interpreter
|
|
||||||
cmd = '%s %s -d %s' % (pythonPath, makeInstancePath, self.instancePath)
|
|
||||||
print cmd
|
|
||||||
os.system(cmd)
|
|
||||||
# Now, make the instance Plone-ready
|
|
||||||
action = 'Copying'
|
|
||||||
if linksForProducts:
|
|
||||||
action = 'Symlinking'
|
|
||||||
print '%s Plone stuff in the Zope instance...' % action
|
|
||||||
if self.ploneVersion in ('plone25', 'plone30'):
|
|
||||||
self.installPlone25or30Stuff(linksForProducts)
|
|
||||||
elif self.ploneVersion == 'plone3x':
|
|
||||||
self.installPlone3Stuff()
|
|
||||||
# Clean the copied folders
|
|
||||||
cleanFolder(os.path.join(self.instancePath, 'Products'))
|
|
||||||
cleanFolder(os.path.join(self.instancePath, 'lib/python'))
|
|
||||||
|
|
||||||
def installPlone25or30Stuff(self, linksForProducts):
|
def installPlone25or30Stuff(self, linksForProducts):
|
||||||
'''Here, we will copy all Plone2-related stuff in the Zope instance
|
'''Here, we will copy all Plone2-related stuff in the Zope instance
|
||||||
|
@ -105,56 +86,9 @@ class NewScript:
|
||||||
# Copy thre product into the instance
|
# Copy thre product into the instance
|
||||||
copyFolder(folderName, destFolder)
|
copyFolder(folderName, destFolder)
|
||||||
|
|
||||||
uglyChunks = ('pkg_resources', '.declare_namespace(')
|
filesToPatch = ('meta.zcml', 'configure.zcml', 'overrides.zcml')
|
||||||
def findPythonPackageInEgg(self, currentFolder):
|
patchRex = re.compile('<includePlugins.*?/>', re.S)
|
||||||
'''Finds the Python package that is deeply hidden into the egg.'''
|
def patchPlone3x(self):
|
||||||
# Find the file __init__.py
|
|
||||||
isFinalPackage = False
|
|
||||||
for elem in os.listdir(currentFolder):
|
|
||||||
elemPath = os.path.join(currentFolder, elem)
|
|
||||||
if elem == '__init__.py':
|
|
||||||
f = file(elemPath)
|
|
||||||
content = f.read()
|
|
||||||
f.close()
|
|
||||||
# Is it a awful egg init ?
|
|
||||||
for chunk in self.uglyChunks:
|
|
||||||
if content.find(chunk) == -1:
|
|
||||||
isFinalPackage = True # It is not an ugly egg init.
|
|
||||||
break
|
|
||||||
if not isFinalPackage:
|
|
||||||
# Maybe we are wrong: our way to identify egg-viciated __init__
|
|
||||||
# files is approximative. If we believe it is not the final package,
|
|
||||||
# but we find other Python files in the folder, we must admit that
|
|
||||||
# we've nevertheless found the final Python package.
|
|
||||||
otherPythonFiles = False
|
|
||||||
for elem in os.listdir(currentFolder):
|
|
||||||
if elem.endswith('.py') and (elem != '__init__.py'):
|
|
||||||
otherPythonFiles = True
|
|
||||||
break
|
|
||||||
if otherPythonFiles:
|
|
||||||
# Ok, this is the final Python package
|
|
||||||
return currentFolder
|
|
||||||
# Find the subfolder and find the Python package into it.
|
|
||||||
for elem in os.listdir(currentFolder):
|
|
||||||
elemPath = os.path.join(currentFolder, elem)
|
|
||||||
if os.path.isdir(elemPath):
|
|
||||||
return self.findPythonPackageInEgg(elemPath)
|
|
||||||
else:
|
|
||||||
return currentFolder
|
|
||||||
|
|
||||||
def getSubFolder(self, folder):
|
|
||||||
'''In p_folder, we now that there is only one subfolder. This method
|
|
||||||
returns the subfolder's absolute path.'''
|
|
||||||
for elem in os.listdir(folder):
|
|
||||||
elemPath = os.path.join(folder, elem)
|
|
||||||
if (elem != 'EGG-INFO') and os.path.isdir(elemPath):
|
|
||||||
return elemPath
|
|
||||||
return None
|
|
||||||
|
|
||||||
viciatedFiles = {'meta.zcml': 'includePlugins',
|
|
||||||
'configure.zcml': 'includePlugins',
|
|
||||||
'overrides.zcml': 'includePluginsOverrides'}
|
|
||||||
def patchPlone(self, productsFolder, libFolder):
|
|
||||||
'''Auto-proclaimed ugly code in z3c forces us to patch some files
|
'''Auto-proclaimed ugly code in z3c forces us to patch some files
|
||||||
in Products.CMFPlone because these guys make the assumption that
|
in Products.CMFPlone because these guys make the assumption that
|
||||||
"plone.xxx" packages are within eggs when they've implemented their
|
"plone.xxx" packages are within eggs when they've implemented their
|
||||||
|
@ -163,102 +97,156 @@ class NewScript:
|
||||||
CMFPlone files. It does not seem to affect Plone behaviour. Indeed,
|
CMFPlone files. It does not seem to affect Plone behaviour. Indeed,
|
||||||
these directives seem to be useful only when adding sad (ie, non
|
these directives seem to be useful only when adding sad (ie, non
|
||||||
Appy) Plone plug-ins.'''
|
Appy) Plone plug-ins.'''
|
||||||
ploneFolder = os.path.join(productsFolder, 'CMFPlone')
|
j = os.path.join
|
||||||
# Patch viciated files
|
ploneFolder = os.path.join(self.productsFolder, 'CMFPlone')
|
||||||
for fileName, uglyDirective in self.viciatedFiles.iteritems():
|
# Patch files
|
||||||
|
for fileName in self.filesToPatch:
|
||||||
filePath = os.path.join(ploneFolder, fileName)
|
filePath = os.path.join(ploneFolder, fileName)
|
||||||
f = file(filePath)
|
f = file(filePath)
|
||||||
fileContent = f.read()
|
fileContent = f.read()
|
||||||
f.close()
|
f.close()
|
||||||
if fileContent.find(uglyDirective) != -1:
|
|
||||||
toReplace = '<%s package="plone" file="%s" />' % \
|
|
||||||
(uglyDirective, fileName)
|
|
||||||
fileContent = fileContent.replace(toReplace, '')
|
|
||||||
f = file(filePath, 'w')
|
f = file(filePath, 'w')
|
||||||
f.write(fileContent)
|
f.write(self.patchRex.sub('<!--Del. includePlugins-->',fileContent))
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
def installPlone3Stuff(self):
|
filesToPatch2 = ('profiles/default/skins.xml')
|
||||||
'''Here, we will copy all Plone3-related stuff in the Zope instance
|
def patchPlone4(self):
|
||||||
we've created, to get a full Plone-ready Zope instance.'''
|
'''Patches Plone 4 that can't live without buildout as-is.'''
|
||||||
# All Plone 3 eggs are in buildout-cache/eggs. We will extract from
|
self.patchPlone3x() # We still need this for Plone 4 as well.
|
||||||
# those silly overstructured folder hierarchies the standard Python
|
# bin/zopectl
|
||||||
# packages that lie in it, and copy them in the instance. Within these
|
content = zopeCtl % (self.pythonPath, self.instancePath, self.zopePath)
|
||||||
# eggs, we need to distinguish:
|
f = file('%s/bin/zopectl' % self.instancePath, 'w')
|
||||||
# - standard Python packages that will be copied in
|
f.write(content)
|
||||||
# <zopeInstance>/lib/python (ie, like Appy applications)
|
f.close()
|
||||||
# - Zope products that will be copied in
|
# bin/runzope
|
||||||
# <zopeInstance>/Products (ie, like Appy generated Zope products)
|
content = runZope % (self.pythonPath, self.instancePath, self.zopePath)
|
||||||
|
f = file('%s/bin/runzope' % self.instancePath, 'w')
|
||||||
|
f.write(content)
|
||||||
|
f.close()
|
||||||
|
j = os.path.join
|
||||||
|
themeFolder = '%s/plonetheme' % self.libFolder
|
||||||
|
for theme in os.listdir(themeFolder):
|
||||||
|
# Create a simlink to every theme in self.productsFolder
|
||||||
|
tFolder = j(themeFolder, theme)
|
||||||
|
if not os.path.isdir(tFolder): continue
|
||||||
|
os.system('ln -s %s %s/%s' % (tFolder, self.productsFolder, theme))
|
||||||
|
# Patch skins.xml
|
||||||
|
fileName = '%s/profiles/default/skins.xml' % tFolder
|
||||||
|
f = file(fileName)
|
||||||
|
content = f.read()
|
||||||
|
f.close()
|
||||||
|
f = file(fileName, 'w')
|
||||||
|
f.write(content.replace('plonetheme.%s:' % theme, '%s/' % theme))
|
||||||
|
f.close()
|
||||||
|
# As eggs have been deleted, Plone can't tell which version of Zope and
|
||||||
|
# Plone are there. So we patch the code that tries to get Plone and Zope
|
||||||
|
# versions.
|
||||||
|
codeFile = "%s/pkg_resources.py" % self.libFolder
|
||||||
|
f = file(codeFile)
|
||||||
|
content = f.read()
|
||||||
|
f.close()
|
||||||
|
content = content.replace("raise DistributionNotFound(req)",
|
||||||
|
"dist = Distribution(project_name=req.project_name, " \
|
||||||
|
"version='1.1.1', platform='linux2', location='%s')" % \
|
||||||
|
self.instancePath)
|
||||||
|
f = file(codeFile, 'w')
|
||||||
|
f.write(content)
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
def copyEggs(self):
|
||||||
|
'''Copy content of eggs into the Zope instance.'''
|
||||||
j = os.path.join
|
j = os.path.join
|
||||||
eggsFolder = j(self.plonePath, 'buildout-cache/eggs')
|
eggsFolder = j(self.plonePath, 'buildout-cache/eggs')
|
||||||
productsFolder = j(self.instancePath, 'Products')
|
self.ploneThemes = []
|
||||||
libFolder = j(self.instancePath, 'lib/python')
|
|
||||||
for name in os.listdir(eggsFolder):
|
for name in os.listdir(eggsFolder):
|
||||||
eggMainFolder = j(eggsFolder, name)
|
if name == 'EGG-INFO': continue
|
||||||
if name.startswith('Products.'):
|
absName = j(eggsFolder, name)
|
||||||
# A Zope product. Copy its content in Products.
|
# Copy every file or sub-folder into self.libFolder or
|
||||||
innerFolder= self.getSubFolder(self.getSubFolder(eggMainFolder))
|
# self.productsFolder.
|
||||||
destFolder = j(productsFolder, os.path.basename(innerFolder))
|
for fileName in os.listdir(absName):
|
||||||
copyFolder(innerFolder, destFolder)
|
absFileName = j(absName, fileName)
|
||||||
|
if fileName == 'Products' and not name.startswith('Zope2-'):
|
||||||
|
# Copy every sub-folder into self.productsFolder
|
||||||
|
for folderName in os.listdir(absFileName):
|
||||||
|
absFolder = j(absFileName, folderName)
|
||||||
|
if not os.path.isdir(absFolder): continue
|
||||||
|
copyFolder(absFolder, j(self.productsFolder,folderName))
|
||||||
|
elif os.path.isdir(absFileName):
|
||||||
|
copyFolder(absFileName, j(self.libFolder, fileName))
|
||||||
else:
|
else:
|
||||||
# A standard Python package. Copy its content in lib/python.
|
shutil.copy(absFileName, self.libFolder)
|
||||||
# Go into the subFolder that is not EGG-INFO.
|
|
||||||
eggFolder = self.getSubFolder(eggMainFolder)
|
def createInstance(self, linksForProducts):
|
||||||
if not eggFolder:
|
'''Calls the Zope script that allows to create a Zope instance and copy
|
||||||
# This egg is malformed and contains basic Python files.
|
into it all the Plone packages and products.'''
|
||||||
# Copy those files directly in libFolder.
|
j = os.path.join
|
||||||
for fileName in os.listdir(eggMainFolder):
|
# Find the Python interpreter running Zope
|
||||||
if fileName.endswith('.py'):
|
for elem in os.listdir(self.plonePath):
|
||||||
fullFileName= j(eggMainFolder, fileName)
|
pythonPath = None
|
||||||
shutil.copy(fullFileName, libFolder)
|
elemPath = j(self.plonePath, elem)
|
||||||
continue
|
if elem.startswith('Python-') and os.path.isdir(elemPath):
|
||||||
eggFolderName = os.path.basename(eggFolder)
|
pythonPath = elemPath + '/bin/python'
|
||||||
if eggFolderName == 'Products':
|
if not os.path.exists(pythonPath):
|
||||||
# Goddamned. This should go in productsFolder and not in
|
raise NewError(PYTHON_EXE_NOT_FOUND % pythonPath)
|
||||||
# libFolder.
|
break
|
||||||
innerFolder = self.getSubFolder(eggFolder)
|
if not pythonPath:
|
||||||
destFolder = j(productsFolder,os.path.basename(innerFolder))
|
raise NewError(PYTHON_NOT_FOUND % self.plonePath)
|
||||||
copyFolder(innerFolder, destFolder)
|
self.pythonPath = pythonPath
|
||||||
|
# Find the Zope script mkzopeinstance.py and Zope itself
|
||||||
|
makeInstancePath = None
|
||||||
|
self.zopePath = None
|
||||||
|
for dirname, dirs, files in os.walk(self.plonePath):
|
||||||
|
# Find Zope
|
||||||
|
for folderName in dirs:
|
||||||
|
if folderName.startswith('Zope2-'):
|
||||||
|
self.zopePath = j(dirname, folderName)
|
||||||
|
# Find mkzopeinstance
|
||||||
|
for fileName in files:
|
||||||
|
if fileName == 'mkzopeinstance.py':
|
||||||
|
if self.ploneVersion == 'plone4':
|
||||||
|
makeInstancePath = j(dirname, fileName)
|
||||||
else:
|
else:
|
||||||
packageFolder = self.findPythonPackageInEgg(eggFolder)
|
if ('/buildout-cache/' not in dirname):
|
||||||
# Create the destination folder(s) in the instance,
|
makeInstancePath = j(dirname, fileName)
|
||||||
# within libFolder
|
if not makeInstancePath:
|
||||||
destFolders = []
|
raise NewError(MKZOPE_NOT_FOUND % self.plonePath)
|
||||||
if packageFolder != eggFolder:
|
# Execute mkzopeinstance.py with the right Python interpreter.
|
||||||
destFolders = [eggFolderName]
|
# For Plone4, we will call it later.
|
||||||
remFolders = packageFolder[len(eggFolder):]
|
cmd = '%s %s -d %s' % (pythonPath, makeInstancePath, self.instancePath)
|
||||||
remFolders = remFolders.strip(os.sep)
|
if self.ploneVersion != 'plone4':
|
||||||
if remFolders.find(os.sep) != -1:
|
print cmd
|
||||||
# There are more subfolders
|
os.system(cmd)
|
||||||
destFolders += remFolders.split(os.sep)[:-1]
|
# Now, make the instance Plone-ready
|
||||||
if destFolders:
|
action = 'Copying'
|
||||||
# We must create the subfolders (if not yet created)
|
if linksForProducts:
|
||||||
# before copying the Python package.
|
action = 'Symlinking'
|
||||||
baseFolder = libFolder
|
print '%s Plone stuff in the Zope instance...' % action
|
||||||
for subFolder in destFolders:
|
if self.ploneVersion in ('plone25', 'plone30'):
|
||||||
subFolderPath = j(baseFolder,subFolder)
|
self.installPlone25or30Stuff(linksForProducts)
|
||||||
if not os.path.exists(subFolderPath):
|
elif self.ploneVersion in ('plone3x', 'plone4'):
|
||||||
os.mkdir(subFolderPath)
|
self.copyEggs()
|
||||||
# Create an empty __init__.py in it.
|
if self.ploneVersion == 'plone3x':
|
||||||
init = j(subFolderPath,'__init__.py')
|
self.patchPlone3x()
|
||||||
f = file(init, 'w')
|
elif self.ploneVersion == 'plone4':
|
||||||
f.write('# Makes me a Python package.')
|
# Create the Zope instance
|
||||||
f.close()
|
os.environ['PYTHONPATH'] = '%s:%s' % \
|
||||||
baseFolder = subFolderPath
|
(j(self.instancePath,'Products'),
|
||||||
destFolder = os.sep.join(destFolders)
|
j(self.instancePath, 'lib/python'))
|
||||||
destFolder = j(libFolder, destFolder)
|
print cmd
|
||||||
if not os.path.exists(destFolder):
|
os.system(cmd)
|
||||||
os.makedirs(destFolder)
|
self.patchPlone4()
|
||||||
else:
|
# Remove .bat files under Linux
|
||||||
destFolder = libFolder
|
if os.name == 'posix':
|
||||||
destFolder = j(destFolder, os.path.basename(packageFolder))
|
cleanFolder(j(self.instancePath, 'bin'), exts=('.bat',))
|
||||||
copyFolder(packageFolder, destFolder)
|
|
||||||
self.patchPlone(productsFolder, libFolder)
|
|
||||||
|
|
||||||
def manageArgs(self, args):
|
def manageArgs(self, args):
|
||||||
'''Ensures that the script was called with the right parameters.'''
|
'''Ensures that the script was called with the right parameters.'''
|
||||||
if len(args) != 3: raise NewError(WRONG_NB_OF_ARGS)
|
if len(args) != 3: raise NewError(WRONG_NB_OF_ARGS)
|
||||||
self.ploneVersion, self.plonePath, self.instancePath = args
|
self.ploneVersion, self.plonePath, self.instancePath = args
|
||||||
|
# Add some more folder definitions
|
||||||
|
j = os.path.join
|
||||||
|
self.productsFolder = j(self.instancePath, 'Products')
|
||||||
|
self.libFolder = j(self.instancePath, 'lib/python')
|
||||||
# Check Plone version
|
# Check Plone version
|
||||||
if self.ploneVersion not in self.ploneVersions:
|
if self.ploneVersion not in self.ploneVersions:
|
||||||
raise NewError(WRONG_PLONE_VERSION % str(self.ploneVersions))
|
raise NewError(WRONG_PLONE_VERSION % str(self.ploneVersions))
|
||||||
|
|
|
@ -189,6 +189,7 @@
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<tal:comment replace="nothing">Show forward reference(s)</tal:comment>
|
<tal:comment replace="nothing">Show forward reference(s)</tal:comment>
|
||||||
|
|
||||||
<table tal:attributes="class python:test(innerRef, '', 'listing nosort');
|
<table tal:attributes="class python:test(innerRef, '', 'listing nosort');
|
||||||
width python:test(innerRef, '100%', appyType['layouts']['view']['width']);"
|
width python:test(innerRef, '100%', appyType['layouts']['view']['width']);"
|
||||||
align="right" tal:condition="python: not appyType['isBack'] and objs" cellpadding="0" cellspacing="0">
|
align="right" tal:condition="python: not appyType['isBack'] and objs" cellpadding="0" cellspacing="0">
|
||||||
|
|
|
@ -100,8 +100,8 @@ class PodEnvironment(OdfEnvironment):
|
||||||
# For the currently read expression, is there style-related information
|
# For the currently read expression, is there style-related information
|
||||||
# associated with it?
|
# associated with it?
|
||||||
self.exprHasStyle = False
|
self.exprHasStyle = False
|
||||||
self.gotNamespaces = False # Namespace definitions were not already
|
# Namespace definitions are not already encountered.
|
||||||
# encountered
|
self.gotNamespaces = False
|
||||||
# Store inserts
|
# Store inserts
|
||||||
self.inserts = inserts
|
self.inserts = inserts
|
||||||
# Currently walked "if" actions
|
# Currently walked "if" actions
|
||||||
|
@ -208,7 +208,8 @@ class PodParser(OdfParser):
|
||||||
e.state = e.IGNORING
|
e.state = e.IGNORING
|
||||||
elif elem == ('%s:annotation' % officeNs):
|
elif elem == ('%s:annotation' % officeNs):
|
||||||
e.state = e.READING_STATEMENT
|
e.state = e.READING_STATEMENT
|
||||||
elif elem == ('%s:change-start' % textNs):
|
elif (elem == ('%s:change-start' % textNs)) or \
|
||||||
|
(elem == ('%s:conditional-text' % textNs)):
|
||||||
e.state = e.READING_EXPRESSION
|
e.state = e.READING_EXPRESSION
|
||||||
e.exprHasStyle = False
|
e.exprHasStyle = False
|
||||||
else:
|
else:
|
||||||
|
@ -280,7 +281,8 @@ class PodParser(OdfParser):
|
||||||
e.currentStatement.append(statementLine)
|
e.currentStatement.append(statementLine)
|
||||||
e.currentContent = ''
|
e.currentContent = ''
|
||||||
elif e.state == e.READING_EXPRESSION:
|
elif e.state == e.READING_EXPRESSION:
|
||||||
if elem == ('%s:change-end' % textNs):
|
if (elem == ('%s:change-end' % textNs)) or \
|
||||||
|
(elem == ('%s:conditional-text' % textNs)):
|
||||||
expression = e.currentContent.strip()
|
expression = e.currentContent.strip()
|
||||||
e.currentContent = ''
|
e.currentContent = ''
|
||||||
# Manage expression
|
# Manage expression
|
||||||
|
|
3280
pod/test/Tests.rtf
3280
pod/test/Tests.rtf
File diff suppressed because it is too large
Load diff
2
pod/test/contexts/FieldExpressions.py
Normal file
2
pod/test/contexts/FieldExpressions.py
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
old = 'OLD'
|
||||||
|
new = 'NEW'
|
BIN
pod/test/results/fieldExpression.odt
Normal file
BIN
pod/test/results/fieldExpression.odt
Normal file
Binary file not shown.
BIN
pod/test/templates/FieldExpressions.odt
Normal file
BIN
pod/test/templates/FieldExpressions.odt
Normal file
Binary file not shown.
|
@ -68,7 +68,7 @@ binaryRex = re.compile(r'[\000-\006\177-\277]')
|
||||||
|
|
||||||
class Resource:
|
class Resource:
|
||||||
'''Every instance of this class represents some web resource accessible
|
'''Every instance of this class represents some web resource accessible
|
||||||
through WebDAV.'''
|
through HTTP.'''
|
||||||
|
|
||||||
def __init__(self, url, username=None, password=None, measure=False):
|
def __init__(self, url, username=None, password=None, measure=False):
|
||||||
self.username = username
|
self.username = username
|
||||||
|
@ -94,9 +94,7 @@ class Resource:
|
||||||
else: raise 'Wrong URL: %s' % str(url)
|
else: raise 'Wrong URL: %s' % str(url)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
port = ':' + str(self.port)
|
return '<Dav resource at %s>' % self.url
|
||||||
if self.port == 80: port = ''
|
|
||||||
return '<Dav resource at %s%s/%s>' % (self.url, port, self.uri)
|
|
||||||
|
|
||||||
def updateHeaders(self, headers):
|
def updateHeaders(self, headers):
|
||||||
# Add credentials if present
|
# Add credentials if present
|
||||||
|
@ -203,12 +201,22 @@ class Resource:
|
||||||
if not uri: uri = self.uri
|
if not uri: uri = self.uri
|
||||||
return self.sendRequest('GET', uri, headers=headers)
|
return self.sendRequest('GET', uri, headers=headers)
|
||||||
|
|
||||||
def post(self, data, uri=None, headers={}):
|
def post(self, data=None, uri=None, headers={}, type='form'):
|
||||||
'''Perform a HTTP POST on the server.'''
|
'''Perform a HTTP POST on the server. If p_type is:
|
||||||
|
- "form", p_data is a dict representing form data that will be
|
||||||
|
form-encoded;
|
||||||
|
- "soap", p_data is a XML request that will be wrapped in a SOAP
|
||||||
|
message.'''
|
||||||
if not uri: uri = self.uri
|
if not uri: uri = self.uri
|
||||||
|
# Prepare the data to send
|
||||||
|
if type == 'form':
|
||||||
# Format the form data and prepare headers
|
# Format the form data and prepare headers
|
||||||
body = DataEncoder(data).encode()
|
body = DataEncoder(data).encode()
|
||||||
headers['Content-Type'] = 'application/x-www-form-urlencoded'
|
headers['Content-Type'] = 'application/x-www-form-urlencoded'
|
||||||
|
elif type =='soap':
|
||||||
|
body = data
|
||||||
|
headers['SOAPAction'] = self.url
|
||||||
|
headers['Content-Type'] = 'text/xml'
|
||||||
headers['Content-Length'] = str(len(body))
|
headers['Content-Length'] = str(len(body))
|
||||||
return self.sendRequest('POST', uri, headers=headers, body=body)
|
return self.sendRequest('POST', uri, headers=headers, body=body)
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -51,7 +51,10 @@ def cleanFolder(folder, exts=extsToClean, verbose=False):
|
||||||
def copyFolder(source, dest, cleanDest=False):
|
def copyFolder(source, dest, cleanDest=False):
|
||||||
'''Copies the content of folder p_source to folder p_dest. p_dest is
|
'''Copies the content of folder p_source to folder p_dest. p_dest is
|
||||||
created, with intermediary subfolders if required. If p_cleanDest is
|
created, with intermediary subfolders if required. If p_cleanDest is
|
||||||
True, it removes completely p_dest if it existed.'''
|
True, it removes completely p_dest if it existed. Else, content of
|
||||||
|
p_source will be added to possibly existing content in p_dest, excepted
|
||||||
|
if file names corresponds. In this case, file in p_source will overwrite
|
||||||
|
file in p_dest.'''
|
||||||
dest = os.path.abspath(dest)
|
dest = os.path.abspath(dest)
|
||||||
# Delete the dest folder if required
|
# Delete the dest folder if required
|
||||||
if os.path.exists(dest) and cleanDest:
|
if os.path.exists(dest) and cleanDest:
|
||||||
|
|
Loading…
Reference in a new issue