Merge ppa-dev-tools:make-check-fixes into ppa-dev-tools:main

Proposed by Bryce Harrington
Status: Merged
Merged at revision: c1451af3a7d727b1499275858e4c24f49e82321e
Proposed branch: ppa-dev-tools:make-check-fixes
Merge into: ppa-dev-tools:main
Diff against target: 817 lines (+132/-82)
14 files modified
ppa/debug.py (+3/-0)
ppa/job.py (+9/-6)
ppa/lp.py (+4/-4)
ppa/ppa.py (+11/-7)
ppa/ppa_group.py (+5/-3)
ppa/processes.py (+8/-6)
ppa/result.py (+1/-2)
ppa/subtest.py (+2/-3)
ppa/text.py (+18/-13)
tests/test_lp.py (+11/-3)
tests/test_ppa.py (+3/-3)
tests/test_ppa_group.py (+15/-7)
tests/test_scripts_ppa.py (+40/-22)
tests/test_version.py (+2/-3)
Reviewer Review Type Date Requested Status
Christian Ehrhardt  (community) Approve
Canonical Server Pending
Canonical Server Reporter Pending
Review via email: mp+430005@code.launchpad.net

Description of the change

Cleanup to prep for 0.2 release.

To post a comment you must log in.
Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

Really seems to be just cleanups, whitespace lines, line length, f-string, import order and useless imports ... the stuff you know from your friendly linters.

I didn't see anything odd, therefore +1 to this

review: Approve
Revision history for this message
Bryce Harrington (bryce) wrote :

Excellent, thanks

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/ppa/debug.py b/ppa/debug.py
index 8339e73..009ead4 100644
--- a/ppa/debug.py
+++ b/ppa/debug.py
@@ -13,6 +13,7 @@ import pprint
1313
14DEBUGGING = False14DEBUGGING = False
1515
16
16def dbg(msg):17def dbg(msg):
17 """Prints information if debugging is enabled"""18 """Prints information if debugging is enabled"""
18 if DEBUGGING:19 if DEBUGGING:
@@ -21,10 +22,12 @@ def dbg(msg):
21 else:22 else:
22 pprint.pprint(msg)23 pprint.pprint(msg)
2324
25
24def warn(msg):26def warn(msg):
25 """Prints message to stderr"""27 """Prints message to stderr"""
26 sys.stderr.write("Warning: {}\n".format(msg))28 sys.stderr.write("Warning: {}\n".format(msg))
2729
30
28def die(msg, code=1):31def die(msg, code=1):
29 """Prints message to stderr and exits with given code"""32 """Prints message to stderr and exits with given code"""
30 sys.stderr.write("Error: {}\n".format(msg))33 sys.stderr.write("Error: {}\n".format(msg))
diff --git a/ppa/job.py b/ppa/job.py
index 2ae06ba..91f015c 100755
--- a/ppa/job.py
+++ b/ppa/job.py
@@ -148,9 +148,9 @@ def show_running(jobs):
148 if n == 1:148 if n == 1:
149 print("Running:")149 print("Running:")
150 ppa_str = ','.join(e.ppas)150 ppa_str = ','.join(e.ppas)
151 trigger_str = ','.join(e.triggers)151 trig_str = ','.join(e.triggers)
152 print(rformat % ("time", "pkg", "release", "arch", "ppa", "trigger"))152 print(rformat % ("time", "pkg", "release", "arch", "ppa", "trigger"))
153 print(rformat % (str(e.submit_time), e.source_package, e.series, e.arch, ppa_str, trigger_str))153 print(rformat % (str(e.submit_time), e.source_package, e.series, e.arch, ppa_str, trig_str))
154 if n == 0:154 if n == 0:
155 print("Running: (none)")155 print("Running: (none)")
156156
@@ -164,7 +164,10 @@ def show_waiting(jobs):
164 if n == 1:164 if n == 1:
165 print("Waiting:")165 print("Waiting:")
166 print(rformat % ("Q-num", "pkg", "release", "arch", "ppa", "trigger"))166 print(rformat % ("Q-num", "pkg", "release", "arch", "ppa", "trigger"))
167 print(rformat % (e.number, e.source_package, e.series, e.arch, ','.join(e.ppas), ','.join(e.triggers)))167
168 ppa_str = ','.join(e.ppas)
169 trig_str = ','.join(e.triggers)
170 print(rformat % (e.number, e.source_package, e.series, e.arch, ppa_str, trig_str))
168 if n == 0:171 if n == 0:
169 print("Waiting: (none)")172 print("Waiting: (none)")
170173
@@ -178,8 +181,8 @@ if __name__ == "__main__":
178 root_dir = os.path.realpath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '..'))181 root_dir = os.path.realpath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '..'))
179 jobinfo = {182 jobinfo = {
180 'triggers': ['a/1', 'b/2.1', 'c/3.2.1'],183 'triggers': ['a/1', 'b/2.1', 'c/3.2.1'],
181 'ppas': ['ppa:me/myppa'],184 'ppas': ['ppa:me/myppa']
182 }185 }
183 job_1 = Job(186 job_1 = Job(
184 number=0,187 number=0,
185 submit_time='time',188 submit_time='time',
@@ -188,7 +191,7 @@ if __name__ == "__main__":
188 arch='amd64',191 arch='amd64',
189 triggers=jobinfo.get('triggers', None),192 triggers=jobinfo.get('triggers', None),
190 ppas=jobinfo.get('ppas', None)193 ppas=jobinfo.get('ppas', None)
191 )194 )
192 print(job_1)195 print(job_1)
193 print(f"triggers: {job_1.triggers}")196 print(f"triggers: {job_1.triggers}")
194 print(f"ppas: {job_1.ppas}")197 print(f"ppas: {job_1.ppas}")
diff --git a/ppa/lp.py b/ppa/lp.py
index c3ebaac..1762345 100644
--- a/ppa/lp.py
+++ b/ppa/lp.py
@@ -14,12 +14,12 @@
14High level wrapper object for Launchpad's API14High level wrapper object for Launchpad's API
15"""15"""
1616
17from os.path import join
18from contextlib import suppress17from contextlib import suppress
19from functools import lru_cache18from functools import lru_cache
2019
21from launchpadlib.launchpad import Launchpad20from launchpadlib.launchpad import Launchpad
2221
22
23class Lp:23class Lp:
24 """24 """
25 This class wrappers the Launchpadlib service to cache object queries25 This class wrappers the Launchpadlib service to cache object queries
@@ -32,8 +32,8 @@ class Lp:
32 itself is passed directly to the Launchpadlib object, so the entire32 itself is passed directly to the Launchpadlib object, so the entire
33 API is available in exactly the same way.33 API is available in exactly the same way.
34 """34 """
35 ROOT_URL = 'https://launchpad.net/'35 ROOT_URL = 'https://launchpad.net/'
36 API_ROOT_URL = 'https://api.launchpad.net/devel/'36 API_ROOT_URL = 'https://api.launchpad.net/devel/'
37 BUGS_ROOT_URL = 'https://bugs.launchpad.net/'37 BUGS_ROOT_URL = 'https://bugs.launchpad.net/'
38 CODE_ROOT_URL = 'https://code.launchpad.net/'38 CODE_ROOT_URL = 'https://code.launchpad.net/'
3939
@@ -68,7 +68,7 @@ class Lp:
6868
69 def __getattr__(self, attr):69 def __getattr__(self, attr):
70 """Wrap launchpadlib so tightly you can't tell the difference."""70 """Wrap launchpadlib so tightly you can't tell the difference."""
71 assert not attr.startswith('_'), "Can't getattr for %s" %(attr)71 assert not attr.startswith('_'), f"Can't getattr for {attr}"
72 instance = super(Lp, self).__getattribute__('_instance')72 instance = super(Lp, self).__getattribute__('_instance')
73 return getattr(instance, attr)73 return getattr(instance, attr)
7474
diff --git a/ppa/ppa.py b/ppa/ppa.py
index 6f744a4..763ed7f 100755
--- a/ppa/ppa.py
+++ b/ppa/ppa.py
@@ -44,7 +44,7 @@ def ppa_address_split(ppa_address, default_team='me'):
44 if ppa_address.startswith('ppa:'):44 if ppa_address.startswith('ppa:'):
45 if '/' not in ppa_address:45 if '/' not in ppa_address:
46 return (None, None)46 return (None, None)
47 rem = ppa_address.split('ppa:',1)[1]47 rem = ppa_address.split('ppa:', 1)[1]
48 team_name = rem.split('/', 1)[0]48 team_name = rem.split('/', 1)[0]
49 ppa_name = rem.split('/', 1)[1]49 ppa_name = rem.split('/', 1)[1]
50 else:50 else:
@@ -193,7 +193,7 @@ class Ppa:
193 :returns: List of architecture names, or None on error.193 :returns: List of architecture names, or None on error.
194 """194 """
195 try:195 try:
196 return [ proc.name for proc in self.archive.processors ]196 return [proc.name for proc in self.archive.processors]
197 except PpaDoesNotExist as e:197 except PpaDoesNotExist as e:
198 print(e)198 print(e)
199 return None199 return None
@@ -208,7 +208,7 @@ class Ppa:
208 :returns: List of architecture names, or None on error.208 :returns: List of architecture names, or None on error.
209 """209 """
210 uri_base = "https://api.launchpad.net/devel/+processors/{}"210 uri_base = "https://api.launchpad.net/devel/+processors/{}"
211 procs = [ uri_base.format(arch) for arch in architectures ]211 procs = [uri_base.format(arch) for arch in architectures]
212 try:212 try:
213 self.archive.setProcessors(processors=procs)213 self.archive.setProcessors(processors=procs)
214 return True214 return True
@@ -225,7 +225,7 @@ class Ppa:
225 :rtype: list[binary_package_publishing_history]225 :rtype: list[binary_package_publishing_history]
226 :returns: List of binaries, or None on error226 :returns: List of binaries, or None on error
227 """227 """
228 if distro == None and series == None and arch == None:228 if distro is None and series is None and arch is None:
229 try:229 try:
230 return self.archive.getPublishedBinaries()230 return self.archive.getPublishedBinaries()
231 except PpaDoesNotExist as e:231 except PpaDoesNotExist as e:
@@ -323,7 +323,9 @@ class Ppa:
323 published_builds[binary_publication.build_link] = binary_publication323 published_builds[binary_publication.build_link] = binary_publication
324324
325 retval = False325 retval = False
326 num_builds_waiting = len(required_builds) - len(pending_publication_builds) - len(published_builds)326 num_builds_waiting = (
327 len(required_builds) - len(pending_publication_builds) - len(published_builds)
328 )
327 if num_builds_waiting != 0:329 if num_builds_waiting != 0:
328 num_build_failures = 0330 num_build_failures = 0
329 builds_waiting_output = ''331 builds_waiting_output = ''
@@ -353,12 +355,14 @@ class Ppa:
353 retval = True355 retval = True
354356
355 if len(pending_publication_builds) != 0:357 if len(pending_publication_builds) != 0:
356 print("* Still waiting on {} build publications:".format(len(pending_publication_builds)))358 num = len(pending_publication_builds)
359 print(f"* Still waiting on {num} build publications:")
357 for pub in pending_publication_builds.values():360 for pub in pending_publication_builds.values():
358 print(" - {}".format(pub.display_name))361 print(" - {}".format(pub.display_name))
359 retval = True362 retval = True
360 if len(pending_publication_sources) != 0:363 if len(pending_publication_sources) != 0:
361 print("* Still waiting on {} source publications:".format(len(pending_publication_sources)))364 num = len(pending_publication_sources)
365 print(f"* Still waiting on {num} source publications:")
362 for pub in pending_publication_sources.values():366 for pub in pending_publication_sources.values():
363 print(" - {}".format(pub.display_name))367 print(" - {}".format(pub.display_name))
364 retval = True368 retval = True
diff --git a/ppa/ppa_group.py b/ppa/ppa_group.py
index cb769ad..1a9c8b7 100755
--- a/ppa/ppa_group.py
+++ b/ppa/ppa_group.py
@@ -14,6 +14,7 @@ from .text import o2str
14from functools import lru_cache14from functools import lru_cache
15from lazr.restfulclient.errors import BadRequest15from lazr.restfulclient.errors import BadRequest
1616
17
17class PpaAlreadyExists(BaseException):18class PpaAlreadyExists(BaseException):
18 '''Exception indicating a PPA operation could not be performed'''19 '''Exception indicating a PPA operation could not be performed'''
1920
@@ -34,7 +35,8 @@ class PpaAlreadyExists(BaseException):
34 if self.message:35 if self.message:
35 return self.message36 return self.message
36 elif self.ppa_name:37 elif self.ppa_name:
37 return "The PPA %s already exists" %(self.ppa_name)38 return f"The PPA {self.ppa_name} already exists"
39
3840
39class PpaGroup:41class PpaGroup:
40 """Represents a team or person that owns one or more PPAs.42 """Represents a team or person that owns one or more PPAs.
@@ -58,7 +60,7 @@ class PpaGroup:
5860
59 def __repr__(self):61 def __repr__(self):
60 return (f'{self.__class__.__name__}('62 return (f'{self.__class__.__name__}('
61 f'service={self.service!r}, name={self.name!r})')63 f'service={self.service!r}, name={self.name!r})')
6264
63 def __str__(self):65 def __str__(self):
64 return 'tbd'66 return 'tbd'
@@ -91,7 +93,7 @@ class PpaGroup:
91 ppa_displayname = ppa_name93 ppa_displayname = ppa_name
9294
93 try:95 try:
94 results = self.team.createPPA(96 self.team.createPPA(
95 name=ppa_name,97 name=ppa_name,
96 description=ppa_description,98 description=ppa_description,
97 displayname=ppa_displayname)99 displayname=ppa_displayname)
diff --git a/ppa/processes.py b/ppa/processes.py
index e008c0c..5f54e39 100644
--- a/ppa/processes.py
+++ b/ppa/processes.py
@@ -28,7 +28,6 @@ from subprocess import (Popen, PIPE)
28from .debug import dbg28from .debug import dbg
29from .text import o2str29from .text import o2str
3030
31# TODO: Integrate use of dbg and ERR from utils
3231
33class ReturnCode(BaseException):32class ReturnCode(BaseException):
34 def __init__(self, code, errors=None):33 def __init__(self, code, errors=None):
@@ -40,11 +39,12 @@ class ReturnCode(BaseException):
4039
41 def __str__(self):40 def __str__(self):
42 text = '\n'.join(self.errors)41 text = '\n'.join(self.errors)
43 return "%sReturned error code %d" %(text, self.code)42 return f"{text}Returned error code {self.code}"
43
4444
45def shell(command, in_text=None):45def shell(command, in_text=None):
46 """Executes command in a shell, returns stdout, raises exception on error"""46 """Executes command in a shell, returns stdout, raises exception on error"""
47 dbg("shell: %s" %(command))47 dbg(f"shell: {command}")
48 if in_text:48 if in_text:
49 p = Popen(command, shell=True, stdout=PIPE, stderr=PIPE, stdin=PIPE)49 p = Popen(command, shell=True, stdout=PIPE, stderr=PIPE, stdin=PIPE)
50 output, errors = p.communicate(input=in_text)50 output, errors = p.communicate(input=in_text)
@@ -55,14 +55,15 @@ def shell(command, in_text=None):
55 raise ReturnCode(p.returncode, o2str(errors))55 raise ReturnCode(p.returncode, o2str(errors))
56 return o2str(output)56 return o2str(output)
5757
58
58def execute(command, in_text=None):59def execute(command, in_text=None):
59 """Executes command, returns stdout; prints errors to stderr"""60 """Executes command, returns stdout; prints errors to stderr"""
60 dbg("execute: `%s`" %(command))61 dbg(f"execute: `{command}`")
61 if in_text is None:62 if in_text is None:
62 p = Popen(command, shell=False, stdout=PIPE, stderr=PIPE)63 p = Popen(command, shell=False, stdout=PIPE, stderr=PIPE)
63 else:64 else:
64 p = Popen(command, shell=False, stdout=PIPE, stderr=PIPE, stdin=PIPE)65 p = Popen(command, shell=False, stdout=PIPE, stderr=PIPE, stdin=PIPE)
65 dbg("execute: polling (%s)..." %(in_text))66 dbg(f"execute: polling ({in_text})...")
66 while p.poll() is None and p.stdin is not None:67 while p.poll() is None and p.stdin is not None:
67 dbg("execute: Sending to process stdin")68 dbg("execute: Sending to process stdin")
68 p.stdin.write(in_text)69 p.stdin.write(in_text)
@@ -70,10 +71,11 @@ def execute(command, in_text=None):
70 sleep(0.01)71 sleep(0.01)
71 output = p.stdout.read()72 output = p.stdout.read()
72 if p.returncode:73 if p.returncode:
73 dbg("Received return code %d" %(p.returncode))74 dbg(f"Received return code {p.returncode}")
74 raise ReturnCode(p.returncode, p.stderr.readlines())75 raise ReturnCode(p.returncode, p.stderr.readlines())
75 return o2str(output)76 return o2str(output)
7677
78
77def execute_with_input(command, in_text):79def execute_with_input(command, in_text):
78 """Executes command, passing in_text to stdin if provided"""80 """Executes command, passing in_text to stdin if provided"""
79 execute(command, in_text)81 execute(command, in_text)
diff --git a/ppa/result.py b/ppa/result.py
index 7a2ca5a..4f4aadd 100755
--- a/ppa/result.py
+++ b/ppa/result.py
@@ -30,7 +30,7 @@ class Result:
30 VALUES = {30 VALUES = {
31 'PASS': "✅",31 'PASS': "✅",
32 'FAIL': "❌",32 'FAIL': "❌",
33 'BAD': "⛔",33 'BAD': "⛔"
34 }34 }
3535
36 def __init__(self, url, time, series, arch, source):36 def __init__(self, url, time, series, arch, source):
@@ -145,7 +145,6 @@ class Result:
145 package, version = t.split('/', 1)145 package, version = t.split('/', 1)
146 yield Trigger(package, version, arch=self.arch, series=self.series)146 yield Trigger(package, version, arch=self.arch, series=self.series)
147147
148
149 @lru_cache148 @lru_cache
150 def get_subtests(self, name=None) -> Iterator[Subtest]:149 def get_subtests(self, name=None) -> Iterator[Subtest]:
151 """Provides list of Subtests that were run for this Result.150 """Provides list of Subtests that were run for this Result.
diff --git a/ppa/subtest.py b/ppa/subtest.py
index c63dda6..90134b8 100755
--- a/ppa/subtest.py
+++ b/ppa/subtest.py
@@ -12,7 +12,6 @@
12"""An individual DEP8 test run"""12"""An individual DEP8 test run"""
1313
14from functools import cached_property14from functools import cached_property
15from typing import List, Iterator
1615
1716
18class Subtest:17class Subtest:
@@ -25,9 +24,9 @@ class Subtest:
25 'PASS': "🟩",24 'PASS': "🟩",
26 'SKIP': "🟧",25 'SKIP': "🟧",
27 'FAIL': "🟥",26 'FAIL': "🟥",
28 'BAD': "⛔",27 'BAD': "⛔",
29 'UNKNOWN': "⚪"28 'UNKNOWN': "⚪"
30 }29 }
3130
32 def __init__(self, line):31 def __init__(self, line):
33 """Initializes a new Subtext object.32 """Initializes a new Subtext object.
diff --git a/ppa/text.py b/ppa/text.py
index fb8c558..b1e1453 100644
--- a/ppa/text.py
+++ b/ppa/text.py
@@ -24,9 +24,11 @@
2424
25'''Routines to encode or convert to and from text'''25'''Routines to encode or convert to and from text'''
2626
27from decimal import Decimal27import sys
28from decimal import Decimal
28from functools import lru_cache29from functools import lru_cache
2930
31
30@lru_cache32@lru_cache
31def quote(msg):33def quote(msg):
32 """34 """
@@ -39,13 +41,14 @@ def quote(msg):
39 msg = msg.replace('>', '>')41 msg = msg.replace('>', '>')
40 return msg42 return msg
4143
44
42@lru_cache45@lru_cache
43def o2str(obj):46def o2str(obj):
44 """47 """
45 Convert a unicode, decimal.Decimal, datetime object, etc. to a str.48 Convert a unicode, decimal.Decimal, datetime object, etc. to a str.
46 Converts lists and tuples of objects into lists of strings.49 Converts lists and tuples of objects into lists of strings.
47 """50 """
48 retval = None51
49 if type(obj) == str:52 if type(obj) == str:
50 return obj53 return obj
51 elif type(obj) == bytes:54 elif type(obj) == bytes:
@@ -60,9 +63,10 @@ def o2str(obj):
60 elif str(type(obj)) == "<type 'datetime.datetime'>":63 elif str(type(obj)) == "<type 'datetime.datetime'>":
61 return obj.ctime()64 return obj.ctime()
62 else:65 else:
63 #print str(type(obj))66 # print str(type(obj))
64 return obj67 return obj
6568
69
66@lru_cache70@lru_cache
67def to_bool(value):71def to_bool(value):
68 """72 """
@@ -70,14 +74,15 @@ def to_bool(value):
70 Possible True values: 1, True, '1', 'TRue', 'yes', 'y', 't'74 Possible True values: 1, True, '1', 'TRue', 'yes', 'y', 't'
71 Possible False values: 0, False, None, [], {}, '', '0', 'faLse', 'no', 'n', 'f', 0.075 Possible False values: 0, False, None, [], {}, '', '0', 'faLse', 'no', 'n', 'f', 0.0
72 """76 """
73 if type(value) == type(''):77 if isinstance(value, str):
74 if value.lower() in ("yes", "y", "true", "t", "1"):78 if value.lower() in ("yes", "y", "true", "t", "1"):
75 return True79 return True
76 if value.lower() in ("no", "n", "false", "f", "0", "none", ""):80 if value.lower() in ("no", "n", "false", "f", "0", "none", ""):
77 return False81 return False
78 raise Exception('Invalid value for boolean conversion: ' + value)82 raise Exception('Invalid value for boolean conversion: ' + value)
79 return bool(value)83 return bool(value)
8084
85
81@lru_cache86@lru_cache
82def o2float(value):87def o2float(value):
83 '''Converts strings like 42%, 123M, 1.2B into floating point numbers88 '''Converts strings like 42%, 123M, 1.2B into floating point numbers
@@ -93,21 +98,21 @@ def o2float(value):
93 elif value == '--':98 elif value == '--':
94 return 0.099 return 0.0
95100
96 value = value.replace(',','')101 value = value.replace(',', '')
97 last = value[len(value)-1]102 last = value[len(value) - 1]
98 if last == 'M':103 if last == 'M':
99 return float(value[:-1])104 return float(value[:-1])
100 elif last == 'B':105 elif last == 'B':
101 return float(value[:-1]) * 1000106 return float(value[:-1]) * 1000
102 elif last == '%':107 elif last == '%':
103 return float(value[:-1])/100.0108 return float(value[:-1]) / 100.0
104 elif last == ')' and value[0] == '(':109 elif last == ')' and value[0] == '(':
105 return -1 * o2float(value[1:-1])110 return -1 * o2float(value[1:-1])
106111
107 try:112 try:
108 return float(value)113 return float(value)
109 except ValueError:114 except ValueError:
110 sys.stderr.write("ofloat: Could not convert '%s' to float\n" %(value))115 sys.stderr.write(f"ofloat: Could not convert '{value}' to float\n")
111 raise116 raise
112117
113118
@@ -132,10 +137,10 @@ if __name__ == "__main__":
132 ({}, False),137 ({}, False),
133 ((), False),138 ((), False),
134 ([1], True),139 ([1], True),
135 ({1:2}, True),140 ({1: 2}, True),
136 ((1,), True),141 ((1,), True),
137 (None, False),142 (None, False),
138 (object(), True),143 (object(), True),
139 ]144 ]
140 for test, expected in test_cases:145 for test, expected in test_cases:
141 assert to_bool(test) == expected, "to_bool("+test+") failed to return "+expected146 assert to_bool(test) == expected, f"to_bool({test}) failed to return {expected}"
diff --git a/tests/test_lp.py b/tests/test_lp.py
index a8fcdcb..d5978ce 100644
--- a/tests/test_lp.py
+++ b/tests/test_lp.py
@@ -30,7 +30,7 @@ Tests for our launchpadlib wrapper & helper methods.
30import sys30import sys
31import os.path31import os.path
3232
33from mock import Mock, patch33from mock import Mock
34import pytest34import pytest
35import logging35import logging
3636
@@ -41,6 +41,7 @@ from launchpadlib.launchpad import Launchpad
4141
42APPNAME = 'test-lp'42APPNAME = 'test-lp'
4343
44
44@pytest.fixture45@pytest.fixture
45def fakelp(tmp_path):46def fakelp(tmp_path):
46 """Connect to Launchpad."""47 """Connect to Launchpad."""
@@ -71,16 +72,19 @@ def test_new_connection(tmp_path):
71 version='devel',72 version='devel',
72 )73 )
7374
75
74def test_api_root(fakelp):76def test_api_root(fakelp):
75 """Ensure we can get LP's API root."""77 """Ensure we can get LP's API root."""
76 fakelp.load(Lp.API_ROOT_URL + 'hi')78 fakelp.load(Lp.API_ROOT_URL + 'hi')
77 fakelp._instance.load.assert_called_once_with(79 fakelp._instance.load.assert_called_once_with(
78 'https://api.launchpad.net/devel/hi')80 'https://api.launchpad.net/devel/hi')
7981
82
80def test_ubuntu(fakelp):83def test_ubuntu(fakelp):
81 fakelp._instance.distributions={'ubuntu': 'UBUNTU'}84 fakelp._instance.distributions = {'ubuntu': 'UBUNTU'}
82 assert fakelp.ubuntu == 'UBUNTU'85 assert fakelp.ubuntu == 'UBUNTU'
8386
87
84def test_ubuntu_active_series(fakelp):88def test_ubuntu_active_series(fakelp):
85 mock_hirsute = Mock(active=False)89 mock_hirsute = Mock(active=False)
86 mock_hirsute.name = 'hirsute'90 mock_hirsute.name = 'hirsute'
@@ -93,10 +97,12 @@ def test_ubuntu_active_series(fakelp):
93 assert fakelp.ubuntu_active_series()[0] == mock_jammy97 assert fakelp.ubuntu_active_series()[0] == mock_jammy
94 assert fakelp.ubuntu_active_series()[0].name == 'jammy'98 assert fakelp.ubuntu_active_series()[0].name == 'jammy'
9599
100
96def test_debian(fakelp):101def test_debian(fakelp):
97 fakelp._instance.distributions={'debian': 'DEBIAN'}102 fakelp._instance.distributions = {'debian': 'DEBIAN'}
98 assert fakelp.debian == 'DEBIAN'103 assert fakelp.debian == 'DEBIAN'
99104
105
100def test_debian_active_series(fakelp):106def test_debian_active_series(fakelp):
101 mock_woody = Mock(active=False)107 mock_woody = Mock(active=False)
102 mock_woody.name = 'woody'108 mock_woody.name = 'woody'
@@ -111,6 +117,7 @@ def test_debian_active_series(fakelp):
111 fakelp._instance.distributions = {'debian': mock_debian}117 fakelp._instance.distributions = {'debian': mock_debian}
112 assert fakelp.debian_active_series()[0].name == 'buster'118 assert fakelp.debian_active_series()[0].name == 'buster'
113119
120
114def test_debian_experimental_series(fakelp):121def test_debian_experimental_series(fakelp):
115 mock_woody = Mock(active=False)122 mock_woody = Mock(active=False)
116 mock_woody.name = 'woody'123 mock_woody.name = 'woody'
@@ -125,6 +132,7 @@ def test_debian_experimental_series(fakelp):
125 fakelp._instance.distributions = {'debian': mock_debian}132 fakelp._instance.distributions = {'debian': mock_debian}
126 assert fakelp.debian_experimental_series() == mock_sid133 assert fakelp.debian_experimental_series() == mock_sid
127134
135
128def test_ppa_team(fakelp):136def test_ppa_team(fakelp):
129 """Return the PPA team object."""137 """Return the PPA team object."""
130 mock_me = Mock(memberships_details=[138 mock_me = Mock(memberships_details=[
diff --git a/tests/test_ppa.py b/tests/test_ppa.py
index a632228..a71336f 100644
--- a/tests/test_ppa.py
+++ b/tests/test_ppa.py
@@ -11,10 +11,8 @@
11import os11import os
12import sys12import sys
1313
14import pytest
15
16sys.path.insert(0, os.path.realpath(14sys.path.insert(0, os.path.realpath(
17 os.path.join(os.path.dirname(__file__), "..")))15 os.path.join(os.path.dirname(__file__), "..")))
1816
19from ppa.ppa import Ppa17from ppa.ppa import Ppa
2018
@@ -24,12 +22,14 @@ def test_object():
24 ppa = Ppa('test-ppa-name', 'test-team-name')22 ppa = Ppa('test-ppa-name', 'test-team-name')
25 assert ppa23 assert ppa
2624
25
27def test_description():26def test_description():
28 """Check specifying a description when creating a PPA"""27 """Check specifying a description when creating a PPA"""
29 ppa = Ppa('test-ppa-name', 'test-team-name', 'test-description')28 ppa = Ppa('test-ppa-name', 'test-team-name', 'test-description')
3029
31 assert 'test-description' in ppa.ppa_description30 assert 'test-description' in ppa.ppa_description
3231
32
33def test_address():33def test_address():
34 """Check getting the PPA address"""34 """Check getting the PPA address"""
35 ppa = Ppa('test', 'team')35 ppa = Ppa('test', 'team')
diff --git a/tests/test_ppa_group.py b/tests/test_ppa_group.py
index dd45e80..e03a841 100644
--- a/tests/test_ppa_group.py
+++ b/tests/test_ppa_group.py
@@ -14,11 +14,12 @@ import sys
14import pytest14import pytest
1515
16sys.path.insert(0, os.path.realpath(16sys.path.insert(0, os.path.realpath(
17 os.path.join(os.path.dirname(__file__), "..")))17 os.path.join(os.path.dirname(__file__), "..")))
1818
19from ppa.ppa import Ppa19from ppa.ppa import Ppa
20from ppa.ppa_group import PpaGroup, PpaAlreadyExists20from ppa.ppa_group import PpaGroup, PpaAlreadyExists
2121
22
22class PersonMock:23class PersonMock:
23 def __init__(self, name):24 def __init__(self, name):
24 self.name = name25 self.name = name
@@ -42,10 +43,10 @@ class PersonMock:
4243
43class LaunchpadMock:44class LaunchpadMock:
44 def __init__(self):45 def __init__(self):
45 self.people = { 'me': PersonMock('me') }46 self.people = {'me': PersonMock('me')}
4647
47 def add_person(self, name):48 def add_person(self, name):
48 print("Adding person %s" %(name))49 print(f"Adding person {name}")
49 self.people[name] = PersonMock(name)50 self.people[name] = PersonMock(name)
5051
51 @property52 @property
@@ -83,6 +84,7 @@ def test_object():
83 ppa_group = PpaGroup(service=LpServiceMock())84 ppa_group = PpaGroup(service=LpServiceMock())
84 assert(ppa_group)85 assert(ppa_group)
8586
87
86def test_create_ppa():88def test_create_ppa():
87 """Checks that PpaGroups can create PPAs"""89 """Checks that PpaGroups can create PPAs"""
88 name = 'test_ppa'90 name = 'test_ppa'
@@ -92,13 +94,15 @@ def test_create_ppa():
92 assert(name in ppa.address)94 assert(name in ppa.address)
93 assert(type(ppa.description) is str)95 assert(type(ppa.description) is str)
9496
97
95def test_create_existing_ppa():98def test_create_existing_ppa():
96 """Check exception creating an already created PPA"""99 """Check exception creating an already created PPA"""
97 name = 'test_ppa'100 name = 'test_ppa'
98 ppa_group = PpaGroup(service=LpServiceMock())101 ppa_group = PpaGroup(service=LpServiceMock())
99 ppa = ppa_group.create(name)102 ppa_group.create(name)
100 with pytest.raises(PpaAlreadyExists):103 with pytest.raises(PpaAlreadyExists):
101 ppa = ppa_group.create(name)104 ppa_group.create(name)
105
102106
103def test_create_with_description():107def test_create_with_description():
104 """Check setting a description for a PPA"""108 """Check setting a description for a PPA"""
@@ -108,6 +112,7 @@ def test_create_with_description():
108 assert(ppa is not None)112 assert(ppa is not None)
109 assert(ppa.description == description)113 assert(ppa.description == description)
110114
115
111def test_create_with_team():116def test_create_with_team():
112 """Check creating a PPA for a particular team"""117 """Check creating a PPA for a particular team"""
113 lp = LpServiceMock()118 lp = LpServiceMock()
@@ -117,22 +122,25 @@ def test_create_with_team():
117 assert(ppa is not None)122 assert(ppa is not None)
118 assert(ppa.address == 'ppa:test_team_name/ppa_test_name')123 assert(ppa.address == 'ppa:test_team_name/ppa_test_name')
119124
125
120def test_create_for_lpbug():126def test_create_for_lpbug():
121 """Check associating a bug # when creating a PPA"""127 """Check associating a bug # when creating a PPA"""
122 ppa_group = PpaGroup(service=LpServiceMock())128 ppa_group = PpaGroup(service=LpServiceMock())
123 lpbug = '1234567'129 lpbug = '1234567'
124 ppa = ppa_group.create('lp'+lpbug)130 ppa = ppa_group.create('lp' + lpbug)
125 assert(ppa is not None)131 assert(ppa is not None)
126 assert(lpbug in ppa.description)132 assert(lpbug in ppa.description)
127133
134
128def test_create_for_merge_proposal():135def test_create_for_merge_proposal():
129 """Check associating a merge proposal when creating a PPA"""136 """Check associating a merge proposal when creating a PPA"""
130 ppa_group = PpaGroup(service=LpServiceMock())137 ppa_group = PpaGroup(service=LpServiceMock())
131 version = '1.2.3-4'138 version = '1.2.3-4'
132 ppa = ppa_group.create('merge.'+version)139 ppa = ppa_group.create('merge.' + version)
133 assert(ppa is not None)140 assert(ppa is not None)
134 assert(version in ppa.description)141 assert(version in ppa.description)
135142
143
136def test_list_ppas():144def test_list_ppas():
137 """Check listing the PPAs for a PPA group"""145 """Check listing the PPAs for a PPA group"""
138 test_ppa_list = ['a', 'b', 'c', 'd']146 test_ppa_list = ['a', 'b', 'c', 'd']
diff --git a/tests/test_scripts_ppa.py b/tests/test_scripts_ppa.py
index dc4e411..4c37e29 100644
--- a/tests/test_scripts_ppa.py
+++ b/tests/test_scripts_ppa.py
@@ -25,14 +25,15 @@ loader = importlib.machinery.SourceFileLoader(SCRIPT_NAME, script_path)
25script = types.ModuleType(loader.name)25script = types.ModuleType(loader.name)
26loader.exec_module(script)26loader.exec_module(script)
2727
28
28@pytest.fixture29@pytest.fixture
29def fake_config():30def fake_config():
30 return {31 return {
31 'ppa_name': 'testing',32 'ppa_name': 'testing',
32 'team_name': 'tester',33 'team_name': 'tester',
33 'wait_seconds': 0.134 'wait_seconds': 0.1
34 }35 }
35 return script.create_config(args)36
3637
37@pytest.fixture38@pytest.fixture
38def fake_source_package():39def fake_source_package():
@@ -41,10 +42,11 @@ def fake_source_package():
41 'name': 'test-source',42 'name': 'test-source',
42 'version': '1.0-2ubuntu3',43 'version': '1.0-2ubuntu3',
43 'binaries': [44 'binaries': [
44 { 'name': 'foo', }45 {'name': 'foo'},
45 { 'name': 'bar', }46 {'name': 'bar'}
46 ]47 ]
47 }48 }
49
4850
49@pytest.fixture51@pytest.fixture
50def fake_binary_package():52def fake_binary_package():
@@ -52,7 +54,8 @@ def fake_binary_package():
52 return {54 return {
53 'name': 'test-binary',55 'name': 'test-binary',
54 'source': 'test-source',56 'source': 'test-source',
55 }57 }
58
5659
57@pytest.fixture60@pytest.fixture
58def fake_build():61def fake_build():
@@ -60,7 +63,8 @@ def fake_build():
60 return {63 return {
61 'binary': 'foo',64 'binary': 'foo',
62 'status': 'Failed',65 'status': 'Failed',
63 }66 }
67
6468
65@pytest.fixture69@pytest.fixture
66def fake_bug_report():70def fake_bug_report():
@@ -69,10 +73,11 @@ def fake_bug_report():
69 'id': 1234,73 'id': 1234,
70 'title': 'foobar',74 'title': 'foobar',
71 'desc': 'baz',75 'desc': 'baz',
72 }76 }
77
7378
74def test_create_parser():79def test_create_parser():
75 parser = script.create_parser()80 # parser = script.create_parser()
7681
77 # TODO: Don't I have an existing example arg-parse test somewhere?82 # TODO: Don't I have an existing example arg-parse test somewhere?
78 # TODO: Check command is recognized83 # TODO: Check command is recognized
@@ -85,74 +90,87 @@ def test_create_parser():
8590
86 pass91 pass
8792
93
88@pytest.mark.xfail(reason="Unimplemented")94@pytest.mark.xfail(reason="Unimplemented")
89def test_create_config():95def test_create_config():
90 args = []96 # args = []
91 # TODO: Set config_filename, ppa_name, team_name in args97 # TODO: Set config_filename, ppa_name, team_name in args
92 config = script.create_config(args)98 # config = script.create_config(args)
9399
94 pass100 pass
95101
102
96# TODO: Monkeypatch in Lp = MockLp103# TODO: Monkeypatch in Lp = MockLp
97@pytest.mark.xfail(reason="Unimplemented")104@pytest.mark.xfail(reason="Unimplemented")
98def test_get_ppa():105def test_get_ppa():
99 # TODO: In fake_config, set ppa_name, team_name, and lp106 # TODO: In fake_config, set ppa_name, team_name, and lp
100 ppa = script.get_ppa(fake_config)107 # ppa = script.get_ppa(fake_config)
101 # TODO: Verify type(ppa) is Ppa108 # TODO: Verify type(ppa) is Ppa
102 # TODO: Verify that ppa_name is set properly in ppa109 # TODO: Verify that ppa_name is set properly in ppa
103 # TODO: Verify that team_name is set properly in ppa110 # TODO: Verify that team_name is set properly in ppa
104 # TODO: Verify that lp is set properly in ppa111 # TODO: Verify that lp is set properly in ppa
112 pass
113
105114
106@pytest.mark.xfail(reason="Unimplemented")115@pytest.mark.xfail(reason="Unimplemented")
107def test_command_create(fake_config):116def test_command_create(fake_config):
108 assert command_create(fake_config) == 0117 assert script.command_create(fake_config) == 0
109118
110 # TODO: Specify a ppa_name and verify it gets used properly119 # TODO: Specify a ppa_name and verify it gets used properly
111 # TODO: Specify a team name120 # TODO: Specify a team name
112 # TODO: Verify if no team name specified, the lp_user is used121 # TODO: Verify if no team name specified, the lp_user is used
113 # instead122 # instead
114 # TODO: Verify the ppa_address is set as expected123 # TODO: Verify the ppa_address is set as expected
124 pass
125
115126
116@pytest.mark.xfail(reason="Unimplemented")127@pytest.mark.xfail(reason="Unimplemented")
117def test_command_desc(fake_config):128def test_command_desc(fake_config):
118 assert command_desc(fake_config) == 0129 assert script.command_desc(fake_config) == 0
119 # TODO: Assert that if --dry-run specified, there are no actual130 # TODO: Assert that if --dry-run specified, there are no actual
120 # changes requested of launchpad131 # changes requested of launchpad
121 # TODO: Verify the description gets set as expected132 # TODO: Verify the description gets set as expected
122133
134
123@pytest.mark.xfail(reason="Unimplemented")135@pytest.mark.xfail(reason="Unimplemented")
124def test_command_destroy(fake_config):136def test_command_destroy(fake_config):
125 # TODO: Create a fake ppa to be destroyed137 # TODO: Create a fake ppa to be destroyed
126 assert command_destroy(fake_config) == 0138 assert script.command_destroy(fake_config) == 0
127 # TODO: Verify the ppa is requested to be deleted139 # TODO: Verify the ppa is requested to be deleted
128140
141
129@pytest.mark.xfail(reason="Unimplemented")142@pytest.mark.xfail(reason="Unimplemented")
130def test_command_list(fake_config):143def test_command_list(fake_config):
131 # TODO: Create a fake ppa with contents to be listed144 # TODO: Create a fake ppa with contents to be listed
132 assert command_list(fake_config) == 0145 assert script.command_list(fake_config) == 0
133 # TODO: Verify the ppa addresses get listed146 # TODO: Verify the ppa addresses get listed
134147
148
135@pytest.mark.xfail(reason="Unimplemented")149@pytest.mark.xfail(reason="Unimplemented")
136def test_command_exists(fake_config):150def test_command_exists(fake_config):
137 # TODO: Create fake ppa that exists151 # TODO: Create fake ppa that exists
138 assert command_exists(fake_config) == 0152 assert script.command_exists(fake_config) == 0
139 # TODO: Verify this returns true when the ppa does exist153 # TODO: Verify this returns true when the ppa does exist
140154
155
141@pytest.mark.xfail(reason="Unimplemented")156@pytest.mark.xfail(reason="Unimplemented")
142def test_command_not_exists(fake_config):157def test_command_not_exists(fake_config):
143 # TODO: Verify this returns true when the ppa does not exist158 # TODO: Verify this returns true when the ppa does not exist
144 assert command_exists(fake_config) == 1159 assert script.command_exists(fake_config) == 1
160
145161
146@pytest.mark.xfail(reason="Unimplemented")162@pytest.mark.xfail(reason="Unimplemented")
147def test_command_show(fake_config):163def test_command_show(fake_config):
148 assert command_show(fake_config) == 0164 assert script.command_show(fake_config) == 0
165
149166
150@pytest.mark.xfail(reason="Unimplemented")167@pytest.mark.xfail(reason="Unimplemented")
151def test_command_status(fake_config):168def test_command_status(fake_config):
152 assert command_status(fake_config) == 0169 assert script.command_status(fake_config) == 0
153 # TODO: Capture stdout and compare with expected170 # TODO: Capture stdout and compare with expected
154171
172
155@pytest.mark.xfail(reason="Unimplemented")173@pytest.mark.xfail(reason="Unimplemented")
156def test_command_wait(fake_config):174def test_command_wait(fake_config):
157 # TODO: Set wait period to 1 sec175 # TODO: Set wait period to 1 sec
158 assert command_wait(fake_config) == 0176 assert script.command_wait(fake_config) == 0
diff --git a/tests/test_version.py b/tests/test_version.py
index 0a1c397..fa6066f 100644
--- a/tests/test_version.py
+++ b/tests/test_version.py
@@ -11,9 +11,7 @@
11import os11import os
12import sys12import sys
13sys.path.insert(0, os.path.realpath(13sys.path.insert(0, os.path.realpath(
14 os.path.join(os.path.dirname(__file__), "..")))14 os.path.join(os.path.dirname(__file__), "..")))
15
16import pytest
1715
18from ppa._version import __version__, __version_info__16from ppa._version import __version__, __version_info__
1917
@@ -24,6 +22,7 @@ def test_version():
24 assert(__version__[0].isdigit())22 assert(__version__[0].isdigit())
25 assert(__version__[-1] != '.')23 assert(__version__[-1] != '.')
2624
25
27def test_version_info():26def test_version_info():
28 assert(type(__version_info__) is tuple)27 assert(type(__version_info__) is tuple)
29 assert(len(__version_info__) > 1)28 assert(len(__version_info__) > 1)

Subscribers

People subscribed via source and target branches

to all changes: