+#! /usr/bin/python
+###
+### Report on available package updates, including security updates.
+
+import time as T
+import os as OS
+import errno as E
+
+import apt_pkg as APT
+import apt.cache as AC
+
+###--------------------------------------------------------------------------
+### Some utility functions.
+
+def cache_up_to_date_p():
+ """Answer whether the cache is up-to-date."""
+
+ ## I use the same stamp file as APT's standard periodic update service.
+ ## This needs prodding via a hook in the APT configuration.
+ now = T.time()
+ try:
+ last = OS.path.getmtime('/var/lib/apt/periodic/update-stamp')
+ except OSError, err:
+ if err.errno == E.ENOENT:
+ return False
+ return now - last < 86400
+
+def upgradable_packages():
+ """Return a list of packages for which updates are available."""
+ cache = AC.Cache()
+ return [pkg for pkg in cache if pkg.is_upgradable]
+
+def security_updates_p(pkg):
+ """Answer whether any update for PKG is security-relevant."""
+
+ ## There doesn't seem to be a good way of doing this. For distributions
+ ## like `testing', security updates are folded into the main distribution
+ ## after the usual triage process, so they stop looking like security
+ ## updates. Worse, for `unstable' there aren't distinct security updates
+ ## anyway: they're all just thrown into the mixer. The good way to tell
+ ## would be to fetch the changelog and look for urgent changes. Debian's
+ ## Aptitude checks explicitly for `security.debian.org'. This check at
+ ## least also captures Ubuntu.
+ for v in pkg.versions:
+ if v < pkg.installed:
+ continue
+ for o in v.origins:
+ if o.site.startswith('security.'):
+ return True
+ return False
+
+###--------------------------------------------------------------------------
+### Main program.
+
+if not cache_up_to_date_p():
+ print 'W: package cache is more than 24 hours of date'
+updates = upgradable_packages()
+if updates:
+ plural = len(updates) != 1
+ print 'I: updates available for %d %s' % \
+ (len(updates), plural and 'packages' or 'package')
+sec = [pkg for pkg in updates if security_updates_p(pkg)]
+if sec:
+ plural = len(sec) != 1
+ print 'W: security updates available for %d %s' % \
+ (len(sec), plural and 'packages' or 'package')
+
+###----- That's all, folks --------------------------------------------------