Make more Python scripts compatible with both Py2 and Py3

While porting other Python code in the repo to run under Py3 (as well
as Py2) it was discovered there were a number of other Python scripts
which also needed porting. However these scripts are never invoked
during a build so there was no easy way to test the porting work. I
assume these scripts are for developers only and/or are
historical. Because there was no way for me to test the porting
changes on these scripts I did not want to include the changes in the
patch for the Py3 porting which fixed scripts that are invoked during
the build (the former patch is mandatory, this patch is optional at
the moment). I did verify the scripts compile cleanly under both Py2
and Py3, however it's possible I missed porting something or the error
does not show up until run-time.

Examples of the required changes are:

* Replace use of the built-in function file() with open().  file()
  does not exist in Py3, open works in both Py2 and Py3.  The code was
  also modified to use a file context manager (e.g. with open(xxx) as
  f:). This assures open files are properly closed when the code block
  using the file goes out of scope. This is a standard modern Python
  idiom.

* Replace all use of the print keyword with the six.print_()
  function, which itself is an emulation of Py3's print function. Py3
  no longer has a print keyword, only a print() function.

* The dict methods .keys(), .values(), .items() no longer return a
  list in Py3, instead they return a "view" object which is an
  iterator whose result is an unordered set. The most notable
  consequence is you cannot index the result of these functions like
  your could in Py2 (e.g. dict.keys()[0] will raise a run time
  exception).

* Replace use of StringIO.StringIO and cStringIO with
  six.StringIO. Py3 no longer has cStringIO and the six variant
  handles the correct import.

* Py3 no longer allows the "except xxx, variable" syntax, where
  variable appering after the comma is assigned the exception object,
  you must use the "as" keyword to perform the variable assignment
  (e.g. execpt xxx as variable)

* Python PEP 3113 removed tuple parameter unpacking. Therefore you can
  no longer define a formal parameter list that contains tuple
  notation representing a single parameter that is unpacked into
  multiple arguments.

License: MIT
Signed-off-by: John Dennis <jdennis@redhat.com>
This commit is contained in:
John Dennis 2018-06-25 18:52:16 -04:00 committed by Benjamin Dauvergne
parent a76390813a
commit 3d9d58d52c
13 changed files with 139 additions and 109 deletions

View File

@ -304,7 +304,7 @@ function lassoRegisterIdWsf2DstService($prefix, $href) {
m.name.endswith('_new_full'):
continue
if not m.name.startswith(method_prefix):
print >> sys.stderr, 'W:', m.name, 'vs', method_prefix
six.print_('W:', m.name, 'vs', method_prefix, file=sys.stderr)
continue
if m.rename:
@ -330,7 +330,7 @@ function lassoRegisterIdWsf2DstService($prefix, $href) {
elif defval.startswith('b:'): # boolean
php_args.append('%s = %s' % (arg_name, defval[2:]))
else:
print >> sys.stderr, "E: don't know what to do with %s" % defval
six.print_("E: don't know what to do with %s" % defval, file=sys.stderr)
sys.exit(1)
else:
php_args.append('%s = null' % arg_name)
@ -396,7 +396,8 @@ function lassoRegisterIdWsf2DstService($prefix, $href) {
elif type == '%': # %TRUE, %FALSE
if var in ('TRUE', 'FALSE'):
return var
print >> sys.stderr, 'W: unknown docstring thingie \'%s\' in \'%s\'' % (s.group(1), func.docstring.orig_docstring)
six.print_('W: unknown docstring thingie \'%s\' in \'%s\'' % (s.group(1), func.docstring.orig_docstring),
file=sys.stderr)
elif type == '@':
if var == first_arg_name:
return '$this'

View File

@ -230,7 +230,8 @@ PHP_MSHUTDOWN_FUNCTION(lasso)
''', file=self.fd)
else:
if not is_cstring(arg):
print >>sys.stderr, 'W: %s has no explicit string annotation' % (arg,)
six.print_('W: %s has no explicit string annotation' % (arg,),
file=sys.stderr)
six.print_('''\
set_array_from_hashtable_of_strings(return_c_value, &return_value);
''', file=self.fd)
@ -279,7 +280,7 @@ PHP_MSHUTDOWN_FUNCTION(lasso)
elif is_time_t_pointer(arg):
parse_tuple_format.append('l')
parse_tuple_args.append('&%s' % (arg_name(arg),))
print >>self.fd, ' time_t %s = 0;' % (arg_name(arg),)
six.print_(' time_t %s = 0;' % (arg_name(arg),), file=self.fd)
elif is_xml_node(arg):
parse_tuple_format.append('s!')
parse_tuple_args.append('&%s_str, &%s_len' % (arg_name(arg), arg_name(arg)))

View File

@ -25,6 +25,7 @@
import unittest
import time
import sys
from six import print_
def xml(text):
if not text:
@ -33,25 +34,25 @@ def xml(text):
class XmlTestResult(unittest.TestResult):
def addSuccess(self, test):
print """ <test result="success">
print_(""" <test result="success">
<id>%s</id>
<description>%s</description>
</test>""" % (test.id(), xml(test.shortDescription()))
</test>""" % (test.id(), xml(test.shortDescription())))
def addError(self, test, err):
unittest.TestResult.addError(self, test, err)
print """ <test result="error">
print_(""" <test result="error">
<id>%s</id>
<description>%s</description>
</test>""" % (test.id(), xml(test.shortDescription()))
</test>""" % (test.id(), xml(test.shortDescription())))
# TODO: add err
def addFailure(self, test, err):
unittest.TestResult.addFailure(self, test, err)
print """ <test result="failure">
print_(""" <test result="failure">
<id>%s</id>
<description>%s</description>
</test>""" % (test.id(), xml(test.shortDescription()))
</test>""" % (test.id(), xml(test.shortDescription())))
# TODO: add err
@ -60,14 +61,14 @@ class XmlTestRunner:
return XmlTestResult()
def run(self, test):
print "<suite>"
print_("<suite>")
result = self._makeResult()
startTime = time.time()
test(result)
stopTime = time.time()
timeTaken = float(stopTime - startTime)
print " <duration>%s</duration>" % timeTaken
print "</suite>"
print_(" <duration>%s</duration>" % timeTaken)
print_("</suite>")
return result

View File

@ -31,6 +31,7 @@ import os
import sys
import time
import unittest
from six import print_
from XmlTestRunner import XmlTestRunner
@ -63,10 +64,10 @@ parser.add_option(
__builtin__.__dict__['dataDir'] = os.path.join(options.srcDir, '../../../tests/data')
if options.xmlMode:
print """<?xml version="1.0"?>"""
print """<testsuites xmlns="http://check.sourceforge.net/ns">"""
print """ <title>Python Bindings</title>"""
print """ <datetime>%s</datetime>""" % time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
print_('<?xml version="1.0"?>')
print_('<testsuites xmlns="http://check.sourceforge.net/ns">')
print_(' <title>Python Bindings</title>')
print_(' <datetime>%s</datetime>' % time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
success = True
for testSuite in testSuites:
@ -77,7 +78,7 @@ for testSuite in testSuites:
if fp:
fp.close()
if not module:
print >> sys.stderr, 'Unable to load test suite:', testSuite
print_('Unable to load test suite:', testSuite, file=sys.stderr)
continue
if module.__doc__:
@ -90,13 +91,13 @@ for testSuite in testSuites:
else:
runner = unittest.TextTestRunner(verbosity=2)
print
print '-' * len(doc)
print doc
print '-' * len(doc)
print_('-' * len(doc))
print_(doc)
print_('-' * len(doc))
result = runner.run(module.allTests)
success = success and result.wasSuccessful()
if options.xmlMode:
print """</testsuites>"""
print_('</testsuites>')
sys.exit(not success)

View File

@ -5,28 +5,28 @@
import os
import re
import sys
from six import print_
functions = {}
for filename in os.listdir('.'):
if filename[-4:] not in ('.txt', '.rst'):
continue
for line in file(filename):
if not 'lasso_' in line:
continue
if not '(' in line:
continue
for f in re.findall(r'(lasso_[a-zA-Z_]+?)\(', line):
functions[f] = 1
with open(filename) as f:
for line in f:
if not 'lasso_' in line:
continue
if not '(' in line:
continue
for f in re.findall(r'(lasso_[a-zA-Z_]+?)\(', line):
functions[f] = 1
#for f in functions:
# print f
known_symbols = [x.strip() for x in file('../reference/build/lasso-decl-list.txt')]
with open('../reference/build/lasso-decl-list.txt') as f:
known_symbols = [x.strip() for x in f]
failure = 0
for f in functions:
if not f in known_symbols:
print f
print_(f)
failure = 1
sys.exit(failure)

View File

@ -5,6 +5,7 @@ import re
import sys
import os
import os.path
from six import print_
enable_wsf = False
@ -45,17 +46,17 @@ for root, dirs, files in os.walk(srcdir):
return x
if type and macro_type:
standard_decl = [ convert(x) for x in [ 'LASSO_%s', 'LASSO_IS_%s', 'LASSO_TYPE_%s', get_type, 'LASSO_%s_CLASS', 'LASSO_IS_%s_CLASS', 'LASSO_%s_GET_CLASS' ] ]
print
print '<SECTION>'
print '<FILE>%s</FILE>' % file_name
print '<TITLE>%s</TITLE>' % type
print type
print_('')
print_('<SECTION>')
print_('<FILE>%s</FILE>' % file_name)
print_('<TITLE>%s</TITLE>' % type)
print_(type)
for x in types + normal_functions:
print x
print '<SUBSECTION Standard>'
print_(x)
print_('<SUBSECTION Standard>')
for x in standard_decl:
print x
print '</SECTION>'
print_(x)
print_('</SECTION>')
except:
continue

View File

@ -7,6 +7,7 @@ import twill
import urllib2
import os.path
import re
from six import print_
CONFIG_FILE = os.path.expanduser('~/.config/lasso_integration.conf')
CONFIG = dict()
@ -19,7 +20,7 @@ if os.path.exists(CONFIG_FILE):
m = re.match('(\w*) = (.*)', line)
CONFIG[m.groups()[0]] = m.groups()[1]
except:
print "Line", i, " of configuration file", CONFIG_FILE, "is invalid:", line
print_("Line", i, " of configuration file", CONFIG_FILE, "is invalid:", line)
i +=1
# Combine default and configuration file
@ -60,13 +61,15 @@ def waitforport(port, start):
def setup():
if not os.path.exists(AUTHENTIC_SRCDIR):
print >> sys.stderr, 'Authentic source dir (%s) does not exist' % AUTHENTIC_SRCDIR
print >> sys.stderr, 'Create it or edit tests/config.py to match your local installation'
print_('Authentic source dir (%s) does not exist' % AUTHENTIC_SRCDIR,
file=sys.stderr)
print_('Create it or edit tests/config.py to match your local installation',
file=sys.stderr)
sys.exit(1)
silent = os.environ.get('NO_SILENT') is None
twill.commands.reset_browser()
twill.set_output(file('/dev/null', 'w'))
twill.set_output(open('/dev/null', 'w'))
base = []
if os.environ.get('VALGRIND') is '1' and os.path.exists('/usr/bin/valgrind'):
base = ['./valgrind-wrapper.sh', 'python']
@ -102,6 +105,7 @@ def teardown():
# valgrind seems to prefer SIGINT to SIGTERM
os.kill(pid, signal.SIGINT)
except OSError:
print >> sys.stderr, 'failed to kill pid %s' % pid
print_('failed to kill pid %s' % pid,
file=sys.stderr)
os.system('rm -rf /tmp/.tests/')

View File

@ -2,7 +2,7 @@ import sys
import os.path
sys.path.append(os.path.join(os.path.dirname(__file__),'../bindings'))
import bindings
from six import print_
def main(args):
@ -27,19 +27,19 @@ def main(args):
d[x.name] = x
for x in binding.structs:
d[x.name] = x
l = d.keys()
l.sort()
l = sorted(d.keys())
for x in l:
if isinstance(d[x], bindings.Function):
print d[x].return_type, " ",
print x,
print '(', ', '.join(map(lambda x: x[0] + ' ' + x[1], d[x].args)), ')'
print_(d[x].return_type, " ",)
print_(x, end='')
print_('(', ', '.join(map(lambda x: x[0] + ' ' + x[1], d[x].args)), ')')
elif isinstance(d[x], bindings.Struct):
print 'struct', x, '{ ',
print ', '.join(map(lambda x: x[0] + ' ' + x[1], d[x].members)),
print ' }'
print_('struct', x, '{ ',)
print_(', '.join(map(lambda x: x[0] + ' ' + x[1], d[x].members)),
end='')
print_(' }')
else:
print x
print_(x)
if __name__ == "__main__":
main(sys.argv)

View File

@ -3,9 +3,12 @@
import sys
import os.path
import re
from six import print_
if len(sys.argv) < 3:
print "Usage: check-lasso-sections.py lasso docs/referenrece/lasso/lasso-sections.txt"
print_("Usage: check-lasso-sections.py "
"lasso docs/referenrece/lasso/lasso-sections.txt",
file=sys.stderr)
sys.exit(1)
source=sys.argv[1]
lasso_sections_txt=sys.argv[2]
@ -15,7 +18,8 @@ methods=[]
for dirpath, dirnames, filenames in os.walk(source):
for filename in filenames:
_, ext = os.path.splitext(filename)
lines = list(file(os.path.join(dirpath, filename)))
with open(os.path.join(dirpath, filename)) as f:
lines = f.readlines()
while lines:
line, lines = lines[0], lines[1:]
line=line.strip()
@ -30,13 +34,13 @@ for dirpath, dirnames, filenames in os.walk(source):
lasso_sections_txt=file(lasso_sections_txt).read()
print ' = Methods missing from lasso-sections.txt =\n'
print_(' = Methods missing from lasso-sections.txt =\n')
for method in methods:
if not method in lasso_sections_txt:
print method
print_(method)
print ' = Methods in lasso-sections.txt which does not exist anymore = \n'
print_(' = Methods in lasso-sections.txt which does not exist anymore = \n')
for line in lasso_sections_txt.splitlines():
if line.startswith('lasso_'):
if line not in methods:
print line
print_(line)

View File

@ -1,4 +1,5 @@
import re
from six import print_
valgrind_log = open('log','r').read()
@ -33,11 +34,11 @@ for line in valgrind_log.splitlines():
i = 43
for x in keep:
block = keep[x]
print "{"
print " suppression", i
print_("{")
print_(" suppression", i)
for x in block[1:]:
print x
print_(x)
if re.search(limit_re, x):
break
print '}'
print_('}')
i += 1

View File

@ -5,6 +5,7 @@ import re
import xml.dom.minidom
import string
import sys
from six import print_
full_constructors = {
'disco_svc_metadata': (
@ -232,7 +233,7 @@ extern "C" {
elif b_pref == 'tns':
includes['wsa:' + self.base_class_name[6:]] = True
else:
print b_pref, self.base_prefix, self.base_class_name
print_(b_pref, self.base_prefix, self.base_class_name)
raise 'XXX'
s.append('#include <lasso/xml/xml.h>')
@ -255,9 +256,9 @@ extern "C" {
else:
s.append('#include "%s.h"' % classes[ns][name].file_name)
except KeyError:
print >> sys.stderr, 'W: missing', ns, name
print_('W: missing', ns, name, file=sys.stderr)
if self.name == 'DataResponseBase':
print classes[ns].keys()
print_(classes[ns].keys())
raise 'toot'
pass
else:
@ -1418,7 +1419,7 @@ for filename in xsd_filenames:
if ns == 'lu':
ns = 'util'
elif ns not in doms.keys():
print 'ref:', ref
print_('ref:', ref)
raise 'NS: %s' % ns
typ = [x for x in doms[ns].getElementsByTagName('xs:attribute') \
if x.attributes.get('name') and x.attributes['name'].value == name][0]
@ -1465,7 +1466,7 @@ for filename in xsd_filenames:
if ns == 'lu':
ns = 'util'
elif ns not in doms.keys():
print 'ref:', ref
print_('ref:', ref)
raise 'NS: %s' % ns
typ = [x for x in doms[ns].getElementsByTagName('xs:attribute') \
if x.attributes.get('name') and x.attributes['name'].value == name][0]
@ -1571,7 +1572,7 @@ for filename in xsd_filenames:
refered = get_by_name_and_attribute(dom, 'xs:element', 'name', ref)
if refered:
if len(refered) >= 1:
print >> sys.stderr, 'W: more than one refered'
print_('W: more than one refered', file=sys.stderr)
refered = refered[0]
if refered.attributes.has_key('type'):
elem_type = refered.attributes['type'].value
@ -1596,9 +1597,9 @@ for filename in xsd_filenames:
klass.has_ds_signature = True
elem_type = 'ds:Signature'
else:
print >> sys.stderr, 'W: missing xmldsig support for %s' % ref
print_('W: missing xmldsig support for %s' % ref, file=sys.stderr)
elif not doms.has_key(ns):
print >> sys.stderr, 'W: missing dom for', ns
print_('W: missing dom for', ns, file=sys.stderr)
elem_type = 'XXX'
if ns == 'samlp':
elem_type = ref
@ -1664,13 +1665,13 @@ for filename in xsd_filenames:
):
klass.elements.append( ('any', 'GList', 'LassoNode'))
else:
print >> sys.stderr, 'W: any occurence for %s (prefix: %s)' % (klass.name, prefix)
print_('W: any occurence for %s (prefix: %s)' % (klass.name, prefix), file=sys.stderr)
# XXX... other occurences of <any>
print klass.name
print_(klass.name)
for elem in klass.elements:
print ' ', elem
print '-'*40
print_(' ', elem)
print_('-'*40)
def get_ordered_classes():
all_classes = []
@ -1733,9 +1734,9 @@ def generate_swig_main(prefix):
for klass_p in classes.keys():
for klass in classes[klass_p].values():
#print klass_p, klass.name
#print_(klass_p, klass.name)
if klass.base_class_name != 'Node':
#print ' <-', klass.base_prefix, ':', klass.base_class_name
#print_(' <-', klass.base_prefix, ':', klass.base_class_name)
if klass.base_prefix:
prefix = klass.base_prefix
else:

View File

@ -4,19 +4,23 @@ import xml.dom.minidom
import os
import stat
import re
from cStringIO import StringIO
from six import StringIO
import sys
import ezt
base_template = ezt.Template()
base_template.parse(file('templates/base.ezt').read())
with open('templates/base.ezt') as f:
base_template.parse(f.read())
buildlog_template = ezt.Template()
buildlog_template.parse(file('templates/buildlog.ezt').read())
with open('templates/buildlog.ezt') as f:
buildlog_template.parse(f.read())
changelog_template = ezt.Template()
changelog_template.parse(file('templates/changelog.ezt').read())
with open('templates/changelog.ezt') as f:
changelog_template.parse(f.read())
tests_template = ezt.Template()
tests_template.parse(file('templates/tests.ezt').read())
with open('templates/tests.ezt') as f:
tests_template.parse(f.read())
def getText(nodelist):
if not nodelist:
@ -114,7 +118,8 @@ class Build:
if self.changelog:
self.changelog = self.changelog.replace('.xml', '')
try:
dom_cl = xml.dom.minidom.parse(file('web' + self.changelog + '.xml'))
with open('web' + self.changelog + '.xml') as f:
dom_cl = xml.dom.minidom.parse(f)
except:
self.nb_commits = '?'
self.last_commit_author = '?'
@ -161,16 +166,19 @@ for BUILDLOGS_DIR in ('build-logs', 'build-logs-wsf'):
continue
if src_file.endswith('.html'):
try:
body = re_body.findall(file(src_file).read())[0][1].strip()
with open(src_file) as f:
body = re_body.findall(f.read())[0][1].strip()
except IndexError:
raise "no body found"
fd = StringIO()
base_template.generate(fd, {'body': body, 'title': 'Build Log', 'section': 'buildbox'})
open(dst_file, 'w').write(fd.getvalue())
with open(dst_file, 'w') as f:
f.write(fd.getvalue())
continue
try:
dom = xml.dom.minidom.parse(file(src_file))
with open(src_file) as f:
dom = xml.dom.minidom.parse(f)
except:
continue
type = dom.childNodes[0].nodeName
@ -181,7 +189,8 @@ for BUILDLOGS_DIR in ('build-logs', 'build-logs-wsf'):
body = fd.getvalue()
fd = StringIO()
base_template.generate(fd, {'body': body, 'title': 'ChangeLog', 'section': 'buildbox'})
open(dst_file, 'w').write(fd.getvalue())
with open(dst_file, 'w') as f:
f.write(fd.getvalue())
if type == 'log':
entries = [ChangelogSvnEntry(x) for x in dom.getElementsByTagName('logentry')]
@ -190,7 +199,8 @@ for BUILDLOGS_DIR in ('build-logs', 'build-logs-wsf'):
body = fd.getvalue()
fd = StringIO()
base_template.generate(fd, {'body': body, 'title': 'ChangeLog', 'section': 'buildbox'})
open(dst_file, 'w').write(fd.getvalue())
with open(dst_file, 'w') as f:
f.write(fd.getvalue())
if type == 'testsuites':
datetime = getText(dom.getElementsByTagName('datetime')[0].childNodes)
@ -203,7 +213,8 @@ for BUILDLOGS_DIR in ('build-logs', 'build-logs-wsf'):
fd = StringIO()
base_template.generate(fd, {'body': body,
'title': 'Test Suite - %s' % title, 'section': 'buildbox'})
open(dst_file, 'w').write(fd.getvalue())
with open(dst_file, 'w') as f:
f.write(fd.getvalue())
day_dirs = os.listdir('web/%s/' % BUILDLOGS_DIR)
@ -237,9 +248,11 @@ for BUILDLOGS_DIR in ('build-logs', 'build-logs-wsf'):
fd = StringIO()
base_template.generate(fd, {'body': body, 'title': 'Build Box', 'section': 'buildbox'})
if BUILDLOGS_DIR == 'build-logs':
open('web-static/buildbox.html', 'w').write(fd.getvalue())
with open('web-static/buildbox.html', 'w') as f:
f.write(fd.getvalue())
elif BUILDLOGS_DIR == 'build-logs-wsf':
open('web-static/buildbox-wsf.html', 'w').write(fd.getvalue())
with open('web-static/buildbox-wsf.html', 'w') as f:
f.write(fd.getvalue())
for base, dirs, files in os.walk('web'):
if '/build-logs' in base or '/news/' in base:
@ -276,7 +289,8 @@ for base, dirs, files in os.walk('web'):
type = None
if ext == '.xml':
dom = xml.dom.minidom.parse(file(src_file))
with open(src_file) as f:
dom = xml.dom.minidom.parse(f)
type = dom.childNodes[0].nodeName
dst_file = dst_file.replace('.xml', '.html')
@ -288,12 +302,14 @@ for base, dirs, files in os.walk('web'):
news_files = news_files[:2]
news = []
for f in news_files:
news.append('<div>%s</div>' % re_div.findall(file(os.path.join('web/news/', f)).read())[0][1].strip())
with open(os.path.join('web/news/', f)) as f:
news.append('<div>%s</div>' % re_div.findall(f.read())[0][1].strip())
news = '\n'.join(news)
section = src_file.split('/')[1].replace('.xml', '')
if ext == '.html' or type == 'html':
content = file(src_file).read()
with open(src_file) as f:
content = f.read()
try:
body = re_body.findall(content)[0][1].strip()
except IndexError:
@ -302,6 +318,7 @@ for base, dirs, files in os.walk('web'):
fd = StringIO()
base_template.generate(fd, {'body': body, 'title': title, 'section': section,
'news': news})
open(dst_file, 'w').write(fd.getvalue())
with open(dst_file, 'w')as f:
f.write(fd.getvalue())
continue

View File

@ -229,11 +229,7 @@ import re
from types import StringType, IntType, FloatType, LongType
import os
import cgi
try:
import cStringIO
except ImportError:
import StringIO
cStringIO = StringIO
from six import StringIO
#
# Formatting types
@ -464,7 +460,8 @@ class Template:
### use the same quoting as HTML for now
self._cmd_print_html(valref, fp, ctx)
def _cmd_include(self, (valref, reader), fp, ctx):
def _cmd_include(self, valref_reader_tuple, fp, ctx):
valref, reader = valref_reader_tuple
fname = _get_value(valref, ctx)
### note: we don't have the set of for_names to pass into this parse.
### I don't think there is anything to do but document it. we also
@ -527,7 +524,7 @@ class Template:
def _cmd_define(self, args, fp, ctx):
((name,), unused, section) = args
valfp = cStringIO.StringIO()
valfp = StringIO()
if section is not None:
self._execute(section, valfp, ctx)
ctx.defines[name] = valfp.getvalue()
@ -587,7 +584,7 @@ def _prepare_ref(refname, for_names, file_args):
return refname, start, rest
def _get_value((refname, start, rest), ctx):
def _get_value(refname_start_rest_tuple, ctx):
"""(refname, start, rest) -> a prepared `value reference' (see above).
ctx -> an execution context instance.
@ -595,6 +592,7 @@ def _get_value((refname, start, rest), ctx):
for blocks take precedence over data dictionary members with the
same name.
"""
refname, start, rest = refname_start_rest_tuple
if rest is None:
# it was a string constant
return start