launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #26494
[Merge] ~cjwatson/launchpad:py3-base64-types into launchpad:master
Colin Watson has proposed merging ~cjwatson/launchpad:py3-base64-types into launchpad:master.
Commit message:
Use correct types for base64 encoding/decoding
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/398930
On Python 3, base64.b64encode takes bytes and returns bytes. base64.b64decode in fact takes either bytes or ASCII-only Unicode strings and returns bytes, but it's more symmetrical and thus clearer to treat it as if it only took bytes.
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:py3-base64-types into launchpad:master.
diff --git a/lib/lp/app/browser/stringformatter.py b/lib/lp/app/browser/stringformatter.py
index c791cf7..b816ae7 100644
--- a/lib/lp/app/browser/stringformatter.py
+++ b/lib/lp/app/browser/stringformatter.py
@@ -1084,7 +1084,8 @@ class FormattersAPI:
# we also have to strip off any padding characters ("=") because
# Python's URL-safe base 64 encoding includes those and they
# aren't allowed in IDs either.
- unique_suffix = urlsafe_b64encode(raw_text)
+ unique_suffix = (
+ urlsafe_b64encode(raw_text.encode('ASCII')).decode('ASCII'))
# Ensure we put a '-' between the id and base 64 encoding.
if id_[-1] != '-':
id_ += '-'
diff --git a/lib/lp/archivepublisher/htaccess.py b/lib/lp/archivepublisher/htaccess.py
index 1d29fb8..613cfde 100644
--- a/lib/lp/archivepublisher/htaccess.py
+++ b/lib/lp/archivepublisher/htaccess.py
@@ -76,7 +76,8 @@ def make_salt(s):
"""
# As long as the input string is at least one character long, there will
# be no padding within the first two characters.
- return base64.b64encode((s or " ").encode("UTF-8"), altchars=b"./")[:2]
+ return base64.b64encode(
+ (s or " ").encode("UTF-8"), altchars=b"./")[:2].decode("ASCII")
def htpasswd_credentials_for_archive(archive):
diff --git a/lib/lp/code/scripts/tests/test_request_daily_builds.py b/lib/lp/code/scripts/tests/test_request_daily_builds.py
index 1be9b9a..0f16bc8 100644
--- a/lib/lp/code/scripts/tests/test_request_daily_builds.py
+++ b/lib/lp/code/scripts/tests/test_request_daily_builds.py
@@ -142,7 +142,10 @@ class FakeTurnipApplication:
if filename not in self.contents[repository_id]:
return self._not_found(start_response)
blob = self.contents[repository_id][filename]
- response = {'size': len(blob), 'data': base64.b64encode(blob)}
+ response = {
+ 'size': len(blob),
+ 'data': base64.b64encode(blob).decode('ASCII'),
+ }
start_response(
'200 OK', [('Content-Type', 'application/octet-stream')])
return [json.dumps(response).encode('UTF-8')]
diff --git a/lib/lp/registry/model/person.py b/lib/lp/registry/model/person.py
index ec5226d..624fab2 100644
--- a/lib/lp/registry/model/person.py
+++ b/lib/lp/registry/model/person.py
@@ -4096,8 +4096,8 @@ class SSHKey(SQLBase):
def getFullKeyText(self):
try:
- ssh_keytype = getNS(base64.b64decode(self.keytext))[0].decode(
- 'ascii')
+ key_blob = base64.b64decode(self.keytext.encode('UTF-8'))
+ ssh_keytype = getNS(key_blob)[0].decode('ascii')
except Exception:
# We didn't always validate keys, so there might be some that
# can't be loaded this way.
diff --git a/lib/lp/registry/stories/team-polls/xx-poll-confirm-vote.txt b/lib/lp/registry/stories/team-polls/xx-poll-confirm-vote.txt
index 27b6cb3..0b4628a 100644
--- a/lib/lp/registry/stories/team-polls/xx-poll-confirm-vote.txt
+++ b/lib/lp/registry/stories/team-polls/xx-poll-confirm-vote.txt
@@ -2,7 +2,8 @@
results of the director-2004 poll.
>>> import base64
- >>> jdub_auth = base64.b64encode('jeff.waugh@xxxxxxxxxxxxxxx:test')
+ >>> jdub_auth = base64.b64encode(
+ ... b'jeff.waugh@xxxxxxxxxxxxxxx:test').decode('ASCII')
>>> print(http(r"""
... GET /~ubuntu-team/+poll/director-2004 HTTP/1.1
... Authorization: Basic %s
diff --git a/lib/lp/services/gpg/tests/test_gpghandler.py b/lib/lp/services/gpg/tests/test_gpghandler.py
index 297db6c..e929187 100644
--- a/lib/lp/services/gpg/tests/test_gpghandler.py
+++ b/lib/lp/services/gpg/tests/test_gpghandler.py
@@ -1,7 +1,6 @@
# Copyright 2009-2020 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
-import base64
from datetime import datetime
import os
import shutil
@@ -507,8 +506,3 @@ class TestGPGHandler(TestCase):
line for line in status if line.startswith(validsig_prefix)]
validsig_tokens = validsig_line[len(validsig_prefix):].split()
self.assertEqual(gpgme.MD_SHA512, int(validsig_tokens[7]))
-
-
-def construct_url(template, owner_id='', fingerprint=''):
- owner_id = base64.b64encode(owner_id, altchars='-_')
- return template.format(owner_id=owner_id, fingerprint=fingerprint)
diff --git a/lib/lp/services/signing/tests/test_proxy.py b/lib/lp/services/signing/tests/test_proxy.py
index f50aa8c..4405fe7 100644
--- a/lib/lp/services/signing/tests/test_proxy.py
+++ b/lib/lp/services/signing/tests/test_proxy.py
@@ -72,7 +72,6 @@ class SigningServiceResponseFactory:
bytes(self.generated_public_key))
self.generated_fingerprint = (
u'338D218488DFD597D8FCB9C328C3E9D9ADA16CEE')
- self.b64_signed_msg = base64.b64encode(b"the-signed-msg")
self.signed_msg_template = "%s::signed!"
@@ -169,8 +168,8 @@ class SigningServiceResponseFactory:
def sign_callback(request):
call_counts['/sign'] += 1
- signed = base64.b64encode(
- self.signed_msg_template % call_counts['/sign'])
+ signed_msg = self.signed_msg_template % call_counts['/sign']
+ signed = base64.b64encode(signed_msg.encode('utf8'))
data = {'signed-message': signed.decode('utf8'),
'public-key': self.b64_generated_public_key.decode('utf8')}
return 201, {}, self._encryptPayload(data, self.response_nonce)
diff --git a/lib/lp/services/webapp/doc/webapp-publication.txt b/lib/lp/services/webapp/doc/webapp-publication.txt
index 8af06ab..d1f0ff3 100644
--- a/lib/lp/services/webapp/doc/webapp-publication.txt
+++ b/lib/lp/services/webapp/doc/webapp-publication.txt
@@ -1103,7 +1103,7 @@ utility to setup the request.
>>> import base64
>>> login(ANONYMOUS) # Get rid of the marker object in the interaction.
>>> foo_bar_auth = 'Basic %s' % (
- ... base64.b64encode('foo.bar@xxxxxxxxxxxxx:test'))
+ ... base64.b64encode(b'foo.bar@xxxxxxxxxxxxx:test').decode('ASCII'))
>>> request, publication = get_request_and_publication(
... extra_environment=dict(HTTP_AUTHORIZATION=foo_bar_auth))
>>> principal = publication.getPrincipal(request)
diff --git a/lib/lp/services/webapp/tests/test_authutility.py b/lib/lp/services/webapp/tests/test_authutility.py
index 279dd3d..6d7000b 100644
--- a/lib/lp/services/webapp/tests/test_authutility.py
+++ b/lib/lp/services/webapp/tests/test_authutility.py
@@ -79,9 +79,9 @@ class TestPlacelessAuth(ContainerPlacelessSetup, testtools.TestCase):
testtools.TestCase.tearDown(self)
def _make(self, login, pwd):
- dict = {
- 'HTTP_AUTHORIZATION':
- 'Basic %s' % base64.b64encode('%s:%s' % (login, pwd))}
+ auth = base64.b64encode(
+ ('%s:%s' % (login, pwd)).encode('ASCII')).decode('ASCII')
+ dict = {'HTTP_AUTHORIZATION': 'Basic %s' % auth}
request = TestRequest(**dict)
return getUtility(IPlacelessAuthUtility), request
diff --git a/lib/lp/services/webservice/stories/xx-service.txt b/lib/lp/services/webservice/stories/xx-service.txt
index f3a5d3f..c07704b 100644
--- a/lib/lp/services/webservice/stories/xx-service.txt
+++ b/lib/lp/services/webservice/stories/xx-service.txt
@@ -166,7 +166,9 @@ scheme (and don't require OAuth).
... LaunchpadWebServiceCaller)
>>> noauth_webservice = LaunchpadWebServiceCaller(
... domain='bugs.launchpad.test')
- >>> sample_auth = 'Basic %s' % base64.b64encode('test@xxxxxxxxxxxxx:test')
+ >>> sample_auth = (
+ ... 'Basic %s' %
+ ... base64.b64encode(b'test@xxxxxxxxxxxxx:test').decode('ASCII'))
>>> print(noauth_webservice.get(
... 'http://bugs.launchpad.test/api/devel/people/+me',
... headers={'Authorization': sample_auth}))
diff --git a/lib/lp/snappy/model/snapbuildbehaviour.py b/lib/lp/snappy/model/snapbuildbehaviour.py
index cdb374f..4dd89f0 100644
--- a/lib/lp/snappy/model/snapbuildbehaviour.py
+++ b/lib/lp/snappy/model/snapbuildbehaviour.py
@@ -94,7 +94,7 @@ class SnapProxyMixin:
build_id=self.build.build_cookie,
timestamp=timestamp)
auth_string = '{}:{}'.format(admin_username, secret).strip()
- auth_header = b'Basic ' + base64.b64encode(auth_string)
+ auth_header = b'Basic ' + base64.b64encode(auth_string.encode('ASCII'))
token = yield self._slave.process_pool.doWork(
RequestProxyTokenCommand,
diff --git a/lib/lp/snappy/model/snapstoreclient.py b/lib/lp/snappy/model/snapstoreclient.py
index 917559d..8055438 100644
--- a/lib/lp/snappy/model/snapstoreclient.py
+++ b/lib/lp/snappy/model/snapstoreclient.py
@@ -98,8 +98,8 @@ class MacaroonAuth(requests.auth.AuthBase):
try:
_, key, value = caveat.caveat_id.split("|")
if key == "account":
- account = json.loads(
- base64.b64decode(value).decode("UTF-8"))
+ account = json.loads(base64.b64decode(
+ value.encode("UTF-8")).decode("UTF-8"))
if "openid" in account:
self.logger.debug(
"%s macaroon: OpenID identifier: %s" %
diff --git a/lib/lp/soyuz/adapters/archivedependencies.py b/lib/lp/soyuz/adapters/archivedependencies.py
index d3cbff3..12e5ff2 100644
--- a/lib/lp/soyuz/adapters/archivedependencies.py
+++ b/lib/lp/soyuz/adapters/archivedependencies.py
@@ -405,7 +405,8 @@ def _get_sources_list_for_dependencies(dependencies, logger=None):
key = yield deferToThread(get_key)
if key is not None:
- trusted_keys[fingerprint] = base64.b64encode(key.export())
+ trusted_keys[fingerprint] = (
+ base64.b64encode(key.export()).decode("ASCII"))
defer.returnValue(
(sources_list_lines, [v for k, v in sorted(trusted_keys.items())]))
diff --git a/lib/lp/soyuz/tests/soyuz.py b/lib/lp/soyuz/tests/soyuz.py
index 52c9fb7..5e0b9fe 100644
--- a/lib/lp/soyuz/tests/soyuz.py
+++ b/lib/lp/soyuz/tests/soyuz.py
@@ -29,7 +29,7 @@ class Base64KeyMatches(Matcher):
self.fingerprint = fingerprint
def match(self, encoded_key):
- key = base64.b64decode(encoded_key)
+ key = base64.b64decode(encoded_key.encode("ASCII"))
return Equals(self.fingerprint).match(
getUtility(IGPGHandler).importPublicKey(key).fingerprint)
diff --git a/lib/lp/testing/factory.py b/lib/lp/testing/factory.py
index 9661a8f..2717264 100644
--- a/lib/lp/testing/factory.py
+++ b/lib/lp/testing/factory.py
@@ -4392,7 +4392,8 @@ class BareLaunchpadObjectFactory(ObjectFactory):
raise AssertionError(
"key_type must be a member of SSH_TEXT_TO_KEY_TYPE, not %r" %
key_type)
- key_text = base64.b64encode(NS(key_type) + b"".join(parameters))
+ key_text = base64.b64encode(
+ NS(key_type) + b"".join(parameters)).decode("ASCII")
if comment is None:
comment = self.getUniqueString()
return "%s %s %s" % (key_type, key_text, comment)
diff --git a/utilities/massage-bug-import-xml b/utilities/massage-bug-import-xml
index 7d92f84..5a304be 100755
--- a/utilities/massage-bug-import-xml
+++ b/utilities/massage-bug-import-xml
@@ -178,7 +178,8 @@ def massage(root, project_name, fix_nickname, tag_nickname):
u"text/plain")
etree.SubElement(attachment, '{%s}contents' % NS).text = (
standard_b64encode(
- first_comment_text.text.encode('utf-8')))
+ first_comment_text.text.encode('utf-8')
+ ).decode('ascii'))
# Trim the comment text.
problem_resolution('Trimming comment text.')
first_comment_text.text = truncate(
diff --git a/utilities/roundup-sniffer.py b/utilities/roundup-sniffer.py
index 224da01..3035d0e 100755
--- a/utilities/roundup-sniffer.py
+++ b/utilities/roundup-sniffer.py
@@ -66,7 +66,9 @@ class RoundupSniffer:
def fetch(self, url):
"""Fetch the URL, consulting the cache first."""
- filename = join(self.cache_dir, urlsafe_b64encode(url))
+ filename = join(
+ self.cache_dir,
+ urlsafe_b64encode(url.encode('UTF-8')).decode('ASCII'))
if not exists(filename):
open(filename, 'wb').write(urlopen(url).read())
return open(filename, 'rb')