launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #27888
[Merge] ~cjwatson/launchpad:pyupgrade-py3-services-1 into launchpad:master
Colin Watson has proposed merging ~cjwatson/launchpad:pyupgrade-py3-services-1 into launchpad:master.
Commit message:
Apply pyupgrade --py3-plus to lp.services.[a-m]*
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/413670
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:pyupgrade-py3-services-1 into launchpad:master.
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index c5316a7..5531052 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -54,6 +54,7 @@ repos:
|oci
|registry
|scripts
+ |services/[a-m]
)/
- repo: https://github.com/PyCQA/isort
rev: 5.9.2
diff --git a/lib/lp/services/apachelogparser/model/parsedapachelog.py b/lib/lp/services/apachelogparser/model/parsedapachelog.py
index f5bca5d..50d8889 100644
--- a/lib/lp/services/apachelogparser/model/parsedapachelog.py
+++ b/lib/lp/services/apachelogparser/model/parsedapachelog.py
@@ -30,7 +30,7 @@ class ParsedApacheLog(Storm):
date_last_parsed = UtcDateTimeCol(notNull=True, default=UTC_NOW)
def __init__(self, first_line, bytes_read):
- super(ParsedApacheLog, self).__init__()
+ super().__init__()
self.first_line = six.ensure_text(first_line)
self.bytes_read = bytes_read
IStore(self.__class__).add(self)
diff --git a/lib/lp/services/apachelogparser/tests/test_apachelogparser.py b/lib/lp/services/apachelogparser/tests/test_apachelogparser.py
index 513ce5d..48af8bd 100644
--- a/lib/lp/services/apachelogparser/tests/test_apachelogparser.py
+++ b/lib/lp/services/apachelogparser/tests/test_apachelogparser.py
@@ -408,7 +408,7 @@ class TestParsedFilesDetection(TestCase):
file_path = os.path.join(root, 'launchpadlibrarian.net.access-log')
def setUp(self):
- super(TestParsedFilesDetection, self).setUp()
+ super().setUp()
switch_dbuser(DBUSER)
def test_sorts_by_mtime(self):
@@ -515,14 +515,14 @@ class Test_create_or_update_parsedlog_entry(TestCase):
layer = LaunchpadZopelessLayer
def setUp(self):
- super(Test_create_or_update_parsedlog_entry, self).setUp()
+ super().setUp()
switch_dbuser(DBUSER)
def test_creation_of_new_entries(self):
# When given a first_line that doesn't exist in the ParsedApacheLog
# table, create_or_update_parsedlog_entry() will create a new entry
# with the given number of bytes read.
- first_line = u'First line'
+ first_line = 'First line'
create_or_update_parsedlog_entry(
first_line, parsed_bytes=len(first_line))
@@ -535,7 +535,7 @@ class Test_create_or_update_parsedlog_entry(TestCase):
# When given a first_line that already exists in the ParsedApacheLog
# table, create_or_update_parsedlog_entry() will update that entry
# with the given number of bytes read.
- first_line = u'First line'
+ first_line = 'First line'
create_or_update_parsedlog_entry(first_line, parsed_bytes=2)
store = IStore(ParsedApacheLog)
entry = store.find(ParsedApacheLog, first_line=first_line).one()
diff --git a/lib/lp/services/auth/enums.py b/lib/lp/services/auth/enums.py
index 351f18e..c590856 100644
--- a/lib/lp/services/auth/enums.py
+++ b/lib/lp/services/auth/enums.py
@@ -3,7 +3,6 @@
"""Enumerations used in lp.services.auth."""
-__metaclass__ = type
__all__ = [
"AccessTokenScope",
]
diff --git a/lib/lp/services/auth/interfaces.py b/lib/lp/services/auth/interfaces.py
index d18d51c..7a9927a 100644
--- a/lib/lp/services/auth/interfaces.py
+++ b/lib/lp/services/auth/interfaces.py
@@ -3,7 +3,6 @@
"""Personal access token interfaces."""
-__metaclass__ = type
__all__ = [
"IAccessToken",
"IAccessTokenSet",
diff --git a/lib/lp/services/auth/model.py b/lib/lp/services/auth/model.py
index b1cc7fc..aa1ff11 100644
--- a/lib/lp/services/auth/model.py
+++ b/lib/lp/services/auth/model.py
@@ -3,7 +3,6 @@
"""Personal access tokens."""
-__metaclass__ = type
__all__ = [
"AccessToken",
"AccessTokenTargetMixin",
diff --git a/lib/lp/services/auth/tests/test_model.py b/lib/lp/services/auth/tests/test_model.py
index 805b02c..82d44b0 100644
--- a/lib/lp/services/auth/tests/test_model.py
+++ b/lib/lp/services/auth/tests/test_model.py
@@ -3,8 +3,6 @@
"""Test personal access tokens."""
-__metaclass__ = type
-
from datetime import (
datetime,
timedelta,
diff --git a/lib/lp/services/auth/utils.py b/lib/lp/services/auth/utils.py
index 99dd2ba..a3b956d 100644
--- a/lib/lp/services/auth/utils.py
+++ b/lib/lp/services/auth/utils.py
@@ -3,7 +3,6 @@
"""Personal access token utilities."""
-__metaclass__ = type
__all__ = [
"create_access_token_secret",
]
diff --git a/lib/lp/services/authserver/tests/test_authserver.py b/lib/lp/services/authserver/tests/test_authserver.py
index 98bdabc..272f02b 100644
--- a/lib/lp/services/authserver/tests/test_authserver.py
+++ b/lib/lp/services/authserver/tests/test_authserver.py
@@ -165,7 +165,7 @@ class MacaroonTests(TestCaseWithFactory):
layer = ZopelessDatabaseLayer
def setUp(self):
- super(MacaroonTests, self).setUp()
+ super().setUp()
self.issuer = DummyMacaroonIssuer()
self.useFixture(ZopeUtilityFixture(
self.issuer, IMacaroonIssuer, name='test'))
diff --git a/lib/lp/services/beautifulsoup.py b/lib/lp/services/beautifulsoup.py
index b61e126..6a39229 100644
--- a/lib/lp/services/beautifulsoup.py
+++ b/lib/lp/services/beautifulsoup.py
@@ -11,14 +11,12 @@ __all__ = [
from bs4 import BeautifulSoup as _BeautifulSoup
from bs4.element import SoupStrainer
-import six
class BeautifulSoup(_BeautifulSoup):
def __init__(self, markup="", features="html.parser", **kwargs):
- if (not isinstance(markup, six.text_type) and
+ if (not isinstance(markup, str) and
"from_encoding" not in kwargs):
kwargs["from_encoding"] = "UTF-8"
- super(BeautifulSoup, self).__init__(
- markup=markup, features=features, **kwargs)
+ super().__init__(markup=markup, features=features, **kwargs)
diff --git a/lib/lp/services/command_spawner.py b/lib/lp/services/command_spawner.py
index f2b34c8..31b8940 100644
--- a/lib/lp/services/command_spawner.py
+++ b/lib/lp/services/command_spawner.py
@@ -170,7 +170,7 @@ class CommandSpawner:
"""Read output from `pipe_file`."""
try:
output = pipe_file.read()
- except IOError as e:
+ except OSError as e:
# "Resource temporarily unavailable"--not an error really,
# just means there's nothing to read.
if e.errno != errno.EAGAIN:
diff --git a/lib/lp/services/comments/interfaces/conversation.py b/lib/lp/services/comments/interfaces/conversation.py
index a8bc146..aa5ff8b 100644
--- a/lib/lp/services/comments/interfaces/conversation.py
+++ b/lib/lp/services/comments/interfaces/conversation.py
@@ -28,7 +28,7 @@ from lp import _
class IComment(Interface):
"""A comment which may have a body or footer."""
- index = Int(title=u'The comment number', required=True, readonly=True)
+ index = Int(title='The comment number', required=True, readonly=True)
extra_css_class = TextLine(
description=_("A css class to apply to the comment's outer div."))
@@ -42,15 +42,15 @@ class IComment(Interface):
readonly=True)
too_long = Bool(
- title=u'Whether the comment body is too long to display in full.',
+ title='Whether the comment body is too long to display in full.',
readonly=True)
too_long_to_render = Bool(
- title=(u'Whether the comment body is so long that rendering is'
+ title=('Whether the comment body is so long that rendering is'
' inappropriate.'), readonly=True)
text_for_display = Text(
- title=u'The comment text to be displayed in the UI.', readonly=True)
+ title='The comment text to be displayed in the UI.', readonly=True)
body_text = Text(
description=_("The body text of the comment."),
diff --git a/lib/lp/services/config/__init__.py b/lib/lp/services/config/__init__.py
index d96005e..87b9b62 100644
--- a/lib/lp/services/config/__init__.py
+++ b/lib/lp/services/config/__init__.py
@@ -15,7 +15,6 @@ import sys
from lazr.config import ImplicitTypeSchema
from lazr.config.interfaces import ConfigErrors
-import six
from lp.services.osutils import open_for_writing
from lp.services.propertycache import (
@@ -288,7 +287,7 @@ class LaunchpadConfig:
config = LaunchpadConfig()
-class DatabaseConfigOverrides(object):
+class DatabaseConfigOverrides:
pass
@@ -330,7 +329,7 @@ class DatabaseConfig:
Overriding a value to None removes the override.
"""
- for attr, value in six.iteritems(kwargs):
+ for attr, value in kwargs.items():
assert attr in self._db_config_attrs, (
"%s cannot be overridden" % attr)
if value is None:
diff --git a/lib/lp/services/config/tests/test_config_lookup.py b/lib/lp/services/config/tests/test_config_lookup.py
index 9e32bcd..d0b4bcf 100644
--- a/lib/lp/services/config/tests/test_config_lookup.py
+++ b/lib/lp/services/config/tests/test_config_lookup.py
@@ -19,7 +19,7 @@ from lp.testing import TestCase
class TestConfigLookup(TestCase):
def setUp(self):
- super(TestConfigLookup, self).setUp()
+ super().setUp()
self.temp_lookup_file = None
self.original_CONFIG_LOOKUP_FILES = config.CONFIG_LOOKUP_FILES
self.original_LPCONFIG = os.environ['LPCONFIG']
@@ -28,7 +28,7 @@ class TestConfigLookup(TestCase):
del self.temp_lookup_file
config.CONFIG_LOOKUP_FILES = self.original_CONFIG_LOOKUP_FILES
os.environ['LPCONFIG'] = self.original_LPCONFIG
- super(TestConfigLookup, self).tearDown()
+ super().tearDown()
def makeLookupFile(self):
self.temp_lookup_file = NamedTemporaryFile()
@@ -100,7 +100,7 @@ class TestInstanceConfigDirLookup(ConfigTestCase):
"""Test where instance config directories are looked up."""
def setUp(self):
- super(TestInstanceConfigDirLookup, self).setUp()
+ super().setUp()
self.setUpConfigRoots()
def test_find_config_dir_raises_ValueError(self):
diff --git a/lib/lp/services/crypto/model.py b/lib/lp/services/crypto/model.py
index 3202656..e2467c2 100644
--- a/lib/lp/services/crypto/model.py
+++ b/lib/lp/services/crypto/model.py
@@ -15,7 +15,6 @@ from nacl.public import (
PublicKey,
SealedBox,
)
-import six
from zope.interface import implementer
from lp.services.crypto.interfaces import (
@@ -46,7 +45,7 @@ class NaClEncryptedContainerBase:
try:
return PublicKey(self.public_key_bytes)
except NaClCryptoError as e:
- six.raise_from(CryptoError(str(e)), e)
+ raise CryptoError(str(e)) from e
else:
return None
@@ -64,7 +63,7 @@ class NaClEncryptedContainerBase:
try:
data_encrypted = SealedBox(self.public_key).encrypt(data)
except NaClCryptoError as e:
- six.raise_from(CryptoError(str(e)), e)
+ raise CryptoError(str(e)) from e
return (
base64.b64encode(self.public_key_bytes).decode("UTF-8"),
base64.b64encode(data_encrypted).decode("UTF-8"))
@@ -84,7 +83,7 @@ class NaClEncryptedContainerBase:
try:
return PrivateKey(self.private_key_bytes)
except NaClCryptoError as e:
- six.raise_from(CryptoError(str(e)), e)
+ raise CryptoError(str(e)) from e
else:
return None
@@ -102,7 +101,7 @@ class NaClEncryptedContainerBase:
public_key_bytes = base64.b64decode(public_key.encode("UTF-8"))
encrypted_bytes = base64.b64decode(encrypted.encode("UTF-8"))
except TypeError as e:
- six.raise_from(CryptoError(str(e)), e)
+ raise CryptoError(str(e)) from e
if public_key_bytes != self.public_key_bytes:
raise ValueError(
"Public key %r does not match configured public key %r" %
@@ -112,4 +111,4 @@ class NaClEncryptedContainerBase:
try:
return SealedBox(self.private_key).decrypt(encrypted_bytes)
except NaClCryptoError as e:
- six.raise_from(CryptoError(str(e)), e)
+ raise CryptoError(str(e)) from e
diff --git a/lib/lp/services/daemons/tests/test_tachandler.py b/lib/lp/services/daemons/tests/test_tachandler.py
index d9cfb23..0eabfb8 100644
--- a/lib/lp/services/daemons/tests/test_tachandler.py
+++ b/lib/lp/services/daemons/tests/test_tachandler.py
@@ -34,7 +34,7 @@ from lp.testing.layers import DatabaseLayer
class SimpleTac(TacTestSetup):
def __init__(self, name, tempdir):
- super(SimpleTac, self).__init__()
+ super().__init__()
self.name, self.tempdir = name, tempdir
@property
diff --git a/lib/lp/services/database/bulk.py b/lib/lp/services/database/bulk.py
index 517e522..9f94220 100644
--- a/lib/lp/services/database/bulk.py
+++ b/lib/lp/services/database/bulk.py
@@ -24,7 +24,6 @@ from operator import (
itemgetter,
)
-import six
from storm.databases.postgres import Returning
from storm.expr import (
And,
@@ -52,7 +51,7 @@ def collate(things, key):
collection = defaultdict(list)
for thing in things:
collection[key(thing)].append(thing)
- return six.iteritems(collection)
+ return collection.items()
def get_type(thing):
diff --git a/lib/lp/services/database/collection.py b/lib/lp/services/database/collection.py
index 94a1b5b..f580f0d 100644
--- a/lib/lp/services/database/collection.py
+++ b/lib/lp/services/database/collection.py
@@ -15,7 +15,7 @@ from storm.expr import (
from lp.services.database.interfaces import IStore
-class Collection(object):
+class Collection:
"""An arbitrary collection of database objects.
Works as a Storm wrapper: create a collection based on another
diff --git a/lib/lp/services/database/debug.py b/lib/lp/services/database/debug.py
index 2c0e5ea..5fa2da1 100644
--- a/lib/lp/services/database/debug.py
+++ b/lib/lp/services/database/debug.py
@@ -49,7 +49,7 @@ def LN(*args, **kwargs):
return text
-class ConnectionWrapper(object):
+class ConnectionWrapper:
_log = None
_real_con = None
diff --git a/lib/lp/services/database/decoratedresultset.py b/lib/lp/services/database/decoratedresultset.py
index b31e1f8..c524b69 100644
--- a/lib/lp/services/database/decoratedresultset.py
+++ b/lib/lp/services/database/decoratedresultset.py
@@ -16,7 +16,7 @@ from zope.security.proxy import (
@delegate_to(IResultSet, context='result_set')
-class DecoratedResultSet(object):
+class DecoratedResultSet:
"""A decorated Storm ResultSet for 'Magic' (presenter) classes.
Because `DistroSeriesBinaryPackage` doesn't actually exist in the
diff --git a/lib/lp/services/database/interfaces.py b/lib/lp/services/database/interfaces.py
index 14407be..5e89515 100644
--- a/lib/lp/services/database/interfaces.py
+++ b/lib/lp/services/database/interfaces.py
@@ -35,7 +35,7 @@ class IRequestExpired(IRuntimeError):
# think it is ever used though ...
class ISQLBase(Interface):
"""An extension of ISQLObject that provides an ID."""
- id = Int(title=u"The integer ID for the instance")
+ id = Int(title="The integer ID for the instance")
#
diff --git a/lib/lp/services/database/policy.py b/lib/lp/services/database/policy.py
index 838df09..a50fe3d 100644
--- a/lib/lp/services/database/policy.py
+++ b/lib/lp/services/database/policy.py
@@ -235,7 +235,7 @@ def LaunchpadDatabasePolicyFactory(request):
# to sniff the request this way. Even though PATH_INFO is always
# present in real requests, we need to tread carefully (``get``) because
# of test requests in our automated tests.
- if request.get('PATH_INFO') in [u'/+opstats', u'/+haproxy']:
+ if request.get('PATH_INFO') in ['/+opstats', '/+haproxy']:
return DatabaseBlockedPolicy(request)
else:
return LaunchpadDatabasePolicy(request)
diff --git a/lib/lp/services/database/postgresql.py b/lib/lp/services/database/postgresql.py
index 6dba9d0..cec01cf 100644
--- a/lib/lp/services/database/postgresql.py
+++ b/lib/lp/services/database/postgresql.py
@@ -8,8 +8,6 @@ and table manipulation
import re
-import six
-
from lp.services.database.sqlbase import (
quote,
quoteIdentifier,
@@ -458,7 +456,7 @@ def drop_tables(cur, tables):
"""
if tables is None or len(tables) == 0:
return
- if isinstance(tables, six.string_types):
+ if isinstance(tables, str):
tables = [tables]
# This syntax requires postgres 8.2 or better
diff --git a/lib/lp/services/database/sqlbase.py b/lib/lp/services/database/sqlbase.py
index 43cd316..83434cc 100644
--- a/lib/lp/services/database/sqlbase.py
+++ b/lib/lp/services/database/sqlbase.py
@@ -222,7 +222,7 @@ class SQLBase(storm.sqlobject.SQLObjectBase):
def destroySelf(self):
my_master = IMasterObject(self)
if self is my_master:
- super(SQLBase, self).destroySelf()
+ super().destroySelf()
else:
my_master.destroySelf()
diff --git a/lib/lp/services/database/sqlobject/__init__.py b/lib/lp/services/database/sqlobject/__init__.py
index a30b27d..381c7d2 100644
--- a/lib/lp/services/database/sqlobject/__init__.py
+++ b/lib/lp/services/database/sqlobject/__init__.py
@@ -6,7 +6,6 @@
# SKIP this file when reformatting, due to the sys mangling.
import datetime
-import six
from storm.expr import SQL
from storm.sqlobject import * # noqa: F401,F403
@@ -32,7 +31,7 @@ def sqlrepr(value, dbname=None):
return value.getquoted()
elif isinstance(value, SQL):
return value.expr
- elif isinstance(value, six.string_types):
+ elif isinstance(value, str):
for orig, repl in _sqlStringReplace:
value = value.replace(orig, repl)
return "E'%s'" % value
diff --git a/lib/lp/services/database/tests/test_bulk.py b/lib/lp/services/database/tests/test_bulk.py
index 03cb64d..a90d11e 100644
--- a/lib/lp/services/database/tests/test_bulk.py
+++ b/lib/lp/services/database/tests/test_bulk.py
@@ -187,9 +187,9 @@ class TestLoaders(TestCaseWithFactory):
# test.
(FeatureFlag.scope, FeatureFlag.priority, FeatureFlag.flag),
sorted(
- [(u'foo', 0, u'bar'), (u'foo', 0, u'baz'),
- (u'foo', 1, u'bar'), (u'foo', 1, u'quux'),
- (u'bar', 0, u'foo')]))
+ [('foo', 0, 'bar'), ('foo', 0, 'baz'),
+ ('foo', 1, 'bar'), ('foo', 1, 'quux'),
+ ('bar', 0, 'foo')]))
self.assertEqual(
"FeatureFlag.scope = E'bar' AND ("
"FeatureFlag.priority = 0 AND FeatureFlag.flag IN (E'foo')) OR "
@@ -219,10 +219,10 @@ class TestLoaders(TestCaseWithFactory):
def test_load_with_compound_primary_keys(self):
# load() can load objects with compound primary keys.
flags = [
- FeatureFlag(u'foo', 0, u'bar', u'true'),
- FeatureFlag(u'foo', 0, u'baz', u'false'),
+ FeatureFlag('foo', 0, 'bar', 'true'),
+ FeatureFlag('foo', 0, 'baz', 'false'),
]
- other_flag = FeatureFlag(u'notfoo', 0, u'notbar', u'true')
+ other_flag = FeatureFlag('notfoo', 0, 'notbar', 'true')
for flag in flags + [other_flag]:
getFeatureStore().add(flag)
diff --git a/lib/lp/services/database/tests/test_isolation.py b/lib/lp/services/database/tests/test_isolation.py
index 552a13f..add0786 100644
--- a/lib/lp/services/database/tests/test_isolation.py
+++ b/lib/lp/services/database/tests/test_isolation.py
@@ -4,7 +4,6 @@
"""Tests of the isolation module."""
from psycopg2.extensions import TRANSACTION_STATUS_IDLE
-import six
from storm.zope.interfaces import IZStorm
import transaction
from zope.component import getUtility
@@ -33,7 +32,7 @@ class TestIsolation(TestCase):
# transactions have been aborted.
transaction.abort()
for name, status in isolation.gen_store_statuses():
- self.assertIsInstance(name, six.string_types)
+ self.assertIsInstance(name, str)
self.assertIn(status, (None, TRANSACTION_STATUS_IDLE))
# At least one store will not be idle when a transaction has
# begun.
diff --git a/lib/lp/services/database/tests/test_stormbase.py b/lib/lp/services/database/tests/test_stormbase.py
index 6328abd..86b106d 100644
--- a/lib/lp/services/database/tests/test_stormbase.py
+++ b/lib/lp/services/database/tests/test_stormbase.py
@@ -36,7 +36,7 @@ class TestStormBase(TestCase):
layer = ZopelessDatabaseLayer
def setUp(self):
- super(TestStormBase, self).setUp()
+ super().setUp()
self.store = getUtility(IStoreSelector).get(MAIN_STORE, DEFAULT_FLAVOR)
self.store.execute("CREATE TABLE StormExample (id serial PRIMARY KEY)")
diff --git a/lib/lp/services/database/tests/test_transaction_policy.py b/lib/lp/services/database/tests/test_transaction_policy.py
index 7122ccf..db19a4f 100644
--- a/lib/lp/services/database/tests/test_transaction_policy.py
+++ b/lib/lp/services/database/tests/test_transaction_policy.py
@@ -21,7 +21,7 @@ class TestTransactionPolicy(TestCaseWithFactory):
layer = ZopelessDatabaseLayer
def setUp(self):
- super(TestTransactionPolicy, self).setUp()
+ super().setUp()
# Start each test with a clean slate: no ongoing transaction
# unless the test says so.
transaction.abort()
diff --git a/lib/lp/services/encoding.py b/lib/lp/services/encoding.py
index f3796bd..c8e8f15 100644
--- a/lib/lp/services/encoding.py
+++ b/lib/lp/services/encoding.py
@@ -111,7 +111,7 @@ def guess(s):
# Calling this method with a Unicode argument indicates a hidden bug
# that will bite you eventually -- StuartBishop 20050709
- if isinstance(s, six.text_type):
+ if isinstance(s, str):
raise TypeError(
'encoding.guess called with Unicode string %r' % (s,)
)
@@ -120,7 +120,7 @@ def guess(s):
# that can encode themselves as ASCII.
if not isinstance(s, bytes):
try:
- return six.text_type(s)
+ return str(s)
except UnicodeDecodeError:
pass
@@ -128,32 +128,32 @@ def guess(s):
try:
for bom, encoding in _boms:
if s.startswith(bom):
- return six.text_type(s[len(bom):], encoding)
+ return str(s[len(bom):], encoding)
except UnicodeDecodeError:
pass
# Try preferred encoding
try:
- return six.text_type(s, 'UTF-8')
+ return str(s, 'UTF-8')
except UnicodeDecodeError:
pass
# If we have characters in this range, it is probably CP1252
if re.search(br"[\x80-\x9f]", s) is not None:
try:
- return six.text_type(s, 'CP1252')
+ return str(s, 'CP1252')
except UnicodeDecodeError:
pass
# If we have characters in this range, it is probably ISO-8859-15
if re.search(br"[\xa4\xa6\xa8\xb4\xb8\xbc-\xbe]", s) is not None:
try:
- return six.text_type(s, 'ISO-8859-15')
+ return str(s, 'ISO-8859-15')
except UnicodeDecodeError:
pass
# Otherwise we default to ISO-8859-1
- return six.text_type(s, 'ISO-8859-1', 'replace')
+ return str(s, 'ISO-8859-1', 'replace')
def escape_nonascii_uniquely(bogus_string):
@@ -223,7 +223,7 @@ def wsgi_native_string(s):
Python 2, we enforce this here.
"""
result = six.ensure_str(s, encoding='ISO-8859-1')
- if isinstance(s, six.text_type):
+ if isinstance(s, str):
# Ensure we're limited to ISO-8859-1.
result.encode('ISO-8859-1')
return result
diff --git a/lib/lp/services/features/browser/edit.py b/lib/lp/services/features/browser/edit.py
index 29e8ae0..25ebdf4 100644
--- a/lib/lp/services/features/browser/edit.py
+++ b/lib/lp/services/features/browser/edit.py
@@ -34,16 +34,16 @@ class IFeatureControlForm(Interface):
self.context = context
feature_rules = Text(
- title=u"Feature rules",
+ title="Feature rules",
description=(
- u"Rules to control feature flags on Launchpad. "
- u"On each line: (flag, scope, priority, value), "
- u"whitespace-separated. Numerically higher "
- u"priorities match first."),
+ "Rules to control feature flags on Launchpad. "
+ "On each line: (flag, scope, priority, value), "
+ "whitespace-separated. Numerically higher "
+ "priorities match first."),
required=False)
comment = Text(
- title=u"Comment",
- description=(u"Who requested this change and why."),
+ title="Comment",
+ description=("Who requested this change and why."),
required=True)
@@ -71,7 +71,7 @@ class FeatureControlView(LaunchpadFormView):
"""Is the user authorized to change the rules?"""
return check_permission('launchpad.Admin', self.context)
- @action(u"Change", name="change", condition=canSubmit)
+ @action("Change", name="change", condition=canSubmit)
def change_action(self, action, data):
original_rules = self.request.features.rule_source.getAllRulesAsText()
rules_text = data.get('feature_rules') or ''
@@ -83,7 +83,7 @@ class FeatureControlView(LaunchpadFormView):
# (whitespace normalized) and ordered consistently so the diff is
# minimal.
new_rules = self.request.features.rule_source.getAllRulesAsText()
- diff = u'\n'.join(self.diff_rules(original_rules, new_rules))
+ diff = '\n'.join(self.diff_rules(original_rules, new_rules))
comment = data['comment']
ChangeLog.append(diff, comment, self.user)
self.diff = FormattersAPI(diff).format_diff()
diff --git a/lib/lp/services/features/browser/tests/test_changelog.py b/lib/lp/services/features/browser/tests/test_changelog.py
index ec76e38..0070832 100644
--- a/lib/lp/services/features/browser/tests/test_changelog.py
+++ b/lib/lp/services/features/browser/tests/test_changelog.py
@@ -29,7 +29,7 @@ class TestChangeLogView(TestCaseWithFactory):
layer = DatabaseFunctionalLayer
def setUp(self):
- super(TestChangeLogView, self).setUp()
+ super().setUp()
self.root = getUtility(ILaunchpadRoot)
self.person = self.factory.makePerson()
diff --git a/lib/lp/services/features/browser/tests/test_feature_editor.py b/lib/lp/services/features/browser/tests/test_feature_editor.py
index 0f4a15a..80172fe 100644
--- a/lib/lp/services/features/browser/tests/test_feature_editor.py
+++ b/lib/lp/services/features/browser/tests/test_feature_editor.py
@@ -34,7 +34,7 @@ class TestFeatureControlPage(BrowserTestCase):
layer = DatabaseFunctionalLayer
def setUp(self):
- super(TestFeatureControlPage, self).setUp()
+ super().setUp()
self.useFixture(FakeLogger())
def getUserBrowserAsTeamMember(self, teams):
@@ -72,8 +72,8 @@ class TestFeatureControlPage(BrowserTestCase):
def test_feature_page_from_database(self):
StormFeatureRuleSource().setAllRules([
- ('ui.icing', 'default', 100, u'3.0'),
- ('ui.icing', 'beta_user', 300, u'4.0'),
+ ('ui.icing', 'default', 100, '3.0'),
+ ('ui.icing', 'beta_user', 300, '4.0'),
])
browser = self.getUserBrowserAsAdmin()
browser.open(self.getFeatureRulesViewURL())
diff --git a/lib/lp/services/features/browser/tests/test_feature_info.py b/lib/lp/services/features/browser/tests/test_feature_info.py
index 4c8e879..3a3cf2c 100644
--- a/lib/lp/services/features/browser/tests/test_feature_info.py
+++ b/lib/lp/services/features/browser/tests/test_feature_info.py
@@ -124,7 +124,7 @@ class TestUndocumentedFeatureFlags(TestCase):
"""Test the code that records accessing of undocumented feature flags."""
def setUp(self):
- super(TestUndocumentedFeatureFlags, self).setUp()
+ super().setUp()
# Stash away any already encountered undocumented flags.
saved_undocumented = undocumented_flags.copy()
saved_documented = documented_flags.copy()
diff --git a/lib/lp/services/features/model.py b/lib/lp/services/features/model.py
index 3ca37d5..1dd3875 100644
--- a/lib/lp/services/features/model.py
+++ b/lib/lp/services/features/model.py
@@ -36,7 +36,7 @@ class FeatureFlag(Storm):
date_modified = DateTime()
def __init__(self, scope, priority, flag, value):
- super(FeatureFlag, self).__init__()
+ super().__init__()
self.scope = scope
self.priority = priority
self.flag = flag
@@ -56,7 +56,7 @@ class FeatureFlagChangelogEntry(Storm):
person = Reference(person_id, 'Person.id')
def __init__(self, diff, comment, person):
- super(FeatureFlagChangelogEntry, self).__init__()
+ super().__init__()
self.diff = six.ensure_text(diff)
self.date_changed = datetime.now(pytz.timezone('UTC'))
self.comment = six.ensure_text(comment)
diff --git a/lib/lp/services/features/rulesource.py b/lib/lp/services/features/rulesource.py
index 00a43cf..44db1c1 100644
--- a/lib/lp/services/features/rulesource.py
+++ b/lib/lp/services/features/rulesource.py
@@ -42,7 +42,7 @@ class DuplicatePriorityError(Exception):
self.flag, self.priority)
-class FeatureRuleSource(object):
+class FeatureRuleSource:
"""Access feature rule sources from the database or elsewhere."""
def getAllRulesAsDict(self):
diff --git a/lib/lp/services/features/scopes.py b/lib/lp/services/features/scopes.py
index 3d7f3ca..7845b92 100644
--- a/lib/lp/services/features/scopes.py
+++ b/lib/lp/services/features/scopes.py
@@ -294,7 +294,7 @@ class ScopesFromRequest(MultiScopeHandler):
TeamScope(person_from_request),
UserSliceScope(person_from_request),
])
- super(ScopesFromRequest, self).__init__(scopes)
+ super().__init__(scopes)
class ScopesForScript(MultiScopeHandler):
@@ -303,4 +303,4 @@ class ScopesForScript(MultiScopeHandler):
def __init__(self, script_name):
scopes = list(default_scopes)
scopes.append(ScriptScope(script_name))
- super(ScopesForScript, self).__init__(scopes)
+ super().__init__(scopes)
diff --git a/lib/lp/services/features/testing.py b/lib/lp/services/features/testing.py
index 4ff828f..f715cc9 100644
--- a/lib/lp/services/features/testing.py
+++ b/lib/lp/services/features/testing.py
@@ -12,7 +12,6 @@ __all__ = [
from fixtures import Fixture
from lazr.restful.utils import get_current_browser_request
import psycopg2
-import six
from lp.services.features import (
get_relevant_feature_controller,
@@ -91,8 +90,8 @@ class FeatureFixtureMixin:
flag=flag_name,
scope='default',
priority=999,
- value=six.text_type(value))
- for flag_name, value in six.iteritems(self.desired_features)
+ value=str(value))
+ for flag_name, value in self.desired_features.items()
if value is not None]
if self.full_feature_rules is not None:
diff --git a/lib/lp/services/features/tests/test_changelog.py b/lib/lp/services/features/tests/test_changelog.py
index a624e12..7a4f348 100644
--- a/lib/lp/services/features/tests/test_changelog.py
+++ b/lib/lp/services/features/tests/test_changelog.py
@@ -28,12 +28,12 @@ class TestFeatureFlagChangelogEntry(TestCaseWithFactory):
person = self.factory.makePerson()
before = datetime.now(pytz.timezone('UTC'))
feature_flag_change = FeatureFlagChangelogEntry(
- diff, u'comment', person)
+ diff, 'comment', person)
after = datetime.now(pytz.timezone('UTC'))
self.assertEqual(
diff, feature_flag_change.diff)
self.assertEqual(
- u'comment', feature_flag_change.comment)
+ 'comment', feature_flag_change.comment)
self.assertEqual(
person, feature_flag_change.person)
self.assertBetween(
@@ -46,7 +46,7 @@ class TestChangeLog(TestCaseWithFactory):
layer = DatabaseFunctionalLayer
def setUp(self):
- super(TestChangeLog, self).setUp()
+ super().setUp()
self.person = self.factory.makePerson()
def test_ChangeLog_append(self):
diff --git a/lib/lp/services/features/tests/test_flags.py b/lib/lp/services/features/tests/test_flags.py
index d8e687e..d22790d 100644
--- a/lib/lp/services/features/tests/test_flags.py
+++ b/lib/lp/services/features/tests/test_flags.py
@@ -21,13 +21,13 @@ from lp.testing import (
notification_name = 'notification.global.text'
-notification_value = u'\N{SNOWMAN} stormy Launchpad weather ahead'
+notification_value = '\N{SNOWMAN} stormy Launchpad weather ahead'
testdata = [
(notification_name, 'beta_user', 100, notification_value),
- ('ui.icing', 'default', 100, u'3.0'),
- ('ui.icing', 'beta_user', 300, u'4.0'),
+ ('ui.icing', 'default', 100, '3.0'),
+ ('ui.icing', 'beta_user', 300, '4.0'),
]
@@ -36,7 +36,7 @@ class TestFeatureFlags(TestCase):
layer = layers.DatabaseFunctionalLayer
def setUp(self):
- super(TestFeatureFlags, self).setUp()
+ super().setUp()
if os.environ.get("STORM_TRACE", None):
from storm.tracer import debug
debug(True)
@@ -57,7 +57,7 @@ class TestFeatureFlags(TestCase):
def test_getFlag(self):
self.populateStore()
control, call_log = self.makeControllerInScopes(['default'])
- self.assertEqual(u'3.0',
+ self.assertEqual('3.0',
control.getFlag('ui.icing'))
self.assertEqual(['beta_user', 'default'], call_log)
@@ -65,12 +65,12 @@ class TestFeatureFlags(TestCase):
# for use in page templates, the flags can be treated as a dict
self.populateStore()
control, call_log = self.makeControllerInScopes(['default'])
- self.assertEqual(u'3.0',
+ self.assertEqual('3.0',
control['ui.icing'])
self.assertEqual(['beta_user', 'default'], call_log)
# after looking this up the value is known and the scopes are
# positively and negatively cached
- self.assertEqual({'ui.icing': u'3.0'}, control.usedFlags())
+ self.assertEqual({'ui.icing': '3.0'}, control.usedFlags())
self.assertEqual(dict(beta_user=False, default=True),
control.usedScopes())
@@ -129,12 +129,12 @@ class TestFeatureFlags(TestCase):
self.populateStore()
default_control, call_log = self.makeControllerInScopes(['default'])
self.assertEqual(
- u'3.0',
+ '3.0',
default_control.getFlag('ui.icing'))
beta_control, call_log = self.makeControllerInScopes(
['beta_user', 'default'])
self.assertEqual(
- u'4.0',
+ '4.0',
beta_control.getFlag('ui.icing'))
def test_undefinedFlag(self):
@@ -157,7 +157,7 @@ class TestFeatureFlags(TestCase):
try:
# then application code can simply ask without needing a context
# object
- self.assertEqual(u'4.0', getFeatureFlag('ui.icing'))
+ self.assertEqual('4.0', getFeatureFlag('ui.icing'))
finally:
install_feature_controller(None)
@@ -172,7 +172,7 @@ class TestFeatureFlags(TestCase):
# when it will make a difference to the result.
self.populateStore()
f, call_log = self.makeControllerInScopes(['beta_user'])
- self.assertEqual(u'4.0', f.getFlag('ui.icing'))
+ self.assertEqual('4.0', f.getFlag('ui.icing'))
# to calculate this it should only have had to check we're in the
# beta_users scope; nothing else makes a difference
self.assertEqual(dict(beta_user=True), f._known_scopes._known)
@@ -201,9 +201,9 @@ class TestFeatureFlags(TestCase):
test_rules_list = [
(notification_name, 'beta_user', 100, notification_value),
- ('ui.icing', 'normal_user', 500, u'5.0'),
- ('ui.icing', 'beta_user', 300, u'4.0'),
- ('ui.icing', 'default', 100, u'3.0'),
+ ('ui.icing', 'normal_user', 500, '5.0'),
+ ('ui.icing', 'beta_user', 300, '4.0'),
+ ('ui.icing', 'default', 100, '3.0'),
]
diff --git a/lib/lp/services/features/tests/test_helpers.py b/lib/lp/services/features/tests/test_helpers.py
index a07b444..89b0f20 100644
--- a/lib/lp/services/features/tests/test_helpers.py
+++ b/lib/lp/services/features/tests/test_helpers.py
@@ -45,13 +45,13 @@ class FeatureFixturesTestsMixin:
self.useFixture(self.fixture_cls({'two': '2'}))
self.assertEqual(getFeatureFlag('one'), None)
- self.assertEqual(getFeatureFlag('two'), u'2')
+ self.assertEqual(getFeatureFlag('two'), '2')
def test_fixture_overrides_previously_set_flags(self):
self.useFixture(self.fixture_cls({'one': '1'}))
self.useFixture(self.fixture_cls({'one': '5'}))
- self.assertEqual(getFeatureFlag('one'), u'5')
+ self.assertEqual(getFeatureFlag('one'), '5')
def test_fixture_does_not_set_value_for_flags_that_are_None(self):
self.useFixture(self.fixture_cls({'nothing': None}))
@@ -62,10 +62,10 @@ class FeatureFixturesTestsMixin:
value_outside_manager = getFeatureFlag(flag)
value_in_manager = None
- with self.fixture_cls({flag: u'on'}):
+ with self.fixture_cls({flag: 'on'}):
value_in_manager = getFeatureFlag(flag)
- self.assertEqual(value_in_manager, u'on')
+ self.assertEqual(value_in_manager, 'on')
self.assertEqual(value_outside_manager, getFeatureFlag(flag))
self.assertNotEqual(value_outside_manager, value_in_manager)
diff --git a/lib/lp/services/features/tests/test_scopes.py b/lib/lp/services/features/tests/test_scopes.py
index 4934b81..843f177 100644
--- a/lib/lp/services/features/tests/test_scopes.py
+++ b/lib/lp/services/features/tests/test_scopes.py
@@ -77,7 +77,7 @@ class TestScopes(TestCaseWithFactory):
self.assertFalse(scopes.lookup("script:other"))
-class FakePerson(object):
+class FakePerson:
id = 7
@@ -113,12 +113,12 @@ class TestUserSliceScopeIntegration(TestCaseWithFactory):
flag='test_feature',
scope='userslice:0,1',
priority=999,
- value=u'on'),
+ value='on'),
dict(
flag='test_not',
scope='userslice:1,1',
priority=999,
- value=u'not_value'),
+ value='not_value'),
]):
with person_logged_in(person):
self.assertEqual(getFeatureFlag('test_feature'), 'on')
diff --git a/lib/lp/services/features/tests/test_webapp.py b/lib/lp/services/features/tests/test_webapp.py
index 5bf6e54..13b6e27 100644
--- a/lib/lp/services/features/tests/test_webapp.py
+++ b/lib/lp/services/features/tests/test_webapp.py
@@ -122,4 +122,4 @@ class TestFeaturesIntoOops(TestCaseWithFactory):
self.assertTrue('features.usedFlags' in oops)
self.assertEqual(
oops['features.usedFlags'],
- u'%r' % {'feature_name': u'value'})
+ '%r' % {'feature_name': 'value'})
diff --git a/lib/lp/services/features/tests/test_xmlrpc.py b/lib/lp/services/features/tests/test_xmlrpc.py
index 10cf61c..ba1960c 100644
--- a/lib/lp/services/features/tests/test_xmlrpc.py
+++ b/lib/lp/services/features/tests/test_xmlrpc.py
@@ -39,45 +39,45 @@ class TestGetFeatureFlag(TestCaseWithFactory):
features.install_feature_controller, old_features)
def test_getFeatureFlag_returns_None_by_default(self):
- self.assertIs(None, self.endpoint.getFeatureFlag(u'unknown'))
+ self.assertIs(None, self.endpoint.getFeatureFlag('unknown'))
def test_getFeatureFlag_returns_true_for_set_flag(self):
- flag_name = u'flag'
+ flag_name = 'flag'
with feature_flags():
- set_feature_flag(flag_name, u'1')
- self.assertEqual(u'1', self.endpoint.getFeatureFlag(flag_name))
+ set_feature_flag(flag_name, '1')
+ self.assertEqual('1', self.endpoint.getFeatureFlag(flag_name))
def test_getFeatureFlag_ignores_relevant_feature_controller(self):
# getFeatureFlag should only consider the scopes it is asked to
# consider, not any that happen to be active due to the XML-RPC
# request itself.
- flag_name = u'flag'
- scope_name = u'scope'
+ flag_name = 'flag'
+ scope_name = 'scope'
self.installFeatureController(
FeatureController(
MultiScopeHandler(
[DefaultScope(), FixedScope(scope_name)]).lookup,
StormFeatureRuleSource()))
- set_feature_flag(flag_name, u'1', scope_name)
+ set_feature_flag(flag_name, '1', scope_name)
self.assertEqual(None, self.endpoint.getFeatureFlag(flag_name))
def test_getFeatureFlag_considers_supplied_scope(self):
- flag_name = u'flag'
- scope_name = u'scope'
+ flag_name = 'flag'
+ scope_name = 'scope'
with feature_flags():
- set_feature_flag(flag_name, u'value', scope_name)
+ set_feature_flag(flag_name, 'value', scope_name)
self.assertEqual(
- u'value',
+ 'value',
self.endpoint.getFeatureFlag(flag_name, [scope_name]))
def test_getFeatureFlag_turns_user_into_team_scope(self):
- flag_name = u'flag'
+ flag_name = 'flag'
person = self.factory.makePerson()
team = self.factory.makeTeam(members=[person])
with feature_flags():
- set_feature_flag(flag_name, u'value', u'team:' + team.name)
+ set_feature_flag(flag_name, 'value', 'team:' + team.name)
self.assertEqual(
- u'value',
+ 'value',
self.endpoint.getFeatureFlag(
flag_name, ['user:' + person.name]))
@@ -85,13 +85,13 @@ class TestGetFeatureFlag(TestCaseWithFactory):
sp = xmlrpc.client.ServerProxy(
config.launchpad.feature_flags_endpoint,
transport=XMLRPCTestTransport(), allow_none=True)
- self.assertEqual(None, sp.getFeatureFlag(u'flag'))
+ self.assertEqual(None, sp.getFeatureFlag('flag'))
def test_xmlrpc_interface_set(self):
sp = xmlrpc.client.ServerProxy(
config.launchpad.feature_flags_endpoint,
transport=XMLRPCTestTransport(), allow_none=True)
- flag_name = u'flag'
+ flag_name = 'flag'
with feature_flags():
- set_feature_flag(flag_name, u'1')
- self.assertEqual(u'1', sp.getFeatureFlag(flag_name))
+ set_feature_flag(flag_name, '1')
+ self.assertEqual('1', sp.getFeatureFlag(flag_name))
diff --git a/lib/lp/services/feeds/feed.py b/lib/lp/services/feeds/feed.py
index 35d5939..9798bc0 100644
--- a/lib/lp/services/feeds/feed.py
+++ b/lib/lp/services/feeds/feed.py
@@ -19,7 +19,6 @@ import operator
import os
import time
-import six
from six.moves.urllib.parse import urljoin
from zope.browserpage import ViewPageTemplateFile
from zope.component import getUtility
@@ -68,7 +67,7 @@ class FeedBase(LaunchpadView):
'html': 'templates/feed-html.pt'}
def __init__(self, context, request):
- super(FeedBase, self).__init__(context, request)
+ super().__init__(context, request)
self.format = self.feed_format
self.root_url = canonical_url(getUtility(ILaunchpadRoot),
rootsite=self.rootsite)
@@ -294,7 +293,7 @@ class FeedTypedData:
for a_tag in a_tags:
if a_tag['href'].startswith('/'):
a_tag['href'] = urljoin(self.root_url, a_tag['href'])
- altered_content = six.text_type(soup)
+ altered_content = str(soup)
else:
altered_content = self._content
@@ -302,7 +301,7 @@ class FeedTypedData:
altered_content = html_escape(altered_content)
elif self.content_type == 'xhtml':
soup = BeautifulSoup(altered_content)
- altered_content = six.text_type(soup)
+ altered_content = str(soup)
return altered_content
diff --git a/lib/lp/services/feeds/interfaces/feed.py b/lib/lp/services/feeds/interfaces/feed.py
index 6cdc31c..7a92ff8 100644
--- a/lib/lp/services/feeds/interfaces/feed.py
+++ b/lib/lp/services/feeds/interfaces/feed.py
@@ -54,34 +54,34 @@ class IFeed(Interface):
# duration in seconds the feed should be cached before being considered
# stale.
max_age = Int(
- title=u"Maximum age",
- description=u"Maximum age in seconds for a feed to be cached.")
+ title="Maximum age",
+ description="Maximum age in seconds for a feed to be cached.")
# A feed could contain an arbitrary large number of entries, so a quantity
# may be specified to limit the number of entries returned.
quantity = Int(
- title=u"Quantity",
- description=u"Number of items to be returned in a feed.")
+ title="Quantity",
+ description="Number of items to be returned in a feed.")
# The title of the feed is prominently displayed in readers and should
# succinctly identify the feed, e.g. "Latest bugs in Kubuntu".
title = TextLine(
- title=u"Title of the feed.")
+ title="Title of the feed.")
# The URL for a feed identifies it uniquely and it should never change.
# The latest bugs in Kubuntu is:
# http://feeds.launchpad.net/kubuntu/latest-bugs.atom
link_self = TextLine(
- title=u"URL for the feed.",
- description=u"The link_self URL for the feed should be "
- "unique and permanent.")
+ title="URL for the feed.",
+ description="The link_self URL for the feed should be "
+ "unique and permanent.")
# The site URL refers to the top-level page for the site serving the
# feed. For Launchpad the site_url should be the mainsite URL,
# i.e. http://launchpad.net.
site_url = TextLine(
- title=u"Site URL",
- description=u"The URL for the main site of Launchpad.")
+ title="Site URL",
+ description="The URL for the main site of Launchpad.")
# Feeds are intended to be machine-readable -- XML to be processed by a
# feed reader and then, possibly, displayed. The alternate URL is the
@@ -89,12 +89,12 @@ class IFeed(Interface):
# announcements the alternate location is
# http://launchpad.net/ubuntu/+announcements.
link_alternate = TextLine(
- title=u"Alternate URL for the feed.",
- description=u"The URL to a resource that is the human-readable "
- "equivalent of the feed. So for: "
- "http://feeds.launchpad.net/ubuntu/announcements.atom "
- "the link_alternate would be: "
- "http://launchpad.net/ubuntu/+announcements")
+ title="Alternate URL for the feed.",
+ description="The URL to a resource that is the human-readable "
+ "equivalent of the feed. So for: "
+ "http://feeds.launchpad.net/ubuntu/announcements.atom "
+ "the link_alternate would be: "
+ "http://launchpad.net/ubuntu/+announcements")
# The feed ID is a permanent ID for the feed and it must be unique across
# all time and domains. That sounds harder than it really is. To make
@@ -103,29 +103,29 @@ class IFeed(Interface):
# So an ID for a Jokosher announcment feed would look like:
# tag:launchpad.net,2006-5-26:/jokosher/+announcements.
feed_id = TextLine(
- title=u"ID for the feed.",
- description=u"The <id> for a feed is permanent and globally unique. "
- "It is constructed following RFC 4151.")
+ title="ID for the feed.",
+ description="The <id> for a feed is permanent and globally unique. "
+ "It is constructed following RFC 4151.")
# The feed format is either 'atom' or 'html'.
feed_format = TextLine(
- title=u"Feed format",
- description=u"Requested feed format. "
- "Raises UnsupportedFeed if not supported.")
+ title="Feed format",
+ description="Requested feed format. "
+ "Raises UnsupportedFeed if not supported.")
# The logo URL points to an image identifying the feed and will likely
# vary from one Launchpad application to another. For example the logo
# for bugs is:
# http://launchpad.net/@@/bug.
logo = TextLine(
- title=u"Logo URL",
- description=u"The URL for the feed logo.")
+ title="Logo URL",
+ description="The URL for the feed logo.")
# The icon URL points to an image identifying the feed. For Launchpad
# feeds the icon is http://launchpad.net/@@/launchpad.
icon = TextLine(
- title=u"Icon URL",
- description=u"The URL for the feed icon.")
+ title="Icon URL",
+ description="The URL for the feed icon.")
# The date updated represents the last date any information in the feed
# changed. For instance for feed for Launchpad announcements the date
@@ -133,8 +133,8 @@ class IFeed(Interface):
# the feed changed. Feed readers use the date updated one criteria as to
# whether to fetch the feed information anew.
date_updated = Datetime(
- title=u"Date update",
- description=u"Date of last update for the feed.")
+ title="Date update",
+ description="Date of last update for the feed.")
def getItems():
"""Get the individual items for the feed.
@@ -164,24 +164,24 @@ class IFeedEntry(Interface):
# succinctly identify the entry, e.g. "Microsoft has a majority market
# share."
title = TextLine(
- title=u"Title",
- description=u"The title of the entry")
+ title="Title",
+ description="The title of the entry")
# The link alternate is an URL specifying the location of the
# human-readable equivalent for the entry. For a Ubuntu announcements, an
# example alternate location is
# http://launchpad.net/ubuntu/+announcement/4.
link_alternate = TextLine(
- title=u"Alternate URL for the entry.",
- description=u"The URL to a resource that is the human-readable "
- "equivalent of the entry, e.g. "
- "http://launchpad.net/ubuntu/+announcement/1")
+ title="Alternate URL for the entry.",
+ description="The URL to a resource that is the human-readable "
+ "equivalent of the entry, e.g. "
+ "http://launchpad.net/ubuntu/+announcement/1")
# The actual content for the entry that is to be displayed in the feed
# reader. It may be text or marked up HTML. It should be an
# IFeedTypedData.
content = Attribute(
- u"Content for the entry. Descriptive content for the entry. "
+ "Content for the entry. Descriptive content for the entry. "
"For an announcement, for example, the content "
"is the text of the announcement. It may be "
"plain text or formatted html, as is done for "
@@ -189,22 +189,22 @@ class IFeedEntry(Interface):
# Date the entry was created in the system, without respect to the feed.
date_created = Datetime(
- title=u"Date Created",
- description=u"Date the entry was originally created in Launchpad.")
+ title="Date Created",
+ description="Date the entry was originally created in Launchpad.")
# Date any aspect of the entry was changed.
date_updated = Datetime(
- title=u"Date Updated",
- description=u"Date the entry was last updated.")
+ title="Date Updated",
+ description="Date the entry was last updated.")
# Date the entry became published.
date_published = Datetime(
- title=u"Date Published",
- description=u"Date the entry was published. "
- "For some content this date will be the same "
- "as the creation date. For others, like an "
- "announcement, it will be the date the announcement "
- "became public.")
+ title="Date Published",
+ description="Date the entry was published. "
+ "For some content this date will be the same "
+ "as the creation date. For others, like an "
+ "announcement, it will be the date the announcement "
+ "became public.")
# The primary authors for the entry.
authors = Attribute(
@@ -221,50 +221,50 @@ class IFeedEntry(Interface):
# The logo representing the entry.
# Not used and ignored.
logo = TextLine(
- title=u"Logo URL",
- description=u"The URL for the entry logo."
- "Currently not used.")
+ title="Logo URL",
+ description="The URL for the entry logo."
+ "Currently not used.")
# The icon representing the entry.
# Not used and ignored.
icon = TextLine(
- title=u"Icon URL",
- description=u"The URL for the entry icon."
- "Currently not used.")
+ title="Icon URL",
+ description="The URL for the entry icon."
+ "Currently not used.")
# The description of the program that generated the feed. May include
# versioning information. Useful for debugging purposes only.
# Not used and ignored.
generator = TextLine(
- title=u"The generator of the feed.",
- description=u"A description of the program generating the feed. "
- "Analogous to a browser USER-AGENT string. "
- "Currently not used.")
+ title="The generator of the feed.",
+ description="A description of the program generating the feed. "
+ "Analogous to a browser USER-AGENT string. "
+ "Currently not used.")
class IFeedTypedData(Interface):
"""Interface for typed data in a feed."""
content_types = List(
- title=u"Content types",
- description=u"List of supported content types",
+ title="Content types",
+ description="List of supported content types",
required=True)
content = Text(
- title=u"Content",
- description=u"Data contents",
+ title="Content",
+ description="Data contents",
required=True)
content_type = Text(
- title=u"Content type",
- description=u"The actual content type for this object. Must be"
- "one of those listed in content_types.",
+ title="Content type",
+ description="The actual content type for this object. Must be"
+ "one of those listed in content_types.",
required=False)
root_url = Text(
- title=u"Root URL",
- description=u"URL for the root of the site that produced the content, "
- "i.e. 'http://code.launchpad.net'",
+ title="Root URL",
+ description="URL for the root of the site that produced the content, "
+ "i.e. 'http://code.launchpad.net'",
required=False)
@@ -272,16 +272,16 @@ class IFeedPerson(Interface):
"""Interface for a person in a feed."""
name = TextLine(
- title=u"Name",
- description=u"The person's name.",
+ title="Name",
+ description="The person's name.",
required=True)
email = TextLine(
- title=u"Email",
- description=u"The person's email address.",
+ title="Email",
+ description="The person's email address.",
required=False)
uri = URI(
- title=u"URI",
- description=u"The URI for the person.",
+ title="URI",
+ description="The URI for the person.",
required=True)
diff --git a/lib/lp/services/feeds/tests/helper.py b/lib/lp/services/feeds/tests/helper.py
index 4170399..7f7f8e8 100644
--- a/lib/lp/services/feeds/tests/helper.py
+++ b/lib/lp/services/feeds/tests/helper.py
@@ -30,7 +30,7 @@ class IThing(Interface):
@implementer(IThing)
-class Thing(object):
+class Thing:
def __init__(self, value):
self.value = value
diff --git a/lib/lp/services/fields/__init__.py b/lib/lp/services/fields/__init__.py
index 7d5ff4e..684ec36 100644
--- a/lib/lp/services/fields/__init__.py
+++ b/lib/lp/services/fields/__init__.py
@@ -63,7 +63,6 @@ from lazr.uri import (
InvalidURIError,
URI,
)
-import six
from zope.component import getUtility
from zope.interface import (
implementer,
@@ -225,7 +224,7 @@ class StrippedTextLine(TextLine):
"""Strip the value and pass up."""
if value is not None:
value = value.strip()
- super(StrippedTextLine, self).set(object, value)
+ super().set(object, value)
@implementer(INoneableTextLine)
@@ -245,7 +244,7 @@ class StrippableText(Text):
"""A text that can be configured to strip when setting."""
def __init__(self, strip_text=False, trailing_only=False, **kwargs):
- super(StrippableText, self).__init__(**kwargs)
+ super().__init__(**kwargs)
self.strip_text = strip_text
self.trailing_only = trailing_only
@@ -261,12 +260,12 @@ class StrippableText(Text):
def set(self, object, value):
"""Strip the value and pass up."""
value = self.normalize(value)
- super(StrippableText, self).set(object, value)
+ super().set(object, value)
def validate(self, value):
"""See `IField`."""
value = self.normalize(value)
- return super(StrippableText, self).validate(value)
+ return super().validate(value)
# Summary
@@ -310,7 +309,7 @@ class FormattableDate(Date):
error_msg = ("Date could not be formatted. Provide a date formatted "
"like YYYY-MM-DD format. The year must be after 1900.")
- super(FormattableDate, self)._validate(value)
+ super()._validate(value)
# The only thing of interest here is whether or the input can be
# formatted properly, not whether it makes sense otherwise.
# As a minimal sanity check, just raise an error if it fails.
@@ -338,7 +337,7 @@ class BugField(Reference):
def __init__(self, *args, **kwargs):
"""The schema will always be `IBug`."""
- super(BugField, self).__init__(Interface, *args, **kwargs)
+ super().__init__(Interface, *args, **kwargs)
def _get_schema(self):
"""Get the schema here to avoid circular imports."""
@@ -401,9 +400,9 @@ class SearchTag(Tag):
if value in ('*', '-*'):
return True
elif value.startswith('-'):
- return super(SearchTag, self).constraint(value[1:])
+ return super().constraint(value[1:])
else:
- return super(SearchTag, self).constraint(value)
+ return super().constraint(value)
class UniqueField(TextLine):
@@ -447,7 +446,7 @@ class UniqueField(TextLine):
object of this same context. The 'input' should be valid as per
TextLine.
"""
- super(UniqueField, self)._validate(input)
+ super()._validate(input)
assert self._content_iface is not None
if self.unchanged(input):
@@ -493,7 +492,7 @@ class BlacklistableContentNameField(ContentNameField):
def _validate(self, input):
"""Check that the given name is valid, unique and not blacklisted."""
- super(BlacklistableContentNameField, self)._validate(input)
+ super()._validate(input)
# Although this check is performed in UniqueField._validate(), we need
# to do it here again to avoid checking whether or not the name is
@@ -594,7 +593,7 @@ class URIField(TextLine):
def __init__(self, allowed_schemes=(), allow_userinfo=True,
allow_port=True, allow_query=True, allow_fragment=True,
trailing_slash=None, **kwargs):
- super(URIField, self).__init__(**kwargs)
+ super().__init__(**kwargs)
self.allowed_schemes = set(allowed_schemes)
self.allow_userinfo = allow_userinfo
self.allow_port = allow_port
@@ -605,7 +604,7 @@ class URIField(TextLine):
def set(self, object, value):
"""Canonicalize a URL and set it as a field value."""
value = self.normalize(value)
- super(URIField, self).set(object, value)
+ super().set(object, value)
def normalize(self, input):
"""See `IURIField`."""
@@ -624,7 +623,7 @@ class URIField(TextLine):
uri = uri.ensureSlash()
else:
uri = uri.ensureNoSlash()
- input = six.text_type(uri)
+ input = str(uri)
return input
def _validate(self, value):
@@ -654,7 +653,7 @@ class URIField(TextLine):
raise LaunchpadValidationError(
'URIs with fragment identifiers are not allowed.')
- super(URIField, self)._validate(value)
+ super()._validate(value)
class FieldNotBoundError(Exception):
@@ -709,7 +708,7 @@ class BaseImageUpload(Bytes):
This image exceeds the maximum allowed size in bytes.""")))
try:
pil_image = PIL.Image.open(io.BytesIO(image))
- except (IOError, ValueError):
+ except (OSError, ValueError):
raise LaunchpadValidationError(_(dedent("""
The file uploaded was not recognized as an image; please
check it and retry.""")))
@@ -737,7 +736,7 @@ class BaseImageUpload(Bytes):
content = value.read()
else:
content = value
- super(BaseImageUpload, self)._validate(content)
+ super()._validate(content)
self._valid_image(content)
def set(self, object, value):
diff --git a/lib/lp/services/fields/tests/test_fields.py b/lib/lp/services/fields/tests/test_fields.py
index 99fd864..6dd3aba 100644
--- a/lib/lp/services/fields/tests/test_fields.py
+++ b/lib/lp/services/fields/tests/test_fields.py
@@ -99,13 +99,13 @@ class TestStrippableText(TestCase):
# The minimum length constraint tests the stripped string.
field = StrippableText(
__name__='test', strip_text=True, min_length=1)
- self.assertRaises(TooShort, field.validate, u' ')
+ self.assertRaises(TooShort, field.validate, ' ')
def test_validate_max_contraints(self):
# The minimum length constraint tests the stripped string.
field = StrippableText(
__name__='test', strip_text=True, max_length=2)
- self.assertEqual(None, field.validate(u' a '))
+ self.assertEqual(None, field.validate(' a '))
class TestWorkItemsTextValidation(TestCaseWithFactory):
@@ -113,7 +113,7 @@ class TestWorkItemsTextValidation(TestCaseWithFactory):
layer = DatabaseFunctionalLayer
def setUp(self):
- super(TestWorkItemsTextValidation, self).setUp()
+ super().setUp()
self.field = WorkItemsText(__name__='test')
def test_parseandvalidate(self):
@@ -198,7 +198,7 @@ class TestWorkItemsTextValidation(TestCaseWithFactory):
class TestWorkItemsText(TestCase):
def setUp(self):
- super(TestWorkItemsText, self).setUp()
+ super().setUp()
self.field = WorkItemsText(__name__='test')
def test_validate_raises_LaunchpadValidationError(self):
@@ -431,10 +431,10 @@ class TestBlacklistableContentNameField(TestCaseWithFactory):
layer = DatabaseFunctionalLayer
def setUp(self):
- super(TestBlacklistableContentNameField, self).setUp()
+ super().setUp()
name_blacklist_set = getUtility(INameBlacklistSet)
self.team = self.factory.makeTeam()
- admin_exp = name_blacklist_set.create(u'fnord', admin=self.team)
+ admin_exp = name_blacklist_set.create('fnord', admin=self.team)
IStore(admin_exp).flush()
def makeTestField(self):
@@ -455,7 +455,7 @@ class TestBlacklistableContentNameField(TestCaseWithFactory):
# Anonymous users, processes, cannot create a name that matches
# a blacklisted name.
field = self.makeTestField()
- date_value = u'fnord'
+ date_value = 'fnord'
self.assertRaises(
LaunchpadValidationError, field.validate, date_value)
@@ -463,7 +463,7 @@ class TestBlacklistableContentNameField(TestCaseWithFactory):
# Users who do not adminster a blacklisted name cannot create
# a matching name.
field = self.makeTestField()
- date_value = u'fnord'
+ date_value = 'fnord'
login_person(self.factory.makePerson())
self.assertRaises(
LaunchpadValidationError, field.validate, date_value)
@@ -472,7 +472,7 @@ class TestBlacklistableContentNameField(TestCaseWithFactory):
# Users in the team that adminsters a blacklisted name may create
# matching names.
field = self.makeTestField()
- date_value = u'fnord'
+ date_value = 'fnord'
login_person(self.team.teamowner)
self.assertEqual(None, field.validate(date_value))
diff --git a/lib/lp/services/fields/tests/test_tag_fields.py b/lib/lp/services/fields/tests/test_tag_fields.py
index d3bdf8e..2ca5a6d 100644
--- a/lib/lp/services/fields/tests/test_tag_fields.py
+++ b/lib/lp/services/fields/tests/test_tag_fields.py
@@ -22,19 +22,19 @@ class TestTag(TestCase):
# Tag allows names all in lowercase, starting with any letter
# of the English alphabet, followed by 1 or more letters,
# numbers or minuses.
- self.assertIs(None, self.field.validate(u'fred'))
- self.assertIs(None, self.field.validate(u'one-two'))
- self.assertIs(None, self.field.validate(u'one-2'))
- self.assertIs(None, self.field.validate(u'one-2-3---5-'))
+ self.assertIs(None, self.field.validate('fred'))
+ self.assertIs(None, self.field.validate('one-two'))
+ self.assertIs(None, self.field.validate('one-2'))
+ self.assertIs(None, self.field.validate('one-2-3---5-'))
def test_too_short(self):
# Tag rejects tags that are less than 2 characters long.
self.assertRaises(
ConstraintNotSatisfied,
- self.field.validate, u'')
+ self.field.validate, '')
self.assertRaises(
ConstraintNotSatisfied,
- self.field.validate, u'x')
+ self.field.validate, 'x')
def test_invalid_characters(self):
# Tag rejects characters outside of the range [a-z0-9-].
@@ -42,20 +42,20 @@ class TestTag(TestCase):
# test_negated_search_form.
self.assertRaises(
ConstraintNotSatisfied,
- self.field.validate, u'char^not^allowed')
+ self.field.validate, 'char^not^allowed')
self.assertRaises(
ConstraintNotSatisfied,
- self.field.validate, u'no whitespace')
+ self.field.validate, 'no whitespace')
self.assertRaises(
ConstraintNotSatisfied,
- self.field.validate, u'really\no-whitespace')
+ self.field.validate, 'really\no-whitespace')
def test_negated_search_form(self):
# Tag rejects tags beginning with minuses. This form is
# reserved to mean "not <tag>".
self.assertRaises(
ConstraintNotSatisfied,
- self.field.validate, u'-fred')
+ self.field.validate, '-fred')
def test_wildcard(self):
# Tag rejects a solitary asterisk, or an asterisk preceded by
@@ -65,10 +65,10 @@ class TestTag(TestCase):
# any tag".
self.assertRaises(
ConstraintNotSatisfied,
- self.field.validate, u'*')
+ self.field.validate, '*')
self.assertRaises(
ConstraintNotSatisfied,
- self.field.validate, u'-*')
+ self.field.validate, '-*')
class TestSearchTag(TestTag):
@@ -78,17 +78,17 @@ class TestSearchTag(TestTag):
def test_negated_search_form(self):
# SearchTag allows tags beginning with minuses. This form is
# reserved to mean "not <tag>".
- self.assertIs(None, self.field.validate(u'-fred'))
+ self.assertIs(None, self.field.validate('-fred'))
def test_wildcard(self):
# SearchTag allows a solitary asterisk, or an asterisk
# preceded by a minus. This means "any tag" or "not any
# tag".
- self.assertIs(None, self.field.validate(u'*'))
- self.assertIs(None, self.field.validate(u'-*'))
+ self.assertIs(None, self.field.validate('*'))
+ self.assertIs(None, self.field.validate('-*'))
def test_wildcard_elsewhere(self):
# Asterisks are not allowed to appear anywhere else in a tag.
self.assertRaises(
ConstraintNotSatisfied,
- self.field.validate, u'sn*t-allowed')
+ self.field.validate, 'sn*t-allowed')
diff --git a/lib/lp/services/geoip/model.py b/lib/lp/services/geoip/model.py
index 53260aa..ab3f3c0 100644
--- a/lib/lp/services/geoip/model.py
+++ b/lib/lp/services/geoip/model.py
@@ -77,7 +77,7 @@ class GeoIP:
@implementer(IRequestLocalLanguages)
-class RequestLocalLanguages(object):
+class RequestLocalLanguages:
def __init__(self, request):
self.request = request
@@ -100,7 +100,7 @@ class RequestLocalLanguages(object):
@implementer(IRequestPreferredLanguages)
-class RequestPreferredLanguages(object):
+class RequestPreferredLanguages:
def __init__(self, request):
self.request = request
diff --git a/lib/lp/services/geoip/tests/test_request_country.py b/lib/lp/services/geoip/tests/test_request_country.py
index 409f861..a72367b 100644
--- a/lib/lp/services/geoip/tests/test_request_country.py
+++ b/lib/lp/services/geoip/tests/test_request_country.py
@@ -29,21 +29,21 @@ class RequestCountryTestCase(unittest.TestCase):
def testRemoteAddr(self):
country = request_country({'REMOTE_ADDR': self.lp})
- self.assertEqual(country.name, u'United Kingdom')
+ self.assertEqual(country.name, 'United Kingdom')
def testXForwardedFor(self):
country = request_country({
'HTTP_X_FORWARDED_FOR': self.lp,
'REMOTE_ADDR': '1.2.3.4',
})
- self.assertEqual(country.name, u'United Kingdom')
+ self.assertEqual(country.name, 'United Kingdom')
def testNestedProxies(self):
country = request_country({
'HTTP_X_FORWARDED_FOR':
'localhost, 127.0.0.1, %s, 1,1,1,1' % self.lp,
})
- self.assertEqual(country.name, u'United Kingdom')
+ self.assertEqual(country.name, 'United Kingdom')
def testMissingHeaders(self):
country = request_country({})
diff --git a/lib/lp/services/gpg/handler.py b/lib/lp/services/gpg/handler.py
index 1f04851..a56cc51 100644
--- a/lib/lp/services/gpg/handler.py
+++ b/lib/lp/services/gpg/handler.py
@@ -15,7 +15,6 @@ import http.client
from io import BytesIO
import os
import shutil
-import socket
import subprocess
import sys
import tempfile
@@ -449,7 +448,7 @@ class GPGHandler:
# XXX michaeln 2010-05-07 bug=576405
# Currently gpgme.Context().keylist fails if passed a unicode
# string even though that's what is returned for fingerprints.
- if isinstance(filter, six.text_type):
+ if isinstance(filter, str):
filter = filter.encode('utf-8')
with gpgme_timeline(
@@ -499,7 +498,7 @@ class GPGHandler:
try:
conn.request("POST", "/pks/add", params, headers)
- except socket.error as err:
+ except OSError as err:
raise GPGUploadFailure(
'Could not reach keyserver at http://%s %s' % (
keyserver_http_url, str(err)))
@@ -581,7 +580,7 @@ class GPGHandler:
@implementer(IPymeSignature)
-class PymeSignature(object):
+class PymeSignature:
"""See IPymeSignature."""
def __init__(self, fingerprint=None, plain_data=None, timestamp=None):
diff --git a/lib/lp/services/gpg/interfaces.py b/lib/lp/services/gpg/interfaces.py
index 90f780e..ee105ca 100644
--- a/lib/lp/services/gpg/interfaces.py
+++ b/lib/lp/services/gpg/interfaces.py
@@ -140,7 +140,7 @@ class GPGKeyNotFoundError(Exception):
if message is None:
message = (
"No GPG key found with the given content: %s" % (fingerprint, ))
- super(GPGKeyNotFoundError, self).__init__(message)
+ super().__init__(message)
@error_status(http.client.INTERNAL_SERVER_ERROR)
@@ -154,8 +154,7 @@ class GPGKeyTemporarilyNotFoundError(GPGKeyNotFoundError):
message = (
"GPG key %s not found due to a server or network failure."
% fingerprint)
- super(GPGKeyTemporarilyNotFoundError, self).__init__(
- fingerprint, message)
+ super().__init__(fingerprint, message)
@error_status(http.client.NOT_FOUND)
@@ -167,8 +166,7 @@ class GPGKeyDoesNotExistOnServer(GPGKeyNotFoundError):
def __init__(self, fingerprint):
message = (
"GPG key %s does not exist on the keyserver." % fingerprint)
- super(GPGKeyDoesNotExistOnServer, self).__init__(
- fingerprint, message)
+ super().__init__(fingerprint, message)
class GPGKeyRevoked(Exception):
@@ -176,8 +174,7 @@ class GPGKeyRevoked(Exception):
def __init__(self, key):
self.key = key
- super(GPGKeyRevoked, self).__init__(
- "%s has been publicly revoked" % (key.fingerprint, ))
+ super().__init__("%s has been publicly revoked" % (key.fingerprint, ))
class GPGKeyExpired(Exception):
@@ -185,8 +182,7 @@ class GPGKeyExpired(Exception):
def __init__(self, key):
self.key = key
- super(GPGKeyExpired, self).__init__(
- "%s has expired" % (key.fingerprint, ))
+ super().__init__("%s has expired" % (key.fingerprint, ))
class GPGKeyMismatchOnServer(Exception):
@@ -200,7 +196,7 @@ class GPGKeyMismatchOnServer(Exception):
message = (
"The keyserver returned the wrong key: expected %s, got %s." %
(expected_fingerprint, keyserver_fingerprint))
- super(GPGKeyMismatchOnServer, self).__init__(message)
+ super().__init__(message)
class SecretGPGKeyImportDetected(Exception):
diff --git a/lib/lp/services/gpg/tests/test_gpghandler.py b/lib/lp/services/gpg/tests/test_gpghandler.py
index 5b023ba..6dba52c 100644
--- a/lib/lp/services/gpg/tests/test_gpghandler.py
+++ b/lib/lp/services/gpg/tests/test_gpghandler.py
@@ -97,7 +97,7 @@ class TestGPGHandler(TestCase):
def setUp(self):
"""Get a gpghandler and login"""
- super(TestGPGHandler, self).setUp()
+ super().setUp()
login(ANONYMOUS)
self.gpg_handler = getUtility(IGPGHandler)
self.gpg_handler.resetLocalState()
@@ -108,7 +108,7 @@ class TestGPGHandler(TestCase):
# This should be a zope test cleanup thing per SteveA.
self.gpg_handler.resetLocalState()
logout()
- super(TestGPGHandler, self).tearDown()
+ super().tearDown()
def populateKeyring(self):
for email in iter_test_key_emails():
@@ -188,7 +188,7 @@ class TestGPGHandler(TestCase):
"""
self.populateKeyring()
- target_fpr = u'340CA3BB270E2716C9EE0B768E7EB7086C64A8C5'
+ target_fpr = '340CA3BB270E2716C9EE0B768E7EB7086C64A8C5'
# Finding a key by its unicode fingerprint.
filtered_keys = self.gpg_handler.localKeys(target_fpr)
@@ -197,7 +197,7 @@ class TestGPGHandler(TestCase):
def test_non_ascii_filter(self):
"""localKeys should not error if passed non-ascii unicode strings."""
- filtered_keys = self.gpg_handler.localKeys(u'non-ascii \u8463')
+ filtered_keys = self.gpg_handler.localKeys('non-ascii \u8463')
self.assertRaises(StopIteration, next, filtered_keys)
def testTestkeyrings(self):
@@ -377,7 +377,7 @@ class TestGPGHandler(TestCase):
# export_file.write(new_key.export())
self.useFixture(FakeGenerateKey("ppa-sample@xxxxxxxxxxxxxxxxx"))
new_key = self.gpg_handler.generateKey(
- u"Launchpad PPA for Celso \xe1\xe9\xed\xf3\xfa Providelo",
+ "Launchpad PPA for Celso \xe1\xe9\xed\xf3\xfa Providelo",
logger=logger)
# generateKey currently only generates passwordless sign-only keys,
# i.e. they can sign content but cannot encrypt. The generated key
@@ -393,10 +393,10 @@ class TestGPGHandler(TestCase):
uids=MatchesListwise([
MatchesStructure.byEquality(
name=(
- u"Launchpad PPA for Celso "
- u"\xe1\xe9\xed\xf3\xfa Providelo"),
- comment=u"",
- email=u""),
+ "Launchpad PPA for Celso "
+ "\xe1\xe9\xed\xf3\xfa Providelo"),
+ comment="",
+ email=""),
])))
# The public key is also available.
pub_key = self.gpg_handler.retrieveKey(new_key.fingerprint)
@@ -411,10 +411,10 @@ class TestGPGHandler(TestCase):
uids=MatchesListwise([
MatchesStructure.byEquality(
name=(
- u"Launchpad PPA for Celso "
- u"\xe1\xe9\xed\xf3\xfa Providelo"),
- comment=u"",
- email=u""),
+ "Launchpad PPA for Celso "
+ "\xe1\xe9\xed\xf3\xfa Providelo"),
+ comment="",
+ email=""),
])))
return new_key
@@ -441,8 +441,8 @@ class TestGPGHandler(TestCase):
new_key = self.assertGeneratesKey(logger=logger)
new_public_key = self.gpg_handler.retrieveKey(new_key.fingerprint)
self.assertEqual(
- u"INFO Injecting key_type OpenPGP 'Launchpad PPA for Celso "
- u"\xe1\xe9\xed\xf3\xfa Providelo' into signing service\n",
+ "INFO Injecting key_type OpenPGP 'Launchpad PPA for Celso "
+ "\xe1\xe9\xed\xf3\xfa Providelo' into signing service\n",
logger.getLogBuffer())
self.assertEqual(1, signing_service_client.inject.call_count)
self.assertThat(
@@ -452,8 +452,8 @@ class TestGPGHandler(TestCase):
Equals(new_key.export()),
Equals(new_public_key.export()),
Equals(
- u"Launchpad PPA for Celso "
- u"\xe1\xe9\xed\xf3\xfa Providelo"),
+ "Launchpad PPA for Celso "
+ "\xe1\xe9\xed\xf3\xfa Providelo"),
Equals(now.replace(tzinfo=pytz.UTC)),
]))
@@ -470,7 +470,7 @@ class TestGPGHandler(TestCase):
self.assertRaisesWithContent(
ValueError, "boom",
self.gpg_handler.generateKey,
- u"Launchpad PPA for Celso \xe1\xe9\xed\xf3\xfa Providelo")
+ "Launchpad PPA for Celso \xe1\xe9\xed\xf3\xfa Providelo")
self.assertEqual(1, signing_service_client.inject.call_count)
self.assertEqual([], list(self.gpg_handler.localKeys()))
diff --git a/lib/lp/services/httpproxy/connect_tunneling.py b/lib/lp/services/httpproxy/connect_tunneling.py
index 39a7786..f42468e 100644
--- a/lib/lp/services/httpproxy/connect_tunneling.py
+++ b/lib/lp/services/httpproxy/connect_tunneling.py
@@ -32,8 +32,7 @@ class TunnelingTCP4ClientEndpoint(TCP4ClientEndpoint):
def __init__(self, reactor, host, port, proxyConf, contextFactory,
timeout=30, bindAddress=None):
proxyHost, proxyPort, self._proxyAuthHeader = proxyConf
- super(TunnelingTCP4ClientEndpoint, self).__init__(reactor, proxyHost,
- proxyPort, timeout, bindAddress)
+ super().__init__(reactor, proxyHost, proxyPort, timeout, bindAddress)
self._tunneledHost = host
self._tunneledPort = port
self._contextFactory = contextFactory
@@ -74,8 +73,7 @@ class TunnelingTCP4ClientEndpoint(TCP4ClientEndpoint):
def connect(self, protocolFactory):
self._protocolFactory = protocolFactory
- self._connectDeferred = super(
- TunnelingTCP4ClientEndpoint, self).connect(protocolFactory)
+ self._connectDeferred = super().connect(protocolFactory)
self._connectDeferred.addCallback(self.requestTunnel)
self._connectDeferred.addErrback(self.connectFailed)
return self._tunnelReadyDeferred
@@ -88,7 +86,7 @@ class TunnelingAgent(Agent):
def __init__(self, reactor, proxyConf, contextFactory=None,
connectTimeout=None, bindAddress=None, pool=None):
- super(TunnelingAgent, self).__init__(reactor, contextFactory,
+ super().__init__(reactor, contextFactory,
connectTimeout, bindAddress, pool)
self._contextFactory = contextFactory
self._connectTimeout = connectTimeout
diff --git a/lib/lp/services/identity/interfaces/account.py b/lib/lp/services/identity/interfaces/account.py
index 63034c5..d7ccb53 100644
--- a/lib/lp/services/identity/interfaces/account.py
+++ b/lib/lp/services/identity/interfaces/account.py
@@ -295,7 +295,7 @@ class AccountStatusChoice(Choice):
raise AccountStatusError(
"The status cannot change from %s to %s" %
(removeSecurityProxy(self.context).status, value))
- super(AccountStatusChoice, self)._validate(value)
+ super()._validate(value)
class IAccountPublic(Interface):
diff --git a/lib/lp/services/identity/model/account.py b/lib/lp/services/identity/model/account.py
index beb0921..e35e976 100644
--- a/lib/lp/services/identity/model/account.py
+++ b/lib/lp/services/identity/model/account.py
@@ -10,7 +10,6 @@ __all__ = [
import datetime
-import six
from storm.locals import ReferenceSet
from zope.interface import implementer
@@ -103,7 +102,7 @@ class AccountSet:
# Create an OpenIdIdentifier record if requested.
if openid_identifier is not None:
- assert isinstance(openid_identifier, six.text_type)
+ assert isinstance(openid_identifier, str)
identifier = OpenIdIdentifier()
identifier.account = account
identifier.identifier = openid_identifier
diff --git a/lib/lp/services/identity/model/emailaddress.py b/lib/lp/services/identity/model/emailaddress.py
index 887dce7..e84ca9c 100644
--- a/lib/lp/services/identity/model/emailaddress.py
+++ b/lib/lp/services/identity/model/emailaddress.py
@@ -87,7 +87,7 @@ class EmailAddress(SQLBase, HasOwnerMixin):
for subscription in store.find(
MailingListSubscription, email_address=self):
store.remove(subscription)
- super(EmailAddress, self).destroySelf()
+ super().destroySelf()
@property
def rdf_sha1(self):
diff --git a/lib/lp/services/identity/tests/test_account.py b/lib/lp/services/identity/tests/test_account.py
index 36cac06..5825e53 100644
--- a/lib/lp/services/identity/tests/test_account.py
+++ b/lib/lp/services/identity/tests/test_account.py
@@ -23,14 +23,14 @@ class TestAccount(TestCaseWithFactory):
def test_account_repr_ansii(self):
# Verify that ANSI displayname is ascii safe.
- distro = self.factory.makeAccount(u'\xdc-account')
+ distro = self.factory.makeAccount('\xdc-account')
ignore, displayname, status = repr(distro).rsplit(' ', 2)
self.assertEqual("'\\xdc-account'", displayname)
self.assertEqual('(Active)>', status)
def test_account_repr_unicode(self):
# Verify that Unicode displayname is ascii safe.
- distro = self.factory.makeAccount(u'\u0170-account')
+ distro = self.factory.makeAccount('\u0170-account')
ignore, displayname, status = repr(distro).rsplit(' ', 2)
self.assertEqual("'\\u0170-account'", displayname)
diff --git a/lib/lp/services/inlinehelp/zcml.py b/lib/lp/services/inlinehelp/zcml.py
index 7642aa5..3f8a852 100644
--- a/lib/lp/services/inlinehelp/zcml.py
+++ b/lib/lp/services/inlinehelp/zcml.py
@@ -25,10 +25,10 @@ from lp.services.webapp.interfaces import ILaunchpadApplication
class IHelpFolderDirective(Interface):
"""Directive to register an help folder."""
folder = Path(
- title=u'The path to the help folder.',
+ title='The path to the help folder.',
required=True)
name = TextLine(
- title=u'The name to register the help folder under.',
+ title='The name to register the help folder under.',
required=True)
diff --git a/lib/lp/services/job/celeryjob.py b/lib/lp/services/job/celeryjob.py
index c872bf8..fcc1c5f 100644
--- a/lib/lp/services/job/celeryjob.py
+++ b/lib/lp/services/job/celeryjob.py
@@ -67,7 +67,7 @@ class CeleryRunJob(RunJob):
"""
self.dbuser = dbuser
task_init(dbuser)
- super(CeleryRunJob, self).run(job_id)
+ super().run(job_id)
def reQueue(self, job_id, fallback_queue):
self.apply_async(args=(job_id, self.dbuser), queue=fallback_queue)
@@ -118,7 +118,7 @@ class PrefixedTask(Task):
"""
if task_id is None and self.task_id_prefix is not None:
task_id = '%s_%s' % (self.task_id_prefix, uuid4())
- return super(PrefixedTask, self).apply_async(
+ return super().apply_async(
args=args, kwargs=kwargs, task_id=task_id, producer=producer,
link=link, link_error=link_error, shadow=shadow, **options)
diff --git a/lib/lp/services/job/runner.py b/lib/lp/services/job/runner.py
index 2823909..9410069 100644
--- a/lib/lp/services/job/runner.py
+++ b/lib/lp/services/job/runner.py
@@ -359,7 +359,7 @@ class BaseJobRunner(LazrJobRunner):
self.error_utility = errorlog.globalErrorUtility
else:
self.error_utility = error_utility
- super(BaseJobRunner, self).__init__(
+ super().__init__(
logger, oops_config=self.error_utility._oops_config,
oopsMessage=self.error_utility.oopsMessage)
@@ -381,7 +381,7 @@ class BaseJobRunner(LazrJobRunner):
if job.lease_expires is not None:
set_default_timeout_function(lambda: job.getTimeout())
try:
- super(BaseJobRunner, self).runJob(IRunnableJob(job), fallback)
+ super().runJob(IRunnableJob(job), fallback)
finally:
set_default_timeout_function(original_timeout_function)
@@ -389,8 +389,7 @@ class BaseJobRunner(LazrJobRunner):
set_request_started(
enable_timeout=False, detail_filter=job.timeline_detail_filter)
try:
- return super(BaseJobRunner, self).runJobHandleError(
- job, fallback=fallback)
+ return super().runJobHandleError(job, fallback=fallback)
finally:
clear_request_started()
@@ -575,7 +574,7 @@ class QuietAMPConnector(main.AMPConnector):
# than ERROR. Launchpad generates OOPSes for anything at
# WARNING or above; we still want to do that if a child process
# exits fatally, but not if it just writes something to stderr.
- main.log.info(u'FROM {n}: {l}', n=self.name, l=line)
+ main.log.info('FROM {n}: {l}', n=self.name, l=line)
class TwistedJobRunner(BaseJobRunner):
@@ -589,7 +588,7 @@ class TwistedJobRunner(BaseJobRunner):
env['LPCONFIG'] = os.environ['LPCONFIG']
starter = VirtualEnvProcessStarter(env=env)
starter.connectorFactory = QuietAMPConnector
- super(TwistedJobRunner, self).__init__(logger, error_utility)
+ super().__init__(logger, error_utility)
self.job_source = job_source
self.import_name = '%s.%s' % (
removeSecurityProxy(job_source).__module__, job_source.__name__)
diff --git a/lib/lp/services/job/scripts/process_job_source.py b/lib/lp/services/job/scripts/process_job_source.py
index a7282bf..79c3686 100644
--- a/lib/lp/services/job/scripts/process_job_source.py
+++ b/lib/lp/services/job/scripts/process_job_source.py
@@ -29,7 +29,7 @@ class ProcessSingleJobSource(LaunchpadCronScript):
"""
def __init__(self, *args, **kwargs):
- super(ProcessSingleJobSource, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
# The fromlist argument is necessary so that __import__()
# returns the bottom submodule instead of the top one.
module = __import__(self.config_section.module,
@@ -76,7 +76,7 @@ class ProcessSingleJobSource(LaunchpadCronScript):
self.parser.print_help()
sys.exit(1)
self.job_source_name = self.args[0]
- super(ProcessSingleJobSource, self).handle_options()
+ super().handle_options()
def job_counts(self, jobs):
"""Return a list of tuples containing the job name and counts."""
@@ -99,7 +99,7 @@ class ProcessSingleJobSource(LaunchpadCronScript):
references across calls to this method.
"""
disconnect_stores()
- super(ProcessSingleJobSource, self)._init_db(isolation)
+ super()._init_db(isolation)
def main(self):
errorlog.globalErrorUtility.configure(self.config_name)
@@ -138,7 +138,7 @@ class ProcessJobSource(LaunchpadScript):
self.parser.print_help()
sys.exit(1)
self.job_source_names = self.args
- super(ProcessJobSource, self).handle_options()
+ super().handle_options()
def main(self):
if self.options.verbose:
diff --git a/lib/lp/services/job/scripts/tests/test_process_job_source.py b/lib/lp/services/job/scripts/tests/test_process_job_source.py
index f9fd3fc..19fcb40 100644
--- a/lib/lp/services/job/scripts/tests/test_process_job_source.py
+++ b/lib/lp/services/job/scripts/tests/test_process_job_source.py
@@ -49,7 +49,7 @@ class ProcessJobSourceTest(TestCaseWithFactory):
script = 'cronscripts/process-job-source.py'
def tearDown(self):
- super(ProcessJobSourceTest, self).tearDown()
+ super().tearDown()
self.layer.force_dirty_database()
def test_missing_argument(self):
@@ -128,7 +128,7 @@ class ProcessJobSourceGroupsTest(TestCaseWithFactory):
return sorted(set(sources))
def tearDown(self):
- super(ProcessJobSourceGroupsTest, self).tearDown()
+ super().tearDown()
self.layer.force_dirty_database()
def test_missing_argument(self):
diff --git a/lib/lp/services/job/tests/test_celeryjob.py b/lib/lp/services/job/tests/test_celeryjob.py
index 9757d36..9d76ef5 100644
--- a/lib/lp/services/job/tests/test_celeryjob.py
+++ b/lib/lp/services/job/tests/test_celeryjob.py
@@ -27,7 +27,7 @@ class TestRunMissingJobs(TestCaseWithFactory):
layer = ZopelessAppServerLayer
def setUp(self):
- super(TestRunMissingJobs, self).setUp()
+ super().setUp()
from lp.services.job.celeryjob import (
find_missing_ready,
run_missing_ready,
diff --git a/lib/lp/services/job/tests/test_runner.py b/lib/lp/services/job/tests/test_runner.py
index d14194c..34cee43 100644
--- a/lib/lp/services/job/tests/test_runner.py
+++ b/lib/lp/services/job/tests/test_runner.py
@@ -165,7 +165,7 @@ class TestJobRunner(StatsMixin, TestCaseWithFactory):
layer = LaunchpadZopelessLayer
def setUp(self):
- super(TestJobRunner, self).setUp()
+ super().setUp()
self.setUpStats()
def makeTwoJobs(self):
@@ -259,7 +259,7 @@ class TestJobRunner(StatsMixin, TestCaseWithFactory):
class DBAlterJob(NullJob):
def __init__(self):
- super(DBAlterJob, self).__init__('')
+ super().__init__('')
def run(self):
self.job.log = 'hello'
@@ -437,7 +437,7 @@ class TestJobRunner(StatsMixin, TestCaseWithFactory):
"""runJob sets a default timeout function for urlfetch."""
class RecordDefaultTimeoutJob(NullJob):
def __init__(self):
- super(RecordDefaultTimeoutJob, self).__init__("")
+ super().__init__("")
def run(self):
self.default_timeout = get_default_timeout_function()()
@@ -641,7 +641,7 @@ class TestTwistedJobRunner(TestCaseWithFactory):
run_tests_with = RunIsolatedTest
def setUp(self):
- super(TestTwistedJobRunner, self).setUp()
+ super().setUp()
# The test relies on _pythonpath being importable. Thus we need to add
# a directory that contains _pythonpath to the sys.path. We can rely
# on the root directory of the checkout containing _pythonpath.
diff --git a/lib/lp/services/librarian/client.py b/lib/lp/services/librarian/client.py
index 17d40d9..a011bc3 100644
--- a/lib/lp/services/librarian/client.py
+++ b/lib/lp/services/librarian/client.py
@@ -103,7 +103,7 @@ class FileUploadClient:
# Register epoll for the socket.
self.state.s_poll = select.epoll()
self.state.s_poll.register(self.state.s.fileno(), select.EPOLLIN)
- except socket.error as x:
+ except OSError as x:
raise UploadFailed(
'[%s:%s]: %s' % (self.upload_host, self.upload_port, x))
@@ -247,7 +247,7 @@ class FileUploadClient:
Store.of(content).flush()
- assert isinstance(aliasID, six.integer_types), \
+ assert isinstance(aliasID, int), \
"aliasID %r not an integer" % (aliasID, )
return aliasID
finally:
diff --git a/lib/lp/services/librarian/model.py b/lib/lp/services/librarian/model.py
index 2c513d3..10a387e 100644
--- a/lib/lp/services/librarian/model.py
+++ b/lib/lp/services/librarian/model.py
@@ -227,7 +227,7 @@ class LibraryFileAlias(SQLBase):
def __storm_invalidated__(self):
"""Make sure that the file is closed across transaction boundary."""
- super(LibraryFileAlias, self).__storm_invalidated__()
+ super().__storm_invalidated__()
self.close()
@@ -247,7 +247,7 @@ class LibraryFileAliasWithParent:
@implementer(ILibraryFileAliasSet)
-class LibraryFileAliasSet(object):
+class LibraryFileAliasSet:
"""Create and find LibraryFileAliases."""
def create(self, name, size, file, contentType, expires=None,
diff --git a/lib/lp/services/librarian/tests/test_client.py b/lib/lp/services/librarian/tests/test_client.py
index 4c2035a..cb054a9 100644
--- a/lib/lp/services/librarian/tests/test_client.py
+++ b/lib/lp/services/librarian/tests/test_client.py
@@ -63,7 +63,7 @@ class PropagatingThread(threading.Thread):
self.exc = e
def join(self):
- super(PropagatingThread, self).join()
+ super().join()
if self.exc:
raise self.exc
@@ -71,7 +71,7 @@ class PropagatingThread(threading.Thread):
class InstrumentedLibrarianClient(LibrarianClient):
def __init__(self, *args, **kwargs):
- super(InstrumentedLibrarianClient, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
self.check_error_calls = 0
sentDatabaseName = False
@@ -89,7 +89,7 @@ class InstrumentedLibrarianClient(LibrarianClient):
def _checkError(self):
self.check_error_calls += 1
- super(InstrumentedLibrarianClient, self)._checkError()
+ super()._checkError()
def make_mock_file(error, max_raise):
@@ -118,7 +118,7 @@ class FakeServerTestSetup(TacTestSetup):
def setUp(self):
self.port = None
- super(FakeServerTestSetup, self).setUp()
+ super().setUp()
def setUpRoot(self):
pass
@@ -143,7 +143,7 @@ class FakeServerTestSetup(TacTestSetup):
pass
def _hasDaemonStarted(self):
- if super(FakeServerTestSetup, self)._hasDaemonStarted():
+ if super()._hasDaemonStarted():
with open(self.logfile) as logfile:
self.port = int(re.search(
r"Site starting on (\d+)", logfile.read()).group(1))
@@ -198,7 +198,7 @@ class EchoServer(threading.Thread):
during the upload process.
"""
def __init__(self):
- super(EchoServer, self).__init__()
+ super().__init__()
self.should_stop = False
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.settimeout(1)
@@ -208,7 +208,7 @@ class EchoServer(threading.Thread):
def join(self, *args, **kwargs):
self.should_stop = True
- super(EchoServer, self).join(*args, **kwargs)
+ super().join(*args, **kwargs)
def run(self):
while not self.should_stop:
diff --git a/lib/lp/services/librarian/tests/test_libraryfilealias_with_parent.py b/lib/lp/services/librarian/tests/test_libraryfilealias_with_parent.py
index a3fa991..d8c69e3 100644
--- a/lib/lp/services/librarian/tests/test_libraryfilealias_with_parent.py
+++ b/lib/lp/services/librarian/tests/test_libraryfilealias_with_parent.py
@@ -21,7 +21,7 @@ class TestLibraryFileAliasForBugAttachment(TestCaseWithFactory):
layer = LaunchpadFunctionalLayer
def setUp(self):
- super(TestLibraryFileAliasForBugAttachment, self).setUp()
+ super().setUp()
self.bug_owner = self.factory.makePerson()
login_person(self.bug_owner)
self.bug = self.factory.makeBug(
diff --git a/lib/lp/services/librarian/tests/test_smoketest.py b/lib/lp/services/librarian/tests/test_smoketest.py
index 185989a..4b1a5e0 100644
--- a/lib/lp/services/librarian/tests/test_smoketest.py
+++ b/lib/lp/services/librarian/tests/test_smoketest.py
@@ -31,7 +31,7 @@ def bad_urlopen(url):
def error_urlopen(url):
"""A urllib replacement for testing that raises an exception."""
- raise IOError('network error')
+ raise OSError('network error')
def explosive_urlopen(exception, url):
@@ -44,7 +44,7 @@ class SmokeTestTestCase(TestCaseWithFactory):
layer = ZopelessDatabaseLayer
def setUp(self):
- super(SmokeTestTestCase, self).setUp()
+ super().setUp()
self.fake_librarian = self.useFixture(FakeLibrarian())
def test_store_file(self):
diff --git a/lib/lp/services/librarianserver/librariangc.py b/lib/lp/services/librarianserver/librariangc.py
index 3779dca..aa3429f 100644
--- a/lib/lp/services/librarianserver/librariangc.py
+++ b/lib/lp/services/librarianserver/librariangc.py
@@ -18,7 +18,6 @@ from time import time
import iso8601
import pytz
-import six
from swiftclient import client as swiftclient
from zope.interface import implementer
@@ -904,7 +903,7 @@ def delete_unwanted_swift_files(con):
def get_file_path(content_id):
"""Return the physical file path to the matching LibraryFileContent id.
"""
- assert isinstance(content_id, six.integer_types), (
+ assert isinstance(content_id, int), (
'Invalid content_id %s' % repr(content_id))
return os.path.join(get_storage_root(), relative_file_path(content_id))
diff --git a/lib/lp/services/librarianserver/storage.py b/lib/lp/services/librarianserver/storage.py
index e8611b2..668815f 100644
--- a/lib/lp/services/librarianserver/storage.py
+++ b/lib/lp/services/librarianserver/storage.py
@@ -192,7 +192,7 @@ class TxSwiftStream(swift.SwiftStream):
return return_chunk
-class LibraryFileUpload(object):
+class LibraryFileUpload:
"""A file upload from a client."""
srcDigest = None
mimetype = 'unknown/unknown'
diff --git a/lib/lp/services/librarianserver/swift.py b/lib/lp/services/librarianserver/swift.py
index 4a1139d..637110f 100644
--- a/lib/lp/services/librarianserver/swift.py
+++ b/lib/lp/services/librarianserver/swift.py
@@ -20,7 +20,6 @@ import os.path
import re
import time
-import six
from six.moves.urllib.parse import quote
from swiftclient import client as swiftclient
@@ -267,7 +266,7 @@ def swift_location(lfc_id):
Per https://answers.launchpad.net/swift/+question/181977, we can't
simply stuff everything into one container.
'''
- assert isinstance(lfc_id, six.integer_types), 'Not a LibraryFileContent.id'
+ assert isinstance(lfc_id, int), 'Not a LibraryFileContent.id'
# Don't change this unless you are also going to rebuild the Swift
# storage, as objects will no longer be found in the expected
diff --git a/lib/lp/services/librarianserver/testing/fake.py b/lib/lp/services/librarianserver/testing/fake.py
index 0dfc37a..b18f9a9 100644
--- a/lib/lp/services/librarianserver/testing/fake.py
+++ b/lib/lp/services/librarianserver/testing/fake.py
@@ -18,7 +18,6 @@ import hashlib
import io
from fixtures import Fixture
-import six
from six.moves.urllib.parse import urljoin
import transaction
from transaction.interfaces import ISynchronizer
@@ -138,7 +137,7 @@ class FakeLibrarian(Fixture):
database transaction.
"""
# Note that all files have been committed to storage.
- for alias in six.itervalues(self.aliases):
+ for alias in self.aliases.values():
alias.file_committed = True
def _makeAlias(self, file_id, name, content, content_type):
@@ -175,7 +174,7 @@ class FakeLibrarian(Fixture):
def findBySHA256(self, sha256):
"See `ILibraryFileAliasSet`."""
- for alias in six.itervalues(self.aliases):
+ for alias in self.aliases.values():
if alias.content.sha256 == sha256:
return alias
diff --git a/lib/lp/services/librarianserver/testing/server.py b/lib/lp/services/librarianserver/testing/server.py
index 67ae838..cc8375e 100644
--- a/lib/lp/services/librarianserver/testing/server.py
+++ b/lib/lp/services/librarianserver/testing/server.py
@@ -146,7 +146,7 @@ class LibrarianServerFixture(TacTestSetup):
os.makedirs(self.root, 0o700)
def _waitForDaemonStartup(self):
- super(LibrarianServerFixture, self)._waitForDaemonStartup()
+ super()._waitForDaemonStartup()
# Expose the dynamically allocated ports, if we used them.
if not self._dynamic_config():
self.download_port = config.librarian.download_port
diff --git a/lib/lp/services/librarianserver/testing/tests/test_fakelibrarian.py b/lib/lp/services/librarianserver/testing/tests/test_fakelibrarian.py
index fdd9a58..0c98684 100644
--- a/lib/lp/services/librarianserver/testing/tests/test_fakelibrarian.py
+++ b/lib/lp/services/librarianserver/testing/tests/test_fakelibrarian.py
@@ -5,7 +5,6 @@
import io
-import six
import transaction
from transaction.interfaces import ISynchronizer
from zope.component import getUtility
@@ -58,7 +57,7 @@ class LibraryAccessScenarioMixin:
def test_insert_retrieve(self):
name, content, alias = self._storeFile()
- self.assertIsInstance(alias.id, six.integer_types)
+ self.assertIsInstance(alias.id, int)
transaction.commit()
@@ -98,7 +97,7 @@ class LibraryAccessScenarioMixin:
def test_addFile_returns_alias_id(self):
alias_id = getUtility(ILibrarianClient).addFile(
'bar.txt', 3, io.BytesIO(b'bar'), 'text/plain')
- self.assertIsInstance(alias_id, six.integer_types)
+ self.assertIsInstance(alias_id, int)
self.assertIsInstance(
getUtility(ILibraryFileAliasSet)[alias_id],
LibraryFileAlias)
@@ -142,7 +141,7 @@ class TestFakeLibrarian(LibraryAccessScenarioMixin, TestCaseWithFactory):
layer = DatabaseFunctionalLayer
def setUp(self):
- super(TestFakeLibrarian, self).setUp()
+ super().setUp()
self.fake_librarian = self.useFixture(FakeLibrarian())
def test_fake(self):
diff --git a/lib/lp/services/librarianserver/tests/test_db.py b/lib/lp/services/librarianserver/tests/test_db.py
index 7b12917..55b87b8 100644
--- a/lib/lp/services/librarianserver/tests/test_db.py
+++ b/lib/lp/services/librarianserver/tests/test_db.py
@@ -31,7 +31,7 @@ class DBTestCase(TestCase):
layer = LaunchpadZopelessLayer
def setUp(self):
- super(DBTestCase, self).setUp()
+ super().setUp()
switch_dbuser('librarian')
def test_lookupByDigest(self):
@@ -93,7 +93,7 @@ class TestLibrarianStuff(TestCase):
run_tests_with = AsynchronousDeferredRunTest.make_factory(timeout=30)
def setUp(self):
- super(TestLibrarianStuff, self).setUp()
+ super().setUp()
switch_dbuser('librarian')
self.store = IStore(LibraryFileContent)
self.content_id = db.Library().add('deadbeef', 1234, 'abababab', 'ba')
diff --git a/lib/lp/services/librarianserver/tests/test_db_outage.py b/lib/lp/services/librarianserver/tests/test_db_outage.py
index d87fda6..5709cd9 100644
--- a/lib/lp/services/librarianserver/tests/test_db_outage.py
+++ b/lib/lp/services/librarianserver/tests/test_db_outage.py
@@ -64,7 +64,7 @@ class TestLibrarianDBOutage(TestCase):
layer = PGBouncerLibrarianLayer
def setUp(self):
- super(TestLibrarianDBOutage, self).setUp()
+ super().setUp()
self.pgbouncer = PGBouncerLibrarianLayer.pgbouncer_fixture
self.client = LibrarianClient()
diff --git a/lib/lp/services/librarianserver/tests/test_gc.py b/lib/lp/services/librarianserver/tests/test_gc.py
index 30dbf3a..716bfa3 100644
--- a/lib/lp/services/librarianserver/tests/test_gc.py
+++ b/lib/lp/services/librarianserver/tests/test_gc.py
@@ -68,7 +68,7 @@ class TestLibrarianGarbageCollectionBase:
layer = LaunchpadZopelessLayer
def setUp(self):
- super(TestLibrarianGarbageCollectionBase, self).setUp()
+ super().setUp()
self.client = LibrarianClient()
self.patch(librariangc, 'log', BufferLogger())
@@ -118,7 +118,7 @@ class TestLibrarianGarbageCollectionBase:
self.con.rollback()
self.con.close()
del self.con
- super(TestLibrarianGarbageCollectionBase, self).tearDown()
+ super().tearDown()
def _makeDupes(self):
"""Create two duplicate LibraryFileContent entries with one
@@ -722,7 +722,7 @@ class TestSwiftLibrarianGarbageCollection(
self.useFixture(FeatureFixture({'librarian.swift.enabled': True}))
- super(TestSwiftLibrarianGarbageCollection, self).setUp()
+ super().setUp()
# Move files into Swift.
path = librariangc.get_file_path(self.f1_id)
@@ -935,7 +935,7 @@ class TestTwoSwiftsLibrarianGarbageCollection(
def setUp(self):
self.old_swift_fixture = self.useFixture(
SwiftFixture(old_instance=True))
- super(TestTwoSwiftsLibrarianGarbageCollection, self).setUp()
+ super().setUp()
def test_swift_files_multiple_instances(self):
# swift_files yields files in the correct order across multiple
@@ -1068,7 +1068,7 @@ class TestBlobCollection(TestCase):
layer = LaunchpadZopelessLayer
def setUp(self):
- super(TestBlobCollection, self).setUp()
+ super().setUp()
# Add in some sample data
cur = cursor()
@@ -1210,7 +1210,7 @@ class TestBlobCollection(TestCase):
def tearDown(self):
self.con.rollback()
self.con.close()
- super(TestBlobCollection, self).tearDown()
+ super().tearDown()
def test_DeleteExpiredBlobs(self):
# Delete expired blobs from the TemporaryBlobStorage table
diff --git a/lib/lp/services/librarianserver/tests/test_storage_db.py b/lib/lp/services/librarianserver/tests/test_storage_db.py
index dd78f09..6d97bbb 100644
--- a/lib/lp/services/librarianserver/tests/test_storage_db.py
+++ b/lib/lp/services/librarianserver/tests/test_storage_db.py
@@ -34,7 +34,7 @@ class LibrarianStorageDBTests(TestCase):
layer = LaunchpadZopelessLayer
def setUp(self):
- super(LibrarianStorageDBTests, self).setUp()
+ super().setUp()
switch_dbuser('librarian')
self.directory = self.useFixture(TempDir()).path
self.storage = LibrarianStorage(self.directory, db.Library())
@@ -146,7 +146,7 @@ class LibrarianStorageSwiftTests(TestCase):
run_tests_with = AsynchronousDeferredRunTest.make_factory(timeout=30)
def setUp(self):
- super(LibrarianStorageSwiftTests, self).setUp()
+ super().setUp()
switch_dbuser('librarian')
self.swift_fixture = self.useFixture(SwiftFixture())
self.useFixture(FeatureFixture({'librarian.swift.enabled': True}))
diff --git a/lib/lp/services/librarianserver/tests/test_swift.py b/lib/lp/services/librarianserver/tests/test_swift.py
index ecdb6d9..02ab7c5 100644
--- a/lib/lp/services/librarianserver/tests/test_swift.py
+++ b/lib/lp/services/librarianserver/tests/test_swift.py
@@ -9,7 +9,6 @@ import os.path
import time
from unittest.mock import patch
-import six
from swiftclient import client as swiftclient
import transaction
@@ -34,7 +33,7 @@ class TestFeedSwift(TestCase):
layer = LaunchpadZopelessLayer
def setUp(self):
- super(TestFeedSwift, self).setUp()
+ super().setUp()
self.swift_fixture = self.useFixture(SwiftFixture())
self.useFixture(FeatureFixture({'librarian.swift.enabled': True}))
transaction.commit()
@@ -59,7 +58,7 @@ class TestFeedSwift(TestCase):
self.lfcs = [lfa.content for lfa in self.lfas]
def tearDown(self):
- super(TestFeedSwift, self).tearDown()
+ super().tearDown()
# Restart the Librarian so it picks up the feature flag change.
self.attachLibrarianLog(LibrarianLayer.librarian_fixture)
LibrarianLayer.librarian_fixture.cleanUp()
@@ -227,7 +226,7 @@ class TestFeedSwift(TestCase):
# stored in Swift as a single object.
size = 512 * 1024 # 512KB
expected_content = b''.join(
- six.int2byte(i % 256) for i in range(0, size))
+ bytes((i % 256,)) for i in range(0, size))
lfa_id = self.add_file('hello_bigboy.xls', expected_content)
# Data round trips when served from disk.
@@ -243,7 +242,7 @@ class TestFeedSwift(TestCase):
size = LibrarianStorage.CHUNK_SIZE * 50
self.assertTrue(size > 1024 * 1024)
expected_content = b''.join(
- six.int2byte(i % 256) for i in range(0, size))
+ bytes((i % 256,)) for i in range(0, size))
lfa_id = self.add_file('hello_bigboy.xls', expected_content)
lfc = IStore(LibraryFileAlias).get(LibraryFileAlias, lfa_id).content
@@ -266,7 +265,7 @@ class TestFeedSwift(TestCase):
size = LibrarianStorage.CHUNK_SIZE * 50 + 1
self.assertTrue(size > 1024 * 1024)
expected_content = b''.join(
- six.int2byte(i % 256) for i in range(0, size))
+ bytes((i % 256,)) for i in range(0, size))
lfa_id = self.add_file('hello_bigboy.xls', expected_content)
lfc = IStore(LibraryFileAlias).get(LibraryFileAlias, lfa_id).content
@@ -286,7 +285,7 @@ class TestFeedSwift(TestCase):
size = LibrarianStorage.CHUNK_SIZE * 50
self.assertTrue(size > 1024 * 1024)
expected_content = b''.join(
- six.int2byte(i % 256) for i in range(0, size))
+ bytes((i % 256,)) for i in range(0, size))
lfa_id = self.add_file('hello_bigboy.xls', expected_content)
lfa = IStore(LibraryFileAlias).get(LibraryFileAlias, lfa_id)
lfc = lfa.content
diff --git a/lib/lp/services/librarianserver/tests/test_web.py b/lib/lp/services/librarianserver/tests/test_web.py
index 6325163..5800724 100644
--- a/lib/lp/services/librarianserver/tests/test_web.py
+++ b/lib/lp/services/librarianserver/tests/test_web.py
@@ -101,7 +101,7 @@ class LibrarianZopelessWebTestMixin(LibrarianWebTestMixin):
layer = LaunchpadZopelessLayer
def setUp(self):
- super(LibrarianZopelessWebTestMixin, self).setUp()
+ super().setUp()
switch_dbuser(config.librarian.dbuser)
def commit(self):
@@ -157,7 +157,7 @@ class LibrarianWebTestCase(LibrarianWebTestMixin, TestCaseWithFactory):
# displaying Ubuntu build logs in the browser. The mimetype should be
# "text/plain" for these files.
client = LibrarianClient()
- contents = 'Build log \N{SNOWMAN}...'.encode('UTF-8')
+ contents = 'Build log \N{SNOWMAN}...'.encode()
build_log = BytesIO()
with GzipFile(mode='wb', fileobj=build_log) as f:
f.write(contents)
@@ -491,7 +491,7 @@ class LibrarianWebMacaroonTestCase(LibrarianWebTestMixin, TestCaseWithFactory):
layer = AppServerLayer
def setUp(self):
- super(LibrarianWebMacaroonTestCase, self).setUp()
+ super().setUp()
# Copy launchpad.internal_macaroon_secret_key from the appserver
# config so that we can issue macaroons using it.
with ConfigUseFixture(self.layer.appserver_config_name):
@@ -553,7 +553,7 @@ class DeletedContentTestCase(unittest.TestCase):
layer = LaunchpadZopelessLayer
def setUp(self):
- super(DeletedContentTestCase, self).setUp()
+ super().setUp()
switch_dbuser(config.librarian.dbuser)
def test_deletedContentNotFound(self):
diff --git a/lib/lp/services/librarianserver/web.py b/lib/lp/services/librarianserver/web.py
index 55ad829..51b997b 100644
--- a/lib/lp/services/librarianserver/web.py
+++ b/lib/lp/services/librarianserver/web.py
@@ -48,7 +48,7 @@ defaultResource = static.Data(b"""
<p><small>Copyright 2004-2021 Canonical Ltd.</small></p>
<!-- kthxbye. -->
</body></html>
- """, type=six.ensure_str('text/html'))
+ """, type='text/html')
fourOhFour = resource.NoResource('No such resource')
@@ -258,7 +258,7 @@ class File(resource.Resource):
@implementer(IPushProducer)
-class FileProducer(object):
+class FileProducer:
buffer_size = abstract.FileDescriptor.bufferSize
@@ -314,7 +314,7 @@ class DigestSearchResource(resource.Resource):
digest = six.ensure_text(request.args[b'digest'][0])
except (LookupError, UnicodeDecodeError):
return static.Data(
- b'Bad search', six.ensure_str('text/plain')).render(request)
+ b'Bad search', 'text/plain').render(request)
deferred = deferToThread(self._matchingAliases, digest)
deferred.addCallback(self._cb_matchingAliases, request)
@@ -333,7 +333,7 @@ class DigestSearchResource(resource.Resource):
text = '\n'.join([str(len(matches))] + matches)
response = static.Data(
text.encode('utf-8'),
- six.ensure_str('text/plain; charset=utf-8')).render(request)
+ 'text/plain; charset=utf-8').render(request)
request.write(response)
request.finish()
@@ -342,7 +342,7 @@ class DigestSearchResource(resource.Resource):
robotsTxt = static.Data(b"""
User-agent: *
Disallow: /
-""", type=six.ensure_str('text/plain'))
+""", type='text/plain')
def _eb(failure, request):
diff --git a/lib/lp/services/limitedlist.py b/lib/lp/services/limitedlist.py
index b9833b0..0084010 100644
--- a/lib/lp/services/limitedlist.py
+++ b/lib/lp/services/limitedlist.py
@@ -10,20 +10,20 @@ class LimitedList(list):
"""A mutable sequence that takes a limited number of elements."""
def __new__(cls, max_length, value=None):
- return super(LimitedList, cls).__new__(cls)
+ return super().__new__(cls)
def __init__(self, max_length, value=None):
if value is None:
value = []
elif len(value) > max_length:
value = value[-max_length:]
- super(LimitedList, self).__init__(value)
+ super().__init__(value)
self.max_length = max_length
def __repr__(self):
return (
'<LimitedList(%s, %s)>'
- % (self.max_length, super(LimitedList, self).__repr__()))
+ % (self.max_length, super().__repr__()))
def _ensureLength(self):
"""Ensure that the maximum length is not exceeded."""
@@ -32,46 +32,44 @@ class LimitedList(list):
del self[0:elements_to_drop]
def __add__(self, other):
- return LimitedList(
- self.max_length, super(LimitedList, self).__add__(other))
+ return LimitedList(self.max_length, super().__add__(other))
def __radd__(self, other):
return LimitedList(self.max_length, other.__add__(self))
def __iadd__(self, other):
- result = super(LimitedList, self).__iadd__(other)
+ result = super().__iadd__(other)
self._ensureLength()
return result
def __mul__(self, other):
- return LimitedList(
- self.max_length, super(LimitedList, self).__mul__(other))
+ return LimitedList(self.max_length, super().__mul__(other))
def __rmul__(self, other):
return self.__mul__(other)
def __imul__(self, other):
- result = super(LimitedList, self).__imul__(other)
+ result = super().__imul__(other)
self._ensureLength()
return result
def __setitem__(self, key, value):
- result = super(LimitedList, self).__setitem__(key, value)
+ result = super().__setitem__(key, value)
if isinstance(key, slice):
self._ensureLength()
return result
def append(self, value):
- result = super(LimitedList, self).append(value)
+ result = super().append(value)
self._ensureLength()
return result
def extend(self, value):
- result = super(LimitedList, self).extend(value)
+ result = super().extend(value)
self._ensureLength()
return result
def insert(self, position, value):
- result = super(LimitedList, self).insert(position, value)
+ result = super().insert(position, value)
self._ensureLength()
return result
diff --git a/lib/lp/services/log/logger.py b/lib/lp/services/log/logger.py
index 848ff0c..0a15759 100644
--- a/lib/lp/services/log/logger.py
+++ b/lib/lp/services/log/logger.py
@@ -107,7 +107,7 @@ class FakeLogger:
return self.loglevel
def _format_message(self, msg, *args):
- if not isinstance(msg, six.string_types):
+ if not isinstance(msg, str):
msg = str(msg)
# To avoid type errors when the msg has % values and args is empty,
# don't expand the string with empty args.
@@ -196,7 +196,7 @@ class BufferLogger(FakeLogger):
# service.
def __init__(self):
- super(BufferLogger, self).__init__(six.StringIO())
+ super().__init__(six.StringIO())
def getLogBuffer(self):
"""Return the existing log messages."""
diff --git a/lib/lp/services/macaroons/interfaces.py b/lib/lp/services/macaroons/interfaces.py
index 3a39356..758a9de 100644
--- a/lib/lp/services/macaroons/interfaces.py
+++ b/lib/lp/services/macaroons/interfaces.py
@@ -23,7 +23,7 @@ class BadMacaroonContext(Exception):
def __init__(self, context, message=None):
if message is None:
message = "Cannot handle context %r." % context
- super(BadMacaroonContext, self).__init__(message)
+ super().__init__(message)
self.context = context
diff --git a/lib/lp/services/macaroons/testing.py b/lib/lp/services/macaroons/testing.py
index b570a54..2b3ed5b 100644
--- a/lib/lp/services/macaroons/testing.py
+++ b/lib/lp/services/macaroons/testing.py
@@ -31,7 +31,7 @@ class MacaroonVerifies(Matcher):
"""Matches if a macaroon can be verified."""
def __init__(self, issuer_name, context, matcher=None, **verify_kwargs):
- super(MacaroonVerifies, self).__init__()
+ super().__init__()
self.issuer_name = issuer_name
self.context = context
self.matcher = matcher
diff --git a/lib/lp/services/mail/basemailer.py b/lib/lp/services/mail/basemailer.py
index 3fcd2ee..04d907e 100644
--- a/lib/lp/services/mail/basemailer.py
+++ b/lib/lp/services/mail/basemailer.py
@@ -10,7 +10,6 @@ import logging
from smtplib import SMTPException
import sys
-import six
from zope.component import getUtility
from zope.error.interfaces import IErrorReportingUtility
from zope.security.management import getSecurityPolicy
@@ -78,7 +77,7 @@ class BaseMailer:
self._subject_template = subject
self._template_name = template_name
self._recipients = NotificationRecipientSet()
- for recipient, reason in six.iteritems(recipients):
+ for recipient, reason in recipients.items():
self._recipients.add(recipient, reason, reason.mail_header)
self.from_address = from_address
self.delta = delta
diff --git a/lib/lp/services/mail/interfaces.py b/lib/lp/services/mail/interfaces.py
index c383c12..bd8387f 100644
--- a/lib/lp/services/mail/interfaces.py
+++ b/lib/lp/services/mail/interfaces.py
@@ -72,8 +72,8 @@ class IMailHandler(Interface):
"""
allow_unknown_users = Bool(
- title=u"Allow unknown users",
- description=u"The handler can handle emails from persons not"
+ title="Allow unknown users",
+ description="The handler can handle emails from persons not"
" registered in Launchpad (which will result in an"
" anonymous interaction being set up.")
diff --git a/lib/lp/services/mail/mailbox.py b/lib/lp/services/mail/mailbox.py
index d1698c6..8dd54a3 100644
--- a/lib/lp/services/mail/mailbox.py
+++ b/lib/lp/services/mail/mailbox.py
@@ -11,7 +11,6 @@ __all__ = [
import os
import poplib
-import socket
import threading
from zope.interface import (
@@ -119,7 +118,7 @@ class POP3MailBox:
popbox = poplib.POP3_SSL(self._host)
else:
popbox = poplib.POP3(self._host)
- except socket.error as e:
+ except OSError as e:
raise MailBoxError(str(e))
try:
popbox.user(self._user)
diff --git a/lib/lp/services/mail/meta.py b/lib/lp/services/mail/meta.py
index 24e3495..efd413d 100644
--- a/lib/lp/services/mail/meta.py
+++ b/lib/lp/services/mail/meta.py
@@ -37,26 +37,26 @@ def testMailBoxHandler(_context):
class IPOP3MailBoxDirective(Interface):
"""Configure a mail box which interfaces to a POP3 server."""
host = ASCII(
- title=u"Host",
- description=u"Host name of the POP3 server.",
+ title="Host",
+ description="Host name of the POP3 server.",
required=True,
)
user = ASCII(
- title=u"User",
- description=u"User name to connect to the POP3 server with.",
+ title="User",
+ description="User name to connect to the POP3 server with.",
required=True,
)
password = ASCII(
- title=u"Password",
- description=u"Password to connect to the POP3 server with.",
+ title="Password",
+ description="Password to connect to the POP3 server with.",
required=True,
)
ssl = Bool(
- title=u"SSL",
- description=u"Use SSL.",
+ title="SSL",
+ description="Use SSL.",
required=False,
default=False)
@@ -69,8 +69,8 @@ def pop3MailBoxHandler(_context, host, user, password, ssl=False):
class IDirectoryMailBoxDirective(Interface):
"""Configure a mail box which interfaces to a directory of raw files."""
directory = ASCII(
- title=u"Directory",
- description=u"The directory containing the raw mail files.",
+ title="Directory",
+ description="The directory containing the raw mail files.",
required=True,
)
@@ -82,28 +82,28 @@ def directorymailBoxHandler(_context, directory):
class IStubMailerDirective(IMailerDirective):
from_addr = ASCII(
- title=u"From Address",
- description=u"All outgoing emails will use this email address",
+ title="From Address",
+ description="All outgoing emails will use this email address",
required=True,
)
to_addr = ASCII(
- title=u"To Address",
+ title="To Address",
description=(
- u"All outgoing emails will be redirected to this email "
- u"address"),
+ "All outgoing emails will be redirected to this email "
+ "address"),
required=True,
)
mailer = ASCII(
- title=u"Mailer to use",
- description=u"""\
+ title="Mailer to use",
+ description="""\
Which registered mailer to use, such as configured with
the smtpMailer or sendmailMailer directives""",
required=False,
default='smtp',
)
rewrite = Bool(
- title=u"Rewrite headers",
- description=u"""\
+ title="Rewrite headers",
+ description="""\
If true, headers are rewritten in addition to the
destination address in the envelope. May me required
to bypass spam filters.""",
@@ -137,19 +137,19 @@ def testMailerHandler(_context, name):
class IMboxMailerDirective(IMailerDirective):
filename = ASCII(
- title=u'File name',
- description=u'Unix mbox file to store outgoing emails in',
+ title='File name',
+ description='Unix mbox file to store outgoing emails in',
required=True,
)
overwrite = Bool(
- title=u'Overwrite',
- description=u'Whether to overwrite the existing mbox file or not',
+ title='Overwrite',
+ description='Whether to overwrite the existing mbox file or not',
required=False,
default=False,
)
mailer = ASCII(
- title=u"Chained mailer to which messages are forwarded",
- description=u"""\
+ title="Chained mailer to which messages are forwarded",
+ description="""\
Optional mailer to forward messages to, such as those configured
with smtpMailer, sendmailMailer, or testMailer directives. When
not given, the message is not forwarded but only stored in the
diff --git a/lib/lp/services/mail/notificationrecipientset.py b/lib/lp/services/mail/notificationrecipientset.py
index ee324ad..ca48e7c 100644
--- a/lib/lp/services/mail/notificationrecipientset.py
+++ b/lib/lp/services/mail/notificationrecipientset.py
@@ -11,7 +11,6 @@ __all__ = [
from operator import attrgetter
-import six
from zope.interface import implementer
from zope.security.proxy import (
isinstance as zope_isinstance,
@@ -76,7 +75,7 @@ class NotificationRecipientSet:
def __contains__(self, person_or_email):
"""See `INotificationRecipientSet`."""
- if zope_isinstance(person_or_email, six.string_types):
+ if zope_isinstance(person_or_email, str):
return person_or_email in self._emailToPerson
elif IPerson.providedBy(person_or_email):
return person_or_email in self._personToRationale
@@ -89,7 +88,7 @@ class NotificationRecipientSet:
def getReason(self, person_or_email):
"""See `INotificationRecipientSet`."""
- if zope_isinstance(person_or_email, six.string_types):
+ if zope_isinstance(person_or_email, str):
try:
person = self._emailToPerson[person_or_email]
except KeyError:
diff --git a/lib/lp/services/mail/sendmail.py b/lib/lp/services/mail/sendmail.py
index 133b423..3e24695 100644
--- a/lib/lp/services/mail/sendmail.py
+++ b/lib/lp/services/mail/sendmail.py
@@ -84,11 +84,9 @@ def do_paranoid_email_content_validation(from_addr, to_addrs, subject, body):
# XXX StuartBishop 2005-03-19:
# These checks need to be migrated upstream if this bug
# still exists in modern Z3.
- assert zisinstance(from_addr, six.string_types), \
- 'Invalid From: %r' % from_addr
- assert zisinstance(subject, six.string_types), \
- 'Invalid Subject: %r' % subject
- assert zisinstance(body, six.string_types), 'Invalid body: %r' % body
+ assert zisinstance(from_addr, str), 'Invalid From: %r' % from_addr
+ assert zisinstance(subject, str), 'Invalid Subject: %r' % subject
+ assert zisinstance(body, str), 'Invalid body: %r' % body
def do_paranoid_envelope_to_validation(to_addrs):
@@ -102,7 +100,7 @@ def do_paranoid_envelope_to_validation(to_addrs):
assert (zisinstance(to_addrs, (list, tuple, set))
and len(to_addrs) > 0), 'Invalid To: %r' % (to_addrs,)
for addr in to_addrs:
- assert zisinstance(addr, six.string_types) and bool(addr), \
+ assert zisinstance(addr, str) and bool(addr), \
'Invalid recipient: %r in %r' % (addr, to_addrs)
assert '\n' not in addr, (
"Address contains carriage returns: %r" % (addr,))
@@ -202,13 +200,13 @@ def simple_sendmail(from_addr, to_addrs, subject, body, headers=None,
return ctrl.send()
-class MailController(object):
+class MailController:
"""Message generation interface closer to peoples' mental model."""
def __init__(self, from_addr, to_addrs, subject, body, headers=None,
envelope_to=None, bulk=True):
self.from_addr = from_addr
- if zisinstance(to_addrs, (bytes, six.text_type)):
+ if zisinstance(to_addrs, (bytes, str)):
to_addrs = [to_addrs]
self.to_addrs = to_addrs
self.envelope_to = envelope_to
@@ -223,7 +221,7 @@ class MailController(object):
def addAttachment(self, content, content_type='application/octet-stream',
inline=False, filename=None, charset=None):
attachment = Message()
- if charset and isinstance(content, six.text_type):
+ if charset and isinstance(content, str):
content = content.encode(charset)
attachment.add_header('Content-Type', content_type)
if inline:
@@ -453,9 +451,9 @@ def sendmail(message, to_addrs=None, bulk=True):
raw_message = message_as_bytes(message)
message_detail = message['Subject']
- if not isinstance(message_detail, six.string_types):
+ if not isinstance(message_detail, str):
# Might be a Header object; can be squashed.
- message_detail = six.text_type(message_detail)
+ message_detail = str(message_detail)
if _immediate_mail_delivery:
# Immediate email delivery is not unit tested, and won't be.
# The immediate-specific stuff is pretty simple though so this
@@ -514,7 +512,7 @@ def raw_sendmail(from_addr, to_addrs, raw_message, message_detail):
:param message_detail: String of detail about the message
to be recorded to help with debugging, eg the message subject.
"""
- assert not isinstance(to_addrs, six.string_types), \
+ assert not isinstance(to_addrs, str), \
'to_addrs must be a sequence'
assert isinstance(raw_message, bytes), 'Not a byte string'
assert raw_message.decode('ascii'), 'Not ASCII - badly encoded message'
diff --git a/lib/lp/services/mail/tests/test_basemailer.py b/lib/lp/services/mail/tests/test_basemailer.py
index c19ee2a..182d063 100644
--- a/lib/lp/services/mail/tests/test_basemailer.py
+++ b/lib/lp/services/mail/tests/test_basemailer.py
@@ -65,7 +65,7 @@ class RaisingMailController(MailController):
if getattr(self, 'raise_on_send', False):
raise SMTPException('boom')
else:
- super(RaisingMailController, self).send(bulk)
+ super().send(bulk)
class RaisingMailControllerFactory:
diff --git a/lib/lp/services/mail/tests/test_dkim.py b/lib/lp/services/mail/tests/test_dkim.py
index 09adeb9..abc9fa4 100644
--- a/lib/lp/services/mail/tests/test_dkim.py
+++ b/lib/lp/services/mail/tests/test_dkim.py
@@ -120,7 +120,7 @@ class TestDKIM(TestCaseWithFactory):
key = b'abcdefg'
else:
raise ValueError(response_type)
- self._dns_responses[u'example._domainkey.canonical.com.'] = key
+ self._dns_responses['example._domainkey.canonical.com.'] = key
def get_dkim_log(self):
return self._log_output.getvalue()
diff --git a/lib/lp/services/mail/tests/test_incoming.py b/lib/lp/services/mail/tests/test_incoming.py
index b442bb0..97f2348 100644
--- a/lib/lp/services/mail/tests/test_incoming.py
+++ b/lib/lp/services/mail/tests/test_incoming.py
@@ -125,7 +125,7 @@ class IncomingTestCase(TestCaseWithFactory):
"An error occurred while processing a mail you sent to "
"Launchpad's email\ninterface.\n\n\n"
"Error message:\n\nSignature couldn't be verified: "
- "(7, 58, %r)" % u"No data",
+ "(7, 58, %r)" % "No data",
body)
def test_expired_key(self):
@@ -270,13 +270,13 @@ class IncomingTestCase(TestCaseWithFactory):
def test_invalid_from_address_unicode(self):
# Invalid From: header such as no "@" is handled.
message, test_handler = self.makeSentMessage(
- u'm\xeda@xxxxxx', 'test@xxxxxx')
+ 'm\xeda@xxxxxx', 'test@xxxxxx')
handleMail()
self.assertEqual([], self.oopses)
self.assertEqual(1, len(test_handler.handledMails))
self.assertEqual(
- u'm\xeda@xxxxxx',
- six.text_type(make_header(decode_header(
+ 'm\xeda@xxxxxx',
+ str(make_header(decode_header(
test_handler.handledMails[0]['From']))))
def test_invalid_from_address_no_mime_encoding(self):
@@ -284,7 +284,7 @@ class IncomingTestCase(TestCaseWithFactory):
# is handled.
test_handler = FakeHandler()
mail_handlers.add('lp.dev', test_handler)
- raw_message = dedent(u"""\
+ raw_message = dedent("""\
Content-Type: text/plain; charset="UTF-8"
MIME-Version: 1.0
Message-Id: <message-id>
@@ -295,7 +295,7 @@ class IncomingTestCase(TestCaseWithFactory):
body
""").encode('UTF-8')
TestMailer().send(
- u'\u05D0 <alef@xxxxxx>'.encode('UTF-8'), 'test@xxxxxx',
+ '\u05D0 <alef@xxxxxx>'.encode(), 'test@xxxxxx',
raw_message)
handleMail()
self.assertEqual([], self.oopses)
@@ -307,13 +307,13 @@ class IncomingTestCase(TestCaseWithFactory):
def test_invalid_cc_address_unicode(self):
# Invalid Cc: header such as no "@" is handled.
message, test_handler = self.makeSentMessage(
- 'me@xxxxxx', 'test@xxxxxx', cc=u'm\xeda@xxxxxx')
+ 'me@xxxxxx', 'test@xxxxxx', cc='m\xeda@xxxxxx')
handleMail()
self.assertEqual([], self.oopses)
self.assertEqual(1, len(test_handler.handledMails))
self.assertEqual(
- u'm\xeda@xxxxxx',
- six.text_type(make_header(decode_header(
+ 'm\xeda@xxxxxx',
+ str(make_header(decode_header(
test_handler.handledMails[0]['Cc']))))
diff --git a/lib/lp/services/mail/tests/test_mailbox.py b/lib/lp/services/mail/tests/test_mailbox.py
index 3ce73c2..d0429ce 100644
--- a/lib/lp/services/mail/tests/test_mailbox.py
+++ b/lib/lp/services/mail/tests/test_mailbox.py
@@ -20,7 +20,7 @@ from lp.testing import (
class TestDirectoryMailBox(TestCase):
def setUp(self):
- super(TestDirectoryMailBox, self).setUp()
+ super().setUp()
# Create a temp directory.
self.email_dir = tempfile.mkdtemp()
self.addCleanup(rmtree, self.email_dir)
diff --git a/lib/lp/services/mail/tests/test_sendmail.py b/lib/lp/services/mail/tests/test_sendmail.py
index 55e00bc..1965ee5 100644
--- a/lib/lp/services/mail/tests/test_sendmail.py
+++ b/lib/lp/services/mail/tests/test_sendmail.py
@@ -6,7 +6,6 @@ import email.header
from email.message import Message
import unittest
-import six
from zope.interface import implementer
from zope.sendmail.interfaces import IMailDelivery
@@ -88,8 +87,8 @@ class TestMailController(TestCase):
def test_MakeMessageSpecialChars(self):
"""A message should have its to and from addrs converted to ascii."""
- to_addr = u'\u1100to@xxxxxxxxxxx'
- from_addr = u'\u1100from@xxxxxxxxxxx'
+ to_addr = '\u1100to@xxxxxxxxxxx'
+ from_addr = '\u1100from@xxxxxxxxxxx'
ctrl = MailController(from_addr, to_addr, 'subject', 'body')
message = ctrl.makeMessage()
self.assertEqual('=?utf-8?b?4YSAZnJvbUBleGFtcGxlLmNvbQ==?=',
@@ -129,7 +128,7 @@ class TestMailController(TestCase):
# UTF-8 encoded MIME text, and the message as a whole can be flattened
# to a string with Unicode errors.
ctrl = MailController(
- 'from@xxxxxxxxxxx', 'to@xxxxxxxxxxx', 'subject', u'Bj\xf6rn')
+ 'from@xxxxxxxxxxx', 'to@xxxxxxxxxxx', 'subject', 'Bj\xf6rn')
message = ctrl.makeMessage()
# Make sure that the message can be flattened to a string as sendmail
# does without raising a UnicodeEncodeError.
@@ -141,7 +140,7 @@ class TestMailController(TestCase):
# UTF-8 encoded MIME text, and the message as a whole can be flattened
# to a string with Unicode errors.
ctrl = MailController(
- 'from@xxxxxxxxxxx', 'to@xxxxxxxxxxx', 'subject', u'Bj\xf6rn')
+ 'from@xxxxxxxxxxx', 'to@xxxxxxxxxxx', 'subject', 'Bj\xf6rn')
ctrl.addAttachment('attach')
message = ctrl.makeMessage()
# Make sure that the message can be flattened to a string as sendmail
@@ -154,7 +153,7 @@ class TestMailController(TestCase):
def test_MakeMessage_with_binary_attachment(self):
"""Message should still encode as ascii with non-ascii attachments."""
ctrl = MailController(
- 'from@xxxxxxxxxxx', 'to@xxxxxxxxxxx', 'subject', u'Body')
+ 'from@xxxxxxxxxxx', 'to@xxxxxxxxxxx', 'subject', 'Body')
ctrl.addAttachment('\x00\xffattach')
message = ctrl.makeMessage()
self.assertTrue(
@@ -163,7 +162,7 @@ class TestMailController(TestCase):
def test_MakeMessage_with_non_binary_attachment(self):
"""Simple ascii attachments should not be encoded."""
ctrl = MailController(
- 'from@xxxxxxxxxxx', 'to@xxxxxxxxxxx', 'subject', u'Body')
+ 'from@xxxxxxxxxxx', 'to@xxxxxxxxxxx', 'subject', 'Body')
ctrl.addAttachment('Hello, I am ascii')
message = ctrl.makeMessage()
body, attachment = message.get_payload()
@@ -225,7 +224,7 @@ class TestMailController(TestCase):
def test_encodeOptimally_with_text(self):
"""Mostly-ascii attachments should be encoded as quoted-printable."""
- text = u'I went to the caf\u00e9 today.'.encode('utf-8')
+ text = 'I went to the caf\u00e9 today.'.encode()
part = Message()
part.set_payload(text)
MailController.encodeOptimally(part)
@@ -301,11 +300,11 @@ class TestMailController(TestCase):
a0 = actions[0]
self.assertEqual(a0.category, 'sendmail')
self.assertEqual(a0.detail, subject)
- self.assertIsInstance(a0.detail, six.string_types)
+ self.assertIsInstance(a0.detail, str)
@implementer(IMailDelivery)
-class RecordingMailer(object):
+class RecordingMailer:
def send(self, from_addr, to_addr, raw_message):
self.from_addr = from_addr
diff --git a/lib/lp/services/memcache/tests/test_memcache_client.py b/lib/lp/services/memcache/tests/test_memcache_client.py
index 5574d22..b9989d8 100644
--- a/lib/lp/services/memcache/tests/test_memcache_client.py
+++ b/lib/lp/services/memcache/tests/test_memcache_client.py
@@ -26,7 +26,7 @@ class MemcacheClientTestCase(TestCase):
layer = LaunchpadZopelessLayer
def setUp(self):
- super(MemcacheClientTestCase, self).setUp()
+ super().setUp()
self.client = getUtility(IMemcacheClient)
def test_basics(self):
diff --git a/lib/lp/services/messages/interfaces/message.py b/lib/lp/services/messages/interfaces/message.py
index ed6a533..a699dd9 100644
--- a/lib/lp/services/messages/interfaces/message.py
+++ b/lib/lp/services/messages/interfaces/message.py
@@ -138,7 +138,7 @@ class IMessageView(IMessageCommon):
title = TextLine(
title=_('The message title, usually just the subject.'),
readonly=True)
- visible = Bool(title=u"This message is visible or not.", required=False,
+ visible = Bool(title="This message is visible or not.", required=False,
default=True)
bugattachments = exported(
diff --git a/lib/lp/services/messages/model/message.py b/lib/lp/services/messages/model/message.py
index 53f4ee2..102a813 100644
--- a/lib/lp/services/messages/model/message.py
+++ b/lib/lp/services/messages/model/message.py
@@ -161,7 +161,7 @@ class Message(SQLBase):
@classmethod
def chunks_text(cls, chunks):
- bits = [six.text_type(chunk) for chunk in chunks if chunk.content]
+ bits = [str(chunk) for chunk in chunks if chunk.content]
return '\n\n'.join(bits)
# XXX flacoste 2006-09-08: Bogus attribute only present so that
@@ -358,7 +358,7 @@ class MessageSet:
decoded = word if charset is None else self.decode(word, charset)
re_encoded_bits.append((decoded.encode('utf-8'), 'utf-8'))
- return six.text_type(make_header(re_encoded_bits))
+ return str(make_header(re_encoded_bits))
def fromEmail(self, email_message, owner=None, filealias=None,
parsed_message=None, create_missing_persons=False,
@@ -573,7 +573,6 @@ class MessageSet:
return message
-@six.python_2_unicode_compatible
@implementer(IMessageChunk)
class MessageChunk(SQLBase):
"""One part of a possibly multipart Message"""
@@ -634,7 +633,7 @@ class UserToUserEmail(Storm):
:param message: the message being sent
:type message: `email.message.Message`
"""
- super(UserToUserEmail, self).__init__()
+ super().__init__()
person_set = getUtility(IPersonSet)
# Find the person who is sending this message.
realname, address = parseaddr(message['from'])
@@ -660,7 +659,7 @@ class UserToUserEmail(Storm):
self.sender = sender
self.recipient = recipient
self.message_id = six.ensure_text(message_id, 'ascii')
- self.subject = six.text_type(make_header(decode_header(subject)))
+ self.subject = str(make_header(decode_header(subject)))
# Add the object to the store of the sender. Our StormMigrationGuide
# recommends against this saying "Note that the constructor should not
# usually add the object to a store -- leave that for a FooSet.new()
diff --git a/lib/lp/services/messages/tests/scenarios.py b/lib/lp/services/messages/tests/scenarios.py
index ab1f298..9faa16c 100644
--- a/lib/lp/services/messages/tests/scenarios.py
+++ b/lib/lp/services/messages/tests/scenarios.py
@@ -18,7 +18,7 @@ class MessageTypeScenariosMixin(WithScenarios):
]
def setUp(self):
- super(MessageTypeScenariosMixin, self).setUp()
+ super().setUp()
self.person = self.factory.makePerson()
login_person(self.person)
diff --git a/lib/lp/services/messages/tests/test_message.py b/lib/lp/services/messages/tests/test_message.py
index 9828dd3..397faf1 100644
--- a/lib/lp/services/messages/tests/test_message.py
+++ b/lib/lp/services/messages/tests/test_message.py
@@ -10,7 +10,6 @@ from email.utils import (
make_msgid,
)
-import six
from testtools.matchers import (
ContainsDict,
EndsWith,
@@ -56,10 +55,10 @@ class TestMessageSet(TestCaseWithFactory):
# characters according to Unicode but not according to ASCII, and this
# would otherwise result in different test output between Python 2 and
# 3.)
- high_characters = b''.join(six.int2byte(c) for c in range(161, 256))
+ high_characters = b''.join(bytes((c,)) for c in range(161, 256))
def setUp(self):
- super(TestMessageSet, self).setUp()
+ super().setUp()
# Testing behaviour, not permissions here.
login('foo.bar@xxxxxxxxxxxxx')
@@ -172,8 +171,8 @@ class TestMessageSet(TestCaseWithFactory):
def test_decode_utf8(self):
"""Test decode with a known encoding."""
- result = MessageSet.decode(u'\u1234'.encode('utf-8'), 'utf-8')
- self.assertEqual(u'\u1234', result)
+ result = MessageSet.decode('\u1234'.encode(), 'utf-8')
+ self.assertEqual('\u1234', result)
def test_decode_macintosh(self):
"""Test decode with macintosh encoding."""
@@ -183,7 +182,7 @@ class TestMessageSet(TestCaseWithFactory):
def test_decode_unknown_ascii(self):
"""Test decode with ascii characters in an unknown encoding."""
result = MessageSet.decode(b'abcde', 'booga')
- self.assertEqual(u'abcde', result)
+ self.assertEqual('abcde', result)
def test_decode_unknown_high_characters(self):
"""Test decode with non-ascii characters in an unknown encoding."""
diff --git a/lib/lp/services/messaging/interfaces.py b/lib/lp/services/messaging/interfaces.py
index 06df94d..e7fd90c 100644
--- a/lib/lp/services/messaging/interfaces.py
+++ b/lib/lp/services/messaging/interfaces.py
@@ -37,7 +37,7 @@ class QueueEmpty(MessagingException):
class IMessageSession(Interface):
is_connected = Bool(
- u"Whether the session is connected to the messaging system.")
+ "Whether the session is connected to the messaging system.")
def connect():
"""Connect to the messaging system.
diff --git a/lib/lp/services/messaging/rabbit.py b/lib/lp/services/messaging/rabbit.py
index 47633be..a720760 100644
--- a/lib/lp/services/messaging/rabbit.py
+++ b/lib/lp/services/messaging/rabbit.py
@@ -13,7 +13,6 @@ __all__ = [
from collections import deque
from functools import partial
import json
-import socket
import sys
import threading
import time
@@ -86,7 +85,7 @@ class RabbitSession(threading.local):
exchange = LAUNCHPAD_EXCHANGE
def __init__(self):
- super(RabbitSession, self).__init__()
+ super().__init__()
self._connection = None
self._deferred = deque()
# Maintain sessions according to transaction boundaries. Keep a strong
@@ -115,7 +114,7 @@ class RabbitSession(threading.local):
if self._connection is not None:
try:
self._connection.close()
- except socket.error:
+ except OSError:
# Socket error is fine; the connection is still closed.
pass
finally:
@@ -186,7 +185,7 @@ class RabbitUnreliableSession(RabbitSession):
other errors but files an oops report for these.
"""
try:
- super(RabbitUnreliableSession, self).finish()
+ super().finish()
except self.suppressed_errors:
pass
except Exception:
@@ -223,7 +222,7 @@ class RabbitRoutingKey(RabbitMessageBase):
"""A RabbitMQ data origination point."""
def __init__(self, session, routing_key):
- super(RabbitRoutingKey, self).__init__(session)
+ super().__init__(session)
self.key = routing_key
def associateConsumer(self, consumer):
@@ -259,7 +258,7 @@ class RabbitQueue(RabbitMessageBase):
"""A RabbitMQ Queue."""
def __init__(self, session, name):
- super(RabbitQueue, self).__init__(session)
+ super().__init__(session)
self.name = name
def receive(self, timeout=0.0):
diff --git a/lib/lp/services/messaging/tests/test_rabbit.py b/lib/lp/services/messaging/tests/test_rabbit.py
index 8666638..c9e6449 100644
--- a/lib/lp/services/messaging/tests/test_rabbit.py
+++ b/lib/lp/services/messaging/tests/test_rabbit.py
@@ -5,9 +5,7 @@
from functools import partial
from itertools import count
-import socket
-import six
from testtools.testcase import ExpectedException
import transaction
from transaction._transaction import Status as TransactionStatus
@@ -93,7 +91,7 @@ class RabbitTestCase(TestCase):
layer = RabbitMQLayer
def tearDown(self):
- super(RabbitTestCase, self).tearDown()
+ super().tearDown()
global_session.reset()
global_unreliable_session.reset()
@@ -133,7 +131,7 @@ class TestRabbitSession(RabbitTestCase):
def new_close(*args, **kwargs):
old_close(*args, **kwargs)
- raise socket.error
+ raise OSError
with monkey_patch(session._connection, close=new_close):
session.disconnect()
@@ -217,7 +215,7 @@ class TestRabbitUnreliableSession(TestRabbitSession):
layer = RabbitMQLayer
def setUp(self):
- super(TestRabbitUnreliableSession, self).setUp()
+ super().setUp()
self.prev_oops = self.getOops()
def getOops(self):
@@ -396,7 +394,7 @@ class TestRabbit(RabbitTestCase):
return set()
else:
return {
- sync.session for sync in six.itervalues(syncs_set.data)
+ sync.session for sync in syncs_set.data.values()
if isinstance(sync, RabbitSessionTransactionSync)}
def test_global_session(self):