HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Getting a list of outdated versions with Python

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
withgettingpythonversionslistoutdated

Problem

I have a list of boxes and need to list only the outdated ones.

For example, input will look something like this:

maier/alpine-3.1.3-x86_64 (virtualbox, 1.2.0)
maier/alpine-3.1.3-x86_64 (virtualbox, 1.3.0)
ubuntu/precise64          (virtualbox, 20151202.0.0)
ubuntu/vivid64            (virtualbox, 20150821.0.0)
ubuntu/vivid64            (virtualbox, 20150903.0.0)
ubuntu/vivid64            (virtualbox, 20151113.0.0)
ubuntu/vivid64            (virtualbox, 20151127.0.0)
ubuntu/vivid64            (virtualbox, 20151211.0.0)
ubuntu/wily64             (virtualbox, 20151203.0.0)


Output will look roughly like this:

maier/alpine-3.1.3-x86_64 (virtualbox, 1.2.0)
ubuntu/vivid64            (virtualbox, 20150821.0.0)
ubuntu/vivid64            (virtualbox, 20150903.0.0)
ubuntu/vivid64            (virtualbox, 20151113.0.0)
ubuntu/vivid64            (virtualbox, 20151127.0.0)


Note the format consists of: name, provider, version

It seems like there would be an easy way to do this from Bash scripting alone, e.g. I can version sort a particular column with sort, but I wasn't quite able to figure it out so I roughed it out in Python instead.

Is there are better way to do this?

```
#!/usr/bin/python3
# -- coding: utf-8 --

"""Attempt to remove outdated Vagrant boxes"""

import os
import re
import subprocess

from distutils.version import StrictVersion

def search(text):
"""Return a dictionary containing all the named subgroups of the match."""

patt = r'^(?P[^ ]+) +\((?P[^ ]+), +(?P[^ ]+)\)$'
return re.search(patt, text).groupdict()

output = subprocess.check_output(['vagrant', 'box', 'list'],
stderr=subprocess.DEVNULL).decode().rstrip()

box_list = (search(line) for line in output.splitlines())

box_dict = {}

for box in box_list:
name = box.get('name')
version = box.get('version')
box_dict[name] = box_dict.get(name, []) + [version]

outdated_boxes = {}

for box in box_dict:
versions = box_dict

Solution

Since everything is printed in order, the "obsolete" ones are all but the last version for the first word. That's tricky. But if we looked at the text backwards, we're printing all but the first one.

And that's easy with awk:

awk '!($1 in seen){print }{seen[$1] = 1}'


And then just invert the input twice:

run_your_version_cmd_here | tac | awk '$1 not in seen{print }{seen[$1] = 1}' | tac

Code Snippets

awk '!($1 in seen){print }{seen[$1] = 1}'
run_your_version_cmd_here | tac | awk '$1 not in seen{print }{seen[$1] = 1}' | tac

Context

StackExchange Code Review Q#113626, answer score: 2

Revisions (0)

No revisions yet.