Merge ~paride/autopkgtest-cloud:pre-commit-pylint into autopkgtest-cloud:master

Proposed by Paride Legovini
Status: Merged
Merged at revision: dbef7e8d5b717d51d47ce76bc8ada8057e0acf1b
Proposed branch: ~paride/autopkgtest-cloud:pre-commit-pylint
Merge into: autopkgtest-cloud:master
Diff against target: 845 lines (+168/-65)
26 files modified
.launchpad.yaml (+26/-2)
.pre-commit-config.yaml (+25/-0)
.pylintrc (+45/-1)
charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/cleanup-instances (+0/-5)
charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/create-armhf-cluster-member (+1/-0)
charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/create-nova-image-with-proposed-package (+1/-0)
charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/filter-amqp (+1/-2)
charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/filter-amqp-dupes-upstream (+3/-3)
charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/metrics (+2/-3)
charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/retry-github-test (+1/-0)
charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/run-autopkgtest (+2/-2)
charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/seed-new-release (+2/-0)
charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/worker/worker (+12/-9)
charms/focal/autopkgtest-cloud-worker/lib/systemd.py (+2/-1)
charms/focal/autopkgtest-cloud-worker/reactive/autopkgtest_cloud_worker.py (+6/-2)
charms/focal/autopkgtest-web/reactive/autopkgtest_web.py (+0/-1)
charms/focal/autopkgtest-web/webcontrol/browse.cgi (+15/-9)
charms/focal/autopkgtest-web/webcontrol/cache-amqp (+1/-0)
charms/focal/autopkgtest-web/webcontrol/download-all-results (+6/-7)
charms/focal/autopkgtest-web/webcontrol/download-results (+0/-1)
charms/focal/autopkgtest-web/webcontrol/private_results/app.py (+2/-3)
charms/focal/autopkgtest-web/webcontrol/publish-db (+1/-3)
charms/focal/autopkgtest-web/webcontrol/request/submit.py (+9/-6)
charms/focal/autopkgtest-web/webcontrol/request/tests/test_app.py (+1/-0)
charms/focal/autopkgtest-web/webcontrol/update-github-jobs (+1/-1)
mojo/add-floating-ip (+3/-4)
Reviewer Review Type Date Requested Status
Tim Andersson Pending
Canonical's Ubuntu QA Pending
Review via email: mp+445630@code.launchpad.net

Commit message

Run pylint via pre-commit and therefore in CI. Fix or disable all the pylint warnings.

To post a comment you must log in.
Revision history for this message
Paride Legovini (paride) wrote :

Individual pylint tags are tackled in separate commits.

Changes that need more attention in review:

* In CI I had to add a PPA where I backported pre-commit to Focal. That's under my LP user. Should I move that under canonical-ubuntu-qa?

* Any better way of installing Python dependencies than the yq trick I used in .launchpad.yaml?

* Do we like the two pylint hooks, one with --disable=import-error (meant for dev machines) and one without that flag (running in CI, where Python deps were installed)?

Revision history for this message
Tim Andersson (andersson123) :
Revision history for this message
Tim Andersson (andersson123) :
Revision history for this message
Tim Andersson (andersson123) :
Revision history for this message
Tim Andersson (andersson123) :
Revision history for this message
Tim Andersson (andersson123) wrote :

Looks like this MP also contains a bunch of linting changes that aren't mentioned in the commits? Presumably from running pre-commit/pylint locally. Is there a way to remove this and put it on a separate commit so we can verify the linting changes are only made by a specific linting program?

Revision history for this message
Tim Andersson (andersson123) wrote :

I think we should also move the ppa to canonical-ubuntu-qa
There is no better way to install python deps.
I like the two pylint hooks as long as the one without import errors doesn't run in CI

Revision history for this message
Paride Legovini (paride) :
Revision history for this message
Paride Legovini (paride) wrote :

Addressed review comments and rebased, however we need Brian to create a PPA under ~canonical-ubuntu-qa.

Revision history for this message
Tim Andersson (andersson123) wrote :

It still looks to me like the linting changes are in the diff or am I wrong? I think this is good to go when we have the new ppa and the linting changes are out

Revision history for this message
Paride Legovini (paride) wrote :

I am not sure I understand this question:

> It still looks to me like the linting changes are in the diff or am I wrong?

The proposed branch is mostly made up of linting changes.

Are you suggesting adding pylint to pre-commit/lpci in a MP, and then the "make pylint happy" changes in a separate one? That is doable, but will mean landing a change that will introduce a CI step that will fail which is not nice. And the linting changes and pre-commit/lpci changes are in separate commits.

Revision history for this message
Paride Legovini (paride) wrote :

I updated the branch to use the canonical-ubuntu-qa/backport-pre-commit PPA. We'll be able to drop once we switch the infra to Jammy. (I may even backport pre-commit to the -backports pocket at some point, given that all it takes is a straightforward no-change rebuild.)

This is ready for review again.

Revision history for this message
Tim Andersson (andersson123) :
Revision history for this message
Tim Andersson (andersson123) wrote :

re-reviewed, LGTM! Just one question about docstring disables in pylint

Revision history for this message
Paride Legovini (paride) :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/.launchpad.yaml b/.launchpad.yaml
index a744b71..ee74e0f 100755
--- a/.launchpad.yaml
+++ b/.launchpad.yaml
@@ -5,12 +5,36 @@ pipeline:
55
6jobs:6jobs:
7 pre_commit:7 pre_commit:
8 series: jammy8 series: focal
9 architectures: amd649 architectures: amd64
10 package-repositories:
11 - type: apt
12 formats: [deb]
13 suites: [focal]
14 ppa: canonical-ubuntu-qa/backport-pre-commit
15 snaps:
16 - name: yq
10 packages:17 packages:
11 - git18 - git
12 - pre-commit19 - pre-commit
13 run: pre-commit run --all-files --show-diff-on-failure20 - pylint
21 # These are not directly declared in layer.yaml.
22 # Maybe they are brought in by some included layer?
23 - python3-systemd
24 - python3-apt
25 run-before: |
26 # Install dependencies as declared in the layer files
27 DEBIAN_FRONTEND=noninteractive \
28 apt-get install -qy \
29 $(cat charms/focal/autopkgtest-cloud-worker/layer.yaml | \
30 yq -r '.options.basic.packages[]') \
31 $(cat charms/focal/autopkgtest-cloud-worker/layer.yaml | \
32 yq -r '.options.apt.packages[]') \
33 $(cat charms/focal/autopkgtest-web/layer.yaml | \
34 yq -r '.options.basic.packages[]') \
35 $(cat charms/focal/autopkgtest-web/layer.yaml | \
36 yq -r '.options.apt.packages[]')
37 run: pre-commit run --hook-stage manual --all-files --show-diff-on-failure
14 build_charms:38 build_charms:
15 series: focal39 series: focal
16 architectures: amd6440 architectures: amd64
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 0735120..d3bc39f 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -22,3 +22,28 @@ repos:
22 rev: 5.12.022 rev: 5.12.0
23 hooks:23 hooks:
24 - id: isort24 - id: isort
25 - repo: local
26 hooks:
27 # Run pylint with --disable import-error.
28 # This is meant to run on developers' machines where not all the
29 # Python modules may be installed.
30 - id: pylint
31 name: pylint
32 stages:
33 [commit-msg, post-checkout, post-commit, post-merge, post-rewrite,
34 pre-commit, pre-merge-commit, pre-push, pre-rebase,
35 prepare-commit-msg]
36 entry: pylint
37 args:
38 - "--disable=import-error"
39 language: system
40 types: [python]
41 # Run pylint without disabling import-error.
42 # This is meant to run in CI (pre-commit run --hook-stage manual).
43 # The CI environment is expected to have all the required dependencies.
44 - id: pylint
45 name: pylint (with import errors)
46 stages: [manual]
47 entry: pylint
48 language: system
49 types: [python]
diff --git a/.pylintrc b/.pylintrc
index a831f0a..b6b77fa 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -2,4 +2,48 @@
22
3jobs=03jobs=0
44
5disable=invalid-name, import-error, no-name-in-module5[MESSAGES CONTROL]
6
7disable=
8 R,
9 anomalous-backslash-in-string,
10 arguments-differ,
11 bad-continuation, # leave this to black
12 bad-option-value, # for older versions of pylint
13 broad-except,
14 broad-exception-caught,
15 consider-using-f-string,
16 duplicate-string-formatting-argument,
17 fixme,
18 global-statement,
19 global-variable-not-assigned,
20 invalid-name,
21 logging-format-interpolation,
22 logging-fstring-interpolation,
23 logging-not-lazy,
24 missing-class-docstring,
25 missing-function-docstring,
26 missing-module-docstring,
27 missing-timeout,
28 possibly-unused-variable,
29 protected-access,
30 redefined-builtin,
31 redefined-outer-name,
32 unspecified-encoding,
33 unused-argument,
34 wrong-import-order, # leave this to isort
35
36[REPORTS]
37
38# Show just the errors, no full report
39reports=no
40score=no
41
42[TYPECHECK]
43
44ignored-modules=
45 amulet,
46 charmhelpers,
47 charms,
48 lib,
49 utils,
diff --git a/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/cleanup-instances b/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/cleanup-instances
index 727634e..024ad93 100755
--- a/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/cleanup-instances
+++ b/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/cleanup-instances
@@ -6,7 +6,6 @@ import re
6import socket6import socket
7import subprocess7import subprocess
8import time8import time
9from urllib.error import HTTPError
109
11import novaclient.client10import novaclient.client
12import novaclient.exceptions11import novaclient.exceptions
@@ -109,7 +108,6 @@ for instance in nova.servers.list():
109 instance.delete()108 instance.delete()
110 except novaclient.exceptions.NotFound:109 except novaclient.exceptions.NotFound:
111 logging.warning("Couldn't delete instance: not found")110 logging.warning("Couldn't delete instance: not found")
112 pass
113 continue111 continue
114112
115 if not instance.name.startswith("adt-"):113 if not instance.name.startswith("adt-"):
@@ -144,7 +142,6 @@ for instance in nova.servers.list():
144 )142 )
145 except novaclient.exceptions.NotFound:143 except novaclient.exceptions.NotFound:
146 logging.warning("Couldn't delete instance: not found")144 logging.warning("Couldn't delete instance: not found")
147 pass
148145
149 # check matching adt-run process for instance name146 # check matching adt-run process for instance name
150 try:147 try:
@@ -180,7 +177,6 @@ for instance in nova.servers.list():
180 )177 )
181 except novaclient.exceptions.NotFound:178 except novaclient.exceptions.NotFound:
182 logging.warning("Couldn't delete instance: not found")179 logging.warning("Couldn't delete instance: not found")
183 pass
184 except IndexError:180 except IndexError:
185 logging.warning("instance %s has invalid name" % instance.name)181 logging.warning("instance %s has invalid name" % instance.name)
186182
@@ -189,4 +185,3 @@ for instance in nova.servers.list():
189 influx_client.write_points(measurements)185 influx_client.write_points(measurements)
190 except InfluxDBClientError as err:186 except InfluxDBClientError as err:
191 logging.warning("Write to InfluxDB failed: %s" % err)187 logging.warning("Write to InfluxDB failed: %s" % err)
192 pass
diff --git a/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/create-armhf-cluster-member b/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/create-armhf-cluster-member
index 75e4c74..c512b22 100755
--- a/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/create-armhf-cluster-member
+++ b/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/create-armhf-cluster-member
@@ -49,6 +49,7 @@ def usage():
4949
50try:50try:
51 role = sys.argv[1]51 role = sys.argv[1]
52 to_join = None
52 if role in ("leader", "node"):53 if role in ("leader", "node"):
53 to_join = sys.argv[2]54 to_join = sys.argv[2]
54except IndexError:55except IndexError:
diff --git a/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/create-nova-image-with-proposed-package b/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/create-nova-image-with-proposed-package
index 641f771..e48f3f4 100755
--- a/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/create-nova-image-with-proposed-package
+++ b/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/create-nova-image-with-proposed-package
@@ -73,6 +73,7 @@ def setup_image(image_path, source):
73 )73 )
7474
75 # find and install proposed binaries for source75 # find and install proposed binaries for source
76 # pylint: disable=line-too-long
76 img_shell.stdin.write(77 img_shell.stdin.write(
77 (78 (
78 """79 """
diff --git a/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/filter-amqp b/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/filter-amqp
index 9ff9df2..76e51ca 100755
--- a/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/filter-amqp
+++ b/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/filter-amqp
@@ -2,9 +2,8 @@
2# Filter out AMQP requests that match a given regex2# Filter out AMQP requests that match a given regex
33
4import logging4import logging
5import optparse5import optparse # pylint: disable=deprecated-module
6import re6import re
7import sys
8import urllib.parse7import urllib.parse
98
10import amqplib.client_0_8 as amqp9import amqplib.client_0_8 as amqp
diff --git a/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/filter-amqp-dupes-upstream b/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/filter-amqp-dupes-upstream
index 9e49803..c255239 100755
--- a/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/filter-amqp-dupes-upstream
+++ b/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/filter-amqp-dupes-upstream
@@ -3,10 +3,8 @@
33
4import json4import json
5import logging5import logging
6import optparse6import optparse # pylint: disable=deprecated-module
7import os7import os
8import re
9import sys
10import urllib.parse8import urllib.parse
11from collections import defaultdict9from collections import defaultdict
1210
@@ -65,6 +63,7 @@ def filter_amqp(options, host):
65 try:63 try:
66 (delivery_tag, old_submit_time) = seen[pkg][pr]64 (delivery_tag, old_submit_time) = seen[pkg][pr]
67 if old_submit_time <= submit_time:65 if old_submit_time <= submit_time:
66 # pylint: disable=line-too-long
68 logging.info(67 logging.info(
69 f"{dry_run}We have seen PR {pr} in {queue_name} before: acking the previous request"68 f"{dry_run}We have seen PR {pr} in {queue_name} before: acking the previous request"
70 )69 )
@@ -99,6 +98,7 @@ def main():
99 help="additionally show queue items that are not removed",98 help="additionally show queue items that are not removed",
100 )99 )
101100
101 # pylint: disable=unused-variable
102 opts, args = parser.parse_args()102 opts, args = parser.parse_args()
103103
104 logging.basicConfig(104 logging.basicConfig(
diff --git a/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/metrics b/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/metrics
index f11d3ca..7224dd3 100755
--- a/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/metrics
+++ b/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/metrics
@@ -84,10 +84,9 @@ def get_units():
84 continue84 continue
8585
86 try:86 try:
87 (region, arch, n) = name_cloud.split("-", -1)87 (_, arch, _) = name_cloud.split("-", -1)
88 except ValueError:88 except ValueError:
89 # autopkgtest@lcy01-1.service89 # autopkgtest@lcy01-1.service
90 (region, n) = name_cloud.split("-", -1)
91 arch = "amd64"90 arch = "amd64"
92 (active, error) = counts.setdefault(arch, (0, 0))91 (active, error) = counts.setdefault(arch, (0, 0))
9392
@@ -111,7 +110,7 @@ def get_remotes():
111 if not r.startswith("lxd"):110 if not r.startswith("lxd"):
112 continue111 continue
113112
114 (_, arch, ip) = r.split("-", 3)113 (_, arch, _) = r.split("-", 3)
115 (cluster_active, cluster_error) = cluster_counts.setdefault(114 (cluster_active, cluster_error) = cluster_counts.setdefault(
116 arch, (0, 0)115 arch, (0, 0)
117 )116 )
diff --git a/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/retry-github-test b/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/retry-github-test
index 4e258a6..799c905 100755
--- a/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/retry-github-test
+++ b/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/retry-github-test
@@ -17,6 +17,7 @@ p.add_argument(
17 help="GitHub PR API URL (e. g. https://api.github.com/repos/JoeDev/coolproj/pulls/1",17 help="GitHub PR API URL (e. g. https://api.github.com/repos/JoeDev/coolproj/pulls/1",
18)18)
19p.add_argument(19p.add_argument(
20 # pylint: disable=line-too-long
20 "test_url",21 "test_url",
21 help="autopkgtest URL (https://autopkgtest.ubuntu.com/request.cgi?release=xenial&arch=i386&...)",22 help="autopkgtest URL (https://autopkgtest.ubuntu.com/request.cgi?release=xenial&arch=i386&...)",
22)23)
diff --git a/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/run-autopkgtest b/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/run-autopkgtest
index f59de0e..2584323 100755
--- a/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/run-autopkgtest
+++ b/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/run-autopkgtest
@@ -122,7 +122,7 @@ def parse_args():
122 # verify syntax of triggers122 # verify syntax of triggers
123 for t in args.trigger:123 for t in args.trigger:
124 try:124 try:
125 (src, ver) = t.split("/")125 (_, _) = t.split("/")
126 except ValueError:126 except ValueError:
127 parser.error(127 parser.error(
128 'Invalid trigger format "%s", must be "sourcepkg/version"' % t128 'Invalid trigger format "%s", must be "sourcepkg/version"' % t
@@ -131,7 +131,7 @@ def parse_args():
131 # verify syntax of PPAs131 # verify syntax of PPAs
132 for t in args.ppa:132 for t in args.ppa:
133 try:133 try:
134 (user, name) = t.split("/")134 (_, _) = t.split("/")
135 except ValueError:135 except ValueError:
136 parser.error(136 parser.error(
137 'Invalid ppa format "%s", must be "lpuser/ppaname"' % t137 'Invalid ppa format "%s", must be "lpuser/ppaname"' % t
diff --git a/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/seed-new-release b/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/seed-new-release
index 05b2aab..3f14045 100755
--- a/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/seed-new-release
+++ b/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/tools/seed-new-release
@@ -40,6 +40,8 @@ def copy_result(rel_path, source, target):
40 to_path = target.split("-")[-1] + rel_path40 to_path = target.split("-")[-1] + rel_path
4141
42 try:42 try:
43 # pylint: disable=used-before-assignment
44 # false positive with older pylint versions
43 print("Getting %s" % from_path)45 print("Getting %s" % from_path)
44 headers, contents = swift_con.get_object(source, from_path)46 headers, contents = swift_con.get_object(source, from_path)
45 except swiftclient.exceptions.ClientException:47 except swiftclient.exceptions.ClientException:
diff --git a/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/worker/worker b/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/worker/worker
index 1bbcbae..2af9dc1 100755
--- a/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/worker/worker
+++ b/charms/focal/autopkgtest-cloud-worker/autopkgtest-cloud/worker/worker
@@ -4,6 +4,8 @@
4#4#
5# Requirements: python3-amqplib python3-swiftclient python3-influxdb5# Requirements: python3-amqplib python3-swiftclient python3-influxdb
6# Requirements for running autopkgtest from git: python3-debian libdpkg-perl6# Requirements for running autopkgtest from git: python3-debian libdpkg-perl
7#
8# pylint: disable=too-many-lines,line-too-long
79
8import argparse10import argparse
9import configparser11import configparser
@@ -267,6 +269,9 @@ def read_per_package_configs(cfg):
267 }269 }
268270
269 for entry in entries:271 for entry in entries:
272 package = None
273 arch = None
274 release = None
270 try:275 try:
271 (package, arch, release) = entry.split("/", 3)276 (package, arch, release) = entry.split("/", 3)
272 except ValueError:277 except ValueError:
@@ -564,9 +569,7 @@ def cleanup_and_sleep(out_dir):
564 """Empty the output dir for the next run, otherwise autopkgtest complains"""569 """Empty the output dir for the next run, otherwise autopkgtest complains"""
565 shutil.rmtree(out_dir)570 shutil.rmtree(out_dir)
566 os.mkdir(out_dir)571 os.mkdir(out_dir)
567 running_test = False
568 time.sleep(300)572 time.sleep(300)
569 running_test = True
570573
571574
572def request(msg):575def request(msg):
@@ -799,13 +802,6 @@ def request(msg):
799 "PPA user %s, name %s has GPG fingerprint %s"802 "PPA user %s, name %s has GPG fingerprint %s"
800 % (ppauser, ppaname, fingerprint)803 % (ppauser, ppaname, fingerprint)
801 )804 )
802 except (IOError, ValueError, KeyError) as e:
803 logging.error(
804 'Cannot get PPA information: "%s". Consuming the request - it will be left dangling; retry once the problem is resolved.'
805 % e
806 )
807 msg.channel.basic_ack(msg.delivery_tag)
808 return
809 except HTTPError as e:805 except HTTPError as e:
810 # It's quite common to get 503s from LP; retry a806 # It's quite common to get 503s from LP; retry a
811 # few times.807 # few times.
@@ -813,6 +809,13 @@ def request(msg):
813 raise809 raise
814 logging.warning("Got error 503 from launchpad API")810 logging.warning("Got error 503 from launchpad API")
815 time.sleep(10)811 time.sleep(10)
812 except (IOError, ValueError, KeyError) as e:
813 logging.error(
814 'Cannot get PPA information: "%s". Consuming the request - it will be left dangling; retry once the problem is resolved.'
815 % e
816 )
817 msg.channel.basic_ack(msg.delivery_tag)
818 return
816 else:819 else:
817 break820 break
818 else:821 else:
diff --git a/charms/focal/autopkgtest-cloud-worker/lib/systemd.py b/charms/focal/autopkgtest-cloud-worker/lib/systemd.py
index 6a87cbd..a7f6c19 100644
--- a/charms/focal/autopkgtest-cloud-worker/lib/systemd.py
+++ b/charms/focal/autopkgtest-cloud-worker/lib/systemd.py
@@ -132,7 +132,7 @@ def get_units():
132 lxd_object_paths = defaultdict(lambda: defaultdict(dict))132 lxd_object_paths = defaultdict(lambda: defaultdict(dict))
133133
134 for unit in units:134 for unit in units:
135 (name, _, _, active, _, _, object_path, _, _, _) = unit135 (name, _, _, _, _, _, object_path, _, _, _) = unit
136 if name.startswith("build-adt-image@") and name.endswith(".timer"):136 if name.startswith("build-adt-image@") and name.endswith(".timer"):
137 name_release_region_arch = name[16:][:-6]137 name_release_region_arch = name[16:][:-6]
138 (release, region, arch) = name_release_region_arch.split("-", -1)138 (release, region, arch) = name_release_region_arch.split("-", -1)
@@ -334,6 +334,7 @@ def set_up_systemd_units(target_cloud_config, target_lxd_config, releases):
334 releases_to_disable = currently_enabled_releases - set(releases)334 releases_to_disable = currently_enabled_releases - set(releases)
335335
336 if releases_to_disable:336 if releases_to_disable:
337 # pylint: disable=line-too-long
337 print(338 print(
338 "Disabling build-adt-image timers for {region}/{arch}/{releases_to_disable}".format(339 "Disabling build-adt-image timers for {region}/{arch}/{releases_to_disable}".format(
339 **locals()340 **locals()
diff --git a/charms/focal/autopkgtest-cloud-worker/reactive/autopkgtest_cloud_worker.py b/charms/focal/autopkgtest-cloud-worker/reactive/autopkgtest_cloud_worker.py
index 12b0b66..2095e42 100644
--- a/charms/focal/autopkgtest-cloud-worker/reactive/autopkgtest_cloud_worker.py
+++ b/charms/focal/autopkgtest-cloud-worker/reactive/autopkgtest_cloud_worker.py
@@ -26,7 +26,6 @@ from charms.reactive import (
26 when_not,26 when_not,
27 when_not_all,27 when_not_all,
28)28)
29from charms.reactive.relations import endpoint_from_flag
30from utils import UnixUser, install_autodep829from utils import UnixUser, install_autodep8
3130
32AUTOPKGTEST_LOCATION = os.path.expanduser("~ubuntu/autopkgtest")31AUTOPKGTEST_LOCATION = os.path.expanduser("~ubuntu/autopkgtest")
@@ -131,6 +130,7 @@ def set_up_systemd_units():
131 dest = os.path.join(os.path.sep, "etc", "systemd", "system", base)130 dest = os.path.join(os.path.sep, "etc", "systemd", "system", base)
132131
133 def link_and_enable():132 def link_and_enable():
133 # pylint: disable=cell-var-from-loop
134 os.symlink(unit, dest)134 os.symlink(unit, dest)
135 if "@" not in base:135 if "@" not in base:
136 subprocess.check_call(["systemctl", "enable", base])136 subprocess.check_call(["systemctl", "enable", base])
@@ -240,6 +240,7 @@ def clear_rabbitmq():
240240
241@when("config.changed.nova-rcs")241@when("config.changed.nova-rcs")
242def update_nova_rcs():242def update_nova_rcs():
243 # pylint: disable=import-outside-toplevel
243 import base64244 import base64
244 from io import BytesIO245 from io import BytesIO
245 from tarfile import TarFile246 from tarfile import TarFile
@@ -303,6 +304,7 @@ def enable_units_initially():
303 "config.changed.releases",304 "config.changed.releases",
304)305)
305def enable_disable_units():306def enable_disable_units():
307 # pylint: disable=import-outside-toplevel
306 from lib.systemd import set_up_systemd_units308 from lib.systemd import set_up_systemd_units
307309
308 nworkers = config().get("n-workers") or ""310 nworkers = config().get("n-workers") or ""
@@ -422,6 +424,7 @@ def write_swift_config():
422)424)
423@when_any("config.set.nova-rcs", "config.set.lxd-remotes")425@when_any("config.set.nova-rcs", "config.set.lxd-remotes")
424def write_worker_config():426def write_worker_config():
427 # pylint: disable=import-outside-toplevel
425 import configparser428 import configparser
426429
427 nworkers = config().get("n-workers") or ""430 nworkers = config().get("n-workers") or ""
@@ -457,7 +460,7 @@ def write_worker_config():
457 "/NET_NAME/": config().get("net-name"),460 "/NET_NAME/": config().get("net-name"),
458 }461 }
459462
460 for k in replacements:463 for k in replacements: # pylint: disable=consider-using-dict-items
461 if replacements[k]:464 if replacements[k]:
462 s = s.replace(k, replacements[k])465 s = s.replace(k, replacements[k])
463466
@@ -535,6 +538,7 @@ def write_mirror():
535@when("autopkgtest.reload-needed")538@when("autopkgtest.reload-needed")
536@when_not("autopkgtest.daemon-reload-needed")539@when_not("autopkgtest.daemon-reload-needed")
537def reload_systemd_units():540def reload_systemd_units():
541 # pylint: disable=import-outside-toplevel
538 from lib.systemd import reload_units542 from lib.systemd import reload_units
539543
540 reload_units()544 reload_units()
diff --git a/charms/focal/autopkgtest-web/reactive/autopkgtest_web.py b/charms/focal/autopkgtest-web/reactive/autopkgtest_web.py
index ccea20f..842348b 100644
--- a/charms/focal/autopkgtest-web/reactive/autopkgtest_web.py
+++ b/charms/focal/autopkgtest-web/reactive/autopkgtest_web.py
@@ -8,7 +8,6 @@ from charmhelpers.core.hookenv import charm_dir, config
8from charms.layer import status8from charms.layer import status
9from charms.reactive import (9from charms.reactive import (
10 clear_flag,10 clear_flag,
11 hook,
12 set_flag,11 set_flag,
13 when,12 when,
14 when_all,13 when_all,
diff --git a/charms/focal/autopkgtest-web/webcontrol/browse.cgi b/charms/focal/autopkgtest-web/webcontrol/browse.cgi
index efdc9b7..d7d7146 100755
--- a/charms/focal/autopkgtest-web/webcontrol/browse.cgi
+++ b/charms/focal/autopkgtest-web/webcontrol/browse.cgi
@@ -7,7 +7,6 @@ import json
7import os7import os
8import re8import re
9import sqlite39import sqlite3
10import urllib.parse
11from collections import OrderedDict10from collections import OrderedDict
12from wsgiref.handlers import CGIHandler11from wsgiref.handlers import CGIHandler
1312
@@ -168,7 +167,7 @@ def get_source_versions(db, release):
168167
169 srcs = {}168 srcs = {}
170 for pkg, ver in db.execute(169 for pkg, ver in db.execute(
171 "SELECT package, version " "FROM current_version " "WHERE release = ?",170 "SELECT package, version FROM current_version WHERE release = ?",
172 (release,),171 (release,),
173 ):172 ):
174 srcs[pkg] = ver173 srcs[pkg] = ver
@@ -185,6 +184,7 @@ def success_count_for_release_and_arch(db, release, arch, src_versions):
185 # but succeeded for a trigger that is not published), don't count it as184 # but succeeded for a trigger that is not published), don't count it as
186 # success185 # success
187 cur_pkg = None186 cur_pkg = None
187 # pylint: disable=unused-variable
188 for pkg, triggers, code in db.execute(188 for pkg, triggers, code in db.execute(
189 "SELECT test.package, triggers, exitcode "189 "SELECT test.package, triggers, exitcode "
190 "FROM test, result, current_version "190 "FROM test, result, current_version "
@@ -213,6 +213,7 @@ def success_count_for_release_and_arch(db, release, arch, src_versions):
213 # it can happen that src_versions does not have a trigger source213 # it can happen that src_versions does not have a trigger source
214 # pacakge if that trigger source got removed in the final release214 # pacakge if that trigger source got removed in the final release
215 if src_versions.get(src) != ver:215 if src_versions.get(src) != ver:
216 # pylint: disable=line-too-long
216 # logging.debug('%s/%s/%s: ignoring non-current trigger %s', release, arch, pkg, trigger)217 # logging.debug('%s/%s/%s: ignoring non-current trigger %s', release, arch, pkg, trigger)
217 continue218 continue
218 # if we arrive here, we have a passing test result for pkg with current219 # if we arrive here, we have a passing test result for pkg with current
@@ -267,6 +268,7 @@ def package_overview(package, _=None):
267 package=package,268 package=package,
268 releases=[269 releases=[
269 release270 release
271 # pylint: disable=consider-iterating-dictionary
270 for release in results.keys()272 for release in results.keys()
271 if release in SUPPORTED_UBUNTU_RELEASES273 if release in SUPPORTED_UBUNTU_RELEASES
272 ],274 ],
@@ -340,7 +342,11 @@ def running():
340 for c in queue_info:342 for c in queue_info:
341 for r in releases:343 for r in releases:
342 for a in arches:344 for a in arches:
343 (queue_length, queue_items) = (345 # pylint: disable=unused-variable
346 (
347 queue_length,
348 queue_items,
349 ) = (
344 queue_info.get(c, {}).get(r, {}).get(a, (0, []))350 queue_info.get(c, {}).get(r, {}).get(a, (0, []))
345 )351 )
346 queue_lengths.setdefault(c, {}).setdefault(r, {})[352 queue_lengths.setdefault(c, {}).setdefault(r, {})[
@@ -367,12 +373,12 @@ def running():
367373
368@app.route("/queue_size.json")374@app.route("/queue_size.json")
369def queuesize_json():375def queuesize_json():
370 out = {}
371 queue_info = get_queue_info()[2]376 queue_info = get_queue_info()[2]
372 # Strip the number of queue items, this is just their contents377 # Strip the number of queue items, this is just their contents
373 for context in queue_info:378 for context in queue_info: # pylint: disable=consider-using-dict-items
374 for release in queue_info[context]:379 for release in queue_info[context]:
375 for arch in queue_info[context][release]:380 for arch in queue_info[context][release]:
381 # pylint: disable=unused-variable
376 (queue_size, queue_items) = queue_info[context][release][arch]382 (queue_size, queue_items) = queue_info[context][release][arch]
377 queue_info[context][release][arch] = len(queue_items)383 queue_info[context][release][arch] = len(queue_items)
378 return json.dumps(queue_info, indent=2)384 return json.dumps(queue_info, indent=2)
@@ -380,12 +386,12 @@ def queuesize_json():
380386
381@app.route("/queues.json")387@app.route("/queues.json")
382def queues_json():388def queues_json():
383 out = {}
384 queue_info = get_queue_info()[2]389 queue_info = get_queue_info()[2]
385 # Strip the number of queue items, this is just their contents390 # Strip the number of queue items, this is just their contents
386 for context in queue_info:391 for context in queue_info: # pylint: disable=consider-using-dict-items
387 for release in queue_info[context]:392 for release in queue_info[context]:
388 for arch in queue_info[context][release]:393 for arch in queue_info[context][release]:
394 # pylint: disable=unused-variable
389 (queue_size, queue_items) = queue_info[context][release][arch]395 (queue_size, queue_items) = queue_info[context][release][arch]
390 queue_info[context][release][arch] = queue_items396 queue_info[context][release][arch] = queue_items
391 return flask.Response(397 return flask.Response(
@@ -416,7 +422,7 @@ def statistics():
416422
417 # ensure we don't run into KeyErrors in the jinja template423 # ensure we don't run into KeyErrors in the jinja template
418 data = {}424 data = {}
419 for release in release_arches:425 for release in release_arches: # pylint: disable=consider-using-dict-items
420 data[release] = {}426 data[release] = {}
421 for arch in release_arches[release]:427 for arch in release_arches[release]:
422 data[release][arch] = {}428 data[release][arch] = {}
@@ -450,7 +456,7 @@ def statistics():
450 pass456 pass
451457
452 # number of packages with tests that pass458 # number of packages with tests that pass
453 for release in release_arches:459 for release in release_arches: # pylint: disable=consider-using-dict-items
454 sources = get_source_versions(db_con, release)460 sources = get_source_versions(db_con, release)
455 for arch in release_arches[release]:461 for arch in release_arches[release]:
456 data[release][arch][462 data[release][arch][
diff --git a/charms/focal/autopkgtest-web/webcontrol/cache-amqp b/charms/focal/autopkgtest-web/webcontrol/cache-amqp
index 1f72747..b626171 100755
--- a/charms/focal/autopkgtest-web/webcontrol/cache-amqp
+++ b/charms/focal/autopkgtest-web/webcontrol/cache-amqp
@@ -62,6 +62,7 @@ class AutopkgtestQueueContents:
62 routing_key=queue_name,62 routing_key=queue_name,
63 )63 )
64 else: # not the leader64 else: # not the leader
65 # pylint: disable=line-too-long
65 logging.error(66 logging.error(
66 "We are not the leader, and there is no semaphore queue yet, we can't do anything - exiting."67 "We are not the leader, and there is no semaphore queue yet, we can't do anything - exiting."
67 )68 )
diff --git a/charms/focal/autopkgtest-web/webcontrol/download-all-results b/charms/focal/autopkgtest-web/webcontrol/download-all-results
index 0ae5c4e..53a3983 100755
--- a/charms/focal/autopkgtest-web/webcontrol/download-all-results
+++ b/charms/focal/autopkgtest-web/webcontrol/download-all-results
@@ -42,10 +42,10 @@ def list_remote_container(container_url):
42 url += f"&marker={urllib.parse.quote(start)}"42 url += f"&marker={urllib.parse.quote(start)}"
4343
44 LOGGER.debug('Retrieving "%s"', url)44 LOGGER.debug('Retrieving "%s"', url)
45 for retry in range(5):45 for _ in range(5):
46 try:46 try:
47 resp = urlopen(url)47 resp = urlopen(url)
48 except http.client.RemoteDisconnected as e:48 except http.client.RemoteDisconnected:
49 LOGGER.debug("Got disconnected, sleeping")49 LOGGER.debug("Got disconnected, sleeping")
50 time.sleep(5)50 time.sleep(5)
51 continue51 continue
@@ -82,6 +82,7 @@ def list_remote_container(container_url):
82def list_our_results(release):82def list_our_results(release):
83 LOGGER.debug("Finding already recorded results for %s", release)83 LOGGER.debug("Finding already recorded results for %s", release)
84 c = db_con.cursor()84 c = db_con.cursor()
85 # pylint: disable=line-too-long
85 c.execute(86 c.execute(
86 "SELECT run_id FROM result INNER JOIN test ON test.id = result.test_id WHERE test.release=?",87 "SELECT run_id FROM result INNER JOIN test ON test.id = result.test_id WHERE test.release=?",
87 (release,),88 (release,),
@@ -108,7 +109,7 @@ def fetch_one_result(url):
108 LOGGER.error("Failure to fetch %s: %s", url, str(e))109 LOGGER.error("Failure to fetch %s: %s", url, str(e))
109 # we tolerate "not found" (something went wrong on uploading the110 # we tolerate "not found" (something went wrong on uploading the
110 # result), but other things indicate infrastructure problems111 # result), but other things indicate infrastructure problems
111 if hasattr(e, "code") and e.code == 404:112 if hasattr(e, "code") and e.code == 404: # pylint: disable=no-member
112 return113 return
113 sys.exit(1)114 sys.exit(1)
114115
@@ -119,7 +120,7 @@ def fetch_one_result(url):
119 srcver = (120 srcver = (
120 tar.extractfile("testpkg-version").read().decode().strip()121 tar.extractfile("testpkg-version").read().decode().strip()
121 )122 )
122 except KeyError as e:123 except KeyError:
123 # not found124 # not found
124 if exitcode in (4, 12, 20):125 if exitcode in (4, 12, 20):
125 # repair it126 # repair it
@@ -137,7 +138,7 @@ def fetch_one_result(url):
137 requester = (138 requester = (
138 tar.extractfile("requester").read().decode().strip()139 tar.extractfile("requester").read().decode().strip()
139 )140 )
140 except KeyError as e:141 except KeyError:
141 requester = ""142 requester = ""
142 except (KeyError, ValueError, tarfile.TarError) as e:143 except (KeyError, ValueError, tarfile.TarError) as e:
143 LOGGER.debug("%s is damaged, ignoring: %s", url, str(e))144 LOGGER.debug("%s is damaged, ignoring: %s", url, str(e))
@@ -194,8 +195,6 @@ def fetch_one_result(url):
194def fetch_container(release, container_url):195def fetch_container(release, container_url):
195 """Download new results from a swift container"""196 """Download new results from a swift container"""
196197
197 marker = ""
198
199 try:198 try:
200 our_results = list_our_results(release)199 our_results = list_our_results(release)
201 known_results = list_remote_container(container_url)200 known_results = list_remote_container(container_url)
diff --git a/charms/focal/autopkgtest-web/webcontrol/download-results b/charms/focal/autopkgtest-web/webcontrol/download-results
index 419af47..0f14155 100755
--- a/charms/focal/autopkgtest-web/webcontrol/download-results
+++ b/charms/focal/autopkgtest-web/webcontrol/download-results
@@ -7,7 +7,6 @@ import os
7import socket7import socket
8import sqlite38import sqlite3
9import urllib.parse9import urllib.parse
10from urllib.request import urlopen
1110
12import amqplib.client_0_8 as amqp11import amqplib.client_0_8 as amqp
13from helpers.utils import get_test_id, init_db12from helpers.utils import get_test_id, init_db
diff --git a/charms/focal/autopkgtest-web/webcontrol/private_results/app.py b/charms/focal/autopkgtest-web/webcontrol/private_results/app.py
index ee7b6d0..9ae1e89 100644
--- a/charms/focal/autopkgtest-web/webcontrol/private_results/app.py
+++ b/charms/focal/autopkgtest-web/webcontrol/private_results/app.py
@@ -15,13 +15,12 @@ from flask import (
15 session,15 session,
16)16)
17from flask_openid import OpenID17from flask_openid import OpenID
18from helpers.utils import setup_key
19from request.submit import Submit
18from werkzeug.middleware.proxy_fix import ProxyFix20from werkzeug.middleware.proxy_fix import ProxyFix
1921
20sys.path.append("..")22sys.path.append("..")
2123
22from helpers.utils import setup_key
23from request.submit import Submit
24
25HTML = """24HTML = """
26<!doctype html>25<!doctype html>
27<html>26<html>
diff --git a/charms/focal/autopkgtest-web/webcontrol/publish-db b/charms/focal/autopkgtest-web/webcontrol/publish-db
index f35c9e8..76a2177 100755
--- a/charms/focal/autopkgtest-web/webcontrol/publish-db
+++ b/charms/focal/autopkgtest-web/webcontrol/publish-db
@@ -4,11 +4,9 @@
4# This is being used for statistics.4# This is being used for statistics.
55
6import configparser6import configparser
7import fcntl
8import gzip7import gzip
9import logging8import logging
10import os9import os
11import shutil
12import sqlite310import sqlite3
13import tempfile11import tempfile
14import urllib.request12import urllib.request
@@ -156,6 +154,7 @@ def get_sources(db_con, release):
156 )154 )
157 temp_file.seek(0)155 temp_file.seek(0)
158 with gzip.open(temp_file) as fd:156 with gzip.open(temp_file) as fd:
157 # pylint: disable=c-extension-no-member
159 for section in apt_pkg.TagFile(fd):158 for section in apt_pkg.TagFile(fd):
160 db_con.execute(159 db_con.execute(
161 "INSERT INTO current_version "160 "INSERT INTO current_version "
@@ -177,7 +176,6 @@ def get_sources(db_con, release):
177 except urllib.error.HTTPError as e:176 except urllib.error.HTTPError as e:
178 if e.code == 304:177 if e.code == 304:
179 logging.debug("url {} not modified".format(url))178 logging.debug("url {} not modified".format(url))
180 pass
181179
182180
183if __name__ == "__main__":181if __name__ == "__main__":
diff --git a/charms/focal/autopkgtest-web/webcontrol/request/submit.py b/charms/focal/autopkgtest-web/webcontrol/request/submit.py
index bc283a7..ac2d5c0 100644
--- a/charms/focal/autopkgtest-web/webcontrol/request/submit.py
+++ b/charms/focal/autopkgtest-web/webcontrol/request/submit.py
@@ -63,6 +63,7 @@ class Submit:
63 assert self.amqp_creds.scheme == "amqp"63 assert self.amqp_creds.scheme == "amqp"
64 logging.debug("AMQP credentials: %s" % repr(self.amqp_creds))64 logging.debug("AMQP credentials: %s" % repr(self.amqp_creds))
6565
66 # pylint: disable=dangerous-default-value
66 def validate_distro_request(67 def validate_distro_request(
67 self, release, arch, package, triggers, requester, ppas=[], **kwargs68 self, release, arch, package, triggers, requester, ppas=[], **kwargs
68 ):69 ):
@@ -132,10 +133,10 @@ class Submit:
132 for trigger in triggers:133 for trigger in triggers:
133 try:134 try:
134 trigsrc, trigver = trigger.split("/")135 trigsrc, trigver = trigger.split("/")
135 except ValueError:136 except ValueError as exc:
136 raise ValueError(137 raise ValueError(
137 "Malformed trigger, must be srcpackage/version"138 "Malformed trigger, must be srcpackage/version"
138 )139 ) from exc
139 # Debian Policy 5.6.1 and 5.6.12140 # Debian Policy 5.6.1 and 5.6.12
140 if not NAME.match(trigsrc) or not VERSION.match(trigver):141 if not NAME.match(trigsrc) or not VERSION.match(trigver):
141 raise ValueError("Malformed trigger")142 raise ValueError("Malformed trigger")
@@ -197,6 +198,7 @@ class Submit:
197 "service." % (package, trigsrc)198 "service." % (package, trigsrc)
198 )199 )
199200
201 # pylint: disable=dangerous-default-value
200 def validate_git_request(202 def validate_git_request(
201 self, release, arch, package, ppas=[], env=[], **kwargs203 self, release, arch, package, ppas=[], env=[], **kwargs
202 ):204 ):
@@ -303,7 +305,7 @@ class Submit:
303 )305 )
304306
305 @classmethod307 @classmethod
306 def post_json(klass, url, data, auth_file, project):308 def post_json(cls, url, data, auth_file, project):
307 """Send POST request with JSON data via basic auth.309 """Send POST request with JSON data via basic auth.
308310
309 'data' is a dictionary which will be posted to 'url' in JSON encoded311 'data' is a dictionary which will be posted to 'url' in JSON encoded
@@ -388,7 +390,7 @@ class Submit:
388 )390 )
389 else:391 else:
390 c.execute(392 c.execute(
391 "SELECT count(arch) FROM test " "WHERE package=? AND arch=?",393 "SELECT count(arch) FROM test WHERE package=? AND arch=?",
392 (package, arch),394 (package, arch),
393 )395 )
394 return c.fetchone()[0] > 0396 return c.fetchone()[0] > 0
@@ -459,18 +461,19 @@ class Submit:
459 )461 )
460 return code >= 200 and code < 300462 return code >= 200 and code < 300
461463
464 # pylint: disable=dangerous-default-value
462 def in_allowed_team(self, person, package=[], teams=[]):465 def in_allowed_team(self, person, package=[], teams=[]):
463 """Check if person is in ALLOWED_TEAMS"""466 """Check if person is in ALLOWED_TEAMS"""
464467
465 for team in teams or ALLOWED_TEAMS:468 for team in teams or ALLOWED_TEAMS:
466 (code, response) = self.lp_request("~%s/participants" % team, {})469 (_, response) = self.lp_request("~%s/participants" % team, {})
467 for e in response.get("entries", []):470 for e in response.get("entries", []):
468 if e.get("name") == person:471 if e.get("name") == person:
469 return True472 return True
470 return False473 return False
471474
472 @classmethod475 @classmethod
473 def lp_request(klass, obj, query):476 def lp_request(cls, obj, query):
474 """Do a Launchpad REST request477 """Do a Launchpad REST request
475478
476 Request https://api.launchpad.net/1.0/<obj>?<query>.479 Request https://api.launchpad.net/1.0/<obj>?<query>.
diff --git a/charms/focal/autopkgtest-web/webcontrol/request/tests/test_app.py b/charms/focal/autopkgtest-web/webcontrol/request/tests/test_app.py
index 44067b9..42dac0c 100644
--- a/charms/focal/autopkgtest-web/webcontrol/request/tests/test_app.py
+++ b/charms/focal/autopkgtest-web/webcontrol/request/tests/test_app.py
@@ -1,3 +1,4 @@
1# pylint: disable=no-value-for-parameter,no-member
1"""Test the Flask app."""2"""Test the Flask app."""
23
3import os4import os
diff --git a/charms/focal/autopkgtest-web/webcontrol/update-github-jobs b/charms/focal/autopkgtest-web/webcontrol/update-github-jobs
index 334722f..6362803 100755
--- a/charms/focal/autopkgtest-web/webcontrol/update-github-jobs
+++ b/charms/focal/autopkgtest-web/webcontrol/update-github-jobs
@@ -21,7 +21,7 @@ external_url = None
2121
22def result_matches_job(result_url, params):22def result_matches_job(result_url, params):
23 # download result.tar and get exit code and testinfo23 # download result.tar and get exit code and testinfo
24 for retry in range(5):24 for _ in range(5):
25 try:25 try:
26 with urllib.request.urlopen(result_url + "/result.tar") as f:26 with urllib.request.urlopen(result_url + "/result.tar") as f:
27 tar_bytes = io.BytesIO(f.read())27 tar_bytes = io.BytesIO(f.read())
diff --git a/mojo/add-floating-ip b/mojo/add-floating-ip
index 57c9839..0a816bf 100755
--- a/mojo/add-floating-ip
+++ b/mojo/add-floating-ip
@@ -8,6 +8,7 @@
8import json8import json
9import os9import os
10import subprocess10import subprocess
11import sys
1112
12import novaclient.client13import novaclient.client
1314
@@ -94,14 +95,14 @@ def get_unit_floating_ip(unit_name):
94 try:95 try:
95 # Get the existing one96 # Get the existing one
96 fip = nova_tenant.floating_ips.find(ip=myip)97 fip = nova_tenant.floating_ips.find(ip=myip)
97 except Exception:98 except Exception as exc:
98 # If this happens you're going to need to either get that back in the list,99 # If this happens you're going to need to either get that back in the list,
99 # or blow away the state file so it gets a new IP.100 # or blow away the state file so it gets a new IP.
100 raise (101 raise (
101 RuntimeError(102 RuntimeError(
102 "Desired IP {} not in floating ips list!".format(myip)103 "Desired IP {} not in floating ips list!".format(myip)
103 )104 )
104 )105 ) from exc
105106
106 if fip.instance_id:107 if fip.instance_id:
107 # If it's already associated, ensure it's associated to us108 # If it's already associated, ensure it's associated to us
@@ -147,8 +148,6 @@ add-floating-ip
147148
148149
149def main():150def main():
150 import sys
151
152 if len(sys.argv) >= 2:151 if len(sys.argv) >= 2:
153 args = sys.argv[1:]152 args = sys.argv[1:]
154 elif "targets" in os.environ:153 elif "targets" in os.environ:

Subscribers

People subscribed via source and target branches