Merge ppa-dev-tools:fix-lp1990244-create-for-owner into ppa-dev-tools:main
- Git
- lp:ppa-dev-tools
- fix-lp1990244-create-for-owner
- Merge into main
Status: | Merged |
---|---|
Merged at revision: | 9dbaa6f713ae958ad415607c771549434fa1db93 |
Proposed branch: | ppa-dev-tools:fix-lp1990244-create-for-owner |
Merge into: | ppa-dev-tools:main |
Diff against target: |
732 lines (+207/-111) 8 files modified
NEWS.md (+9/-0) ppa/ppa.py (+35/-29) ppa/ppa_group.py (+9/-9) scripts/ppa (+38/-18) tests/helpers.py (+3/-2) tests/test_ppa.py (+32/-32) tests/test_ppa_group.py (+5/-5) tests/test_scripts_ppa.py (+76/-16) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Lena Voytek (community) | Approve | ||
Canonical Server packageset reviewers | Pending | ||
PpaDevTools Developers | Pending | ||
Canonical Server Reporter | Pending | ||
Review via email:
|
Commit message
Description of the change
This adds the ability to create PPAs against other teams that your LP user account has access to, fixing LP: #1990244. You can specify the team by a command line argument, config file variable, or the ppa address.
For example:
$ ./scripts/ppa create --team ppa-dev-tools-devs foobar
PPA 'foobar' created for the following architectures:
i386, amd64, armhf, ppc64el, s390x, arm64, powerpc
The PPA can be viewed at:
https:/
...
$ ./scripts/ppa create ppa-dev-
PPA 'example' created for the following architectures:
i386, amd64, armhf, ppc64el, s390x, arm64, powerpc
The PPA can be viewed at:
https:/
...
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Christian Ehrhardt (paelzer) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Lena Voytek (lvoytek) wrote : | # |
LGTM, added a few comments below for formatting/
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Bryce Harrington (bryce) wrote : | # |
Thanks, I've updated with the changes as suggested and landed:
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
To git+ssh:
2a8e2ef..9dbaa6f main -> main
Preview Diff
1 | diff --git a/NEWS.md b/NEWS.md | |||
2 | index 61c117e..e6bdaeb 100644 | |||
3 | --- a/NEWS.md | |||
4 | +++ b/NEWS.md | |||
5 | @@ -9,6 +9,15 @@ jobs that it is monitoring are failed builds. These options are aimed | |||
6 | 9 | to facilitate CI/CD integration, but can also improve performance of the | 9 | to facilitate CI/CD integration, but can also improve performance of the |
7 | 10 | waiting operation on larger PPAs. | 10 | waiting operation on larger PPAs. |
8 | 11 | 11 | ||
9 | 12 | It is now possible to create PPAs under a different team's ownership via | ||
10 | 13 | the --owner option: | ||
11 | 14 | |||
12 | 15 | $ ppa create --owner foobar my-ppa | ||
13 | 16 | |||
14 | 17 | As a convenience, this can also be specified in ppa address form, i.e.: | ||
15 | 18 | |||
16 | 19 | $ ppa create ppa:foobar/my-ppa | ||
17 | 20 | |||
18 | 12 | 21 | ||
19 | 13 | # 0.4.0 # | 22 | # 0.4.0 # |
20 | 14 | 23 | ||
21 | diff --git a/ppa/ppa.py b/ppa/ppa.py | |||
22 | index 6e3a071..0cccb10 100755 | |||
23 | --- a/ppa/ppa.py | |||
24 | +++ b/ppa/ppa.py | |||
25 | @@ -36,14 +36,15 @@ class PendingReason(enum.Enum): | |||
26 | 36 | class PpaDoesNotExist(BaseException): | 36 | class PpaDoesNotExist(BaseException): |
27 | 37 | """Exception indicating a requested PPA could not be found.""" | 37 | """Exception indicating a requested PPA could not be found.""" |
28 | 38 | 38 | ||
30 | 39 | def __init__(self, ppa_name, team_name, message=None): | 39 | def __init__(self, ppa_name, owner_name, message=None): |
31 | 40 | """Initializes the exception object. | 40 | """Initializes the exception object. |
32 | 41 | 41 | ||
33 | 42 | :param str ppa_name: The name of the missing PPA. | 42 | :param str ppa_name: The name of the missing PPA. |
34 | 43 | :param str owner_name: The person or team the PPA belongs to. | ||
35 | 43 | :param str message: An error message. | 44 | :param str message: An error message. |
36 | 44 | """ | 45 | """ |
37 | 45 | self.ppa_name = ppa_name | 46 | self.ppa_name = ppa_name |
39 | 46 | self.team_name = team_name | 47 | self.owner_name = owner_name |
40 | 47 | self.message = message | 48 | self.message = message |
41 | 48 | 49 | ||
42 | 49 | def __str__(self): | 50 | def __str__(self): |
43 | @@ -54,7 +55,7 @@ class PpaDoesNotExist(BaseException): | |||
44 | 54 | """ | 55 | """ |
45 | 55 | if self.message: | 56 | if self.message: |
46 | 56 | return self.message | 57 | return self.message |
48 | 57 | return f"The PPA '{self.ppa_name}' does not exist for team or user '{self.team_name}'" | 58 | return f"The PPA '{self.ppa_name}' does not exist for person or team '{self.owner_name}'" |
49 | 58 | 59 | ||
50 | 59 | 60 | ||
51 | 60 | class Ppa: | 61 | class Ppa: |
52 | @@ -70,25 +71,27 @@ class Ppa: | |||
53 | 70 | " + Launchpad Build Page: {build_page}\n" | 71 | " + Launchpad Build Page: {build_page}\n" |
54 | 71 | ) | 72 | ) |
55 | 72 | 73 | ||
57 | 73 | def __init__(self, ppa_name, team_name, ppa_description=None, service=None): | 74 | def __init__(self, ppa_name, owner_name, ppa_description=None, service=None): |
58 | 74 | """Initializes a new Ppa object for a given PPA. | 75 | """Initializes a new Ppa object for a given PPA. |
59 | 75 | 76 | ||
60 | 76 | This creates only the local representation of the PPA, it does | 77 | This creates only the local representation of the PPA, it does |
61 | 77 | not cause a new PPA to be created in Launchpad. For that, see | 78 | not cause a new PPA to be created in Launchpad. For that, see |
62 | 78 | PpaGroup.create() | 79 | PpaGroup.create() |
63 | 79 | 80 | ||
66 | 80 | :param str ppa_name: The name of the PPA within the team's namespace. | 81 | :param str ppa_name: The name of the PPA within the owning |
67 | 81 | :param str team_name: The name of the team or user that owns the PPA. | 82 | person or team's namespace. |
68 | 83 | :param str owner_name: The name of the person or team the PPA | ||
69 | 84 | belongs to. | ||
70 | 82 | :param str ppa_description: Optional description text for the PPA. | 85 | :param str ppa_description: Optional description text for the PPA. |
71 | 83 | :param launchpadlib.service service: The Launchpad service object. | 86 | :param launchpadlib.service service: The Launchpad service object. |
72 | 84 | """ | 87 | """ |
73 | 85 | if not ppa_name: | 88 | if not ppa_name: |
74 | 86 | raise ValueError("undefined ppa_name.") | 89 | raise ValueError("undefined ppa_name.") |
77 | 87 | if not team_name: | 90 | if not owner_name: |
78 | 88 | raise ValueError("undefined team_name.") | 91 | raise ValueError("undefined owner_name.") |
79 | 89 | 92 | ||
80 | 90 | self.ppa_name = ppa_name | 93 | self.ppa_name = ppa_name |
82 | 91 | self.team_name = team_name | 94 | self.owner_name = owner_name |
83 | 92 | if ppa_description is None: | 95 | if ppa_description is None: |
84 | 93 | self.ppa_description = '' | 96 | self.ppa_description = '' |
85 | 94 | else: | 97 | else: |
86 | @@ -102,7 +105,7 @@ class Ppa: | |||
87 | 102 | :returns: Official string representation of the object. | 105 | :returns: Official string representation of the object. |
88 | 103 | """ | 106 | """ |
89 | 104 | return (f'{self.__class__.__name__}(' | 107 | return (f'{self.__class__.__name__}(' |
91 | 105 | f'ppa_name={self.ppa_name!r}, team_name={self.team_name!r})') | 108 | f'ppa_name={self.ppa_name!r}, owner_name={self.owner_name!r})') |
92 | 106 | 109 | ||
93 | 107 | def __str__(self) -> str: | 110 | def __str__(self) -> str: |
94 | 108 | """Returns a displayable string identifying the PPA. | 111 | """Returns a displayable string identifying the PPA. |
95 | @@ -110,7 +113,7 @@ class Ppa: | |||
96 | 110 | :rtype: str | 113 | :rtype: str |
97 | 111 | :returns: Displayable representation of the PPA. | 114 | :returns: Displayable representation of the PPA. |
98 | 112 | """ | 115 | """ |
100 | 113 | return f"{self.team_name}/{self.name}" | 116 | return f"{self.owner_name}/{self.name}" |
101 | 114 | 117 | ||
102 | 115 | @property | 118 | @property |
103 | 116 | @lru_cache | 119 | @lru_cache |
104 | @@ -124,10 +127,10 @@ class Ppa: | |||
105 | 124 | if not self._service: | 127 | if not self._service: |
106 | 125 | raise AttributeError("Ppa object not connected to the Launchpad service") | 128 | raise AttributeError("Ppa object not connected to the Launchpad service") |
107 | 126 | try: | 129 | try: |
109 | 127 | owner = self._service.people[self.team_name] | 130 | owner = self._service.people[self.owner_name] |
110 | 128 | return owner.getPPAByName(name=self.ppa_name) | 131 | return owner.getPPAByName(name=self.ppa_name) |
111 | 129 | except NotFound: | 132 | except NotFound: |
113 | 130 | raise PpaDoesNotExist(self.ppa_name, self.team_name) | 133 | raise PpaDoesNotExist(self.ppa_name, self.owner_name) |
114 | 131 | 134 | ||
115 | 132 | @lru_cache | 135 | @lru_cache |
116 | 133 | def exists(self) -> bool: | 136 | def exists(self) -> bool: |
117 | @@ -146,7 +149,7 @@ class Ppa: | |||
118 | 146 | :rtype: str | 149 | :rtype: str |
119 | 147 | :returns: The full identification string for the PPA. | 150 | :returns: The full identification string for the PPA. |
120 | 148 | """ | 151 | """ |
122 | 149 | return "ppa:{}/{}".format(self.team_name, self.ppa_name) | 152 | return "ppa:{}/{}".format(self.owner_name, self.ppa_name) |
123 | 150 | 153 | ||
124 | 151 | @property | 154 | @property |
125 | 152 | def name(self): | 155 | def name(self): |
126 | @@ -269,8 +272,8 @@ class Ppa: | |||
127 | 269 | base = self._service.API_ROOT_URL.rstrip('/') | 272 | base = self._service.API_ROOT_URL.rstrip('/') |
128 | 270 | new_ppa_deps = [] | 273 | new_ppa_deps = [] |
129 | 271 | for ppa_address in ppa_addresses: | 274 | for ppa_address in ppa_addresses: |
132 | 272 | team_name, ppa_name = ppa_address_split(ppa_address) | 275 | owner_name, ppa_name = ppa_address_split(ppa_address) |
133 | 273 | new_ppa_dep = f'{base}/~{team_name}/+archive/ubuntu/{ppa_name}' | 276 | new_ppa_dep = f'{base}/~{owner_name}/+archive/ubuntu/{ppa_name}' |
134 | 274 | new_ppa_deps.append(new_ppa_dep) | 277 | new_ppa_deps.append(new_ppa_dep) |
135 | 275 | 278 | ||
136 | 276 | # TODO: Remove all existing dependencies | 279 | # TODO: Remove all existing dependencies |
137 | @@ -529,44 +532,47 @@ class Ppa: | |||
138 | 529 | return [] | 532 | return [] |
139 | 530 | 533 | ||
140 | 531 | 534 | ||
143 | 532 | def ppa_address_split(ppa_address, default_team=None): | 535 | def ppa_address_split(ppa_address): |
144 | 533 | """Parse an address for a PPA into its team and name components. | 536 | """Parse an address for a PPA into its owner and name components. |
145 | 534 | 537 | ||
146 | 535 | :param str ppa_address: A ppa name or address. | 538 | :param str ppa_address: A ppa name or address. |
147 | 536 | :param str default_team: (Optional) name of team to use if missing. | ||
148 | 537 | :rtype: tuple(str, str) | 539 | :rtype: tuple(str, str) |
150 | 538 | :returns: The team name and ppa name as a tuple, or (None, None) on error. | 540 | :returns: The owner name and ppa name as a tuple, or (None, None) on error. |
151 | 539 | """ | 541 | """ |
152 | 542 | owner_name = None | ||
153 | 543 | |||
154 | 540 | if not ppa_address or len(ppa_address) < 2: | 544 | if not ppa_address or len(ppa_address) < 2: |
155 | 541 | return (None, None) | 545 | return (None, None) |
156 | 542 | if ppa_address.startswith('ppa:'): | 546 | if ppa_address.startswith('ppa:'): |
157 | 543 | if '/' not in ppa_address: | 547 | if '/' not in ppa_address: |
158 | 544 | return (None, None) | 548 | return (None, None) |
159 | 545 | rem = ppa_address.split('ppa:', 1)[1] | 549 | rem = ppa_address.split('ppa:', 1)[1] |
161 | 546 | team_name = rem.split('/', 1)[0] | 550 | owner_name = rem.split('/', 1)[0] |
162 | 547 | ppa_name = rem.split('/', 1)[1] | 551 | ppa_name = rem.split('/', 1)[1] |
163 | 548 | elif ppa_address.startswith('http'): | 552 | elif ppa_address.startswith('http'): |
164 | 549 | # Only launchpad PPA urls are supported | 553 | # Only launchpad PPA urls are supported |
165 | 550 | m = re.search(r'https:\/\/launchpad\.net\/~([^/]+)\/\+archive\/ubuntu\/(.+)$', ppa_address) | 554 | m = re.search(r'https:\/\/launchpad\.net\/~([^/]+)\/\+archive\/ubuntu\/(.+)$', ppa_address) |
166 | 551 | if not m: | 555 | if not m: |
167 | 552 | return (None, None) | 556 | return (None, None) |
169 | 553 | team_name = m.group(1) | 557 | owner_name = m.group(1) |
170 | 554 | ppa_name = m.group(2) | 558 | ppa_name = m.group(2) |
171 | 555 | elif '/' in ppa_address: | 559 | elif '/' in ppa_address: |
173 | 556 | team_name = ppa_address.split('/', 1)[0] | 560 | owner_name = ppa_address.split('/', 1)[0] |
174 | 557 | ppa_name = ppa_address.split('/', 1)[1] | 561 | ppa_name = ppa_address.split('/', 1)[1] |
175 | 558 | else: | 562 | else: |
176 | 559 | team_name = default_team | ||
177 | 560 | ppa_name = ppa_address | 563 | ppa_name = ppa_address |
178 | 561 | 564 | ||
182 | 562 | if (team_name | 565 | if owner_name is not None: |
183 | 563 | and ppa_name | 566 | if len(owner_name) < 1: |
184 | 564 | and not (any(x.isupper() for x in team_name)) | 567 | return (None, None) |
185 | 568 | owner_name = owner_name.lower() | ||
186 | 569 | |||
187 | 570 | if (ppa_name | ||
188 | 565 | and not (any(x.isupper() for x in ppa_name)) | 571 | and not (any(x.isupper() for x in ppa_name)) |
189 | 566 | and ppa_name.isascii() | 572 | and ppa_name.isascii() |
190 | 567 | and '/' not in ppa_name | 573 | and '/' not in ppa_name |
191 | 568 | and len(ppa_name) > 1): | 574 | and len(ppa_name) > 1): |
193 | 569 | return (team_name, ppa_name) | 575 | return (owner_name, ppa_name) |
194 | 570 | 576 | ||
195 | 571 | return (None, None) | 577 | return (None, None) |
196 | 572 | 578 | ||
197 | @@ -600,7 +606,7 @@ def get_ppa(lp, config): | |||
198 | 600 | """ | 606 | """ |
199 | 601 | return Ppa( | 607 | return Ppa( |
200 | 602 | ppa_name=config.get('ppa_name', None), | 608 | ppa_name=config.get('ppa_name', None), |
202 | 603 | team_name=config.get('team_name', None), | 609 | owner_name=config.get('owner_name', None), |
203 | 604 | service=lp) | 610 | service=lp) |
204 | 605 | 611 | ||
205 | 606 | 612 | ||
206 | diff --git a/ppa/ppa_group.py b/ppa/ppa_group.py | |||
207 | index 59011ea..c9747a5 100755 | |||
208 | --- a/ppa/ppa_group.py | |||
209 | +++ b/ppa/ppa_group.py | |||
210 | @@ -8,7 +8,7 @@ | |||
211 | 8 | # Released under GNU GPLv2 or later, read the file 'LICENSE.GPLv2+' for | 8 | # Released under GNU GPLv2 or later, read the file 'LICENSE.GPLv2+' for |
212 | 9 | # more information. | 9 | # more information. |
213 | 10 | 10 | ||
215 | 11 | """A team or person that owns one or more PPAs in Launchpad.""" | 11 | """A person or team that owns one or more PPAs in Launchpad.""" |
216 | 12 | 12 | ||
217 | 13 | from functools import lru_cache | 13 | from functools import lru_cache |
218 | 14 | from lazr.restfulclient.errors import BadRequest | 14 | from lazr.restfulclient.errors import BadRequest |
219 | @@ -42,7 +42,7 @@ class PpaAlreadyExists(BaseException): | |||
220 | 42 | 42 | ||
221 | 43 | 43 | ||
222 | 44 | class PpaGroup: | 44 | class PpaGroup: |
224 | 45 | """Represents a team or person that owns one or more PPAs. | 45 | """Represents a person or team that owns one or more PPAs. |
225 | 46 | 46 | ||
226 | 47 | This class provides a proxy object for interacting with collections | 47 | This class provides a proxy object for interacting with collections |
227 | 48 | of PPA. | 48 | of PPA. |
228 | @@ -51,7 +51,7 @@ class PpaGroup: | |||
229 | 51 | """Initializes a new PpaGroup object for a named person or team. | 51 | """Initializes a new PpaGroup object for a named person or team. |
230 | 52 | 52 | ||
231 | 53 | :param launchpadlib.service service: The Launchpad service object. | 53 | :param launchpadlib.service service: The Launchpad service object. |
233 | 54 | :param str name: Launchpad username or team name. | 54 | :param str name: Launchpad username for a person or team. |
234 | 55 | """ | 55 | """ |
235 | 56 | if not service: | 56 | if not service: |
236 | 57 | raise ValueError("undefined service.") | 57 | raise ValueError("undefined service.") |
237 | @@ -80,8 +80,8 @@ class PpaGroup: | |||
238 | 80 | 80 | ||
239 | 81 | @property | 81 | @property |
240 | 82 | @lru_cache | 82 | @lru_cache |
243 | 83 | def team(self): | 83 | def owner(self): |
244 | 84 | """The team that owns this collection of PPAs. | 84 | """The person or team that owns this collection of PPAs. |
245 | 85 | 85 | ||
246 | 86 | :rtype: launchpadlib.person | 86 | :rtype: launchpadlib.person |
247 | 87 | :returns: Launchpad person object that owns this PPA. | 87 | :returns: Launchpad person object that owns this PPA. |
248 | @@ -106,11 +106,11 @@ class PpaGroup: | |||
249 | 106 | } | 106 | } |
250 | 107 | 107 | ||
251 | 108 | try: | 108 | try: |
253 | 109 | self.team.createPPA( | 109 | self.owner.createPPA( |
254 | 110 | name=ppa_name, | 110 | name=ppa_name, |
255 | 111 | **ppa_settings | 111 | **ppa_settings |
256 | 112 | ) | 112 | ) |
258 | 113 | self.team.lp_save() | 113 | self.owner.lp_save() |
259 | 114 | except BadRequest as e: | 114 | except BadRequest as e: |
260 | 115 | if "You already have a PPA" in o2str(e.content): | 115 | if "You already have a PPA" in o2str(e.content): |
261 | 116 | raise PpaAlreadyExists(ppa_name, e.content) | 116 | raise PpaAlreadyExists(ppa_name, e.content) |
262 | @@ -127,7 +127,7 @@ class PpaGroup: | |||
263 | 127 | :rtype: Iterator[ppa.Ppa] | 127 | :rtype: Iterator[ppa.Ppa] |
264 | 128 | :returns: Each PPA in the group as a ppa.Ppa object. | 128 | :returns: Each PPA in the group as a ppa.Ppa object. |
265 | 129 | """ | 129 | """ |
267 | 130 | for lp_ppa in self.team.ppas: | 130 | for lp_ppa in self.owner.ppas: |
268 | 131 | if '-deletedppa' in lp_ppa.name: | 131 | if '-deletedppa' in lp_ppa.name: |
269 | 132 | continue | 132 | continue |
270 | 133 | yield Ppa(lp_ppa.name, self.name, | 133 | yield Ppa(lp_ppa.name, self.name, |
271 | @@ -140,7 +140,7 @@ class PpaGroup: | |||
272 | 140 | :rtype: ppa.Ppa | 140 | :rtype: ppa.Ppa |
273 | 141 | :returns: A Ppa object describing the named ppa. | 141 | :returns: A Ppa object describing the named ppa. |
274 | 142 | """ | 142 | """ |
276 | 143 | lp_ppa = self.team.getPPAByName(name=ppa_name) | 143 | lp_ppa = self.owner.getPPAByName(name=ppa_name) |
277 | 144 | if not lp_ppa: | 144 | if not lp_ppa: |
278 | 145 | return None | 145 | return None |
279 | 146 | return Ppa(lp_ppa.name, self.name, | 146 | return Ppa(lp_ppa.name, self.name, |
280 | diff --git a/scripts/ppa b/scripts/ppa | |||
281 | index b6aebbb..ee97f4d 100755 | |||
282 | --- a/scripts/ppa | |||
283 | +++ b/scripts/ppa | |||
284 | @@ -254,6 +254,10 @@ def create_arg_parser() -> argparse.ArgumentParser: | |||
285 | 254 | create_parser.add_argument('ppa_name', metavar='ppa-name', | 254 | create_parser.add_argument('ppa_name', metavar='ppa-name', |
286 | 255 | action='store', | 255 | action='store', |
287 | 256 | help="Name of the PPA to be created") | 256 | help="Name of the PPA to be created") |
288 | 257 | create_parser.add_argument('--owner-name', '--owner', '--team-name', '--team', metavar='NAME', | ||
289 | 258 | action='store', | ||
290 | 259 | default=None, | ||
291 | 260 | help="Person or team to create PPA under, if not specified via the ppa address (defaults to current LP user)") | ||
292 | 257 | add_basic_config_options(create_parser) | 261 | add_basic_config_options(create_parser) |
293 | 258 | 262 | ||
294 | 259 | # Desc Command | 263 | # Desc Command |
295 | @@ -395,7 +399,7 @@ def create_arg_parser() -> argparse.ArgumentParser: | |||
296 | 395 | DEFAULT_CONFIG = { | 399 | DEFAULT_CONFIG = { |
297 | 396 | 'debug': False, | 400 | 'debug': False, |
298 | 397 | 'ppa_name': None, | 401 | 'ppa_name': None, |
300 | 398 | 'team_name': None, | 402 | 'owner_name': None, |
301 | 399 | 'wait_seconds': 10.0 | 403 | 'wait_seconds': 10.0 |
302 | 400 | } | 404 | } |
303 | 401 | 405 | ||
304 | @@ -430,16 +434,32 @@ def create_config(lp: Lp, args: argparse.Namespace) -> dict[str, Any]: | |||
305 | 430 | for k, v in DEFAULT_CONFIG.items(): | 434 | for k, v in DEFAULT_CONFIG.items(): |
306 | 431 | config.setdefault(k, v) | 435 | config.setdefault(k, v) |
307 | 432 | 436 | ||
308 | 433 | lp_username = None | ||
309 | 434 | if lp.me: | ||
310 | 435 | lp_username = lp.me.name | ||
311 | 436 | if not hasattr(args, 'ppa_name'): | 437 | if not hasattr(args, 'ppa_name'): |
312 | 437 | warn("No ppa name given") | 438 | warn("No ppa name given") |
313 | 438 | return None | 439 | return None |
314 | 439 | 440 | ||
317 | 440 | config['team_name'], config['ppa_name'] = ppa_address_split(args.ppa_name, lp_username) | 441 | owner_name, ppa_name = ppa_address_split(args.ppa_name) |
318 | 441 | if not config['team_name'] or not config['ppa_name']: | 442 | if owner_name: |
319 | 443 | # First use the owner if present in the PPA address itself, | ||
320 | 444 | # overriding any configured defaults or specified arguments. | ||
321 | 445 | config['owner_name'] = owner_name | ||
322 | 446 | elif config.get('owner_name'): | ||
323 | 447 | # Next use any owner name from config file or cli args. | ||
324 | 448 | pass | ||
325 | 449 | elif config.get('team_name'): | ||
326 | 450 | # Support legacy config term 'team_name' as alias for 'owner_name' | ||
327 | 451 | config['owner_name'] = config['team_name'] | ||
328 | 452 | del config['team_name'] | ||
329 | 453 | elif lp.me: | ||
330 | 454 | # Lastly, fallback to the current Launchpad username, if available. | ||
331 | 455 | config['owner_name'] = lp.me.name | ||
332 | 456 | else: | ||
333 | 457 | warn("No owning person or team identified for the PPA") | ||
334 | 458 | return None | ||
335 | 459 | |||
336 | 460 | if not ppa_name: | ||
337 | 442 | raise ValueError("Invalid ppa name '{}'".format(args.ppa_name)) | 461 | raise ValueError("Invalid ppa name '{}'".format(args.ppa_name)) |
338 | 462 | config['ppa_name'] = ppa_name | ||
339 | 443 | 463 | ||
340 | 444 | if args.dry_run: | 464 | if args.dry_run: |
341 | 445 | config['dry_run'] = True | 465 | config['dry_run'] = True |
342 | @@ -472,9 +492,9 @@ def command_create(lp: Lp, config: dict[str, str]) -> int: | |||
343 | 472 | warn("Could not determine PPA name") | 492 | warn("Could not determine PPA name") |
344 | 473 | return os.EX_USAGE | 493 | return os.EX_USAGE |
345 | 474 | 494 | ||
349 | 475 | team_name = config.get('team_name') | 495 | owner_name = config.get('owner_name') |
350 | 476 | if not team_name: | 496 | if not owner_name: |
351 | 477 | warn("Could not determine team name") | 497 | warn("Could not determine owning person or team LP username") |
352 | 478 | return os.EX_USAGE | 498 | return os.EX_USAGE |
353 | 479 | 499 | ||
354 | 480 | publish = config.get('publish', None) | 500 | publish = config.get('publish', None) |
355 | @@ -485,7 +505,7 @@ def command_create(lp: Lp, config: dict[str, str]) -> int: | |||
356 | 485 | 505 | ||
357 | 486 | try: | 506 | try: |
358 | 487 | if not config.get('dry_run', False): | 507 | if not config.get('dry_run', False): |
360 | 488 | ppa_group = PpaGroup(service=lp, name=team_name) | 508 | ppa_group = PpaGroup(service=lp, name=owner_name) |
361 | 489 | the_ppa = ppa_group.create(ppa_name, ppa_description=description) | 509 | the_ppa = ppa_group.create(ppa_name, ppa_description=description) |
362 | 490 | the_ppa.set_publish(publish) | 510 | the_ppa.set_publish(publish) |
363 | 491 | if architectures: | 511 | if architectures: |
364 | @@ -498,7 +518,7 @@ def command_create(lp: Lp, config: dict[str, str]) -> int: | |||
365 | 498 | the_ppa.set_dependencies(ppa_addresses) | 518 | the_ppa.set_dependencies(ppa_addresses) |
366 | 499 | 519 | ||
367 | 500 | else: | 520 | else: |
369 | 501 | the_ppa = Ppa(ppa_name, team_name, description) | 521 | the_ppa = Ppa(ppa_name, owner_name, description) |
370 | 502 | arch_str = ', '.join(architectures) | 522 | arch_str = ', '.join(architectures) |
371 | 503 | if not config.get('quiet', False): | 523 | if not config.get('quiet', False): |
372 | 504 | print("PPA '{}' created for the following architectures:\n".format(the_ppa.ppa_name)) | 524 | print("PPA '{}' created for the following architectures:\n".format(the_ppa.ppa_name)) |
373 | @@ -590,16 +610,16 @@ def command_list(lp: Lp, config: dict[str, str], filter_func=None) -> int: | |||
374 | 590 | if not lp: | 610 | if not lp: |
375 | 591 | return 1 | 611 | return 1 |
376 | 592 | 612 | ||
379 | 593 | team_name = config.get('team_name') | 613 | owner_name = config.get('owner_name') |
380 | 594 | if not team_name: | 614 | if not owner_name: |
381 | 595 | if lp.me: | 615 | if lp.me: |
383 | 596 | team_name = lp.me.name | 616 | owner_name = lp.me.name |
384 | 597 | else: | 617 | else: |
386 | 598 | warn("Could not determine team name") | 618 | warn("Could not determine owning person or team name") |
387 | 599 | return os.EX_USAGE | 619 | return os.EX_USAGE |
388 | 600 | 620 | ||
389 | 601 | try: | 621 | try: |
391 | 602 | ppa_group = PpaGroup(service=lp, name=team_name) | 622 | ppa_group = PpaGroup(service=lp, name=owner_name) |
392 | 603 | for p in ppa_group.ppas: | 623 | for p in ppa_group.ppas: |
393 | 604 | print(p.address) | 624 | print(p.address) |
394 | 605 | return os.EX_OK | 625 | return os.EX_OK |
395 | @@ -826,7 +846,7 @@ def command_tests(lp: Lp, config: dict[str, str]) -> int: | |||
396 | 826 | 846 | ||
397 | 827 | the_ppa = get_ppa(lp, config) | 847 | the_ppa = get_ppa(lp, config) |
398 | 828 | if not the_ppa.exists(): | 848 | if not the_ppa.exists(): |
400 | 829 | error(f"PPA {the_ppa.name} does not exist for user {the_ppa.team_name}") | 849 | error(f"PPA {the_ppa.name} does not exist for user {the_ppa.owner_name}") |
401 | 830 | return 1 | 850 | return 1 |
402 | 831 | 851 | ||
403 | 832 | architectures = config.get('architectures', ARCHES_AUTOPKGTEST) | 852 | architectures = config.get('architectures', ARCHES_AUTOPKGTEST) |
404 | @@ -909,7 +929,7 @@ def command_tests(lp: Lp, config: dict[str, str]) -> int: | |||
405 | 909 | results = [] | 929 | results = [] |
406 | 910 | for release in releases: | 930 | for release in releases: |
407 | 911 | base_results_fmt = f"{URL_AUTOPKGTEST}/results/autopkgtest-%s-%s-%s/" | 931 | base_results_fmt = f"{URL_AUTOPKGTEST}/results/autopkgtest-%s-%s-%s/" |
409 | 912 | base_results_url = base_results_fmt % (release, the_ppa.team_name, the_ppa.name) | 932 | base_results_url = base_results_fmt % (release, the_ppa.owner_name, the_ppa.name) |
410 | 913 | url = f"{base_results_url}?format=plain" | 933 | url = f"{base_results_url}?format=plain" |
411 | 914 | response = open_url(url) | 934 | response = open_url(url) |
412 | 915 | if response: | 935 | if response: |
413 | diff --git a/tests/helpers.py b/tests/helpers.py | |||
414 | index 72a965e..c607d3c 100644 | |||
415 | --- a/tests/helpers.py | |||
416 | +++ b/tests/helpers.py | |||
417 | @@ -40,9 +40,10 @@ class ProcessorMock: | |||
418 | 40 | 40 | ||
419 | 41 | class ArchiveMock: | 41 | class ArchiveMock: |
420 | 42 | """A stand-in for a Launchpad Archive object.""" | 42 | """A stand-in for a Launchpad Archive object.""" |
422 | 43 | def __init__(self, name, description): | 43 | def __init__(self, name, description, owner): |
423 | 44 | self.displayname = name | 44 | self.displayname = name |
424 | 45 | self.description = description | 45 | self.description = description |
425 | 46 | self.owner = owner | ||
426 | 46 | self.publish = True | 47 | self.publish = True |
427 | 47 | self.processors = [ProcessorMock(proc_name) for proc_name in ARCHES_PPA_DEFAULT] | 48 | self.processors = [ProcessorMock(proc_name) for proc_name in ARCHES_PPA_DEFAULT] |
428 | 48 | self.published_sources = [] | 49 | self.published_sources = [] |
429 | @@ -68,7 +69,7 @@ class PersonMock: | |||
430 | 68 | if ppa.name == name: | 69 | if ppa.name == name: |
431 | 69 | raise PpaAlreadyExists(name) | 70 | raise PpaAlreadyExists(name) |
432 | 70 | ppa = Ppa(name, self.name, description) | 71 | ppa = Ppa(name, self.name, description) |
434 | 71 | Ppa.archive = ArchiveMock(ppa.name, ppa.description) | 72 | Ppa.archive = ArchiveMock(ppa.name, ppa.description, self) |
435 | 72 | self._ppas.append(ppa) | 73 | self._ppas.append(ppa) |
436 | 73 | return True | 74 | return True |
437 | 74 | 75 | ||
438 | diff --git a/tests/test_ppa.py b/tests/test_ppa.py | |||
439 | index 2410f83..9bb76e9 100644 | |||
440 | --- a/tests/test_ppa.py | |||
441 | +++ b/tests/test_ppa.py | |||
442 | @@ -21,59 +21,59 @@ from ppa.ppa import Ppa, ppa_address_split, get_ppa | |||
443 | 21 | 21 | ||
444 | 22 | def test_object(): | 22 | def test_object(): |
445 | 23 | """Check that PPA objects can be instantiated.""" | 23 | """Check that PPA objects can be instantiated.""" |
447 | 24 | ppa = Ppa('test-ppa-name', 'test-team-name') | 24 | ppa = Ppa('test-ppa-name', 'test-owner-name') |
448 | 25 | assert ppa | 25 | assert ppa |
449 | 26 | 26 | ||
450 | 27 | 27 | ||
451 | 28 | def test_description(): | 28 | def test_description(): |
452 | 29 | """Check specifying a description when creating a PPA.""" | 29 | """Check specifying a description when creating a PPA.""" |
454 | 30 | ppa = Ppa('test-ppa-name', 'test-team-name', 'test-description') | 30 | ppa = Ppa('test-ppa-name', 'test-owner-name', 'test-description') |
455 | 31 | 31 | ||
456 | 32 | assert 'test-description' in ppa.ppa_description | 32 | assert 'test-description' in ppa.ppa_description |
457 | 33 | 33 | ||
458 | 34 | 34 | ||
459 | 35 | def test_address(): | 35 | def test_address(): |
460 | 36 | """Check getting the PPA address.""" | 36 | """Check getting the PPA address.""" |
463 | 37 | ppa = Ppa('test', 'team') | 37 | ppa = Ppa('test', 'owner') |
464 | 38 | assert ppa.address == "ppa:team/test" | 38 | assert ppa.address == "ppa:owner/test" |
465 | 39 | 39 | ||
466 | 40 | 40 | ||
468 | 41 | @pytest.mark.parametrize('address, default_team, expected', [ | 41 | @pytest.mark.parametrize('address, expected', [ |
469 | 42 | # Successful cases | 42 | # Successful cases |
476 | 43 | ('bb', 'me', ('me', 'bb')), | 43 | ('bb', (None, 'bb')), |
477 | 44 | ('123', 'me', ('me', '123')), | 44 | ('123', (None, '123')), |
478 | 45 | ('a/123', 'me', ('a', '123')), | 45 | ('a/123', ('a', '123')), |
479 | 46 | ('ppa:a/bb', None, ('a', 'bb')), | 46 | ('ppa:A/bb', ('a', 'bb')), |
480 | 47 | ('ppa:ç/bb', None, ('ç', 'bb')), | 47 | ('ppa:a/bb', ('a', 'bb')), |
481 | 48 | ('https://launchpad.net/~a/+archive/ubuntu/bb', None, ('a', 'bb')), | 48 | ('ppa:ç/bb', ('ç', 'bb')), |
482 | 49 | ('https://launchpad.net/~a/+archive/ubuntu/bb', ('a', 'bb')), | ||
483 | 49 | 50 | ||
484 | 50 | # Expected failure cases | 51 | # Expected failure cases |
502 | 51 | ('ppa:', None, (None, None)), | 52 | ('ppa:', (None, None)), |
503 | 52 | (None, None, (None, None)), | 53 | (None, (None, None)), |
504 | 53 | ('', None, (None, None)), | 54 | ('', (None, None)), |
505 | 54 | ('/', None, (None, None)), | 55 | ('/', (None, None)), |
506 | 55 | (':/', None, (None, None)), | 56 | (':/', (None, None)), |
507 | 56 | ('////', None, (None, None)), | 57 | ('////', (None, None)), |
508 | 57 | ('ppa:/', None, (None, None)), | 58 | ('ppa:/', (None, None)), |
509 | 58 | ('ppa:a/', None, (None, None)), | 59 | ('ppa:a/', (None, None)), |
510 | 59 | ('ppa:/bb', None, (None, None)), | 60 | ('ppa:/bb', (None, None)), |
511 | 60 | ('ppa:a/bç', None, (None, None)), | 61 | ('ppa:a/bç', (None, None)), |
512 | 61 | ('ppa:A/bb', None, (None, None)), | 62 | ('ppa/a/bb', (None, None)), |
513 | 62 | ('ppa/a/bb', None, (None, None)), | 63 | ('ppa:a/bb/c', (None, None)), |
514 | 63 | ('ppa:a/bb/c', None, (None, None)), | 64 | ('ppa:a/bB', (None, None)), |
515 | 64 | ('ppa:a/bB', None, (None, None)), | 65 | ('http://launchpad.net/~a/+archive/ubuntu/bb', (None, None)), |
516 | 65 | ('http://launchpad.net/~a/+archive/ubuntu/bb', None, (None, None)), | 66 | ('https://example.com/~a/+archive/ubuntu/bb', (None, None)), |
517 | 66 | ('https://example.com/~a/+archive/ubuntu/bb', None, (None, None)), | 67 | ('https://launchpad.net/~a/+archive/nobuntu/bb', (None, None)), |
501 | 67 | ('https://launchpad.net/~a/+archive/nobuntu/bb', None, (None, None)), | ||
518 | 68 | ]) | 68 | ]) |
520 | 69 | def test_ppa_address_split(address, default_team, expected): | 69 | def test_ppa_address_split(address, expected): |
521 | 70 | """Check ppa address input strings can be parsed properly.""" | 70 | """Check ppa address input strings can be parsed properly.""" |
523 | 71 | result = ppa_address_split(address, default_team=default_team) | 71 | result = ppa_address_split(address) |
524 | 72 | assert result == expected | 72 | assert result == expected |
525 | 73 | 73 | ||
526 | 74 | 74 | ||
527 | 75 | def test_get_ppa(): | 75 | def test_get_ppa(): |
529 | 76 | ppa = get_ppa(None, {'team_name': 'a', 'ppa_name': 'bb'}) | 76 | ppa = get_ppa(None, {'owner_name': 'a', 'ppa_name': 'bb'}) |
530 | 77 | assert type(ppa) is Ppa | 77 | assert type(ppa) is Ppa |
532 | 78 | assert ppa.team_name == 'a' | 78 | assert ppa.owner_name == 'a' |
533 | 79 | assert ppa.ppa_name == 'bb' | 79 | assert ppa.ppa_name == 'bb' |
534 | diff --git a/tests/test_ppa_group.py b/tests/test_ppa_group.py | |||
535 | index d9d83de..f53799f 100644 | |||
536 | --- a/tests/test_ppa_group.py | |||
537 | +++ b/tests/test_ppa_group.py | |||
538 | @@ -59,14 +59,14 @@ def test_create_with_description(): | |||
539 | 59 | assert ppa.description == description | 59 | assert ppa.description == description |
540 | 60 | 60 | ||
541 | 61 | 61 | ||
544 | 62 | def test_create_with_team(): | 62 | def test_create_with_owner(): |
545 | 63 | """Check creating a PPA for a particular team.""" | 63 | """Check creating a PPA for a particular owner.""" |
546 | 64 | lp = LpServiceMock() | 64 | lp = LpServiceMock() |
549 | 65 | lp.launchpad.add_person('test_team_name') | 65 | lp.launchpad.add_person('test_owner_name') |
550 | 66 | ppa_group = PpaGroup(service=lp, name='test_team_name') | 66 | ppa_group = PpaGroup(service=lp, name='test_owner_name') |
551 | 67 | ppa = ppa_group.create('ppa_test_name') | 67 | ppa = ppa_group.create('ppa_test_name') |
552 | 68 | assert ppa is not None | 68 | assert ppa is not None |
554 | 69 | assert ppa.address == 'ppa:test_team_name/ppa_test_name' | 69 | assert ppa.address == 'ppa:test_owner_name/ppa_test_name' |
555 | 70 | 70 | ||
556 | 71 | 71 | ||
557 | 72 | def test_list_ppas(): | 72 | def test_list_ppas(): |
558 | diff --git a/tests/test_scripts_ppa.py b/tests/test_scripts_ppa.py | |||
559 | index 80347ba..f82a9e4 100644 | |||
560 | --- a/tests/test_scripts_ppa.py | |||
561 | +++ b/tests/test_scripts_ppa.py | |||
562 | @@ -53,7 +53,7 @@ loader.exec_module(script) | |||
563 | 53 | def fake_config(): | 53 | def fake_config(): |
564 | 54 | return { | 54 | return { |
565 | 55 | 'ppa_name': 'testing', | 55 | 'ppa_name': 'testing', |
567 | 56 | 'team_name': 'me', | 56 | 'owner_name': 'me', |
568 | 57 | 'wait_seconds': 0.1, | 57 | 'wait_seconds': 0.1, |
569 | 58 | 'quiet': True | 58 | 'quiet': True |
570 | 59 | } | 59 | } |
571 | @@ -257,6 +257,39 @@ def test_create_arg_parser_basic_config(command): | |||
572 | 257 | args.publish = None | 257 | args.publish = None |
573 | 258 | 258 | ||
574 | 259 | 259 | ||
575 | 260 | def test_create_arg_parser_create(): | ||
576 | 261 | """Checks argument parsing for the 'create' command. | ||
577 | 262 | |||
578 | 263 | Most of the create command's args are covered by | ||
579 | 264 | test_create_arg_parser_basic_config(), this just verifies | ||
580 | 265 | the few that aren't. | ||
581 | 266 | """ | ||
582 | 267 | parser = script.create_arg_parser() | ||
583 | 268 | command = 'create' | ||
584 | 269 | |||
585 | 270 | # Check ppa_name | ||
586 | 271 | args = parser.parse_args([command, 'test-ppa']) | ||
587 | 272 | assert args.ppa_name == 'test-ppa' | ||
588 | 273 | args = parser.parse_args([command, 'my-team/test-ppa']) | ||
589 | 274 | assert args.ppa_name == 'my-team/test-ppa' | ||
590 | 275 | args = parser.parse_args([command, 'ppa:my-team/test-ppa']) | ||
591 | 276 | assert args.ppa_name == 'ppa:my-team/test-ppa' | ||
592 | 277 | |||
593 | 278 | # Check --owner, --owner-name, --team, --team-name | ||
594 | 279 | args = parser.parse_args([command, 'test-ppa', '--owner', 'x']) | ||
595 | 280 | assert args.owner_name == 'x' | ||
596 | 281 | args.owner_name = None | ||
597 | 282 | args = parser.parse_args([command, 'test-ppa', '--owner-name', 'x']) | ||
598 | 283 | assert args.owner_name == 'x' | ||
599 | 284 | args.owner_name = None | ||
600 | 285 | args = parser.parse_args([command, 'test-ppa', '--team', 'x']) | ||
601 | 286 | assert args.owner_name == 'x' | ||
602 | 287 | args.owner_name = None | ||
603 | 288 | args = parser.parse_args([command, 'test-ppa', '--team-name', 'x']) | ||
604 | 289 | assert args.owner_name == 'x' | ||
605 | 290 | args.owner_name = None | ||
606 | 291 | |||
607 | 292 | |||
608 | 260 | def test_create_arg_parser_show(): | 293 | def test_create_arg_parser_show(): |
609 | 261 | """Checks argument parsing for the 'show' command.""" | 294 | """Checks argument parsing for the 'show' command.""" |
610 | 262 | parser = script.create_arg_parser() | 295 | parser = script.create_arg_parser() |
611 | @@ -387,13 +420,19 @@ def test_create_arg_parser_tests(): | |||
612 | 387 | 420 | ||
613 | 388 | @pytest.mark.parametrize('command_line_options, expected_config', [ | 421 | @pytest.mark.parametrize('command_line_options, expected_config', [ |
614 | 389 | pytest.param([], {}), | 422 | pytest.param([], {}), |
618 | 390 | (['status', 'ppa:aa/bb'], {'command': 'status', 'team_name': 'aa', 'ppa_name': 'bb'}), | 423 | (['status', 'ppa:aa/bb'], {'command': 'status', 'owner_name': 'aa', 'ppa_name': 'bb'}), |
619 | 391 | (['status', 'aa/bb'], {'team_name': 'aa', 'ppa_name': 'bb'}), | 424 | (['status', 'aa/bb'], {'owner_name': 'aa', 'ppa_name': 'bb'}), |
620 | 392 | (['status', 'bb'], {'team_name': 'me', 'ppa_name': 'bb'}), | 425 | (['status', 'bb'], {'owner_name': 'me', 'ppa_name': 'bb'}), |
621 | 393 | (['--debug', 'status', 'ppa:aa/bb'], {'debug': True}), | 426 | (['--debug', 'status', 'ppa:aa/bb'], {'debug': True}), |
622 | 394 | (['--dry-run', 'status', 'ppa:aa/bb'], {'dry_run': True}), | 427 | (['--dry-run', 'status', 'ppa:aa/bb'], {'dry_run': True}), |
623 | 395 | (['--verbose', 'status', 'ppa:aa/bb'], {'verbose': True}), | 428 | (['--verbose', 'status', 'ppa:aa/bb'], {'verbose': True}), |
624 | 396 | (['--quiet', 'status', 'ppa:aa/bb'], {'quiet': True}), | 429 | (['--quiet', 'status', 'ppa:aa/bb'], {'quiet': True}), |
625 | 430 | (['create', 'ppa:aa/bb'], {'command': 'create', 'owner_name': 'aa', 'ppa_name': 'bb'}), | ||
626 | 431 | (['create', 'aa/bb'], {'command': 'create', 'owner_name': 'aa', 'ppa_name': 'bb'}), | ||
627 | 432 | (['create', 'bb', '--owner', 'aa'], {'command': 'create', 'owner_name': 'aa', 'ppa_name': 'bb'}), | ||
628 | 433 | (['create', 'bb', '--owner-name', 'aa'], {'command': 'create', 'owner_name': 'aa', 'ppa_name': 'bb'}), | ||
629 | 434 | (['create', 'bb', '--team', 'aa'], {'command': 'create', 'owner_name': 'aa', 'ppa_name': 'bb'}), | ||
630 | 435 | (['create', 'bb', '--team-name', 'aa'], {'command': 'create', 'owner_name': 'aa', 'ppa_name': 'bb'}), | ||
631 | 397 | ]) | 436 | ]) |
632 | 398 | def test_create_config_from_args(command_line_options, expected_config): | 437 | def test_create_config_from_args(command_line_options, expected_config): |
633 | 399 | '''Checks creation of a config object from an argparser object. | 438 | '''Checks creation of a config object from an argparser object. |
634 | @@ -462,8 +501,8 @@ def test_command_create(fake_config, monkeypatch, stdin, params, expected_ppa_co | |||
635 | 462 | assert script.command_create(lp, config) == 0 | 501 | assert script.command_create(lp, config) == 0 |
636 | 463 | 502 | ||
637 | 464 | # Retrieve the newly created PPA | 503 | # Retrieve the newly created PPA |
640 | 465 | team = lp.people[config['team_name']] | 504 | owner = lp.people[config['owner_name']] |
641 | 466 | lp_ppa = team.getPPAByName(config['ppa_name']) | 505 | lp_ppa = owner.getPPAByName(config['ppa_name']) |
642 | 467 | assert lp_ppa | 506 | assert lp_ppa |
643 | 468 | 507 | ||
644 | 469 | # Verify the expected items are present in the new PPA | 508 | # Verify the expected items are present in the new PPA |
645 | @@ -471,6 +510,27 @@ def test_command_create(fake_config, monkeypatch, stdin, params, expected_ppa_co | |||
646 | 471 | assert getattr(lp_ppa, key) == value | 510 | assert getattr(lp_ppa, key) == value |
647 | 472 | 511 | ||
648 | 473 | 512 | ||
649 | 513 | @pytest.mark.parametrize('params, owner_name', [ | ||
650 | 514 | # Defaults | ||
651 | 515 | ({'owner_name': 'a', 'ppa_name': 'x'}, 'a'), | ||
652 | 516 | ]) | ||
653 | 517 | def test_command_create_with_owner(fake_config, monkeypatch, params, owner_name): | ||
654 | 518 | '''Checks create command produces a PPA for a specified owner.''' | ||
655 | 519 | lp = LpServiceMock() | ||
656 | 520 | lp.launchpad.add_person(owner_name) | ||
657 | 521 | monkeypatch.setattr("sys.stdin", io.StringIO('x')) | ||
658 | 522 | |||
659 | 523 | # Check success of the create command | ||
660 | 524 | config = {**fake_config, **params} | ||
661 | 525 | print(config) | ||
662 | 526 | assert script.command_create(lp, config) == 0 | ||
663 | 527 | |||
664 | 528 | # Retrieve the newly created PPA | ||
665 | 529 | owner = lp.people[owner_name] | ||
666 | 530 | lp_ppa = owner.getPPAByName(config['ppa_name']) | ||
667 | 531 | assert lp_ppa | ||
668 | 532 | |||
669 | 533 | |||
670 | 474 | @pytest.mark.parametrize('architectures, expected_processors', [ | 534 | @pytest.mark.parametrize('architectures, expected_processors', [ |
671 | 475 | (None, ARCHES_PPA_DEFAULT), | 535 | (None, ARCHES_PPA_DEFAULT), |
672 | 476 | ('a', ['a']), | 536 | ('a', ['a']), |
673 | @@ -487,8 +547,8 @@ def test_command_create_with_architectures(monkeypatch, fake_config, architectur | |||
674 | 487 | assert script.command_create(lp, config) == 0 | 547 | assert script.command_create(lp, config) == 0 |
675 | 488 | 548 | ||
676 | 489 | # Retrieve the newly created PPA | 549 | # Retrieve the newly created PPA |
679 | 490 | team = lp.people[config['team_name']] | 550 | owner = lp.people[config['owner_name']] |
680 | 491 | lp_ppa = team.getPPAByName(config['ppa_name']) | 551 | lp_ppa = owner.getPPAByName(config['ppa_name']) |
681 | 492 | 552 | ||
682 | 493 | # Check processor architectures | 553 | # Check processor architectures |
683 | 494 | assert lp_ppa.processors | 554 | assert lp_ppa.processors |
684 | @@ -549,15 +609,15 @@ def test_command_set(fake_config, params, expected_ppa_config): | |||
685 | 549 | lp = LpServiceMock() | 609 | lp = LpServiceMock() |
686 | 550 | 610 | ||
687 | 551 | # Create a default PPA, for modification later | 611 | # Create a default PPA, for modification later |
690 | 552 | team = lp.people[fake_config['team_name']] | 612 | owner = lp.people[fake_config['owner_name']] |
691 | 553 | team.createPPA(fake_config['ppa_name'], 'x', 'y') | 613 | owner.createPPA(fake_config['ppa_name'], 'x', 'y') |
692 | 554 | 614 | ||
693 | 555 | # Check success of the set command | 615 | # Check success of the set command |
694 | 556 | config = {**fake_config, **params} | 616 | config = {**fake_config, **params} |
695 | 557 | assert script.command_set(lp, config) | 617 | assert script.command_set(lp, config) |
696 | 558 | 618 | ||
697 | 559 | # Retrieve the PPA we created earlier | 619 | # Retrieve the PPA we created earlier |
699 | 560 | lp_ppa = team.getPPAByName(fake_config['ppa_name']) | 620 | lp_ppa = owner.getPPAByName(fake_config['ppa_name']) |
700 | 561 | 621 | ||
701 | 562 | # Verify the expected items are present in the updated PPA | 622 | # Verify the expected items are present in the updated PPA |
702 | 563 | for key, value in expected_ppa_config.items(): | 623 | for key, value in expected_ppa_config.items(): |
703 | @@ -577,15 +637,15 @@ def test_command_set_architectures(fake_config, architectures, expected_processo | |||
704 | 577 | lp = LpServiceMock() | 637 | lp = LpServiceMock() |
705 | 578 | 638 | ||
706 | 579 | # Create a default PPA, for modification later | 639 | # Create a default PPA, for modification later |
709 | 580 | team = lp.people[fake_config['team_name']] | 640 | owner = lp.people[fake_config['owner_name']] |
710 | 581 | team.createPPA(fake_config['ppa_name'], 'x', 'y') | 641 | owner.createPPA(fake_config['ppa_name'], 'x', 'y') |
711 | 582 | 642 | ||
712 | 583 | # Check success of the set command | 643 | # Check success of the set command |
713 | 584 | config = {**fake_config, **{'architectures': architectures}} | 644 | config = {**fake_config, **{'architectures': architectures}} |
714 | 585 | assert script.command_set(lp, config) | 645 | assert script.command_set(lp, config) |
715 | 586 | 646 | ||
716 | 587 | # Retrieve the PPA we created earlier | 647 | # Retrieve the PPA we created earlier |
718 | 588 | lp_ppa = team.getPPAByName(fake_config['ppa_name']) | 648 | lp_ppa = owner.getPPAByName(fake_config['ppa_name']) |
719 | 589 | 649 | ||
720 | 590 | # Check processor architectures | 650 | # Check processor architectures |
721 | 591 | assert lp_ppa.processors | 651 | assert lp_ppa.processors |
722 | @@ -629,8 +689,8 @@ def test_command_tests(urlopen_mock, | |||
723 | 629 | Ppa.get_autopkgtest_waiting = lambda x, y: [] | 689 | Ppa.get_autopkgtest_waiting = lambda x, y: [] |
724 | 630 | 690 | ||
725 | 631 | # Create a default PPA, for modification later | 691 | # Create a default PPA, for modification later |
728 | 632 | team = lp.people[fake_config['team_name']] | 692 | owner = lp.people[fake_config['owner_name']] |
729 | 633 | team.createPPA(fake_config['ppa_name'], 'x', 'y') | 693 | owner.createPPA(fake_config['ppa_name'], 'x', 'y') |
730 | 634 | the_ppa = lp.me.getPPAByName(fake_config['ppa_name']) | 694 | the_ppa = lp.me.getPPAByName(fake_config['ppa_name']) |
731 | 635 | 695 | ||
732 | 636 | # Add some fake publications | 696 | # Add some fake publications |
I like this, I do not feel I was able to do a full review - but for whatever it is worth it LGTM.
Furthermore I have left a few small comments inline for you to think about.