Skip to content

Instantly share code, notes, and snippets.

@seanupton
Created March 31, 2014 22:44
Show Gist options
  • Save seanupton/9904076 to your computer and use it in GitHub Desktop.
Save seanupton/9904076 to your computer and use it in GitHub Desktop.
Recursive checker for Plone 3 to Plone 4 product upgrade
import os
import re
import sys
import urllib2
from z3c.pt.language import Parser
defines = {
'template_id' : 'template/getId',
'normalizeString' : 'nocall:context/@@plone/normalizeString',
'toLocalizedTime' : 'nocall:context/@@plone/toLocalizedTime',
'portal_properties' : 'context/portal_properties',
'site_properties' : 'context/portal_properties/site_properties',
'here_url' : 'context/@@plone_context_state/object_url',
'portal' : 'context/@@plone_portal_state/portal',
'isAnon' : 'context/@@plone_portal_state/anonymous',
'member' : 'context/@@plone_portal_state/member',
'actions' : 'python:context.portal_actions.listFilteredActionsFor(context)',
'mtool' : 'context/portal_membership',
'wtool' : 'context/portal_workflow',
'wf_state' : 'context/@@plone_context_state/workflow_state',
'default_language' : 'context/@@plone_portal_state/default_language',
'is_editable' : 'context/@@plone_context_state/is_editable',
'isContextDefaultPage' : 'context/@@plone_context_state/is_default_page',
'object_title' : 'context/@@plone_context_state/object_title',
'putils' : 'context/plone_utils',
'ztu' : 'modules/ZTUtils',
'acl_users' : 'context/acl_users',
'ifacetool' : 'context/portal_interface',
'syntool' : 'context/portal_syndication',
}
literal_tokens = (
'template_id', 'normalizeString', 'toLocalizedTime',
'portal_properties', 'site_properties', 'here_url',
'isAnon', 'mtool', 'wtool', 'wf_state', 'default_language',
'is_editable', 'isContextDefaultPage', 'object_title',
'putils', 'ztu', 'acl_users', 'ifacetool', 'syntool',
)
re_tokens = {
re.compile('portal[.]') : 'portal',
re.compile('portal[/]') : 'portal',
re.compile('member[.]') : 'member',
re.compile('member[/]') : 'member',
re.compile('actions[/]') : 'actions',
re.compile('actions[.]') : 'actions',
}
LINEBR = re.compile('[\r\n]+')
parser = Parser()
def main(prod_dir, suggest_fix=False):
"""
Parse and grep for possible Plone 4 template issues in a Product/package
designed for Plone 3.
Attempt xml parsing ZPT template with z3c.pt, grep for
identifier names relying on Plone 3 global defines that no
longer exist in Plone 4.
If suggest_fix is True, print a suggested div tag fragment with
necessary defines to copy and paste into the problem template.
"""
v = [
[os.path.realpath(
os.path.join(e[0], i))
for i in e[2] if i.endswith('pt')]
for e in os.walk(prod_dir) ]
template_files = reduce(lambda x,y: x+y, v)
for fname in template_files:
content = urllib2.urlopen('file://%s' % fname).read()
dname = fname.replace(prod_dir, '') #display name relative path
marked = []
try:
chameleon_doc = parser.parse(content) #parse
except:
print 'XML well-formedness parsing error: %s' % fname
# fun grep-like scanning:
lines = LINEBR.split(content)
lineno = 1
for line in lines:
for token in literal_tokens:
if token in line:
marked.append((lineno, token, line))
for expr,token in re_tokens.items():
if expr.search(line):
marked.append((lineno, token, line))
lineno += 1
if marked:
print dname
print '-'*len(dname)
if suggest_fixes:
block = '<div tal:define="'
indent = 0
for token in set([m[1] for m in marked]):
block += (' '*indent) + '%s %s;\n' % (token, defines[token])
indent = 17
block += '">\n'
print block
print '---'
for instance in marked:
print '[Line %s] matched token: %s\n\t%s' % instance
print '='*78
if __name__ == '__main__':
if len(sys.argv) < 2 or (len(sys.argv)==2 and sys.argv[-1]=='--fix'):
print >> sys.stderr, 'Usage: check.py [--fix] <product_dir>'
exit(0)
prod_dir = sys.argv[-1]
suggest_fixes = '--fix' in sys.argv
main(prod_dir, suggest_fixes)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment