From 99333f691b156e19caf9128ec6826ba1cad3e66d Mon Sep 17 00:00:00 2001 From: Jordan Reiter Date: Tue, 12 Jul 2016 16:48:59 -0400 Subject: [PATCH 1/2] More compatibility changes for Python 3 Updated old-style exception handling and raising, and fixed urlib/urllib.parse import. --- src/oaipmh/server.py | 48 ++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/src/oaipmh/server.py b/src/oaipmh/server.py index 668b27a..7582c10 100644 --- a/src/oaipmh/server.py +++ b/src/oaipmh/server.py @@ -1,7 +1,10 @@ from lxml.etree import ElementTree, Element, SubElement from lxml import etree from datetime import datetime -from urllib import quote, unquote, urlencode +try: + from urllib import quote, unquote, urlencode +except ImportError: + from urllib.parse import quote, unquote, urlencode import sys, cgi from oaipmh import common, metadata, validation, error @@ -207,8 +210,9 @@ def _outputResuming(self, element, input_func, output_func, kw): # but input_func (listSets) should have already raised # NoSetHierarchyError in that case if not result: - raise error.NoRecordsMatchError,\ - "No records match for request." + raise error.NoRecordsMatchError( + "No records match for request." + ) # without resumption token keys are fine token_kw = kw output_func(element, result, token_kw) @@ -231,8 +235,9 @@ def _outputHeader(self, element, header): def _outputMetadata(self, element, metadata_prefix, metadata): e_metadata = SubElement(element, nsoai('metadata')) if not self._metadata_registry.hasWriter(metadata_prefix): - raise error.CannotDisseminateFormatError,\ - "Unknown metadata format: %s" % metadata_prefix + raise error.CannotDisseminateFormatError( + "Unknown metadata format: %s" % metadata_prefix + ) self._metadata_registry.writeMetadata( metadata_prefix, e_metadata, metadata) @@ -255,28 +260,30 @@ def handleRequest(self, request_kw): new_kw = {} try: for key, value in request_kw.items(): - new_kw[str(key)] = value + new_kw[bytes(key, 'ascii').decode('ascii')] = value except UnicodeError: - raise error.BadVerbError,\ - "Non-ascii keys in request." + raise error.BadVerbError( + "Non-ascii keys in request." + ) request_kw = new_kw try: verb = request_kw.pop('verb') except KeyError: verb = 'unknown' - raise error.BadVerbError,\ - "Required verb argument not found." + raise error.BadVerbError( + "Required verb argument not found." + ) if verb not in ['GetRecord', 'Identify', 'ListIdentifiers', 'GetMetadata', 'ListMetadataFormats', 'ListRecords', 'ListSets']: - raise error.BadVerbError, "Illegal verb: %s" % verb + raise error.BadVerbError("Illegal verb: %s" % verb) # replace from and until arguments if necessary from_ = request_kw.get('from') if from_ is not None: # rename to from_ for internal use try: request_kw['from_'] = datestamp_to_datetime(from_) - except DatestampError, err: + except DatestampError as err: raise error.BadArgumentError( "The value '%s' of the argument " "'%s' is not valid." %(from_, 'from')) @@ -286,7 +293,7 @@ def handleRequest(self, request_kw): try: request_kw['until'] = datestamp_to_datetime(until, inclusive=True) - except DatestampError, err: + except DatestampError as err: raise error.BadArgumentError( "The value '%s' of the argument " "'%s' is not valid." %(until, 'until')) @@ -301,9 +308,9 @@ def handleRequest(self, request_kw): # now validate parameters try: validation.validateResumptionArguments(verb, request_kw) - except validation.BadArgumentError, e: + except validation.BadArgumentError as e: # have to raise this as a error.BadArgumentError - raise error.BadArgumentError, str(e) + raise error.BadArgumentError(str(e)) # now handle verb return self.handleVerb(verb, request_kw) except: @@ -453,8 +460,9 @@ def decodeResumptionToken(token): try: kw = cgi.parse_qs(token, True, True) except ValueError: - raise error.BadResumptionTokenError,\ - "Unable to decode resumption token: %s" % token + raise error.BadResumptionTokenError( + "Unable to decode resumption token: %s" % token + ) result = {} for key, value in kw.items(): value = value[0] @@ -464,8 +472,9 @@ def decodeResumptionToken(token): try: cursor = int(result.pop('cursor')) except (KeyError, ValueError): - raise error.BadResumptionTokenError,\ - "Unable to decode resumption token (bad cursor): %s" % token + raise error.BadResumptionTokenError( + "Unable to decode resumption token (bad cursor): %s" % token + ) # XXX should also validate result contents. Need verb information # for this, and somewhat more flexible verb validation support return result, cursor @@ -492,3 +501,4 @@ def nsoaidc(name): def nsdc(name): return '{%s}%s' % (NS_DC, name) + From 3f0316dbd96488be149649fbbde6a50fac10492d Mon Sep 17 00:00:00 2001 From: Jordan Reiter Date: Thu, 14 Jul 2016 12:04:39 -0400 Subject: [PATCH 2/2] Fix to restore Python 2 compatibility! Looks like bytes() behaves different in Python 2, so I changed the code to make use of the six library instead. --- src/oaipmh/server.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/oaipmh/server.py b/src/oaipmh/server.py index 7582c10..948ed1d 100644 --- a/src/oaipmh/server.py +++ b/src/oaipmh/server.py @@ -1,3 +1,5 @@ +import six + from lxml.etree import ElementTree, Element, SubElement from lxml import etree from datetime import datetime @@ -260,7 +262,7 @@ def handleRequest(self, request_kw): new_kw = {} try: for key, value in request_kw.items(): - new_kw[bytes(key, 'ascii').decode('ascii')] = value + new_kw[six.text_type(key).encode('ascii').decode('ascii')] = value except UnicodeError: raise error.BadVerbError( "Non-ascii keys in request."