Merge lp:~malizor/update-manager/ppa-changelogs into lp:update-manager

Proposed by Nicolas Delvaux
Status: Merged
Merged at revision: 2730
Proposed branch: lp:~malizor/update-manager/ppa-changelogs
Merge into: lp:update-manager
Diff against target: 141 lines (+67/-4)
3 files modified
UpdateManager/Core/MyCache.py (+59/-4)
debian/changelog (+7/-0)
debian/control (+1/-0)
To merge this branch: bzr merge lp:~malizor/update-manager/ppa-changelogs
Reviewer Review Type Date Requested Status
Colin Watson Needs Fixing
Review via email: mp+297119@code.launchpad.net

Commit message

Retrieve Changelogs from PPA sources if python3-launchpadlib is installed.

This uses the approach suggested by Colin Watson in LP: #253119.

Description of the change

Retrieve Changelogs from PPA sources if python3-launchpadlib is installed.

This uses the approach suggested by Colin Watson in LP: #253119.

I don't think it would be reasonable to add python3-launchpadlib to the hard dependency list: it would pull it and its dependencies into the default install, which is an additional 3269kB on Xenial.

Therefore, I only set python3-launchpadlib as a suggest dependency and I made the whole feature optional: if launchpadlib is not installed, nothing change except for a new warning in logs to suggest to install the library.

To post a comment you must log in.
Revision history for this message
Brian Murray (brian-murray) wrote :

Thanks for working on this, I appreciate it a lot. Generally, this looks good to me, but I have some comments which you'll find in line. You might also want to add a changelog entry to debian/changelog.

Revision history for this message
Colin Watson (cjwatson) wrote :

I would honestly just depend on python3-launchpadlib. Yes, we don't have anything in the desktop requiring it right now, but that isn't a strong reason not to add it; and without it, most people will continue not to see PPA changelogs, which seems more compelling to me.

Other than that, this seems like a good start and the use of the LP API seems mostly right, but there are a few details to fix up. Thanks!

review: Needs Fixing
Revision history for this message
Nicolas Delvaux (malizor) wrote :
Download full text (4.0 KiB)

Thanks for your comments so far.
I will try to adress them as soon as I'm back in front of a computer, which should be next week.

Le 15/06/16 02:34 Colin Watson a écrit :

Review: Needs Fixing

I would honestly just depend on python3-launchpadlib. Yes, we don't have anything in the desktop requiring it right now, but that isn't a strong reason not to add it; and without it, most people will continue not to see PPA changelogs, which seems more compelling to me.

Other than that, this seems like a good start and the use of the LP API seems mostly right, but there are a few details to fix up. Thanks!

Diff comments:

> === modified file 'UpdateManager/Core/MyCache.py'
> --- UpdateManager/Core/MyCache.py 2014-06-26 07:03:08 +0000
> +++ UpdateManager/Core/MyCache.py 2016-06-10 23:11:06 +0000
> @@ -268,6 +274,52 @@
> alllines = alllines + line
> return alllines
>
> + def _extract_ppa_changelog_uri(self, name):
> + """Return the changelog URI from the Launchpad API
> +
> + Return None in case of an error.
> + """
> + if Launchpad is None:
> + logging.warning("Please install 'python3-launchpadlib' to enable "
> + "changelog retrieval for PPAs.")
> + return
> + cdt = self[name].candidate
> + for uri in cdt.uris:
> + match = re.search('http.*/(.*)/(.*)/ubuntu/.*', uri)

This should use urllib.parse as the first step, and should only do anything if the hostname is ppa.launchpad.net.

> + if match is not None:
> + user, ppa = match.group(1), match.group(2)
> + break
> + else:
> + logging.error('Unable to extract the changelog from the PPA')
> + return
> +
> + # Login on launchpad if we are not already
> + if self.launchpad is None:
> + try:
> + self.launchpad = Launchpad.login_anonymously('update-manager',
> + 'production',
> + version='devel')
> + except:

Never use bare except. To catch everything that's reasonable to catch in most cases, use "except Exception:".

> + logging.exception("Unable to connect to Launchpad to retrieve "
> + "the changelog")
> + return
> +
> + archive = self.launchpad.archives.getByReference(
> + reference='~%s/ubuntu/%s' % (user, ppa)
> + )
> + if archive is None:
> + logging.error('Unable to extract the changelog from the PPA')
> + return
> +
> + spph = archive.getPublishedSources(source_name=cdt.source_name,
> + exact_match=True,
> + version=cdt.version)

It would be more conventional to use "spphs" given that this is plural.

> + if not spph:
> + logging.error('Unable to extract the changelog from the PPA')
> + return
> +
> + return spph[0].changelogUrl()

Why would a KeyError be relevant? Testing that the collection is non-empty should be enough to ensure that spphs[0] works, and there's no reason to suppose that .changelogUrl() will raise a KeyError. It may be worth catching HTTP exceptions (I forget the exact details), though, as temporary Launchpad outages shouldn't cause update-manager to explode.

> +
> def _guess_third_party_changelogs_uri_by_source(self, name):
> pkg = self[name]
> deb_uri = pkg.candidate.uri
> @@ -314,14 +366,21 @@
> if news:
> self.all_news[name] = news
>
> - def _fetch_changelog_for_third_party_package(self, name):
> + def _fetch_changelog_for_third_party_package(self, name, ori...

Read more...

2729. By Nicolas Delvaux

Attempt to retrieve Changelogs from PPA sources (LP: #253119)

2730. By Nicolas Delvaux

Add a new entry to debian/changelog

Revision history for this message
Nicolas Delvaux (malizor) wrote :

I fixed what you suggested:

* Move the try/except block to the calling function, to catch all API errors
* Different messages for different errors (and end them with periods!)
* Check that candidate URI hostname matches ppa.launchpad.net
* Do not use bare excepts
* Use "spphs" instead of the singular form
* Add a missing break
* Add an entry in debian/changelog

Revision history for this message
Brian Murray (brian-murray) wrote :

Thanks for making those fixes. I have one more question in-line.

Revision history for this message
Colin Watson (cjwatson) :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'UpdateManager/Core/MyCache.py'
--- UpdateManager/Core/MyCache.py 2014-06-26 07:03:08 +0000
+++ UpdateManager/Core/MyCache.py 2016-06-19 21:14:49 +0000
@@ -43,6 +43,7 @@
43import re43import re
44import DistUpgrade.DistUpgradeCache44import DistUpgrade.DistUpgradeCache
45from gettext import gettext as _45from gettext import gettext as _
46from launchpadlib.launchpad import Launchpad
4647
47SYNAPTIC_PINFILE = "/var/lib/synaptic/preferences"48SYNAPTIC_PINFILE = "/var/lib/synaptic/preferences"
48CHANGELOGS_POOL = "http://changelogs.ubuntu.com/changelogs/pool/"49CHANGELOGS_POOL = "http://changelogs.ubuntu.com/changelogs/pool/"
@@ -79,6 +80,7 @@
79 self.saveDistUpgrade()80 self.saveDistUpgrade()
80 assert (self._depcache.broken_count == 0 and81 assert (self._depcache.broken_count == 0 and
81 self._depcache.del_count == 0)82 self._depcache.del_count == 0)
83 self.launchpad = None
8284
83 def _dpkgJournalDirty(self):85 def _dpkgJournalDirty(self):
84 """86 """
@@ -222,7 +224,7 @@
222 # and so its possible to do a man-in-the-middle attack to steal the224 # and so its possible to do a man-in-the-middle attack to steal the
223 # credentials225 # credentials
224 res = urlsplit(uri)226 res = urlsplit(uri)
225 if res.scheme == "https" and res.username != "":227 if res.scheme == "https" and res.username:
226 raise HttpsChangelogsUnsupportedError(228 raise HttpsChangelogsUnsupportedError(
227 "https locations with username/password are not"229 "https locations with username/password are not"
228 "supported to fetch changelogs")230 "supported to fetch changelogs")
@@ -268,6 +270,48 @@
268 alllines = alllines + line270 alllines = alllines + line
269 return alllines271 return alllines
270272
273 def _extract_ppa_changelog_uri(self, name):
274 """Return the changelog URI from the Launchpad API
275
276 Return None in case of an error.
277 """
278 cdt = self[name].candidate
279 for uri in cdt.uris:
280 if urlsplit(uri).hostname != 'ppa.launchpad.net':
281 continue
282 match = re.search('http.*/(.*)/(.*)/ubuntu/.*', uri)
283 if match is not None:
284 user, ppa = match.group(1), match.group(2)
285 break
286 else:
287 logging.error("Unable to find a valid PPA candidate URL.")
288 return
289
290 # Login on launchpad if we are not already
291 if self.launchpad is None:
292 self.launchpad = Launchpad.login_anonymously('update-manager',
293 'production',
294 version='devel')
295
296
297 archive = self.launchpad.archives.getByReference(
298 reference='~%s/ubuntu/%s' % (user, ppa)
299 )
300 if archive is None:
301 logging.error("Unable to retrieve the archive from the Launchpad "
302 "API.")
303 return
304
305 spphs = archive.getPublishedSources(source_name=cdt.source_name,
306 exact_match=True,
307 version=cdt.version)
308 if not spphs:
309 logging.error("No published sources were retrieved from the "
310 "Launchpad API.")
311 return
312
313 return spphs[0].changelogUrl()
314
271 def _guess_third_party_changelogs_uri_by_source(self, name):315 def _guess_third_party_changelogs_uri_by_source(self, name):
272 pkg = self[name]316 pkg = self[name]
273 deb_uri = pkg.candidate.uri317 deb_uri = pkg.candidate.uri
@@ -314,14 +358,25 @@
314 if news:358 if news:
315 self.all_news[name] = news359 self.all_news[name] = news
316360
317 def _fetch_changelog_for_third_party_package(self, name):361 def _fetch_changelog_for_third_party_package(self, name, origins):
362 # Special case for PPAs
363 changelogs_uri_ppa = None
364 for origin in origins:
365 if origin.origin.startswith('LP-PPA-'):
366 try:
367 changelogs_uri_ppa = self._extract_ppa_changelog_uri(name)
368 break
369 except Exception:
370 logging.exception("Unable to connect to the Launchpad API.")
318 # Try non official changelog location371 # Try non official changelog location
319 changelogs_uri_binary = \372 changelogs_uri_binary = \
320 self._guess_third_party_changelogs_uri_by_binary(name)373 self._guess_third_party_changelogs_uri_by_binary(name)
321 changelogs_uri_source = \374 changelogs_uri_source = \
322 self._guess_third_party_changelogs_uri_by_source(name)375 self._guess_third_party_changelogs_uri_by_source(name)
323 error_message = ""376 error_message = ""
324 for changelogs_uri in [changelogs_uri_binary, changelogs_uri_source]:377 for changelogs_uri in [changelogs_uri_ppa,
378 changelogs_uri_binary,
379 changelogs_uri_source]:
325 if changelogs_uri:380 if changelogs_uri:
326 try:381 try:
327 changelog = self._get_changelog_or_news(382 changelog = self._get_changelog_or_news(
@@ -349,7 +404,7 @@
349 (name, getattr(self[name].installed, "version", None),404 (name, getattr(self[name].installed, "version", None),
350 self[name].candidate.version)405 self[name].candidate.version)
351 if self.CHANGELOG_ORIGIN not in [o.origin for o in origins]:406 if self.CHANGELOG_ORIGIN not in [o.origin for o in origins]:
352 self._fetch_changelog_for_third_party_package(name)407 self._fetch_changelog_for_third_party_package(name, origins)
353 return408 return
354 # fixup epoch handling version409 # fixup epoch handling version
355 srcpkg = self[name].candidate.source_name410 srcpkg = self[name].candidate.source_name
356411
=== modified file 'debian/changelog'
--- debian/changelog 2016-05-10 14:32:42 +0000
+++ debian/changelog 2016-06-19 21:14:49 +0000
@@ -1,3 +1,10 @@
1update-manager (1:16.10.2) UNRELEASED; urgency=medium
2
3 * Attempt to retrieve Changelogs from PPA sources (LP: #253119)
4 * Correctly detect the usage of a username in changelog URIs
5
6 -- Nicolas Delvaux <contact@nicolas-delvaux.org> Sun, 19 Jun 2016 23:12:22 +0200
7
1update-manager (1:16.10.1) yakkety; urgency=medium8update-manager (1:16.10.1) yakkety; urgency=medium
29
3 * Correctly calculate the end of support, and return correctly when support10 * Correctly calculate the end of support, and return correctly when support
411
=== modified file 'debian/control'
--- debian/control 2016-04-06 22:38:57 +0000
+++ debian/control 2016-06-19 21:14:49 +0000
@@ -41,6 +41,7 @@
41 ${misc:Depends},41 ${misc:Depends},
42 python3-apt (>= 0.8.5~),42 python3-apt (>= 0.8.5~),
43 python3-distupgrade,43 python3-distupgrade,
44 python3-launchpadlib,
44 lsb-release45 lsb-release
45Description: python 3.x module for update-manager46Description: python 3.x module for update-manager
46 Python module for update-manager (UpdateManager).47 Python module for update-manager (UpdateManager).

Subscribers

People subscribed via source and target branches

to status/vote changes: