Merge ~cjwatson/launchpad:upgrade-type-annotations into launchpad:master

Proposed by Colin Watson
Status: Merged
Approved by: Colin Watson
Approved revision: f19cac695402ef7b341922b990cefde855867ca7
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~cjwatson/launchpad:upgrade-type-annotations
Merge into: launchpad:master
Diff against target: 1496 lines (+154/-157)
84 files modified
.pre-commit-config.yaml (+0/-2)
lib/lp/answers/adapters.py (+1/-1)
lib/lp/answers/browser/faqcollection.py (+1/-1)
lib/lp/answers/browser/tests/test_question.py (+1/-1)
lib/lp/answers/browser/tests/test_views.py (+1/-1)
lib/lp/answers/mail/__init__.py (+1/-1)
lib/lp/answers/security.py (+1/-1)
lib/lp/answers/tests/test_question_workflow.py (+1/-1)
lib/lp/answers/tests/test_questiontarget.py (+1/-1)
lib/lp/app/__init__.py (+1/-1)
lib/lp/app/browser/launchpadform.py (+3/-3)
lib/lp/app/browser/multistep.py (+1/-1)
lib/lp/app/browser/root.py (+1/-1)
lib/lp/app/browser/tests/test_vocabulary.py (+1/-1)
lib/lp/app/browser/tests/test_webservice.py (+3/-1)
lib/lp/app/browser/webservice.py (+1/-1)
lib/lp/app/security.py (+2/-2)
lib/lp/app/tests/test_yuitests.py (+1/-1)
lib/lp/app/utilities/celebrities.py (+1/-1)
lib/lp/app/widgets/date.py (+2/-1)
lib/lp/app/widgets/tests/test_itemswidgets.py (+2/-2)
lib/lp/archivepublisher/customupload.py (+2/-1)
lib/lp/archivepublisher/security.py (+1/-1)
lib/lp/archiveuploader/tests/test_buildduploads.py (+4/-3)
lib/lp/blueprints/browser/specification.py (+1/-1)
lib/lp/blueprints/browser/specificationbranch.py (+1/-1)
lib/lp/blueprints/browser/specificationsubscription.py (+1/-1)
lib/lp/blueprints/browser/sprint.py (+1/-1)
lib/lp/blueprints/mail/__init__.py (+1/-1)
lib/lp/bugs/browser/bug.py (+1/-1)
lib/lp/bugs/browser/bugalsoaffects.py (+2/-2)
lib/lp/bugs/browser/bugbranch.py (+1/-1)
lib/lp/bugs/browser/bugnomination.py (+1/-1)
lib/lp/bugs/browser/bugsubscription.py (+1/-1)
lib/lp/bugs/browser/bugtask.py (+1/-1)
lib/lp/bugs/externalbugtracker/base.py (+1/-1)
lib/lp/bugs/scripts/checkwatches/core.py (+1/-1)
lib/lp/bugs/scripts/tests/test_bugnotification.py (+7/-7)
lib/lp/bugs/scripts/tests/test_uct.py (+1/-1)
lib/lp/bugs/scripts/uct/models.py (+14/-16)
lib/lp/bugs/scripts/uct/uctexport.py (+4/-4)
lib/lp/bugs/scripts/uct/uctimport.py (+9/-9)
lib/lp/bugs/tests/externalbugtracker.py (+4/-4)
lib/lp/bugs/tests/test_buglinktarget.py (+1/-1)
lib/lp/bugs/tests/test_bugsearch_conjoined.py (+1/-1)
lib/lp/bugs/tests/test_bugtarget.py (+1/-1)
lib/lp/bugs/tests/test_bugtracker_components.py (+1/-1)
lib/lp/bugs/tests/test_bugwatch.py (+4/-4)
lib/lp/bugs/tests/test_bzremotecomponentfinder.py (+1/-1)
lib/lp/bugs/tests/test_externalbugtracker.py (+1/-1)
lib/lp/bugs/tests/test_yuitests.py (+1/-1)
lib/lp/buildmaster/downloader.py (+1/-1)
lib/lp/buildmaster/tests/test_buildfarmjob.py (+1/-1)
lib/lp/buildmaster/tests/test_manager.py (+1/-1)
lib/lp/charms/model/charmrecipebuildbehaviour.py (+1/-1)
lib/lp/code/model/cibuildbehaviour.py (+1/-1)
lib/lp/code/model/recipebuilder.py (+1/-1)
lib/lp/oci/model/ocirecipebuildbehaviour.py (+1/-1)
lib/lp/registry/browser/product.py (+1/-1)
lib/lp/registry/scripts/closeaccount.py (+1/-1)
lib/lp/registry/scripts/tests/test_closeaccount.py (+2/-2)
lib/lp/services/feeds/browser.py (+2/-2)
lib/lp/services/looptuner.py (+1/-1)
lib/lp/services/mail/commands.py (+1/-1)
lib/lp/services/scripts/base.py (+2/-2)
lib/lp/services/webapp/breadcrumb.py (+1/-1)
lib/lp/services/webapp/menu.py (+2/-2)
lib/lp/services/webapp/publisher.py (+2/-2)
lib/lp/services/webapp/vocabulary.py (+1/-1)
lib/lp/snappy/adapters/buildarch.py (+5/-7)
lib/lp/snappy/model/snapbuildbehaviour.py (+2/-2)
lib/lp/soyuz/browser/archivesubscription.py (+1/-1)
lib/lp/soyuz/model/binarypackagebuildbehaviour.py (+1/-1)
lib/lp/soyuz/model/livefsbuildbehaviour.py (+1/-3)
lib/lp/soyuz/security.py (+1/-1)
lib/lp/testing/__init__.py (+3/-3)
lib/lp/testing/pgsql.py (+5/-5)
lib/lp/testing/swift/tests/test_fixture.py (+2/-2)
lib/lp/testing/tests/test_layers.py (+2/-2)
lib/lp/testing/tests/test_sampledata.py (+2/-2)
lib/lp/testing/tests/test_standard_yuixhr_test_template.py (+2/-2)
lib/lp/testing/tests/test_yuixhr_fixture.py (+3/-3)
lib/lp/testing/tests/test_yuixhr_fixture_facet.py (+2/-2)
pyproject.toml (+1/-1)
Reviewer Review Type Date Requested Status
Jürgen Gmach Approve
Review via email: mp+456419@code.launchpad.net

Commit message

Upgrade variable type annotations to 3.6+ style

Description of the change

I haven't quite got as far as upgrading `flake8` since it reports a few other issues, but this gets us pretty close.

I had to add `Optional` to a few more places since otherwise `mypy` complained.

To post a comment you must log in.
Revision history for this message
Jürgen Gmach (jugmac00) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
2index 8f1b599..05418f1 100644
3--- a/.pre-commit-config.yaml
4+++ b/.pre-commit-config.yaml
5@@ -51,8 +51,6 @@ repos:
6 name: isort
7 args: [--profile, black]
8 - repo: https://github.com/PyCQA/flake8
9- # 6.0.0 drops support for `# type:` comments, which we need until we
10- # upgrade to Python >= 3.6.
11 rev: 5.0.4
12 hooks:
13 - id: flake8
14diff --git a/lib/lp/answers/adapters.py b/lib/lp/answers/adapters.py
15index 8a3865a..2c19616 100644
16--- a/lib/lp/answers/adapters.py
17+++ b/lib/lp/answers/adapters.py
18@@ -7,7 +7,7 @@ from typing import List
19
20 from lp.answers.interfaces.faqtarget import IFAQTarget
21
22-__all__ = [] # type: List[str]
23+__all__: List[str] = []
24
25
26 def question_to_questiontarget(question):
27diff --git a/lib/lp/answers/browser/faqcollection.py b/lib/lp/answers/browser/faqcollection.py
28index bf05b47..3eb527f 100644
29--- a/lib/lp/answers/browser/faqcollection.py
30+++ b/lib/lp/answers/browser/faqcollection.py
31@@ -31,7 +31,7 @@ from lp.services.webapp.menu import enabled_with_permission
32 class FAQCollectionMenu(NavigationMenu):
33 """Base menu definition for `IFAQCollection`."""
34
35- usedfor = IFAQCollection # type: Type[Interface]
36+ usedfor: Type[Interface] = IFAQCollection
37 facet = "answers"
38 links = ["list_all", "create_faq"]
39
40diff --git a/lib/lp/answers/browser/tests/test_question.py b/lib/lp/answers/browser/tests/test_question.py
41index c1583aa..a57c08c 100644
42--- a/lib/lp/answers/browser/tests/test_question.py
43+++ b/lib/lp/answers/browser/tests/test_question.py
44@@ -14,7 +14,7 @@ from lp.testing import TestCaseWithFactory, login_person, person_logged_in
45 from lp.testing.layers import DatabaseFunctionalLayer
46 from lp.testing.views import create_initialized_view
47
48-__all__ = [] # type: List[str]
49+__all__: List[str] = []
50
51
52 class TestQuestionAddView(TestCaseWithFactory):
53diff --git a/lib/lp/answers/browser/tests/test_views.py b/lib/lp/answers/browser/tests/test_views.py
54index c329907..d08678b 100644
55--- a/lib/lp/answers/browser/tests/test_views.py
56+++ b/lib/lp/answers/browser/tests/test_views.py
57@@ -10,7 +10,7 @@ from lp.testing import BrowserTestCase
58 from lp.testing.layers import DatabaseFunctionalLayer
59 from lp.testing.systemdocs import LayeredDocFileSuite, setUp, tearDown
60
61-__all__ = [] # type: List[str]
62+__all__: List[str] = []
63
64
65 class TestEmailObfuscated(BrowserTestCase):
66diff --git a/lib/lp/answers/mail/__init__.py b/lib/lp/answers/mail/__init__.py
67index 11b146c..eb81875 100644
68--- a/lib/lp/answers/mail/__init__.py
69+++ b/lib/lp/answers/mail/__init__.py
70@@ -2,4 +2,4 @@
71 # GNU Affero General Public License version 3 (see the file LICENSE).
72 from typing import List
73
74-__all__ = [] # type: List[str]
75+__all__: List[str] = []
76diff --git a/lib/lp/answers/security.py b/lib/lp/answers/security.py
77index 530b4f8..1ad66c4 100644
78--- a/lib/lp/answers/security.py
79+++ b/lib/lp/answers/security.py
80@@ -17,7 +17,7 @@ from lp.registry.interfaces.distributionsourcepackage import (
81 )
82 from lp.registry.security import EditByOwnersOrAdmins
83
84-__all__ = [] # type: List[str]
85+__all__: List[str] = []
86
87
88 class AdminQuestion(AuthorizationBase):
89diff --git a/lib/lp/answers/tests/test_question_workflow.py b/lib/lp/answers/tests/test_question_workflow.py
90index 2569042..28dcdeb 100644
91--- a/lib/lp/answers/tests/test_question_workflow.py
92+++ b/lib/lp/answers/tests/test_question_workflow.py
93@@ -38,7 +38,7 @@ from lp.testing import (
94 from lp.testing.fixture import ZopeEventHandlerFixture
95 from lp.testing.layers import DatabaseFunctionalLayer
96
97-__all__ = [] # type: List[str]
98+__all__: List[str] = []
99
100
101 class BaseAnswerTrackerWorkflowTestCase(TestCase):
102diff --git a/lib/lp/answers/tests/test_questiontarget.py b/lib/lp/answers/tests/test_questiontarget.py
103index dcaf579..f2dd83a 100644
104--- a/lib/lp/answers/tests/test_questiontarget.py
105+++ b/lib/lp/answers/tests/test_questiontarget.py
106@@ -17,7 +17,7 @@ from lp.testing import (
107 )
108 from lp.testing.layers import DatabaseFunctionalLayer
109
110-__all__ = [] # type: List[str]
111+__all__: List[str] = []
112
113
114 class QuestionTargetAnswerContactTestCase(TestCaseWithFactory):
115diff --git a/lib/lp/app/__init__.py b/lib/lp/app/__init__.py
116index 1df36b8..d847688 100644
117--- a/lib/lp/app/__init__.py
118+++ b/lib/lp/app/__init__.py
119@@ -16,7 +16,7 @@ from zope.formlib import itemswidgets
120 # for first page load.
121 import lp.app.versioninfo # noqa: F401
122
123-__all__ = [] # type: List[str]
124+__all__: List[str] = []
125
126
127 # Zope recently changed the behaviour of items widgets with regards to missing
128diff --git a/lib/lp/app/browser/launchpadform.py b/lib/lp/app/browser/launchpadform.py
129index 119bace..4ab0239 100644
130--- a/lib/lp/app/browser/launchpadform.py
131+++ b/lib/lp/app/browser/launchpadform.py
132@@ -61,9 +61,9 @@ class LaunchpadFormView(LaunchpadView):
133 prefix = "field"
134
135 # The form schema
136- schema = None # type: Type[Interface]
137+ schema: Optional[Type[Interface]] = None
138 # Subset of fields to use
139- field_names = None # type: Optional[List[str]]
140+ field_names: Optional[List[str]] = None
141
142 # The next URL to redirect to on successful form submission
143 @property
144@@ -93,7 +93,7 @@ class LaunchpadFormView(LaunchpadView):
145 # The for_input is passed through to create the fields. If this value
146 # is set to true in derived classes, then fields that are marked
147 # read only will have editable widgets created for them.
148- for_input = None # type: Optional[bool]
149+ for_input: Optional[bool] = None
150
151 def __init__(self, context, request):
152 LaunchpadView.__init__(self, context, request)
153diff --git a/lib/lp/app/browser/multistep.py b/lib/lp/app/browser/multistep.py
154index a8df433..6ac6cfb 100644
155--- a/lib/lp/app/browser/multistep.py
156+++ b/lib/lp/app/browser/multistep.py
157@@ -149,7 +149,7 @@ class StepView(LaunchpadFormView):
158 TextWidget, visible=False
159 )
160
161- _field_names = [] # type: List[str]
162+ _field_names: List[str] = []
163 step_name = ""
164 main_action_label = "Continue"
165 next_step = None
166diff --git a/lib/lp/app/browser/root.py b/lib/lp/app/browser/root.py
167index 5dc4181..2a87d2b 100644
168--- a/lib/lp/app/browser/root.py
169+++ b/lib/lp/app/browser/root.py
170@@ -56,7 +56,7 @@ class LaunchpadRootIndexView(HasAnnouncementsView, LaunchpadView):
171 """An view for the default view of the LaunchpadRoot."""
172
173 page_title = "Launchpad"
174- featured_projects = [] # type: List[Any]
175+ featured_projects: List[Any] = []
176 featured_projects_top = None
177
178 # Used by the footer to display the lp-arcana section.
179diff --git a/lib/lp/app/browser/tests/test_vocabulary.py b/lib/lp/app/browser/tests/test_vocabulary.py
180index 81f80cf..cfaaa90 100644
181--- a/lib/lp/app/browser/tests/test_vocabulary.py
182+++ b/lib/lp/app/browser/tests/test_vocabulary.py
183@@ -501,7 +501,7 @@ class TestDistributionPickerEntrySourceAdapter(TestCaseWithFactory):
184
185 @implementer(IHugeVocabulary)
186 class TestPersonVocabulary:
187- test_persons = [] # type: List[Person]
188+ test_persons: List[Person] = []
189
190 @classmethod
191 def setTestData(cls, person_list: List[Person]):
192diff --git a/lib/lp/app/browser/tests/test_webservice.py b/lib/lp/app/browser/tests/test_webservice.py
193index 2defa9d..634003d 100644
194--- a/lib/lp/app/browser/tests/test_webservice.py
195+++ b/lib/lp/app/browser/tests/test_webservice.py
196@@ -3,6 +3,8 @@
197
198 """Tests for webservice features across Launchpad."""
199
200+from typing import Optional
201+
202 from lazr.restful.interfaces import IFieldHTMLRenderer
203 from lazr.restful.utils import get_current_web_service_request
204 from zope.component import getMultiAdapter
205@@ -54,7 +56,7 @@ class BaseMissingObjectWebService:
206
207 layer = DatabaseFunctionalLayer
208
209- object_type = None # type: str
210+ object_type: Optional[str] = None
211
212 def test_object_not_found(self):
213 """Missing top-level objects generate 404s but not OOPS."""
214diff --git a/lib/lp/app/browser/webservice.py b/lib/lp/app/browser/webservice.py
215index 6fc2943..64f8734 100644
216--- a/lib/lp/app/browser/webservice.py
217+++ b/lib/lp/app/browser/webservice.py
218@@ -16,7 +16,7 @@ from zope.schema.interfaces import IText
219 from lp.app.browser.stringformatter import FormattersAPI
220 from lp.app.browser.tales import format_link
221
222-__all__ = [] # type: List[str]
223+__all__: List[str] = []
224
225
226 @component.adapter(Interface, IReference, IWebServiceClientRequest)
227diff --git a/lib/lp/app/security.py b/lib/lp/app/security.py
228index 37ccc27..3c37dce 100644
229--- a/lib/lp/app/security.py
230+++ b/lib/lp/app/security.py
231@@ -21,8 +21,8 @@ from lp.app.interfaces.security import IAuthorization
232
233 @implementer(IAuthorization)
234 class AuthorizationBase:
235- permission = None # type: Optional[str]
236- usedfor = None # type: Optional[Type[Interface]]
237+ permission: Optional[str] = None
238+ usedfor: Optional[Type[Interface]] = None
239
240 def __init__(self, obj):
241 self.obj = obj
242diff --git a/lib/lp/app/tests/test_yuitests.py b/lib/lp/app/tests/test_yuitests.py
243index cfa0a8e..7c3b8fc 100644
244--- a/lib/lp/app/tests/test_yuitests.py
245+++ b/lib/lp/app/tests/test_yuitests.py
246@@ -7,7 +7,7 @@ from typing import List
247 from lp.testing import YUIUnitTestCase, build_yui_unittest_suite
248 from lp.testing.layers import YUITestLayer
249
250-__all__ = [] # type: List[str]
251+__all__: List[str] = []
252
253
254 class AppYUIUnitTestCase(YUIUnitTestCase):
255diff --git a/lib/lp/app/utilities/celebrities.py b/lib/lp/app/utilities/celebrities.py
256index 3f54349..e17ac36 100644
257--- a/lib/lp/app/utilities/celebrities.py
258+++ b/lib/lp/app/utilities/celebrities.py
259@@ -105,7 +105,7 @@ class PersonCelebrityDescriptor(CelebrityDescriptor):
260 """
261
262 # Populated by the constructor.
263- names = set() # type: Set[str]
264+ names: Set[str] = set()
265
266 def __init__(self, name):
267 PersonCelebrityDescriptor.names.add(name)
268diff --git a/lib/lp/app/widgets/date.py b/lib/lp/app/widgets/date.py
269index a54e85f..99d8f3f 100644
270--- a/lib/lp/app/widgets/date.py
271+++ b/lib/lp/app/widgets/date.py
272@@ -18,6 +18,7 @@ __all__ = [
273 ]
274
275 from datetime import datetime, timezone, tzinfo
276+from typing import Optional
277
278 from dateutil import tz
279 from zope.browserpage import ViewPageTemplateFile
280@@ -114,7 +115,7 @@ class DateTimeWidget(TextWidget):
281 """
282
283 timeformat = "%Y-%m-%d %H:%M:%S"
284- required_time_zone_name = None # type: str
285+ required_time_zone_name: Optional[str] = None
286 display_zone = True
287 from_date = None
288 to_date = None
289diff --git a/lib/lp/app/widgets/tests/test_itemswidgets.py b/lib/lp/app/widgets/tests/test_itemswidgets.py
290index 4a604b9..7d4e427 100644
291--- a/lib/lp/app/widgets/tests/test_itemswidgets.py
292+++ b/lib/lp/app/widgets/tests/test_itemswidgets.py
293@@ -2,7 +2,7 @@
294 # GNU Affero General Public License version 3 (see the file LICENSE).
295
296 import doctest
297-from typing import Any, Type
298+from typing import Any, Optional, Type
299
300 from lazr.enum import EnumeratedType, Item
301 from lazr.enum._enum import DBEnumeratedType, DBItem
302@@ -32,7 +32,7 @@ class ItemWidgetTestCase(TestCaseWithFactory):
303
304 layer = DatabaseFunctionalLayer
305
306- WIDGET_CLASS = None # type: Type[Any]
307+ WIDGET_CLASS: Optional[Type[Any]] = None
308 SAFE_TERM = SimpleTerm("object-1", "token-1", "Safe title")
309 UNSAFE_TERM = SimpleTerm("object-2", "token-2", "<unsafe> &nbsp; title")
310
311diff --git a/lib/lp/archivepublisher/customupload.py b/lib/lp/archivepublisher/customupload.py
312index 2759c2f..348f8f8 100644
313--- a/lib/lp/archivepublisher/customupload.py
314+++ b/lib/lp/archivepublisher/customupload.py
315@@ -17,6 +17,7 @@ import os
316 import shutil
317 import tarfile
318 import tempfile
319+from typing import Optional
320
321 from zope.interface import implementer
322
323@@ -113,7 +114,7 @@ class CustomUpload:
324 """Base class for custom upload handlers"""
325
326 # This should be set as a class property on each subclass.
327- custom_type = None # type: str
328+ custom_type: Optional[str] = None
329
330 @classmethod
331 def publish(cls, packageupload, libraryfilealias, logger=None):
332diff --git a/lib/lp/archivepublisher/security.py b/lib/lp/archivepublisher/security.py
333index 3326cf9..8e186d6 100644
334--- a/lib/lp/archivepublisher/security.py
335+++ b/lib/lp/archivepublisher/security.py
336@@ -7,7 +7,7 @@ from typing import List
337 from lp.archivepublisher.interfaces.publisherconfig import IPublisherConfig
338 from lp.security import AdminByAdminsTeam
339
340-__all__ = [] # type: List[str]
341+__all__: List[str] = []
342
343
344 # If edit access to this is ever opened up beyond admins, then we need to
345diff --git a/lib/lp/archiveuploader/tests/test_buildduploads.py b/lib/lp/archiveuploader/tests/test_buildduploads.py
346index c368db7..edb18b3 100644
347--- a/lib/lp/archiveuploader/tests/test_buildduploads.py
348+++ b/lib/lp/archiveuploader/tests/test_buildduploads.py
349@@ -4,6 +4,7 @@
350 """Test buildd uploads use-cases."""
351
352 import os
353+from typing import Optional
354
355 from zope.component import getUtility
356
357@@ -26,9 +27,9 @@ from lp.testing.gpgkeys import import_public_test_keys
358 class TestStagedBinaryUploadBase(TestUploadProcessorBase):
359 name = "baz"
360 version = "1.0-1"
361- distribution_name = None # type: str
362- distroseries_name = None # type: str
363- pocket = None # type: PackagePublishingPocket
364+ distribution_name: Optional[str] = None
365+ distroseries_name: Optional[str] = None
366+ pocket: Optional[PackagePublishingPocket] = None
367 policy = "buildd"
368 no_mails = True
369
370diff --git a/lib/lp/blueprints/browser/specification.py b/lib/lp/blueprints/browser/specification.py
371index 262b7d6..d35775b 100644
372--- a/lib/lp/blueprints/browser/specification.py
373+++ b/lib/lp/blueprints/browser/specification.py
374@@ -1043,7 +1043,7 @@ class SpecificationGoalDecideView(LaunchpadFormView):
375 """
376
377 schema = Interface
378- field_names = [] # type: List[str]
379+ field_names: List[str] = []
380
381 @property
382 def label(self):
383diff --git a/lib/lp/blueprints/browser/specificationbranch.py b/lib/lp/blueprints/browser/specificationbranch.py
384index 1ee6fe9..357bf24 100644
385--- a/lib/lp/blueprints/browser/specificationbranch.py
386+++ b/lib/lp/blueprints/browser/specificationbranch.py
387@@ -47,7 +47,7 @@ class SpecificationBranchStatusView(LaunchpadEditFormView):
388 """Edit the summary of the SpecificationBranch link."""
389
390 schema = ISpecificationBranch
391- field_names = [] # type: List[str]
392+ field_names: List[str] = []
393 label = _("Delete link between specification and branch")
394
395 def initialize(self):
396diff --git a/lib/lp/blueprints/browser/specificationsubscription.py b/lib/lp/blueprints/browser/specificationsubscription.py
397index c8f9432..ba94b5f 100644
398--- a/lib/lp/blueprints/browser/specificationsubscription.py
399+++ b/lib/lp/blueprints/browser/specificationsubscription.py
400@@ -79,7 +79,7 @@ class SpecificationSubscriptionDeleteView(LaunchpadFormView):
401 """Used to unsubscribe someone from a blueprint."""
402
403 schema = ISpecificationSubscription
404- field_names = [] # type: List[str]
405+ field_names: List[str] = []
406
407 @property
408 def label(self):
409diff --git a/lib/lp/blueprints/browser/sprint.py b/lib/lp/blueprints/browser/sprint.py
410index d7eb8d0..a22ebaa 100644
411--- a/lib/lp/blueprints/browser/sprint.py
412+++ b/lib/lp/blueprints/browser/sprint.py
413@@ -403,7 +403,7 @@ class SprintDeleteView(LaunchpadFormView):
414 """Form for deleting sprints."""
415
416 schema = ISprint
417- field_names = [] # type: List[str]
418+ field_names: List[str] = []
419 next_url = None
420
421 @property
422diff --git a/lib/lp/blueprints/mail/__init__.py b/lib/lp/blueprints/mail/__init__.py
423index 11b146c..eb81875 100644
424--- a/lib/lp/blueprints/mail/__init__.py
425+++ b/lib/lp/blueprints/mail/__init__.py
426@@ -2,4 +2,4 @@
427 # GNU Affero General Public License version 3 (see the file LICENSE).
428 from typing import List
429
430-__all__ = [] # type: List[str]
431+__all__: List[str] = []
432diff --git a/lib/lp/bugs/browser/bug.py b/lib/lp/bugs/browser/bug.py
433index 3805a15..9cbd9a4 100644
434--- a/lib/lp/bugs/browser/bug.py
435+++ b/lib/lp/bugs/browser/bug.py
436@@ -188,7 +188,7 @@ class BugSetNavigation(Navigation):
437 class BugContextMenu(ContextMenu):
438 """Context menu of actions that can be performed upon a Bug."""
439
440- usedfor = IBug # type: Type[Interface]
441+ usedfor: Type[Interface] = IBug
442 links = [
443 "editdescription",
444 "markduplicate",
445diff --git a/lib/lp/bugs/browser/bugalsoaffects.py b/lib/lp/bugs/browser/bugalsoaffects.py
446index 3558dc4..ff6e6cb 100644
447--- a/lib/lp/bugs/browser/bugalsoaffects.py
448+++ b/lib/lp/bugs/browser/bugalsoaffects.py
449@@ -215,7 +215,7 @@ class BugTaskCreationStep(AlsoAffectsStep):
450
451 initial_focus_widget = "bug_url"
452 step_name = "specify_remote_bug_url"
453- target_field_names = () # type: Tuple[str, ...]
454+ target_field_names: Tuple[str, ...] = ()
455
456 # This is necessary so that other views which dispatch work to this one
457 # have access to the newly created task.
458@@ -759,7 +759,7 @@ class BugTrackerCreationStep(AlsoAffectsStep):
459 )
460 step_name = "bugtracker_creation"
461 main_action_label = "Register Bug Tracker and Add to Bug Report"
462- _next_step = None # type: Type[StepView]
463+ _next_step: Type[StepView] = None
464
465 def main_action(self, data):
466 assert (
467diff --git a/lib/lp/bugs/browser/bugbranch.py b/lib/lp/bugs/browser/bugbranch.py
468index 1dc0cd1..02e2292 100644
469--- a/lib/lp/bugs/browser/bugbranch.py
470+++ b/lib/lp/bugs/browser/bugbranch.py
471@@ -67,7 +67,7 @@ class BugBranchDeleteView(LaunchpadEditFormView):
472
473 schema = IBugBranch
474
475- field_names = [] # type: List[str]
476+ field_names: List[str] = []
477
478 def initialize(self):
479 LaunchpadEditFormView.initialize(self)
480diff --git a/lib/lp/bugs/browser/bugnomination.py b/lib/lp/bugs/browser/bugnomination.py
481index 22d8941..91b328d 100644
482--- a/lib/lp/bugs/browser/bugnomination.py
483+++ b/lib/lp/bugs/browser/bugnomination.py
484@@ -172,7 +172,7 @@ class BugNominationEditView(LaunchpadFormView):
485 """Browser view class for approving and declining nominations."""
486
487 schema = Interface
488- field_names = [] # type: List[str]
489+ field_names: List[str] = []
490
491 @property
492 def label(self):
493diff --git a/lib/lp/bugs/browser/bugsubscription.py b/lib/lp/bugs/browser/bugsubscription.py
494index 4514f80..7d8a776 100644
495--- a/lib/lp/bugs/browser/bugsubscription.py
496+++ b/lib/lp/bugs/browser/bugsubscription.py
497@@ -712,7 +712,7 @@ class BugMuteSelfView(LaunchpadFormView):
498 """A view to mute a user's bug mail for a given bug."""
499
500 schema = IBugSubscription
501- field_names = [] # type: List[str]
502+ field_names: List[str] = []
503
504 @property
505 def label(self):
506diff --git a/lib/lp/bugs/browser/bugtask.py b/lib/lp/bugs/browser/bugtask.py
507index 2b2aaed..8fcb135 100644
508--- a/lib/lp/bugs/browser/bugtask.py
509+++ b/lib/lp/bugs/browser/bugtask.py
510@@ -1730,7 +1730,7 @@ class BugTaskDeletionView(ReturnToReferrerMixin, LaunchpadFormView):
511 """Used to delete a bugtask."""
512
513 schema = IBugTask
514- field_names = [] # type: List[str]
515+ field_names: List[str] = []
516
517 label = "Remove bug task"
518 page_title = label
519diff --git a/lib/lp/bugs/externalbugtracker/base.py b/lib/lp/bugs/externalbugtracker/base.py
520index ee7be38..13860cd 100644
521--- a/lib/lp/bugs/externalbugtracker/base.py
522+++ b/lib/lp/bugs/externalbugtracker/base.py
523@@ -157,7 +157,7 @@ def repost_on_redirect_hook(response, *args, **kwargs):
524 class ExternalBugTracker:
525 """Base class for an external bug tracker."""
526
527- batch_size = None # type: Optional[int]
528+ batch_size: Optional[int] = None
529 batch_query_threshold = config.checkwatches.batch_query_threshold
530 timeout = config.checkwatches.default_socket_timeout
531 comment_template = "default_remotecomment_template.txt"
532diff --git a/lib/lp/bugs/scripts/checkwatches/core.py b/lib/lp/bugs/scripts/checkwatches/core.py
533index 9589bd4..fca0235 100644
534--- a/lib/lp/bugs/scripts/checkwatches/core.py
535+++ b/lib/lp/bugs/scripts/checkwatches/core.py
536@@ -60,7 +60,7 @@ from lp.services.scripts.logger import log as default_log
537 LOGIN = "bugwatch@bugs.launchpad.net"
538
539 # A list of product names for which comments should be synchronized.
540-SYNCABLE_GNOME_PRODUCTS = [] # type: List[str]
541+SYNCABLE_GNOME_PRODUCTS: List[str] = []
542
543 # When syncing with a remote bug tracker that reports its idea of the
544 # current time, this defined the maximum acceptable skew between the
545diff --git a/lib/lp/bugs/scripts/tests/test_bugnotification.py b/lib/lp/bugs/scripts/tests/test_bugnotification.py
546index e6a8cd9..0e612f5 100644
547--- a/lib/lp/bugs/scripts/tests/test_bugnotification.py
548+++ b/lib/lp/bugs/scripts/tests/test_bugnotification.py
549@@ -82,7 +82,7 @@ class MockBug:
550
551 duplicateof = None
552 information_type = InformationType.PUBLIC
553- messages = [] # type: List[Message]
554+ messages: List[Message] = []
555
556 def __init__(self, id, owner):
557 self.id = id
558@@ -721,12 +721,12 @@ class EmailNotificationTestBase(TestCaseWithFactory):
559
560
561 class EmailNotificationsBugMixin:
562- change_class = None # type: Optional[Type[Any]]
563- change_name = None # type: Optional[str]
564- old = None # type: Any
565- new = None # type: Any
566- alt = None # type: Any
567- unexpected_bytes = None # type: Optional[bytes]
568+ change_class: Optional[Type[Any]] = None
569+ change_name: Optional[str] = None
570+ old: Any = None
571+ new: Any = None
572+ alt: Any = None
573+ unexpected_bytes: Optional[bytes] = None
574
575 def change(self, old, new):
576 self.bug.addChange(
577diff --git a/lib/lp/bugs/scripts/tests/test_uct.py b/lib/lp/bugs/scripts/tests/test_uct.py
578index c6aa91f..f029f28 100644
579--- a/lib/lp/bugs/scripts/tests/test_uct.py
580+++ b/lib/lp/bugs/scripts/tests/test_uct.py
581@@ -713,7 +713,7 @@ class TestUCTImporterExporter(TestCaseWithFactory):
582 self.checkBugAttachments(bug, cve)
583
584 def checkBugTasks(self, bug: Bug, cve: CVE):
585- bug_tasks = bug.bugtasks # type: List[BugTask]
586+ bug_tasks: List[BugTask] = bug.bugtasks
587
588 self.assertEqual(
589 len(cve.distro_packages)
590diff --git a/lib/lp/bugs/scripts/uct/models.py b/lib/lp/bugs/scripts/uct/models.py
591index 91cb076..e11ce8c 100644
592--- a/lib/lp/bugs/scripts/uct/models.py
593+++ b/lib/lp/bugs/scripts/uct/models.py
594@@ -153,15 +153,13 @@ class UCTRecord:
595 applying some data transformations along the way.
596 """
597
598- cve_data = load_cve(str(cve_path)) # type: Dict[str, Any]
599+ cve_data: Dict[str, Any] = load_cve(str(cve_path))
600
601 packages = []
602- tags = cls._pop_cve_property(
603- cve_data, "tags"
604- ) # type: Dict[str, Set[str]]
605- patches = cls._pop_cve_property(
606+ tags: Dict[str, Set[str]] = cls._pop_cve_property(cve_data, "tags")
607+ patches: Dict[str, List[Tuple[str, str]]] = cls._pop_cve_property(
608 cve_data, "patches"
609- ) # type: Dict[str, List[Tuple[str, str]]]
610+ )
611 for package, statuses_dict in cls._pop_cve_property(
612 cve_data, "pkgs"
613 ).items():
614@@ -515,7 +513,7 @@ class CVE:
615 self.notes = notes
616 self.mitigation = mitigation
617 self.cvss = cvss
618- self.patch_urls = patch_urls or [] # type: List[CVE.PatchURL]
619+ self.patch_urls: List[CVE.PatchURL] = patch_urls or []
620
621 @classmethod
622 def make_from_uct_record(cls, uct_record: UCTRecord) -> "CVE":
623@@ -531,9 +529,9 @@ class CVE:
624
625 spn_set = getUtility(ISourcePackageNameSet)
626
627- upstream_statuses = (
628- OrderedDict()
629- ) # type: Dict[SourcePackageName, UCTRecord.SeriesPackageStatus]
630+ upstream_statuses: Dict[
631+ SourcePackageName, UCTRecord.SeriesPackageStatus
632+ ] = OrderedDict()
633
634 for uct_package in uct_record.packages:
635 source_package_name = spn_set.getOrCreateByName(uct_package.name)
636@@ -669,22 +667,22 @@ class CVE:
637
638 This maps Launchpad data structures to the format that UCT understands.
639 """
640- series_packages_by_name = defaultdict(
641- list
642- ) # type: Dict[SourcePackageName, List[CVE.SeriesPackage]]
643+ series_packages_by_name: Dict[
644+ SourcePackageName, List[CVE.SeriesPackage]
645+ ] = defaultdict(list)
646 for series_package in self.series_packages:
647 series_packages_by_name[series_package.package_name].append(
648 series_package
649 )
650
651- packages_by_name = OrderedDict() # type: Dict[str, UCTRecord.Package]
652- processed_packages = set() # type: Set[SourcePackageName]
653+ packages_by_name: Dict[str, UCTRecord.Package] = OrderedDict()
654+ processed_packages: Set[SourcePackageName] = set()
655 for distro_package in self.distro_packages:
656 spn = distro_package.package_name
657 if spn in processed_packages:
658 continue
659 processed_packages.add(spn)
660- statuses = [] # type: List[UCTRecord.SeriesPackageStatus]
661+ statuses: List[UCTRecord.SeriesPackageStatus] = []
662 for series_package in series_packages_by_name[spn]:
663 series = series_package.target.distroseries
664 if series.status == SeriesStatus.DEVELOPMENT:
665diff --git a/lib/lp/bugs/scripts/uct/uctexport.py b/lib/lp/bugs/scripts/uct/uctexport.py
666index e91fba5..3745874 100644
667--- a/lib/lp/bugs/scripts/uct/uctexport.py
668+++ b/lib/lp/bugs/scripts/uct/uctexport.py
669@@ -91,13 +91,13 @@ class UCTExporter:
670 raise ValueError(
671 f"Bug with ID: {bug.id} does not have vulnerabilities"
672 )
673- vulnerability = vulnerabilities[0] # type: Vulnerability
674+ vulnerability: Vulnerability = vulnerabilities[0]
675 if not vulnerability.cve:
676 raise ValueError(
677 "Bug with ID: {} - vulnerability "
678 "is not linked to a CVE".format(bug.id)
679 )
680- lp_cve = vulnerability.cve # type: CveModel
681+ lp_cve: CveModel = vulnerability.cve
682
683 parsed_description = self._parse_bug_description(bug.description)
684
685@@ -105,7 +105,7 @@ class UCTExporter:
686 for bug_watch in bug.watches:
687 bug_urls.append(bug_watch.url)
688
689- bug_tasks = list(bug.bugtasks) # type: List[BugTask]
690+ bug_tasks: List[BugTask] = list(bug.bugtasks)
691
692 cve_importance = vulnerability.importance
693
694@@ -118,7 +118,7 @@ class UCTExporter:
695 # DistroPackage importance
696 package_importances = {}
697
698- package_name_by_product = {} # type: Dict[Product, SourcePackageName]
699+ package_name_by_product: Dict[Product, SourcePackageName] = {}
700 # We need to process all distribution package tasks before processing
701 # the distro-series tasks to collect importance value for each package.
702 distro_packages = []
703diff --git a/lib/lp/bugs/scripts/uct/uctimport.py b/lib/lp/bugs/scripts/uct/uctimport.py
704index 17a4ed7..845b060 100644
705--- a/lib/lp/bugs/scripts/uct/uctimport.py
706+++ b/lib/lp/bugs/scripts/uct/uctimport.py
707@@ -104,9 +104,9 @@ class UCTImporter:
708 cve.series_packages,
709 )
710 return
711- lp_cve = removeSecurityProxy(
712+ lp_cve: CveModel = removeSecurityProxy(
713 getUtility(ICveSet)[cve.sequence]
714- ) # type: CveModel
715+ )
716 if lp_cve is None:
717 logger.warning(
718 "%s: could not find the CVE in LP. Aborting.", cve.sequence
719@@ -154,7 +154,7 @@ class UCTImporter:
720 distro_package = cve.distro_packages[0]
721
722 # Create the bug
723- bug = getUtility(IBugSet).createBug(
724+ bug: BugModel = getUtility(IBugSet).createBug(
725 CreateBugParams(
726 comment=self._make_bug_description(cve),
727 title=cve.sequence,
728@@ -164,7 +164,7 @@ class UCTImporter:
729 importance=distro_package.importance,
730 cve=lp_cve,
731 )
732- ) # type: BugModel
733+ )
734
735 self._update_external_bug_urls(bug, cve.bug_urls)
736 self._update_patches(bug, cve.patch_urls)
737@@ -274,7 +274,7 @@ class UCTImporter:
738 :param distro_packages: list of `DistroPackage`s from a `CVE`
739 :param series_packages: list of `SeriesPackage`s from a `CVE`
740 """
741- bug_tasks = bug.bugtasks # type: List[BugTask]
742+ bug_tasks: List[BugTask] = bug.bugtasks
743 bug_task_by_target = {t.target: t for t in bug_tasks}
744 bug_task_set = getUtility(IBugTaskSet)
745 for package in chain(
746@@ -301,14 +301,14 @@ class UCTImporter:
747 :param distribution: a `Distribution` affected by the vulnerability
748 :return: a Vulnerability
749 """
750- vulnerability = getUtility(IVulnerabilitySet).new(
751+ vulnerability: Vulnerability = getUtility(IVulnerabilitySet).new(
752 distribution=distribution,
753 status=cve.status,
754 importance=cve.importance,
755 creator=bug.owner,
756 information_type=InformationType.PUBLICSECURITY,
757 cve=lp_cve,
758- ) # type: Vulnerability
759+ )
760 self._update_vulnerability(vulnerability, cve)
761
762 vulnerability.linkBug(bug, bug.owner)
763@@ -393,10 +393,10 @@ class UCTImporter:
764 :param distro_packages: list of `DistroPackage`s from a `CVE`
765 :param series_packages: list of `SeriesPackage`s from a `CVE`
766 """
767- bug_tasks = bug.bugtasks # type: List[BugTask]
768+ bug_tasks: List[BugTask] = bug.bugtasks
769 bug_task_by_target = {t.target: t for t in bug_tasks}
770
771- package_importances = {} # type: Dict[str, BugTaskImportance]
772+ package_importances: Dict[str, BugTaskImportance] = {}
773
774 for dp in distro_packages:
775 task = bug_task_by_target[dp.target]
776diff --git a/lib/lp/bugs/tests/externalbugtracker.py b/lib/lp/bugs/tests/externalbugtracker.py
777index 7e24caa..59b9e3d 100644
778--- a/lib/lp/bugs/tests/externalbugtracker.py
779+++ b/lib/lp/bugs/tests/externalbugtracker.py
780@@ -543,11 +543,11 @@ class TestBugzillaXMLRPCTransport(RequestsTransport):
781 }
782
783 # Methods that require authentication.
784- auth_required_methods = (
785+ auth_required_methods: Tuple[str, ...] = (
786 "add_comment",
787 "login_required",
788 "set_link",
789- ) # type: Tuple[str, ...]
790+ )
791
792 expired_cookie = None
793
794@@ -1363,8 +1363,8 @@ def strip_trac_comment(comment):
795 class TestTracXMLRPCTransport(RequestsTransport):
796 """An XML-RPC transport to be used when testing Trac."""
797
798- remote_bugs = {} # type: Dict[str, Dict[str, Any]]
799- launchpad_bugs = {} # type: Dict[str, int]
800+ remote_bugs: Dict[str, Dict[str, Any]] = {}
801+ launchpad_bugs: Dict[str, int] = {}
802 seconds_since_epoch = None
803 local_timezone = "UTC"
804 utc_offset = 0
805diff --git a/lib/lp/bugs/tests/test_buglinktarget.py b/lib/lp/bugs/tests/test_buglinktarget.py
806index 9618d00..e96e5e2 100644
807--- a/lib/lp/bugs/tests/test_buglinktarget.py
808+++ b/lib/lp/bugs/tests/test_buglinktarget.py
809@@ -20,7 +20,7 @@ from lp.testing.factory import LaunchpadObjectFactory
810 from lp.testing.layers import LaunchpadFunctionalLayer
811 from lp.testing.systemdocs import LayeredDocFileSuite, setUp, tearDown
812
813-__all__ = [] # type: List[str]
814+__all__: List[str] = []
815
816
817 def questionSetUp(test):
818diff --git a/lib/lp/bugs/tests/test_bugsearch_conjoined.py b/lib/lp/bugs/tests/test_bugsearch_conjoined.py
819index cdb2f82..b4bbce4 100644
820--- a/lib/lp/bugs/tests/test_bugsearch_conjoined.py
821+++ b/lib/lp/bugs/tests/test_bugsearch_conjoined.py
822@@ -20,7 +20,7 @@ from lp.testing import (
823 from lp.testing.layers import DatabaseFunctionalLayer
824 from lp.testing.matchers import HasQueryCount
825
826-__all__ = [] # type: List[str]
827+__all__: List[str] = []
828
829
830 class TestSearchBase(TestCaseWithFactory):
831diff --git a/lib/lp/bugs/tests/test_bugtarget.py b/lib/lp/bugs/tests/test_bugtarget.py
832index f1427b7..06ff959 100644
833--- a/lib/lp/bugs/tests/test_bugtarget.py
834+++ b/lib/lp/bugs/tests/test_bugtarget.py
835@@ -23,7 +23,7 @@ from lp.testing import TestCaseWithFactory, person_logged_in
836 from lp.testing.layers import DatabaseFunctionalLayer
837 from lp.testing.systemdocs import LayeredDocFileSuite, setUp, tearDown
838
839-__all__ = [] # type: List[str]
840+__all__: List[str] = []
841
842
843 def bugtarget_filebug(bugtarget, summary, status=None):
844diff --git a/lib/lp/bugs/tests/test_bugtracker_components.py b/lib/lp/bugs/tests/test_bugtracker_components.py
845index 3da7150..a8c640a 100644
846--- a/lib/lp/bugs/tests/test_bugtracker_components.py
847+++ b/lib/lp/bugs/tests/test_bugtracker_components.py
848@@ -9,7 +9,7 @@ import transaction
849 from lp.testing import TestCaseWithFactory, login_person, ws_object
850 from lp.testing.layers import AppServerLayer, DatabaseFunctionalLayer
851
852-__all__ = [] # type: List[str]
853+__all__: List[str] = []
854
855
856 class BugTrackerComponentTestCase(TestCaseWithFactory):
857diff --git a/lib/lp/bugs/tests/test_bugwatch.py b/lib/lp/bugs/tests/test_bugwatch.py
858index d9779d1..f12097e 100644
859--- a/lib/lp/bugs/tests/test_bugwatch.py
860+++ b/lib/lp/bugs/tests/test_bugwatch.py
861@@ -228,16 +228,16 @@ class ExtractBugTrackerAndBugTest(WithScenarios, TestCase):
862 layer = LaunchpadFunctionalLayer
863
864 # A URL to an unregistered bug tracker.
865- base_url = None # type: str
866+ base_url: str = None
867
868 # The bug tracker type to be tested.
869 bugtracker_type = None
870
871 # A sample URL to a bug in the bug tracker.
872- bug_url = None # type: str
873+ bug_url: str = None
874
875 # The bug id in the sample bug_url.
876- bug_id = None # type: Optional[str]
877+ bug_id: Optional[str] = None
878
879 # True if the bug tracker is already registered in sampledata.
880 already_registered = False
881@@ -383,7 +383,7 @@ class EmailAddressExtractBugTrackerAndBugTest(ExtractBugTrackerAndBugTest):
882 Ensure BugWatchSet.extractBugTrackerAndBug works with email addresses.
883 """
884
885- scenarios = [] # type: List
886+ scenarios: List = []
887 bugtracker_type = BugTrackerType.EMAILADDRESS
888 bug_url = "mailto:foo.bar@example.com"
889 base_url = "mailto:foo.bar@example.com"
890diff --git a/lib/lp/bugs/tests/test_bzremotecomponentfinder.py b/lib/lp/bugs/tests/test_bzremotecomponentfinder.py
891index 3e2c210..b1fa024 100644
892--- a/lib/lp/bugs/tests/test_bzremotecomponentfinder.py
893+++ b/lib/lp/bugs/tests/test_bzremotecomponentfinder.py
894@@ -20,7 +20,7 @@ from lp.testing import TestCaseWithFactory, login
895 from lp.testing.layers import DatabaseFunctionalLayer
896 from lp.testing.sampledata import ADMIN_EMAIL
897
898-__all__ = [] # type: List[str]
899+__all__: List[str] = []
900
901
902 def read_test_file(name):
903diff --git a/lib/lp/bugs/tests/test_externalbugtracker.py b/lib/lp/bugs/tests/test_externalbugtracker.py
904index 44d2398..0762d42 100644
905--- a/lib/lp/bugs/tests/test_externalbugtracker.py
906+++ b/lib/lp/bugs/tests/test_externalbugtracker.py
907@@ -9,7 +9,7 @@ from typing import List
908 from lp.testing.layers import LaunchpadFunctionalLayer
909 from lp.testing.systemdocs import LayeredDocFileSuite, setUp, tearDown
910
911-__all__ = [] # type: List[str]
912+__all__: List[str] = []
913
914
915 def test_suite():
916diff --git a/lib/lp/bugs/tests/test_yuitests.py b/lib/lp/bugs/tests/test_yuitests.py
917index 7ba7c62..761a13f 100644
918--- a/lib/lp/bugs/tests/test_yuitests.py
919+++ b/lib/lp/bugs/tests/test_yuitests.py
920@@ -7,7 +7,7 @@ from typing import List
921 from lp.testing import YUIUnitTestCase, build_yui_unittest_suite
922 from lp.testing.layers import YUITestLayer
923
924-__all__ = [] # type: List[str]
925+__all__: List[str] = []
926
927
928 class BugsYUIUnitTestCase(YUIUnitTestCase):
929diff --git a/lib/lp/buildmaster/downloader.py b/lib/lp/buildmaster/downloader.py
930index 68aab4d..fc16852 100644
931--- a/lib/lp/buildmaster/downloader.py
932+++ b/lib/lp/buildmaster/downloader.py
933@@ -30,7 +30,7 @@ class DownloadCommand(amp.Command):
934 (b"path_to_write", amp.Unicode()),
935 (b"timeout", amp.Integer()),
936 ]
937- response = [] # type: List[Tuple[bytes, amp.Argument]]
938+ response: List[Tuple[bytes, amp.Argument]] = []
939 errors = {
940 RequestException: b"REQUEST_ERROR",
941 StreamingError: b"STREAMING_ERROR",
942diff --git a/lib/lp/buildmaster/tests/test_buildfarmjob.py b/lib/lp/buildmaster/tests/test_buildfarmjob.py
943index caf952f..86ceae3 100644
944--- a/lib/lp/buildmaster/tests/test_buildfarmjob.py
945+++ b/lib/lp/buildmaster/tests/test_buildfarmjob.py
946@@ -31,7 +31,7 @@ from lp.testing.layers import (
947
948
949 class TestBuildFarmJobBase:
950- layer = DatabaseFunctionalLayer # type: Type[BaseLayer]
951+ layer: Type[BaseLayer] = DatabaseFunctionalLayer
952
953 def setUp(self, *args, **kwargs):
954 """Create a build farm job with which to test."""
955diff --git a/lib/lp/buildmaster/tests/test_manager.py b/lib/lp/buildmaster/tests/test_manager.py
956index 78d42df..74c2626 100644
957--- a/lib/lp/buildmaster/tests/test_manager.py
958+++ b/lib/lp/buildmaster/tests/test_manager.py
959@@ -1128,7 +1128,7 @@ class TestPrefetchedBuilderFactory(TestCaseWithFactory):
960 class FakeBuilddManager:
961 """A minimal fake version of `BuilddManager`."""
962
963- pending_logtails = {} # type: Dict[int, str]
964+ pending_logtails: Dict[int, str] = {}
965
966 def addLogTail(self, build_queue_id, logtail):
967 self.pending_logtails[build_queue_id] = logtail
968diff --git a/lib/lp/charms/model/charmrecipebuildbehaviour.py b/lib/lp/charms/model/charmrecipebuildbehaviour.py
969index 9e95250..5e7bf50 100644
970--- a/lib/lp/charms/model/charmrecipebuildbehaviour.py
971+++ b/lib/lp/charms/model/charmrecipebuildbehaviour.py
972@@ -78,7 +78,7 @@ class CharmRecipeBuildBehaviour(BuilderProxyMixin, BuildFarmJobBehaviourBase):
973 Return the extra arguments required by the worker for the given build.
974 """
975 build = self.build
976- args = yield super().extraBuildArgs(logger=logger) # type: BuildArgs
977+ args: BuildArgs = yield super().extraBuildArgs(logger=logger)
978 yield self.addProxyArgs(args)
979 args["name"] = build.recipe.store_name or build.recipe.name
980 channels = build.channels or {}
981diff --git a/lib/lp/code/model/cibuildbehaviour.py b/lib/lp/code/model/cibuildbehaviour.py
982index def2e95..648546b 100644
983--- a/lib/lp/code/model/cibuildbehaviour.py
984+++ b/lib/lp/code/model/cibuildbehaviour.py
985@@ -175,7 +175,7 @@ class CIBuildBehaviour(BuilderProxyMixin, BuildFarmJobBehaviourBase):
986 % (build.git_repository.unique_name, build.commit_sha1)
987 )
988
989- args = yield super().extraBuildArgs(logger=logger) # type: BuildArgs
990+ args: BuildArgs = yield super().extraBuildArgs(logger=logger)
991 yield self.addProxyArgs(args)
992 (
993 args["archives"],
994diff --git a/lib/lp/code/model/recipebuilder.py b/lib/lp/code/model/recipebuilder.py
995index 5b73659..8564b88 100644
996--- a/lib/lp/code/model/recipebuilder.py
997+++ b/lib/lp/code/model/recipebuilder.py
998@@ -70,7 +70,7 @@ class RecipeBuildBehaviour(BuildFarmJobBehaviourBase):
999 )
1000
1001 # Build extra arguments.
1002- args = yield super().extraBuildArgs(logger=logger) # type: BuildArgs
1003+ args: BuildArgs = yield super().extraBuildArgs(logger=logger)
1004 args["suite"] = self.build.distroseries.getSuite(self.build.pocket)
1005 requester = self.build.requester
1006 if requester.preferredemail is None:
1007diff --git a/lib/lp/oci/model/ocirecipebuildbehaviour.py b/lib/lp/oci/model/ocirecipebuildbehaviour.py
1008index b5fe6a7..4ce649a 100644
1009--- a/lib/lp/oci/model/ocirecipebuildbehaviour.py
1010+++ b/lib/lp/oci/model/ocirecipebuildbehaviour.py
1011@@ -135,7 +135,7 @@ class OCIRecipeBuildBehaviour(BuilderProxyMixin, BuildFarmJobBehaviourBase):
1012 Return the extra arguments required by the worker for the given build.
1013 """
1014 build = self.build
1015- args = yield super().extraBuildArgs(logger=logger) # type: BuildArgs
1016+ args: BuildArgs = yield super().extraBuildArgs(logger=logger)
1017 yield self.addProxyArgs(args, build.recipe.allow_internet)
1018 # XXX twom 2020-02-17 This may need to be more complex, and involve
1019 # distribution name.
1020diff --git a/lib/lp/registry/browser/product.py b/lib/lp/registry/browser/product.py
1021index 3d55e4b..3a5008a 100644
1022--- a/lib/lp/registry/browser/product.py
1023+++ b/lib/lp/registry/browser/product.py
1024@@ -1437,7 +1437,7 @@ class ProductBrandingView(BrandingChangeView):
1025
1026 @implementer(IProductEditMenu)
1027 class ProductConfigureBase(ReturnToReferrerMixin, LaunchpadEditFormView):
1028- schema = IProduct # type: Type[Interface]
1029+ schema: Type[Interface] = IProduct
1030 usage_fieldname = None
1031
1032 def setUpFields(self):
1033diff --git a/lib/lp/registry/scripts/closeaccount.py b/lib/lp/registry/scripts/closeaccount.py
1034index 6f92c73..f408478 100644
1035--- a/lib/lp/registry/scripts/closeaccount.py
1036+++ b/lib/lp/registry/scripts/closeaccount.py
1037@@ -479,7 +479,7 @@ def close_account(username, log):
1038 if non_referenced_ppa_ids:
1039 store.find(Archive, Archive.id.is_in(non_referenced_ppa_ids)).remove()
1040
1041- reference_counts = [] # type: List[Tuple[str, int]]
1042+ reference_counts: List[Tuple[str, int]] = []
1043
1044 # Check for non-deleted PPAs
1045 count = store.find(
1046diff --git a/lib/lp/registry/scripts/tests/test_closeaccount.py b/lib/lp/registry/scripts/tests/test_closeaccount.py
1047index 4a377c5..e0b0c14 100644
1048--- a/lib/lp/registry/scripts/tests/test_closeaccount.py
1049+++ b/lib/lp/registry/scripts/tests/test_closeaccount.py
1050@@ -1259,9 +1259,9 @@ class TestCloseAccount(TestCaseWithFactory):
1051 account_id = person.account.id
1052
1053 milestone = self.factory.makeMilestone(**milestone_target)
1054- product_release = milestone.createProductRelease(
1055+ product_release: ProductRelease = milestone.createProductRelease(
1056 milestone.product.owner, datetime.now(timezone.utc)
1057- ) # type: ProductRelease
1058+ )
1059 product_release.addReleaseFile(
1060 "test.txt", b"test", "text/plain", person
1061 )
1062diff --git a/lib/lp/services/feeds/browser.py b/lib/lp/services/feeds/browser.py
1063index 80a37af..7c9fba7 100644
1064--- a/lib/lp/services/feeds/browser.py
1065+++ b/lib/lp/services/feeds/browser.py
1066@@ -372,7 +372,7 @@ class FeedsMixin:
1067 feed_links: Returns a list of objects subclassed from FeedLinkBase.
1068 """
1069
1070- feed_types = (
1071+ feed_types: Tuple[Type[FeedLinkBase, ...]] = (
1072 AnnouncementsFeedLink,
1073 BranchFeedLink,
1074 BugFeedLink,
1075@@ -384,7 +384,7 @@ class FeedsMixin:
1076 ProjectBranchesFeedLink,
1077 ProjectRevisionsFeedLink,
1078 RootAnnouncementsFeedLink,
1079- ) # type: Tuple[Type[FeedLinkBase, ...]]
1080+ )
1081
1082 @property
1083 def feed_links(self):
1084diff --git a/lib/lp/services/looptuner.py b/lib/lp/services/looptuner.py
1085index 91ce581..286b3fd 100644
1086--- a/lib/lp/services/looptuner.py
1087+++ b/lib/lp/services/looptuner.py
1088@@ -391,7 +391,7 @@ class TunableLoop:
1089
1090 goal_seconds = 2
1091 minimum_chunk_size = 1
1092- maximum_chunk_size = None # type: int
1093+ maximum_chunk_size: int = None
1094 cooldown_time = 0
1095
1096 def __init__(self, log, abort_time=None):
1097diff --git a/lib/lp/services/mail/commands.py b/lib/lp/services/mail/commands.py
1098index e12c670..2ff7919 100644
1099--- a/lib/lp/services/mail/commands.py
1100+++ b/lib/lp/services/mail/commands.py
1101@@ -59,7 +59,7 @@ class EmailCommand:
1102 Both name the values in the args list are strings.
1103 """
1104
1105- _numberOfArguments = None # type: int
1106+ _numberOfArguments: int = None
1107
1108 # Should command arguments be converted to lowercase?
1109 case_insensitive_args = True
1110diff --git a/lib/lp/services/scripts/base.py b/lib/lp/services/scripts/base.py
1111index 6184599..4674109 100644
1112--- a/lib/lp/services/scripts/base.py
1113+++ b/lib/lp/services/scripts/base.py
1114@@ -136,8 +136,8 @@ class LaunchpadScript:
1115
1116 lock = None
1117 txn = None
1118- usage = None # type: Optional[str]
1119- description = None # type: Optional[str]
1120+ usage: Optional[str] = None
1121+ description: Optional[str] = None
1122 lockfilepath = None
1123 loglevel = logging.INFO
1124
1125diff --git a/lib/lp/services/webapp/breadcrumb.py b/lib/lp/services/webapp/breadcrumb.py
1126index 8bf39b7..a21e6ff 100644
1127--- a/lib/lp/services/webapp/breadcrumb.py
1128+++ b/lib/lp/services/webapp/breadcrumb.py
1129@@ -23,7 +23,7 @@ class Breadcrumb:
1130 This class is intended for use as an adapter.
1131 """
1132
1133- text = None # type: str
1134+ text: str = None
1135 _detail = None
1136 _url = None
1137 inside = None
1138diff --git a/lib/lp/services/webapp/menu.py b/lib/lp/services/webapp/menu.py
1139index 4341425..7b8b5c6 100644
1140--- a/lib/lp/services/webapp/menu.py
1141+++ b/lib/lp/services/webapp/menu.py
1142@@ -199,7 +199,7 @@ MENU_ANNOTATION_KEY = "lp.services.webapp.menu.links"
1143 class MenuBase(UserAttributeCache):
1144 """Base class for facets and menus."""
1145
1146- links = None # type: Sequence[str]
1147+ links: Sequence[str] = None
1148 extra_attributes = None
1149 enable_only = ALL_LINKS
1150 _baseclassname = "MenuBase"
1151@@ -401,7 +401,7 @@ class NavigationMenu(MenuBase):
1152
1153 _baseclassname = "NavigationMenu"
1154
1155- title = None # type: str
1156+ title: str = None
1157 disabled = False
1158
1159 def initLink(self, linkname, request_url):
1160diff --git a/lib/lp/services/webapp/publisher.py b/lib/lp/services/webapp/publisher.py
1161index c45cfed..18aca49 100644
1162--- a/lib/lp/services/webapp/publisher.py
1163+++ b/lib/lp/services/webapp/publisher.py
1164@@ -518,7 +518,7 @@ class LaunchpadView(UserAttributeCache):
1165 return None
1166
1167 # Names of feature flags which affect a view.
1168- related_features = {} # type: Dict[str, bool]
1169+ related_features: Dict[str, bool] = {}
1170
1171 @property
1172 def related_feature_info(self):
1173@@ -893,7 +893,7 @@ class Navigation:
1174 self.request = request
1175
1176 # Set this if you want to set a new layer before doing any traversal.
1177- newlayer = None # type: Optional[Type[Any]]
1178+ newlayer: Optional[Type[Any]] = None
1179
1180 def traverse(self, name):
1181 """Override this method to handle traversal.
1182diff --git a/lib/lp/services/webapp/vocabulary.py b/lib/lp/services/webapp/vocabulary.py
1183index b13b797..baedb43 100644
1184--- a/lib/lp/services/webapp/vocabulary.py
1185+++ b/lib/lp/services/webapp/vocabulary.py
1186@@ -277,7 +277,7 @@ class StormVocabularyBase(FilteredVocabularyBase):
1187 should derive from StormVocabularyBase.
1188 """
1189
1190- _order_by = None # type: Optional[str]
1191+ _order_by: Optional[str] = None
1192 _clauses = []
1193
1194 def __init__(self, context=None):
1195diff --git a/lib/lp/snappy/adapters/buildarch.py b/lib/lp/snappy/adapters/buildarch.py
1196index bd36747..df5acfd 100644
1197--- a/lib/lp/snappy/adapters/buildarch.py
1198+++ b/lib/lp/snappy/adapters/buildarch.py
1199@@ -99,13 +99,13 @@ class SnapArchitecture:
1200 :param build_error: string; build-error property from
1201 snapcraft.yaml.
1202 """
1203- self.build_on = (
1204+ self.build_on: List[str] = (
1205 [build_on] if isinstance(build_on, str) else build_on
1206- ) # type: List[str]
1207+ )
1208 if build_for:
1209- self.build_for = (
1210+ self.build_for: List[str] = (
1211 [build_for] if isinstance(build_for, str) else build_for
1212- ) # type: List[str]
1213+ )
1214 else:
1215 self.build_for = self.build_on
1216 self.build_error = build_error
1217@@ -185,9 +185,7 @@ def determine_architectures_to_build(
1218 we can create builds for.
1219 :return: a list of `SnapBuildInstance`s.
1220 """
1221- architectures_list = snapcraft_data.get(
1222- "architectures"
1223- ) # type: Optional[List]
1224+ architectures_list: Optional[List] = snapcraft_data.get("architectures")
1225
1226 if architectures_list:
1227 # First, determine what style we're parsing. Is it a list of
1228diff --git a/lib/lp/snappy/model/snapbuildbehaviour.py b/lib/lp/snappy/model/snapbuildbehaviour.py
1229index 39d8238..e0fa800 100644
1230--- a/lib/lp/snappy/model/snapbuildbehaviour.py
1231+++ b/lib/lp/snappy/model/snapbuildbehaviour.py
1232@@ -114,8 +114,8 @@ class SnapBuildBehaviour(BuilderProxyMixin, BuildFarmJobBehaviourBase):
1233 """
1234 Return the extra arguments required by the worker for the given build.
1235 """
1236- build = self.build # type: ISnapBuild
1237- args = yield super().extraBuildArgs(logger=logger) # type: BuildArgs
1238+ build: ISnapBuild = self.build
1239+ args: BuildArgs = yield super().extraBuildArgs(logger=logger)
1240 yield self.addProxyArgs(args, build.snap.allow_internet)
1241 args["name"] = build.snap.store_name or build.snap.name
1242 channels = build.channels or {}
1243diff --git a/lib/lp/soyuz/browser/archivesubscription.py b/lib/lp/soyuz/browser/archivesubscription.py
1244index 50e6903..2925e21 100644
1245--- a/lib/lp/soyuz/browser/archivesubscription.py
1246+++ b/lib/lp/soyuz/browser/archivesubscription.py
1247@@ -355,7 +355,7 @@ class PersonArchiveSubscriptionsView(LaunchpadView):
1248 # check results
1249 viewable_archives = []
1250 non_viewable_archives = []
1251- archive_set = getUtility(IArchiveSet) # type: IArchiveSet
1252+ archive_set: IArchiveSet = getUtility(IArchiveSet)
1253 for archive, has_view_permission in archive_set.checkViewPermission(
1254 archives, self.user
1255 ).items():
1256diff --git a/lib/lp/soyuz/model/binarypackagebuildbehaviour.py b/lib/lp/soyuz/model/binarypackagebuildbehaviour.py
1257index 4b65e9c..4f1387d 100644
1258--- a/lib/lp/soyuz/model/binarypackagebuildbehaviour.py
1259+++ b/lib/lp/soyuz/model/binarypackagebuildbehaviour.py
1260@@ -161,7 +161,7 @@ class BinaryPackageBuildBehaviour(BuildFarmJobBehaviourBase):
1261 das = build.distro_arch_series
1262
1263 # Build extra arguments.
1264- args = yield super().extraBuildArgs(logger=logger) # type: BuildArgs
1265+ args: BuildArgs = yield super().extraBuildArgs(logger=logger)
1266 args["arch_indep"] = build.arch_indep
1267 args["suite"] = das.distroseries.getSuite(build.pocket)
1268
1269diff --git a/lib/lp/soyuz/model/livefsbuildbehaviour.py b/lib/lp/soyuz/model/livefsbuildbehaviour.py
1270index d9f1cfd..aaa6a2f 100644
1271--- a/lib/lp/soyuz/model/livefsbuildbehaviour.py
1272+++ b/lib/lp/soyuz/model/livefsbuildbehaviour.py
1273@@ -101,9 +101,7 @@ class LiveFSBuildBehaviour(BuildFarmJobBehaviourBase):
1274 Return the extra arguments required by the worker for the given build.
1275 """
1276 build = self.build
1277- base_args = yield super().extraBuildArgs(
1278- logger=logger
1279- ) # type: BuildArgs
1280+ base_args: BuildArgs = yield super().extraBuildArgs(logger=logger)
1281 # Non-trivial metadata values may have been security-wrapped, which
1282 # is pointless here and just gets in the way of xmlrpc.client
1283 # serialisation.
1284diff --git a/lib/lp/soyuz/security.py b/lib/lp/soyuz/security.py
1285index c7ef5a7..1622c45 100644
1286--- a/lib/lp/soyuz/security.py
1287+++ b/lib/lp/soyuz/security.py
1288@@ -293,7 +293,7 @@ class ViewArchive(AuthorizationBase):
1289
1290 def checkAuthenticated(self, user):
1291 """Verify that the user can view the archive."""
1292- archive_set = getUtility(IArchiveSet) # type: IArchiveSet
1293+ archive_set: IArchiveSet = getUtility(IArchiveSet)
1294 return archive_set.checkViewPermission([self.obj], user.person)[
1295 self.obj
1296 ]
1297diff --git a/lib/lp/testing/__init__.py b/lib/lp/testing/__init__.py
1298index a095111..3c5f69e 100644
1299--- a/lib/lp/testing/__init__.py
1300+++ b/lib/lp/testing/__init__.py
1301@@ -1071,13 +1071,13 @@ class WebServiceTestCase(TestCaseWithFactory):
1302
1303
1304 class AbstractYUITestCase(TestCase):
1305- layer = None # type: Type[BaseLayer]
1306+ layer: Optional[Type[BaseLayer]] = None
1307 suite_name = ""
1308 # 30 seconds for the suite.
1309 suite_timeout = 30000
1310 # By default we do not restrict per-test or times. yuixhr tests do.
1311- incremental_timeout = None # type: Optional[int]
1312- initial_timeout = None # type: Optional[int]
1313+ incremental_timeout: Optional[int] = None
1314+ initial_timeout: Optional[int] = None
1315 html_uri = None
1316 test_path = None
1317
1318diff --git a/lib/lp/testing/pgsql.py b/lib/lp/testing/pgsql.py
1319index d2159d4..1ec7c26 100644
1320--- a/lib/lp/testing/pgsql.py
1321+++ b/lib/lp/testing/pgsql.py
1322@@ -92,7 +92,7 @@ class CursorWrapper:
1323 """
1324
1325 real_cursor = None
1326- last_executed_sql = [] # type: List[str]
1327+ last_executed_sql: List[str] = []
1328 record_sql = False
1329
1330 def __init__(self, real_cursor):
1331@@ -167,16 +167,16 @@ def uninstallFakeConnect():
1332
1333 class PgTestSetup:
1334 # Shared:
1335- connections = [] # type: List[ConnectionWrapper]
1336+ connections: List[ConnectionWrapper] = []
1337 # Use a dynamically generated dbname:
1338 dynamic = object()
1339
1340 template = "template1"
1341 # Needs to match configs/testrunner*/*:
1342 dbname = "launchpad_ftest"
1343- dbuser = None # type: Optional[str]
1344- host = None # type: Optional[str]
1345- port = None # type: Optional[int]
1346+ dbuser: Optional[str] = None
1347+ host: Optional[str] = None
1348+ port: Optional[int] = None
1349
1350 # Class attributes. With PostgreSQL 8.4, pg_shdepend bloats
1351 # hugely when we drop and create databases, because this
1352diff --git a/lib/lp/testing/swift/tests/test_fixture.py b/lib/lp/testing/swift/tests/test_fixture.py
1353index 122e2b4..717b8c2 100644
1354--- a/lib/lp/testing/swift/tests/test_fixture.py
1355+++ b/lib/lp/testing/swift/tests/test_fixture.py
1356@@ -3,8 +3,6 @@
1357
1358 """Testing the mock Swift test fixture."""
1359
1360-__all__ = [] # type: List[str]
1361-
1362 from datetime import datetime
1363 from hashlib import md5
1364 from typing import List
1365@@ -21,6 +19,8 @@ from lp.testing.layers import BaseLayer
1366 from lp.testing.swift import fakeswift
1367 from lp.testing.swift.fixture import SwiftFixture
1368
1369+__all__: List[str] = []
1370+
1371
1372 class TestSwiftFixture(TestCase):
1373 layer = BaseLayer
1374diff --git a/lib/lp/testing/tests/test_layers.py b/lib/lp/testing/tests/test_layers.py
1375index 386586e..aa4546c 100644
1376--- a/lib/lp/testing/tests/test_layers.py
1377+++ b/lib/lp/testing/tests/test_layers.py
1378@@ -3,14 +3,14 @@
1379
1380 """Tests for test layers."""
1381
1382-__all__ = [] # type: List[str]
1383-
1384 import threading
1385 from typing import List
1386
1387 from lp.testing import TestCase
1388 from lp.testing.layers import BaseLayer
1389
1390+__all__: List[str] = []
1391+
1392
1393 class TestThreadWaiting(TestCase):
1394 layer = BaseLayer
1395diff --git a/lib/lp/testing/tests/test_sampledata.py b/lib/lp/testing/tests/test_sampledata.py
1396index 1b17765..662267b 100644
1397--- a/lib/lp/testing/tests/test_sampledata.py
1398+++ b/lib/lp/testing/tests/test_sampledata.py
1399@@ -8,8 +8,6 @@ silently switching off some of our constraints. We can detect this by
1400 doing a dump and restore - this will fail if the data is corrupt.
1401 """
1402
1403-__all__ = [] # type: List[str]
1404-
1405 import subprocess
1406 from typing import List
1407
1408@@ -17,6 +15,8 @@ from lp.testing import TestCase
1409 from lp.testing.layers import DatabaseLayer
1410 from lp.testing.pgsql import PgTestSetup
1411
1412+__all__: List[str] = []
1413+
1414
1415 class SampleDataTestCase(TestCase):
1416 layer = DatabaseLayer
1417diff --git a/lib/lp/testing/tests/test_standard_yuixhr_test_template.py b/lib/lp/testing/tests/test_standard_yuixhr_test_template.py
1418index c7672d4..713cd4d 100644
1419--- a/lib/lp/testing/tests/test_standard_yuixhr_test_template.py
1420+++ b/lib/lp/testing/tests/test_standard_yuixhr_test_template.py
1421@@ -4,14 +4,14 @@
1422 """{Describe your test suite here}.
1423 """
1424
1425-__all__ = [] # type: List[str]
1426-
1427 from typing import List
1428
1429 from lp.testing import person_logged_in
1430 from lp.testing.factory import LaunchpadObjectFactory
1431 from lp.testing.yuixhr import login_as_person, make_suite, setup
1432
1433+__all__: List[str] = []
1434+
1435 # This is one half of a YUI app test. The other half is a .js test of
1436 # exactly the same name as your Python file, just with different file
1437 # extensions.
1438diff --git a/lib/lp/testing/tests/test_yuixhr_fixture.py b/lib/lp/testing/tests/test_yuixhr_fixture.py
1439index 65e6a08..87584b9 100644
1440--- a/lib/lp/testing/tests/test_yuixhr_fixture.py
1441+++ b/lib/lp/testing/tests/test_yuixhr_fixture.py
1442@@ -4,8 +4,6 @@
1443 """These are yui appserver fixtures for the yui appserver test code's tests.
1444 """
1445
1446-__all__ = [] # type: List[str]
1447-
1448 from typing import Any, Dict, List, Tuple
1449
1450 from zope.security.proxy import removeSecurityProxy
1451@@ -14,10 +12,12 @@ from lp.testing import login_person
1452 from lp.testing.factory import LaunchpadObjectFactory
1453 from lp.testing.yuixhr import login_as_person, make_suite, setup
1454
1455+__all__: List[str] = []
1456+
1457 # The following are the fixtures needed by the tests.
1458
1459 # We use this variable for test results.
1460-_received = [] # type: List[Tuple[str, Any, Dict[str, str]]]
1461+_received: List[Tuple[str, Any, Dict[str, str]]] = []
1462
1463
1464 @setup
1465diff --git a/lib/lp/testing/tests/test_yuixhr_fixture_facet.py b/lib/lp/testing/tests/test_yuixhr_fixture_facet.py
1466index 5e7a0e9..c54ea2c 100644
1467--- a/lib/lp/testing/tests/test_yuixhr_fixture_facet.py
1468+++ b/lib/lp/testing/tests/test_yuixhr_fixture_facet.py
1469@@ -4,12 +4,12 @@
1470 """Test the ability to specify a facet for the yuixhr tests.
1471 """
1472
1473-__all__ = [] # type: List[str]
1474-
1475 from typing import List
1476
1477 from lp.testing.yuixhr import make_suite
1478
1479+__all__: List[str] = []
1480+
1481
1482 def test_suite():
1483 # You can specify a facet, as found in the vhost.* names in
1484diff --git a/pyproject.toml b/pyproject.toml
1485index cf22bee..c276370 100644
1486--- a/pyproject.toml
1487+++ b/pyproject.toml
1488@@ -3,7 +3,7 @@ line-length = 79
1489 target-version = ['py35']
1490
1491 [tool.mypy]
1492-python_version = "3.5"
1493+python_version = "3.8"
1494 exclude = [
1495 '/interfaces/',
1496 'interfaces\.py$',

Subscribers

People subscribed via source and target branches

to status/vote changes: