This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
formalad/qa.py

559 lines
19 KiB
Python

#! /usr/bin/env python
import sys
import re
import random
import hashlib
class ShorterException(Exception):
pass
class LongerException(Exception):
pass
class Item:
def __init__(self, line, parent):
self.parent = parent
self.indent = len(re.findall(r'^\s*', line)[0]) + 1
self.text = line[self.indent+1:].strip()
self.elems = []
self.set_identifier()
if '{' in self.text:
self.massage_identifier()
def set_identifier(self):
self.identifier = 'x' + hashlib.md5(str(random.random())).hexdigest()[:10]
def feed(self, line):
if line.strip()[1] == ':': # command
if not line.startswith(' '*self.indent):
raise ShorterException()
raise LongerException()
self.text += '\n' + line.strip()
if '{' in self.text:
self.massage_identifier()
def massage_identifier(self):
self.identifier = re.findall (r'\{(.*)\}', self.text)[0]
if self.parent:
self.identifier = self.parent.identifier + '_' + self.identifier
self.text = self.text[:self.text.index('{')].strip()
def prt(self):
print ('\t'*self.indent) + 'text:' + repr(self.text)
for elem in self.elems:
elem.prt()
def as_schema_field(self):
return ''
def get_child_schema_fields(self):
return []
def get_child_schema_fields(self):
r = []
for child in self.elems:
if isinstance(child, Yes) or isinstance(child, No):
if child.text:
r.append(child.as_schema_field())
else:
for grandchild in child.elems:
r.append(grandchild.as_schema_field())
r.extend(grandchild.get_child_schema_fields())
else:
r.append(child.as_schema_field())
return r
class Question(Item):
def as_schema_field(self):
s = []
s.append('''
StringField(
name='%s',
widget=MasterSelectWidget(
label=u"""%s""",
slave_fields =
''' % (self.identifier, self.text))
for child in self.elems:
if isinstance(child, No):
if child.text:
slaves = "'%s'" % child.identifier
else:
slaves = ', '.join(["'%s'" % x.identifier for x in child.elems])
s.append(''' slaveFields('showIfNo', %s)''' % slaves)
elif isinstance(child, Yes):
if child.text:
slaves = "'%s'" % child.identifier
else:
slaves = ', '.join(["'%s'" % x.identifier for x in child.elems])
s.append(''' slaveFields('showIfYes', %s)''' % slaves)
else:
raise AssertionError('unhandled child: %r' % child)
if child is self.elems[-1]:
s.append(',')
else:
s.append(' + \\\n')
s.append('''
label_msgid='AvisLegis_%s',
i18n_domain='Avis',
),
enforceVocabulary=True,
required=True,\n''' % self.identifier)
if self.elems and isinstance(self.elems[0], Yes):
s.append(""" vocabulary='getResponses'\n""")
else:
s.append(""" vocabulary='getResponsesInversed'\n""")
s.append(' ),\n')
return ''.join(s)
class Answer(Item):
def set_identifier(self):
self.identifier = self.parent.identifier + '_analyse'
def as_schema_field(self):
return '''
TextField(
name='%s',
widget=TextAreaWidget(
label=u"Analyse",
label_msgid='Avis_label_%s',
i18n_domain='Avis',
),
default_output_type="text/html",
default=defaultAnalysisValues['%s']['%s']
),
''' % (self.identifier, self.identifier, self.identifier, self.default_answer)
class No(Answer):
default_answer = 'no'
def get_analysis_value(self):
return """
'%s': \\
{'yes': '',
'no' : u'''%s'''
},""" % (self.identifier, self.text)
class Yes(Answer):
default_answer = 'yes'
def get_analysis_value(self):
return """
'%s': \\
{'yes': u'''%s''',
'no' : ''
},""" % (self.identifier, self.text)
class Title(Item):
pass
class Subtitle(Item):
pass
class Comment(Item):
pass
def new_from_line(line, parent):
line0 = line.strip()[0]
if line0 == 'C':
return Comment(line, parent=parent)
if line0 == 'T':
return Title(line, parent=parent)
if line0 == 't':
return Subtitle(line, parent=parent)
if line0 == 'Q':
return Question(line, parent=parent)
if line0 == 'Y':
return Yes(line, parent=parent)
if line0 == 'N':
return No(line, parent=parent)
print 'unknown type:', line.strip()[0]
print repr(line)
def parse_file(filename):
elems = []
stack = []
for line in file(filename):
if not line.strip():
continue
try:
stack[-1].feed(line)
except IndexError: # empty stack
current_item = new_from_line(line, parent=None)
elems.append(current_item)
stack.append(current_item)
except ShorterException:
new_indent = len(re.findall(r'^\s*', line)[0])
while stack and stack[-1].indent > new_indent:
stack.pop()
if len(stack):
current_item = new_from_line(line, parent=stack[-1])
stack[-1].elems.append(current_item)
else:
current_item = new_from_line(line, parent=None)
elems.append(current_item)
stack.append(current_item)
except LongerException:
if len(stack):
current_item = new_from_line(line, parent=stack[-1])
stack[-1].elems.append(current_item)
else:
current_item = new_from_line(line, parent=None)
elems.append(current_item)
stack.append(current_item)
return elems
def get_analysis_values(elems, results):
for x in elems:
if isinstance(x, Answer):
results.append(x.get_analysis_value())
if x.elems:
get_analysis_values(x.elems, results)
def flatten_elems(elems, results):
for x in elems:
results.append(x)
if x.elems:
flatten_elems(x.elems, results)
def write_py_file(fd, elems):
schema_fields = []
for elem in elems:
schema_fields.append(elem.as_schema_field())
schema_fields.extend(elem.get_child_schema_fields())
print >> fd, '# -*- coding: utf-8 -*-'
r = []
print >> fd, 'defaultAnalysisValues = {'
get_analysis_values(elems, r)
for analysis_value in r:
print >> fd, analysis_value
print >> fd, '}'
print >> fd, """
from Products.Archetypes.atapi import *
from Products.MasterSelectWidget.MasterSelectWidget import MasterSelectWidget
def slaveFields(action, *slaves):
'''Helps to define more smartly the slave fields of a master field
(MasterSelectWidget). The master is always a "yes/no" field.
If p_action is:
- "showIfYes": slaves will be shown when master is "yes" ;
- "showIfNo": slaves will be shown when master is "no" ;
- "setValue": it defines slaves whose values may change depending on
actions on the master. '''
res = []
for slave in slaves:
slaveDict = {'name': slave}
if action == "showIfYes":
slaveDict.update({'action': 'show', 'hide_values': ['yes'] })
elif action == "showIfNo":
slaveDict.update({'action': 'show', 'hide_values': ['no'] })
elif action == "setValue":
sName = slave[:-7]
slaveDict.update({'action': 'value',
'vocab_method': 'defo%s' % sName,
'control_param': '%sCP' % sName})
res.append(slaveDict)
return tuple(res)
"""
print >> fd, 'schema = Schema(('
for s in schema_fields:
print >> fd, s
print >> fd, '),)'
def write_edit_pt_file(fd, elems):
print >> fd, """
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US"
lang="en-US" i18n:domain="plone">
<body>
<!-- Body redefinition -->
<div metal:define-macro="body"
tal:define="portal_type portal_type|string:unknowntype">
<form name="edit_form"
method="post"
enctype="multipart/form-data"
class="enableUnloadProtection atBaseEditForm"
action=""
id=""
tal:attributes="action python:here.absolute_url()+'/'+template.id;
id string:${portal_type}-base-edit">
<metal:block define-slot="extra_top" />
<metal:block define-slot="widgets">
"""
flattened_elems = []
flatten_elems(elems, flattened_elems)
in_fieldset = False
for elem in flattened_elems:
if isinstance(elem, Title):
if in_fieldset:
print >> fd, '</fieldset>'
print >> fd, '''<fieldset style="border-width: 4px;"><legend>%s</legend>''' % \
unicode(elem.text, 'utf-8').encode('ascii', 'xmlcharrefreplace')
in_fieldset = True
elif isinstance(elem, Subtitle):
print >> fd, '''<h3>%s</h3>''' % unicode(elem.text, 'utf-8').encode('ascii', 'xmlcharrefreplace')
elif isinstance(elem, Comment):
print >> fd, '''<p>%s</p>''' % unicode(elem.text, 'utf-8').encode('ascii', 'xmlcharrefreplace')
elif isinstance(elem, Question) or (isinstance(elem, Answer) and not elem.elems):
print >> fd, '''<span metal:use-macro="python:here.widget('%s', mode='edit')" />''' % elem.identifier
if in_fieldset:
print >> fd, '</fieldset>'
print >> fd, """
</metal:block>
<metal:block define-slot="extra_bottom" />
<div class="formControls">
<input type="hidden"
name="fieldset"
value="default"
tal:attributes="value fieldset"
/>
<input type="hidden"
name="form.submitted"
value="1"
/>
<input type="hidden"
name="add_reference.field:record"
value=""
/>
<input type="hidden"
name="add_reference.type:record"
value=""
/>
<input type="hidden"
name="add_reference.destination:record"
value=""
/>
<tal:env define="env request/controller_state/kwargs">
<tal:loop repeat="varname python:('reference_source_url', 'reference_source_field', 'reference_source_fieldset')">
<tal:reference define="items python:env.get(varname, request.get(varname))"
condition="items">
<input tal:repeat="item items"
type="hidden"
name="form_env.reference_source_url:list:record"
value="value"
tal:attributes="value item;
name string:form_env.${varname}:list:record"
/>
</tal:reference>
</tal:loop>
</tal:env>
<tal:comment replace="nothing">
Turn 'persistent_' variables from controller_state persistent
</tal:comment>
<tal:env repeat="env request/controller_state/kwargs/items">
<input type="hidden"
name="key"
value="value"
tal:define="key python:env[0];
value python:env[1]"
tal:condition="python:key.startswith('persistent_')"
tal:attributes="name string:form_env.${key}:record;
value value"
/>
</tal:env>
<tal:comment replace="nothing">
Turn 'persistent_' variables from forms (GET/POST) persistent
</tal:comment>
<tal:env repeat="env request/form">
<input type="hidden"
name="key"
value="value"
tal:define="key env;
value request/?env"
tal:condition="python:key.startswith('persistent_')"
tal:attributes="name string:form_env.${key}:record;
value value"
/>
</tal:env>
<tal:comment replace="nothing">
Store referrer to remember where to go back
</tal:comment>
<input type="hidden"
name="last_referer"
tal:define="last_referer python:here.session_restore_value('HTTP_REFERER', request.form.get('last_referer', request.get('HTTP_REFERER')))"
tal:attributes="value python:(last_referer and '%s/%s' % (here.absolute_url(), template.id) not in last_referer) and last_referer or (here.getParentNode() and here.getParentNode().absolute_url())"
/>
<metal:block define-slot="buttons"
tal:define="fieldset_index python:fieldsets.index(fieldset);
n_fieldsets python:len(fieldsets)">
<input tal:condition="python:fieldset_index &gt; 0"
class="context"
tabindex=""
type="submit"
name="form_previous"
value="Previous"
i18n:attributes="value label_previous;"
tal:attributes="tabindex tabindex/next;
disabled python:test(isLocked, 'disabled', None);"
/>
<input tal:condition="python:fieldset_index &lt; n_fieldsets - 1"
class="context"
tabindex=""
type="submit"
name="form_next"
value="Next"
i18n:attributes="value label_next;"
tal:attributes="tabindex tabindex/next;
disabled python:test(isLocked, 'disabled', None);"
/>
<input class="context"
tabindex=""
type="submit"
name="form_submit"
value="Save"
i18n:attributes="value label_save;"
tal:attributes="tabindex tabindex/next;
disabled python:test(isLocked, 'disabled', None);"
/>
<input class="standalone"
tabindex=""
type="submit"
name="form.button.cancel"
value="Cancel"
i18n:attributes="value label_cancel;"
tal:attributes="tabindex tabindex/next"
/>
</metal:block>
<metal:block define-slot="extra_buttons" />
</div>
</form>
</div>
</body>
</html>
"""
def write_view_pt_file(fd, elems):
print >> fd, """
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US"
lang="en-US" i18n:domain="plone">
<body>
<!-- Body redefinition -->
<div metal:define-macro="body">
<fieldset>
<legend>Texte en projet</legend>
<div tal:define="f python:here.getField('apTitle')">
<b tal:content="f/widget/label"></b>&nbsp;:&nbsp;<span tal:content="here/getApTitle"></span>
</div>
<div tal:define="f python:here.getField('apDescription')">
<b tal:content="f/widget/label"></b>&nbsp;:&nbsp;<span tal:content="here/getApDescription"></span>
</div>
<div tal:define="f python:here.getField('apType')">
<b tal:content="f/widget/label"></b>&nbsp;:&nbsp;<span tal:content="python: f.vocabulary.getValue(here.getApType())"></span>
</div>
"""
flattened_elems = []
flatten_elems(elems, flattened_elems)
in_fieldset = False
for elem in flattened_elems:
if isinstance(elem, Title):
if in_fieldset:
print >> fd, '</fieldset>'
print >> fd, '''<fieldset style="border-width: 4px;"><legend>%s</legend>''' % \
unicode(elem.text, 'utf-8').encode('ascii', 'xmlcharrefreplace')
in_fieldset = True
elif isinstance(elem, Subtitle):
print >> fd, '''<h3>%s</h3>''' % unicode(elem.text, 'utf-8').encode('ascii', 'xmlcharrefreplace')
elif isinstance(elem, Comment):
print >> fd, '''<p>%s</p>''' % unicode(elem.text, 'utf-8').encode('ascii', 'xmlcharrefreplace')
elif isinstance(elem, Question) or (isinstance(elem, Answer) and not elem.elems):
print >> fd, '''<div tal:define="f python:here.getField('%s')">''' % elem.identifier
print >> fd, ''' <b tal:content="f/widget/label"></b>&nbsp;'''
print >> fd, ''' <span i18n:translate="" tal:content="here/%s"></span>''' % \
('get' + elem.identifier[0].upper() + elem.identifier[1:])
print >> fd, '''</div>'''
if in_fieldset:
print >> fd, '</fieldset>'
print >> fd, """
</div>
</body>
</html>
"""
def write_section_tests(fd, elems):
flattened_elems = []
flatten_elems(elems, flattened_elems)
for elem in flattened_elems:
if isinstance(elem, Title):
print >> fd, ' def has_section_%s(self):' % elem.identifier
print >> fd, ' return \\'
in_fieldset = True
elif isinstance(elem, Question):
print >> fd, ' not(self.hasFieldDefaultValue(\'%s\')) or \\' % elem.identifier
def write_ooo_qa(fd, elems):
flattened_elems = []
flatten_elems(elems, flattened_elems)
for elem in flattened_elems:
if isinstance(elem, Title):
print >> fd, '\n'*3
if isinstance(elem, Subtitle):
print >> fd, '\n'*3
elif isinstance(elem, Question):
print >> fd, ''' <text:p text:style-name="Standard"><office:annotation><dc:date>2007-05-16T00:00:00</dc:date><text:p>do text if not avis.legis.hasFieldDefaultValue('%s')</text:p></office:annotation>%s</text:p>''' % (elem.identifier, elem.text)
prev_identifier = elem.identifier
elif isinstance(elem, Answer) and not elem.elems:
print >> fd, ''' <text:p text:style-name="Analyse"><office:annotation><dc:date>2007-05-16T00:00:00</dc:date><text:p>do text if not avis.legis.hasFieldDefaultValue('%s')</text:p><text:p>from xhtml(avis.legis.%s)</text:p></office:annotation>%s</text:p>''' % (prev_identifier, elem.identifier, elem.identifier)
if __name__ == '__main__':
elems = parse_file(sys.argv[1])
fd = file(sys.argv[2], 'w')
write_py_file(fd, elems)
fd = file(sys.argv[3], 'w')
write_edit_pt_file(fd, elems)
fd = file(sys.argv[4], 'w')
write_view_pt_file(fd, elems)
fd = sys.stdout
write_ooo_qa(fd, elems)