commit d526669810e0dc0a454260d5081fc96e16fc9e13 Author: John Dennis Date: Mon Jun 25 16:26:24 2018 -0400 Make Python scripts compatible with both Py2 and Py3 During the build if the Python3 interpreter is used a number of scripts will fail because they were never ported from Py2 to Py3. In general we want Python code to be compatible with both Py2 and Py3. This patch brings the scripts up to date with Py3 but retains backwards compatibility with Py2 (specifically Py 2.7, the last Py2 release). 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) Note: the modifications in this patch are the minimum necessary to get the build to run with the Py3 interpreter. There are numerous other Python scripts in the repo which need Py3 porting as well but because they are not invoked during a build they will be updated in a subsequent patch. License: MIT Signed-off-by: John Dennis diff --git a/bindings/python/examples/get_attributes_from_assertion.py b/bindings/python/examples/get_attributes_from_assertion.py index 44ceb9e5..8f37a337 100644 --- a/bindings/python/examples/get_attributes_from_assertion.py +++ b/bindings/python/examples/get_attributes_from_assertion.py @@ -1,8 +1,10 @@ # Example SP Python code to get attributes from an assertion +from six import print_ + for attribute in assertion.attributeStatement[0].attribute: if attribute.name == lasso.SAML2_ATTRIBUTE_NAME_EPR: continue - print 'attribute : ' + attribute.name + print_('attribute : ' + attribute.name) for value in attribute.attributeValue: - print ' value : ' + value.any[0].content + print_(' value : ' + value.any[0].content) diff --git a/bindings/python/tests/binding_tests.py b/bindings/python/tests/binding_tests.py index 6d8e0dfa..54c3635f 100755 --- a/bindings/python/tests/binding_tests.py +++ b/bindings/python/tests/binding_tests.py @@ -311,8 +311,8 @@ class BindingTestCase(unittest.TestCase): ''' node = lasso.Node.newFromXmlNode(content) assert 'next_url' in node.any[1] - assert 'huhu' in node.attributes.keys()[0] - assert node.attributes.values()[0] == 'xxx' + assert '{https://www.entrouvert.com/}huhu' in node.attributes.keys() + assert 'xxx' in node.attributes.values() node.any = ('coin',) node.attributes = {'michou': 'zozo'} assert 'coin' in node.dump() diff --git a/bindings/python/tests/idwsf2_tests.py b/bindings/python/tests/idwsf2_tests.py index 6f80c53d..4e47a4a1 100755 --- a/bindings/python/tests/idwsf2_tests.py +++ b/bindings/python/tests/idwsf2_tests.py @@ -27,7 +27,7 @@ import os import unittest import sys -from StringIO import StringIO +from six import StringIO import logging logging.basicConfig() @@ -310,11 +310,11 @@ class MetadataTestCase(IdWsf2TestCase): self.failUnless(idp_disco.request.svcMD[0].svcMDID is None) try: idp_disco.checkSecurityMechanism() - except lasso.Error, e: + except lasso.Error as e: self.fail(e) try: idp_disco.validateRequest() - except lasso.Error, e: + except lasso.Error as e: self.fail(e) self.failUnless(idp_disco.response is not None) self.failUnlessEqual(len(idp_disco.metadatas), 1) @@ -391,16 +391,16 @@ class MetadataTestCase(IdWsf2TestCase): self.failUnless(idp_disco is not None) try: idp_disco.processRequestMsg(wsp_disco.msgBody) - except lasso.Error, e: + except lasso.Error as e: self.fail(e) self.failUnless(idp_disco.request is not None) try: idp_disco.checkSecurityMechanism() - except lasso.Error, e: + except lasso.Error as e: self.fail(e) try: idp_disco.failRequest(lasso.IDWSF2_DISCOVERY_STATUS_CODE_FAILED, lasso.IDWSF2_DISCOVERY_STATUS_CODE_FORBIDDEN) - except lasso.Error, e: + except lasso.Error as e: self.fail(e) self.failUnless(idp_disco.response is not None) self.failUnless(idp_disco.response.status is not None) @@ -415,7 +415,7 @@ class MetadataTestCase(IdWsf2TestCase): wsp_disco.processResponseMsg(idp_disco.msgBody) except lasso.Idwsf2DiscoveryForbiddenError: pass - except lasso.Error, e: + except lasso.Error as e: self.fail(e) def test03(self): @@ -475,7 +475,7 @@ class MetadataTestCase(IdWsf2TestCase): self.failUnless(soap_envelope.getMessageId() is not None) try: idp_disco.checkSecurityMechanism() - except lasso.Error, e: + except lasso.Error as e: self.fail(e) # redirect interactionUrl = spInteractionUrl @@ -488,7 +488,7 @@ class MetadataTestCase(IdWsf2TestCase): self.failUnless(response.detail.any[0].redirectURL.startswith(interactionUrl + '?transactionID=')) try: idp_disco.buildResponseMsg() - except lasso.Error, e: + except lasso.Error as e: self.fail(e) self.failUnless(idp_disco.msgBody is not None) @@ -500,7 +500,7 @@ class MetadataTestCase(IdWsf2TestCase): wsp_disco.processResponseMsg(idp_disco.msgBody) except lasso.WsfprofileRedirectRequestError: pass - except lasso.Error, e: + except lasso.Error as e: self.fail(e) response_envelope = wsp_disco.getSoapEnvelopeResponse() self.failUnless(response_envelope.sb2GetRedirectRequestUrl().startswith(interactionUrl + '?transactionID=')) @@ -527,11 +527,11 @@ class MetadataTestCase(IdWsf2TestCase): self.failUnless(idp_disco.request.svcMD[0].svcMDID is None) try: idp_disco.checkSecurityMechanism() - except lasso.Error, e: + except lasso.Error as e: self.fail(e) try: idp_disco.validateRequest() - except lasso.Error, e: + except lasso.Error as e: self.fail(e) self.failUnless(idp_disco.response is not None) self.failUnlessEqual(len(idp_disco.metadatas), 1) diff --git a/lasso/build_strerror.py b/lasso/build_strerror.py index fca59628..908638d5 100644 --- a/lasso/build_strerror.py +++ b/lasso/build_strerror.py @@ -1,42 +1,42 @@ #! /usr/bin/env python -from cStringIO import StringIO import glob import re import sys import os +from six import print_, StringIO srcdir = sys.argv[1] -hlines = file('%s/errors.h' % srcdir,'r').readlines() messages = dict() description = '' -for line in hlines: - m = re.match(r'^ \* LASSO.*ERROR', line) - if m: - description = '' - continue - m = re.match(r'^ \* (.*[^:])$', line) - if m: - description += m.group(1) - m = re.match(r'#define (LASSO_\w*ERROR\w+)', line) - if m and description: - description = re.sub(r'[ \n]+', ' ', description).strip() - messages[m.group(1)] = description - description = '' - else: - m = re.match(r'#define (LASSO_\w*ERROR\w+)',line) +with open('%s/errors.h' % srcdir,'r') as f: + for line in f: + m = re.match(r'^ \* LASSO.*ERROR', line) if m: - messages[m.group(1)] = m.group(1) + description = '' + continue + m = re.match(r'^ \* (.*[^:])$', line) + if m: + description += m.group(1) + m = re.match(r'#define (LASSO_\w*ERROR\w+)', line) + if m and description: + description = re.sub(r'[ \n]+', ' ', description).strip() + messages[m.group(1)] = description + description = '' + else: + m = re.match(r'#define (LASSO_\w*ERROR\w+)',line) + if m: + messages[m.group(1)] = m.group(1) -clines = file('%s/errors.c.in' % srcdir,'r').readlines() -for line in clines: - if '@ERROR_CASES@' in line: - keys = messages.keys() - keys.sort() - for k in keys: - print """ case %s: - return "%s";""" % (k,messages[k].rstrip('\n')) - else: - print line, +with open('%s/errors.c.in' % srcdir,'r') as f: + for line in f: + if '@ERROR_CASES@' in line: + keys = sorted(messages.keys()) + for k in keys: + print_(' case %s:\n' + ' return "%s";' % + (k,messages[k].rstrip('\n'))) + else: + print_(line, end="")