launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #23164
[Merge] lp:~cjwatson/launchpad/six-1.12.0 into lp:launchpad
Colin Watson has proposed merging lp:~cjwatson/launchpad/six-1.12.0 into lp:launchpad.
Commit message:
Upgrade to six 1.12.0, and use the new six.ensure_* where appropriate.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/six-1.12.0/+merge/360475
These reduce noise from isinstance checks in a number of places, and provide a more convenient way of obtaining a native string appropriate to the Python version (previously done using twisted.python.compat.nativeString, which is odd in non-Twisted contexts).
--
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad/six-1.12.0 into lp:launchpad.
=== modified file 'constraints.txt'
--- constraints.txt 2018-07-16 10:51:04 +0000
+++ constraints.txt 2018-12-10 14:09:32 +0000
@@ -348,7 +348,7 @@
setuptools-scm==1.15.7
simplejson==3.8.2
SimpleTAL==4.3
-six==1.11.0
+six==1.12.0
snowballstemmer==1.2.1
soupmatchers==0.4
sphinxcontrib-websupport==1.0.1
=== modified file 'lib/lp/bugs/externalbugtracker/xmlrpc.py'
--- lib/lp/bugs/externalbugtracker/xmlrpc.py 2018-07-13 12:48:19 +0000
+++ lib/lp/bugs/externalbugtracker/xmlrpc.py 2018-12-10 14:09:32 +0000
@@ -21,6 +21,7 @@
import requests
from requests.cookies import RequestsCookieJar
+import six
from lp.bugs.externalbugtracker.base import repost_on_redirect_hook
from lp.services.config import config
@@ -71,8 +72,7 @@
url = urlunparse((self.scheme, host, handler, '', '', ''))
# httplib can raise a UnicodeDecodeError when using a Unicode
# URL, a non-ASCII body and a proxy. http://bugs.python.org/issue12398
- if not isinstance(url, bytes):
- url = url.encode('utf-8')
+ url = six.ensure_binary(url)
try:
with override_timeout(self.timeout):
response = urlfetch(
=== modified file 'lib/lp/buildmaster/model/packagebuild.py'
--- lib/lp/buildmaster/model/packagebuild.py 2015-02-17 07:39:47 +0000
+++ lib/lp/buildmaster/model/packagebuild.py 2018-12-10 14:09:32 +0000
@@ -1,4 +1,4 @@
-# Copyright 2010-2013 Canonical Ltd. This software is licensed under the
+# Copyright 2010-2018 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
__metaclass__ = type
@@ -9,6 +9,7 @@
from cStringIO import StringIO
+import six
from zope.component import getUtility
from lp.buildmaster.enums import BuildStatus
@@ -82,8 +83,7 @@
if filename is None:
filename = 'upload_%s_log.txt' % self.id
contentType = filenameToContentType(filename)
- if isinstance(content, unicode):
- content = content.encode('utf-8')
+ content = six.ensure_binary(content)
file_size = len(content)
file_content = StringIO(content)
restricted = self.is_private
=== modified file 'lib/lp/code/interfaces/codehosting.py'
--- lib/lp/code/interfaces/codehosting.py 2013-01-07 02:40:55 +0000
+++ lib/lp/code/interfaces/codehosting.py 2018-12-10 14:09:32 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2018 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Internal Codehosting API interfaces."""
@@ -25,6 +25,7 @@
import urllib
from lazr.uri import URI
+import six
from zope.interface import Interface
from lp.app.validators.name import valid_name
@@ -201,11 +202,9 @@
accepted_schemes.add('sftp')
assert scheme in accepted_schemes, "Unknown scheme: %s" % scheme
host = URI(config.codehosting.supermirror_root).host
- if isinstance(unique_name, unicode):
- unique_name = unique_name.encode('utf-8')
# After quoting and encoding, the path should be perfectly
# safe as a plain ASCII string, str() just enforces this
- path = '/' + str(urllib.quote(unique_name, safe='/~+'))
+ path = '/' + str(urllib.quote(six.ensure_binary(unique_name), safe='/~+'))
if suffix:
path = os.path.join(path, suffix)
return str(URI(scheme=scheme, host=host, path=path))
=== modified file 'lib/lp/code/model/branch.py'
--- lib/lp/code/model/branch.py 2018-07-09 09:27:06 +0000
+++ lib/lp/code/model/branch.py 2018-12-10 14:09:32 +0000
@@ -18,6 +18,7 @@
from bzrlib.revision import NULL_REVISION
from lazr.lifecycle.event import ObjectCreatedEvent
import pytz
+import six
from six.moves.urllib_parse import urlsplit
from sqlobject import (
ForeignKey,
@@ -813,10 +814,9 @@
memcache_client = getUtility(IMemcacheClient)
instance_name = urlsplit(
config.codehosting.internal_bzr_api_endpoint).hostname
- memcache_key = '%s:bzr-file-list:%s:%s:%s' % (
- instance_name, self.id, revision_id, dirname)
- if not isinstance(memcache_key, bytes):
- memcache_key = memcache_key.encode('UTF-8')
+ memcache_key = six.ensure_binary(
+ '%s:bzr-file-list:%s:%s:%s' % (
+ instance_name, self.id, revision_id, dirname))
cached_file_list = memcache_client.get(memcache_key)
if cached_file_list is not None:
try:
=== modified file 'lib/lp/code/model/gitlookup.py'
--- lib/lp/code/model/gitlookup.py 2018-09-28 13:54:16 +0000
+++ lib/lp/code/model/gitlookup.py 2018-12-10 14:09:32 +0000
@@ -12,6 +12,7 @@
InvalidURIError,
URI,
)
+import six
from zope.component import (
adapter,
getUtility,
@@ -235,9 +236,7 @@
self.traversed = []
def next(self):
- segment = next(self._iterator)
- if not isinstance(segment, unicode):
- segment = segment.decode("US-ASCII")
+ segment = six.ensure_text(next(self._iterator), encoding="US-ASCII")
self.traversed.append(segment)
return segment
=== modified file 'lib/lp/code/model/gitref.py'
--- lib/lp/code/model/gitref.py 2018-11-09 22:06:43 +0000
+++ lib/lp/code/model/gitref.py 2018-12-10 14:09:32 +0000
@@ -21,6 +21,7 @@
from lazr.lifecycle.event import ObjectCreatedEvent
import pytz
import requests
+import six
from storm.locals import (
DateTime,
Int,
@@ -329,8 +330,7 @@
memcache_key += ":limit=%s" % limit
if stop is not None:
memcache_key += ":stop=%s" % stop
- if isinstance(memcache_key, unicode):
- memcache_key = memcache_key.encode("UTF-8")
+ memcache_key = six.ensure_binary(memcache_key)
cached_log = memcache_client.get(memcache_key)
if cached_log is not None:
try:
=== modified file 'lib/lp/code/model/gitrepository.py'
--- lib/lp/code/model/gitrepository.py 2018-12-03 14:44:26 +0000
+++ lib/lp/code/model/gitrepository.py 2018-12-10 14:09:32 +0000
@@ -29,6 +29,7 @@
from lazr.lifecycle.event import ObjectModifiedEvent
from lazr.lifecycle.snapshot import Snapshot
import pytz
+import six
from storm.databases.postgres import Returning
from storm.expr import (
And,
@@ -580,9 +581,7 @@
raise ValueError('ref info sha1 is not a 40-character string')
if obj["type"] not in object_type_map:
raise ValueError('ref info type is not a recognised object type')
- sha1 = obj["sha1"]
- if isinstance(sha1, bytes):
- sha1 = sha1.decode("US-ASCII")
+ sha1 = six.ensure_text(obj["sha1"], encoding="US-ASCII")
return {"sha1": sha1, "type": object_type_map[obj["type"]]}
def createOrUpdateRefs(self, refs_info, get_objects=False, logger=None):
@@ -1320,12 +1319,10 @@
grants_for_user[grant.rule].append(grant)
for ref_path in ref_paths:
- encoded_ref_path = (
- ref_path if isinstance(ref_path, bytes)
- else ref_path.encode("UTF-8"))
matching_rules = [
- rule for rule in rules if
- fnmatch(encoded_ref_path, rule.ref_pattern.encode("UTF-8"))]
+ rule for rule in rules if fnmatch(
+ six.ensure_binary(ref_path),
+ rule.ref_pattern.encode("UTF-8"))]
if is_owner and not matching_rules:
# If there are no matching rules, then the repository owner
# can do anything.
=== modified file 'lib/lp/code/xmlrpc/codehosting.py'
--- lib/lp/code/xmlrpc/codehosting.py 2015-07-08 16:05:11 +0000
+++ lib/lp/code/xmlrpc/codehosting.py 2018-12-10 14:09:32 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2015 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2018 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Implementations of the XML-RPC APIs for codehosting."""
@@ -18,6 +18,7 @@
unescape,
)
import pytz
+import six
import transaction
from zope.component import getUtility
from zope.interface import implementer
@@ -109,9 +110,8 @@
# Don't pass in an actual user. Instead pass in LAUNCHPAD_SERVICES
# and expect `function` to use `removeSecurityProxy` or similar.
return function(login_id, *args, **kwargs)
- if isinstance(login_id, basestring):
- if isinstance(login_id, bytes):
- login_id = login_id.decode("UTF-8")
+ if isinstance(login_id, (six.binary_type, six.text_type)):
+ login_id = six.ensure_text(login_id)
# OpenID identifiers must contain a slash, while names must not.
if "/" in login_id:
requester = getUtility(IPersonSet).getByOpenIDIdentifier(login_id)
@@ -242,10 +242,7 @@
branch = namespace.createBranch(
BranchType.HOSTED, branch_name, requester)
except LaunchpadValidationError as e:
- msg = e.args[0]
- if isinstance(msg, unicode):
- msg = msg.encode('utf-8')
- return faults.PermissionDenied(msg)
+ return faults.PermissionDenied(six.ensure_binary(e.args[0]))
except BranchCreationException as e:
return faults.PermissionDenied(str(e))
=== modified file 'lib/lp/code/xmlrpc/git.py'
--- lib/lp/code/xmlrpc/git.py 2018-11-21 00:54:42 +0000
+++ lib/lp/code/xmlrpc/git.py 2018-12-10 14:09:32 +0000
@@ -11,6 +11,7 @@
import sys
from pymacaroons import Macaroon
+import six
from six.moves import xmlrpc_client
from storm.store import Store
import transaction
@@ -313,11 +314,9 @@
requester_id = auth_params.get("uid")
if requester_id is None:
requester_id = LAUNCHPAD_ANONYMOUS
- if isinstance(path, str):
- path = path.decode('utf-8')
return run_with_login(
requester_id, self._translatePath,
- path.strip("/"), permission, auth_params)
+ six.ensure_text(path).strip("/"), permission, auth_params)
def notify(self, translated_path):
"""See `IGitAPI`."""
=== modified file 'lib/lp/codehosting/codeimport/uifactory.py'
--- lib/lp/codehosting/codeimport/uifactory.py 2011-12-19 23:38:16 +0000
+++ lib/lp/codehosting/codeimport/uifactory.py 2018-12-10 14:09:32 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2018 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""A UIFactory useful for code imports."""
@@ -12,6 +12,7 @@
from bzrlib.ui import NoninteractiveUIFactory
from bzrlib.ui.text import TextProgressView
+import six
class LoggingUIFactory(NoninteractiveUIFactory):
@@ -45,9 +46,7 @@
"%s", self.format_user_warning(warning_id, message_args))
def show_warning(self, msg):
- if isinstance(msg, unicode):
- msg = msg.encode("utf-8")
- self.logger.warning("%s", msg)
+ self.logger.warning("%s", six.ensure_binary(msg))
def get_username(self, prompt, **kwargs):
return None
=== modified file 'lib/lp/codehosting/inmemory.py'
--- lib/lp/codehosting/inmemory.py 2015-10-01 10:25:19 +0000
+++ lib/lp/codehosting/inmemory.py 2018-12-10 14:09:32 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2012 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2018 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""In-memory doubles of core codehosting objects."""
@@ -16,6 +16,7 @@
escape,
unescape,
)
+import six
from twisted.internet import defer
from zope.component import (
adapter,
@@ -715,10 +716,7 @@
except LaunchpadFault as e:
return e
except LaunchpadValidationError as e:
- msg = e.args[0]
- if isinstance(msg, unicode):
- msg = msg.encode('utf-8')
- return faults.PermissionDenied(msg)
+ return faults.PermissionDenied(six.ensure_binary(e.args[0]))
def requestMirror(self, requester_id, branch_id):
self._branch_set.get(branch_id).requestMirror()
=== modified file 'lib/lp/codehosting/vfs/branchfs.py'
--- lib/lp/codehosting/vfs/branchfs.py 2018-01-26 13:47:51 +0000
+++ lib/lp/codehosting/vfs/branchfs.py 2018-12-10 14:09:32 +0000
@@ -73,6 +73,7 @@
from bzrlib.transport import get_transport
from bzrlib.transport.memory import MemoryServer
from lazr.uri import URI
+import six
from twisted.internet import (
defer,
error,
@@ -609,9 +610,7 @@
fault = trap_fault(
fail, faults.NotFound, faults.PermissionDenied,
faults.InvalidSourcePackageName, faults.InvalidProductName)
- faultString = fault.faultString
- if isinstance(faultString, unicode):
- faultString = faultString.encode('utf-8')
+ faultString = six.ensure_binary(fault.faultString)
return failure.Failure(
PermissionDenied(virtual_url_fragment, faultString))
=== modified file 'lib/lp/registry/scripts/tests/test_closeaccount.py'
--- lib/lp/registry/scripts/tests/test_closeaccount.py 2018-12-04 17:33:38 +0000
+++ lib/lp/registry/scripts/tests/test_closeaccount.py 2018-12-10 14:09:32 +0000
@@ -7,12 +7,12 @@
__metaclass__ = type
+import six
from testtools.matchers import (
Not,
StartsWith,
)
import transaction
-from twisted.python.compat import nativeString
from zope.component import getUtility
from zope.security.proxy import removeSecurityProxy
@@ -143,7 +143,7 @@
person_id = person.id
account_id = person.account.id
self.factory.makeProduct(owner=person)
- script = self.makeScript([nativeString(person.name)])
+ script = self.makeScript([six.ensure_str(person.name)])
with dbuser('launchpad'):
self.assertRaisesWithContent(
LaunchpadScriptFailure,
@@ -157,14 +157,14 @@
def test_single_by_name(self):
person, person_id, account_id = self.makePopulatedUser()
- script = self.makeScript([nativeString(person.name)])
+ script = self.makeScript([six.ensure_str(person.name)])
with dbuser('launchpad'):
self.runScript(script)
self.assertRemoved(account_id, person_id)
def test_single_by_email(self):
person, person_id, account_id = self.makePopulatedUser()
- script = self.makeScript([nativeString(person.preferredemail.email)])
+ script = self.makeScript([six.ensure_str(person.preferredemail.email)])
with dbuser('launchpad'):
self.runScript(script)
self.assertRemoved(account_id, person_id)
@@ -199,7 +199,7 @@
snap = self.factory.makeSnap()
snap_build = self.factory.makeSnapBuild(requester=person, snap=snap)
specification = self.factory.makeSpecification(drafter=person)
- script = self.makeScript([nativeString(person.name)])
+ script = self.makeScript([six.ensure_str(person.name)])
with dbuser('launchpad'):
self.runScript(script)
self.assertRemoved(account_id, person_id)
@@ -219,7 +219,7 @@
question.addComment(person, "comment")
removeSecurityProxy(question).status = status
questions.append(question)
- script = self.makeScript([nativeString(person.name)])
+ script = self.makeScript([six.ensure_str(person.name)])
with dbuser('launchpad'):
self.runScript(script)
self.assertRemoved(account_id, person_id)
@@ -241,7 +241,7 @@
question.addComment(person, "comment")
removeSecurityProxy(question).status = status
questions[status] = question
- script = self.makeScript([nativeString(person.name)])
+ script = self.makeScript([six.ensure_str(person.name)])
with dbuser('launchpad'):
self.runScript(script)
self.assertRemoved(account_id, person_id)
=== modified file 'lib/lp/registry/stories/teammembership/xx-teammembership.txt'
--- lib/lp/registry/stories/teammembership/xx-teammembership.txt 2016-11-15 17:49:49 +0000
+++ lib/lp/registry/stories/teammembership/xx-teammembership.txt 2018-12-10 14:09:32 +0000
@@ -224,13 +224,13 @@
well as the former members and the ones which proposed themselves or that
have been invited.
+ >>> import six
+
>>> def print_members(contents, type):
... table = find_tag_by_id(contents, type)
... for link in table.findAll('a'):
... if link.renderContents() != 'Edit' and not link.find('img'):
- ... contents = link.renderContents()
- ... if isinstance(contents, str):
- ... contents = contents.decode('utf-8')
+ ... contents = six.ensure_text(link.renderContents())
... print contents.encode('ascii', 'replace')
>>> browser.open('http://launchpad.dev/~landscape-developers')
=== modified file 'lib/lp/scripts/utilities/test.py'
--- lib/lp/scripts/utilities/test.py 2017-05-08 11:56:10 +0000
+++ lib/lp/scripts/utilities/test.py 2018-12-10 14:09:32 +0000
@@ -22,6 +22,7 @@
import time
import warnings
+import six
from zope.testing import testrunner
from zope.testing.testrunner import options
@@ -39,9 +40,7 @@
class _SpoofOut(doctest._SpoofOut):
def write(self, value):
- if isinstance(value, unicode):
- value = value.encode('utf8')
- _RealSpoofOut.write(self, value)
+ _RealSpoofOut.write(self, six.ensure_binary(value))
doctest._SpoofOut = _SpoofOut
=== modified file 'lib/lp/services/librarian/client.py'
--- lib/lp/services/librarian/client.py 2016-06-02 17:52:18 +0000
+++ lib/lp/services/librarian/client.py 2018-12-10 14:09:32 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2016 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2018 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
__metaclass__ = type
@@ -32,6 +32,7 @@
)
from lazr.restful.utils import get_current_browser_request
+import six
from storm.store import Store
from zope.interface import implementer
@@ -142,8 +143,7 @@
if size <= min_size:
raise UploadFailed('Invalid length: %d' % size)
- if isinstance(name, unicode):
- name = name.encode('utf-8')
+ name = six.ensure_binary(name)
# Import in this method to avoid a circular import
from lp.services.librarian.model import LibraryFileContent
@@ -235,8 +235,7 @@
raise TypeError('No data')
if size <= 0:
raise UploadFailed('No data')
- if isinstance(name, unicode):
- name = name.encode('utf-8')
+ name = six.ensure_binary(name)
self._connect()
try:
database_name = ConnectionString(dbconfig.main_master).dbname
=== modified file 'lib/lp/services/oauth/model.py'
--- lib/lp/services/oauth/model.py 2016-01-28 17:52:53 +0000
+++ lib/lp/services/oauth/model.py 2018-12-10 14:09:32 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2016 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2018 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
__metaclass__ = type
@@ -17,6 +17,9 @@
)
import hashlib
import re
+
+import pytz
+import six
from storm.locals import (
Bool,
DateTime,
@@ -24,8 +27,6 @@
Reference,
Unicode,
)
-
-import pytz
from zope.interface import implementer
from lp.registry.interfaces.distribution import IDistribution
@@ -81,10 +82,7 @@
this is straightforward because hexdigest() returns that anyway, but in
Python 2 we must decode.
"""
- digest = hashlib.sha256(data).hexdigest()
- if isinstance(digest, bytes):
- digest = digest.decode('ASCII')
- return digest
+ return six.ensure_text(hashlib.sha256(data).hexdigest(), encoding='ASCII')
@implementer(IOAuthConsumer)
=== modified file 'lib/lp/services/webapp/authentication.py'
--- lib/lp/services/webapp/authentication.py 2016-02-28 19:13:17 +0000
+++ lib/lp/services/webapp/authentication.py 2018-12-10 14:09:32 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2016 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2018 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
__metaclass__ = type
@@ -15,6 +15,7 @@
import binascii
from contrib.oauth import OAuthRequest
+import six
from zope.authentication.interfaces import ILoginPassword
from zope.component import getUtility
from zope.event import notify
@@ -283,9 +284,7 @@
# http://oauth.net/core/1.0/#encoding_parameters says "Text names
# and values MUST be encoded as UTF-8 octets before percent-encoding
# them", so we can reasonably fail if this hasn't been done.
- if isinstance(header, bytes):
- header = header.decode("UTF-8")
- return OAuthRequest._split_header(header)
+ return OAuthRequest._split_header(six.ensure_text(header))
else:
return request.form
=== modified file 'lib/lp/services/webapp/login.py'
--- lib/lp/services/webapp/login.py 2017-01-14 15:16:36 +0000
+++ lib/lp/services/webapp/login.py 2018-12-10 14:09:32 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2017 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2018 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Stuff to do with logging in and logging out."""
@@ -26,6 +26,7 @@
HTTPBadRequest,
HTTPException,
)
+import six
import transaction
from z3c.ptcompat import ViewPageTemplateFile
from zope.authentication.interfaces import IUnauthenticatedPrincipal
@@ -262,17 +263,12 @@
else:
value_list = [value]
- def encode_utf8(element):
- # urllib.urlencode will just encode unicode values to ASCII.
- # For our purposes, we can be a little more liberal and
- # allow UTF-8.
- if isinstance(element, unicode):
- element = element.encode('UTF-8')
- return element
-
+ # urllib.urlencode will just encode unicode values to ASCII.
+ # For our purposes, we can be a little more liberal and allow
+ # UTF-8.
yield (
- encode_utf8(name),
- [encode_utf8(value) for value in value_list])
+ six.ensure_binary(name),
+ [six.ensure_binary(value) for value in value_list])
class OpenIDCallbackView(OpenIDLogin):
=== modified file 'lib/lp/services/webapp/servers.py'
--- lib/lp/services/webapp/servers.py 2018-02-01 18:39:04 +0000
+++ lib/lp/services/webapp/servers.py 2018-12-10 14:09:32 +0000
@@ -542,21 +542,11 @@
porting to Python 3 via an intermediate stage of Unicode literals in
Python 2, we enforce this here.
"""
- # Based on twisted.python.compat.nativeString, but using a different
- # encoding.
- if not isinstance(s, (bytes, unicode)):
- raise TypeError('%r is neither bytes nor unicode' % s)
- if six.PY3:
- if isinstance(s, bytes):
- return s.decode('ISO-8859-1')
- else:
- # Ensure we're limited to ISO-8859-1.
- s.encode('ISO-8859-1')
- else:
- if isinstance(s, unicode):
- return s.encode('ISO-8859-1')
- # Bytes objects are always decodable as ISO-8859-1.
- return s
+ result = six.ensure_str(s, encoding='ISO-8859-1')
+ if six.PY3 and isinstance(s, six.text_type):
+ # Ensure we're limited to ISO-8859-1.
+ result.encode('ISO-8859-1')
+ return result
class LaunchpadBrowserRequestMixin:
@@ -1311,9 +1301,7 @@
# Try to retrieve a consumer based on the User-Agent
# header.
anonymous_request = True
- consumer_key = request.getHeader('User-Agent', '')
- if isinstance(consumer_key, bytes):
- consumer_key = consumer_key.decode('UTF-8')
+ consumer_key = six.ensure_text(request.getHeader('User-Agent', ''))
if consumer_key == u'':
consumer_key = u'anonymous client'
consumer = consumers.getByKey(consumer_key)
=== modified file 'lib/lp/services/webservice/configuration.py'
--- lib/lp/services/webservice/configuration.py 2016-09-14 11:13:06 +0000
+++ lib/lp/services/webservice/configuration.py 2018-12-10 14:09:32 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2016 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2018 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""A configuration class describing the Launchpad web service."""
@@ -9,6 +9,7 @@
]
from lazr.restful.simple import BaseWebServiceConfiguration
+import six
from zope.component import getUtility
from lp.app import versioninfo
@@ -64,8 +65,8 @@
"""See `IWebServiceConfiguration`."""
# The request is going to try to decode the 'PATH_INFO' using utf-8,
# so if it is currently unicode, encode it.
- if isinstance(environ.get('PATH_INFO'), unicode):
- environ['PATH_INFO'] = environ['PATH_INFO'].encode('utf-8')
+ if 'PATH_INFO' in environ:
+ environ['PATH_INFO'] = six.ensure_binary(environ['PATH_INFO'])
request = WebServiceClientRequest(body_instream, environ)
request.setPublication(WebServicePublication(None))
return request
=== modified file 'lib/lp/snappy/model/snapstoreclient.py'
--- lib/lp/snappy/model/snapstoreclient.py 2018-05-02 23:55:51 +0000
+++ lib/lp/snappy/model/snapstoreclient.py 2018-12-10 14:09:32 +0000
@@ -24,6 +24,7 @@
from pymacaroons import Macaroon
import requests
from requests_toolbelt import MultipartEncoder
+import six
from zope.component import getUtility
from zope.interface import implementer
from zope.security.proxy import removeSecurityProxy
@@ -189,9 +190,8 @@
error_message = "\n".join(
error["message"]
for error in response_data["error_list"])
- detail = requests_error.response.content
- if isinstance(detail, bytes):
- detail = detail.decode("UTF-8", errors="replace")
+ detail = six.ensure_text(
+ requests_error.response.content, errors="replace")
can_retry = requests_error.response.status_code in (502, 503)
return error_class(error_message, detail=detail, can_retry=can_retry)
=== modified file 'lib/lp/soyuz/mail/packageupload.py'
--- lib/lp/soyuz/mail/packageupload.py 2016-11-04 10:44:22 +0000
+++ lib/lp/soyuz/mail/packageupload.py 2018-12-10 14:09:32 +0000
@@ -1,4 +1,4 @@
-# Copyright 2011-2016 Canonical Ltd. This software is licensed under the
+# Copyright 2011-2018 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
__metaclass__ = type
@@ -9,6 +9,7 @@
from collections import OrderedDict
import os.path
+import six
from zope.component import getUtility
from zope.security.proxy import isinstance as zope_isinstance
@@ -620,7 +621,5 @@
debug(self.logger, " Bcc: %s" % ctrl.headers['Bcc'])
debug(self.logger, " Body:")
for line in ctrl.body.splitlines():
- if isinstance(line, bytes):
- line = line.decode('utf-8', 'replace')
- debug(self.logger, line)
+ debug(self.logger, six.ensure_text(line, errors="replace"))
return ctrl
=== modified file 'lib/lp/soyuz/model/packageset.py'
--- lib/lp/soyuz/model/packageset.py 2015-09-27 23:00:53 +0000
+++ lib/lp/soyuz/model/packageset.py 2018-12-10 14:09:32 +0000
@@ -1,10 +1,11 @@
-# Copyright 2009-2014 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2018 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
__metaclass__ = type
__all__ = ['Packageset', 'PackagesetSet']
import pytz
+import six
from storm.expr import SQL
from storm.locals import (
DateTime,
@@ -377,8 +378,7 @@
def getByName(self, distroseries, name):
"""See `IPackagesetSet`."""
store = IStore(Packageset)
- if not isinstance(name, unicode):
- name = unicode(name, 'utf-8')
+ name = six.ensure_text(name)
package_set = store.find(
Packageset, Packageset.name == name,
Packageset.distroseries == distroseries).one()
=== modified file 'lib/lp/testing/_webservice.py'
--- lib/lp/testing/_webservice.py 2016-01-26 15:14:01 +0000
+++ lib/lp/testing/_webservice.py 2018-12-10 14:09:32 +0000
@@ -1,4 +1,4 @@
-# Copyright 2010-2016 Canonical Ltd. This software is licensed under the
+# Copyright 2010-2018 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
__metaclass__ = type
@@ -19,6 +19,7 @@
Credentials,
)
from launchpadlib.launchpad import Launchpad
+import six
import transaction
from zope.component import getUtility
import zope.testing.cleanup
@@ -133,8 +134,7 @@
"""
# XXX cjwatson 2016-01-22: Callers should be updated to pass Unicode
# directly, but that's a big change.
- if isinstance(consumer_name, bytes):
- consumer_name = unicode(consumer_name)
+ consumer_name = six.ensure_text(consumer_name)
if person is None:
token = AnonymousAccessToken()
credentials = Credentials(consumer_name, access_token=token)
=== modified file 'lib/lp/testing/pages.py'
--- lib/lp/testing/pages.py 2018-05-13 10:35:52 +0000
+++ lib/lp/testing/pages.py 2018-12-10 14:09:32 +0000
@@ -32,6 +32,7 @@
OAuthToken,
)
from lazr.restful.testing.webservice import WebServiceCaller
+import six
import transaction
from zope.app.testing.functional import (
HTTPCaller,
@@ -76,6 +77,7 @@
stop,
)
+
SAMPLEDATA_ACCESS_SECRETS = {
u'salgado-read-nonprivate': u'secret',
u'salgado-change-anything': u'test',
@@ -140,8 +142,7 @@
if oauth_consumer_key is not None and oauth_access_key is not None:
# XXX cjwatson 2016-01-25: Callers should be updated to pass
# Unicode directly, but that's a big change.
- if isinstance(oauth_consumer_key, bytes):
- oauth_consumer_key = unicode(oauth_consumer_key)
+ oauth_consumer_key = six.ensure_text(oauth_consumer_key)
self.consumer = OAuthConsumer(oauth_consumer_key, u'')
if oauth_access_secret is None:
oauth_access_secret = SAMPLEDATA_ACCESS_SECRETS.get(
=== modified file 'lib/lp/translations/model/potranslation.py'
--- lib/lp/translations/model/potranslation.py 2015-10-14 16:23:18 +0000
+++ lib/lp/translations/model/potranslation.py 2018-12-10 14:09:32 +0000
@@ -1,9 +1,10 @@
-# Copyright 2009 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2018 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
__metaclass__ = type
__all__ = ['POTranslation']
+import six
from sqlobject import (
SQLObjectNotFound,
StringCol,
@@ -48,13 +49,10 @@
"""Return a POTranslation object for the given translation, or create
it if it doesn't exist.
"""
- if isinstance(key, str):
- # If this is not a unicode object, it had better be ASCII or
- # UTF-8.
- # XXX: JeroenVermeulen 2008-06-06 bug=237868: non-ascii str
- # strings should be contained in the parser or the browser
- # code.
- key = key.decode('UTF-8')
+ # If this is not a unicode object, it had better be ASCII or UTF-8.
+ # XXX: JeroenVermeulen 2008-06-06 bug=237868: non-ascii str strings
+ # should be contained in the parser or the browser code.
+ key = six.ensure_text(key)
try:
return cls.byTranslation(key)
=== modified file 'lib/lp/translations/utilities/translationmerger.py'
--- lib/lp/translations/utilities/translationmerger.py 2018-02-02 10:06:24 +0000
+++ lib/lp/translations/utilities/translationmerger.py 2018-12-10 14:09:32 +0000
@@ -11,6 +11,7 @@
from operator import methodcaller
+import six
from storm.locals import (
ClassAlias,
Store,
@@ -273,9 +274,7 @@
subset = self.template_set.getSharingSubset(
product=product, distribution=distribution,
sourcepackagename=sourcepackagename)
- template_regex = self.options.template_names
- if isinstance(template_regex, str):
- template_regex = template_regex.decode('utf-8')
+ template_regex = six.ensure_text(self.options.template_names)
equivalence_classes = subset.groupEquivalentPOTemplates(template_regex)
class_count = len(equivalence_classes)
Follow ups