dictionary comparison

Bengt Richter bokr at oz.net
Thu May 5 16:01:44 EDT 2005


On 5 May 2005 08:19:31 -0700, "rickle" <devrick88 at gmail.com> wrote:

>I'm trying to compare sun patch levels on a server to those of what sun
>is recommending.  For those that aren't familiar with sun patch
>numbering here is a quick run down.
>
>A patch number shows up like this:
>113680-03
>^^^^^^ ^^
>patch#  revision
>
>What I want to do is make a list.  I want to show what server x has
>versus what sun recommends, and if the patch exists, but the revision
>is different, I want to show that difference.
>
>Here are some sample patches that sun recommends:
>117000-05
>116272-03
>116276-01
>116278-01
>116378-02
>116455-01
>116602-01
>116606-01
>
>Here are some sample patches that server x has:
>117000-01
>116272-02
>116272-01
>116602-02
>
>So there are some that are the same, some that sun recommends that
>server x doesn't have, and some where the patch is the same but the
>revision is different.
>
>I've thrown the data into dictionaries, but I just can't seem to figure
>out how I should actually compare the data and present it.  Here's what
>I have so far (the split is in place because there is actually a lot
>more data in the file, so I split it out so I just get the patch number
>and revision).  So I end up with (for example) 116272-01, then split so
>field[0] is 116272 and field[1] is 01.
>
>def sun():
>        sun = open('sun-patchlist', 'r')
>        for s in sun:
>                sun_fields = s.split(None, 7)
>                for sun_field in sun_fields:
>                        sun_field = sun_field.strip()
>                sun_patch = {}
>                sun_patch['number'] = sun_fields[0]
>                sun_patch['rev'] = sun_fields[1]
>                print sun_patch['number'], sun_patch['rev']
>        sun.close()
>
>def serverx():
>        serverx = open('serverx-patchlist', 'r')
>        for p in serverx:
>                serverx_fields = p.split(None, 7)
>                for serverx_field in serverx_fields:
>                        serverx_field = serverx_field.strip()
>                serverx_patch = {}
>                serverx_patch['number'] = serverx_fields[0]
>                serverx_patch['rev'] = serverx_fields[1]
>                print serverx_patch['number'], serverx_patch['rev']
>        serverx.close()
>
>if __name__=='__main__':
>        sun()
>        serverx()
>
>
>Right now I'm just printing the data, just to be sure that each
>dictionary contains the correct data, which it does.  But now I need
>the comparison and I just can't seem to figure it out.  I could
>probably write this in perl or a shell script, but I'm trying really
>hard to force myself to learn Python so I want this to be a python
>script, created with only built-in modules.
>
>Any help would be greatly appreciated,
>
In place of sun_rec.splitlines() and x_has.splitlines() you can substitute
 open('sun-patchlist') adn open('serverx-patchlist') respectively,
and you can wrap it all in some rountine for your convenience etc.
But this shows recommended revs that are either there, missing, and/or have unrecommended revs present.
I added some test data to illustrate. You might want to make the input a little more forgiving about
e.g. blank lines etc or raise exceptions for what's not allowed or expected.

----< sunpatches.py >--------------------------------------------------------------
#Here are some sample patches that sun recommends:
sun_rec = """\
117000-05
116272-03
116276-01
116278-01
116378-02
116455-01
116602-01
116606-01
testok-01
testok-02
testok-03
test_0-01
test_0-02
test_0-03
test_2-01
test_2-02
test_2-03
test23-02
test23-03
"""

#Here are some sample patches that server x has:
x_has = """\
117000-01
116272-02
116272-01
116602-02
testok-01
testok-02
testok-03
test_2-01
test_2-02
test23-01
test23-02
test23-03
"""

def mkdict(lineseq):
    dct = {}
    for line in lineseq:
        patch, rev = line.split('-')
        dct.setdefault(patch, set()).add(rev)
    return dct
    
dct_x_has = mkdict(x_has.splitlines()) # or e.g., mkdict(open('sunrecfile.txt'))
dct_sun_rec = mkdict(sun_rec.splitlines())

for sunpatch, sunrevs in sorted(dct_sun_rec.items()):
    xrevs = dct_x_has.get(sunpatch, set())
    print 'patch %s: recommended revs %s, missing %s, actual other %s'%(
        sunpatch, map(str,sunrevs&xrevs) or '(none)',
        map(str,sunrevs-xrevs) or '(none)', map(str,xrevs-sunrevs) or '(none)')
----------------------------------------------------------------------------------
Result:

[12:51] C:\pywk\clp>py24 sunpatches.py
patch 116272: recommended revs (none), missing ['03'], actual other ['02', '01']
patch 116276: recommended revs (none), missing ['01'], actual other (none)
patch 116278: recommended revs (none), missing ['01'], actual other (none)
patch 116378: recommended revs (none), missing ['02'], actual other (none)
patch 116455: recommended revs (none), missing ['01'], actual other (none)
patch 116602: recommended revs (none), missing ['01'], actual other ['02']
patch 116606: recommended revs (none), missing ['01'], actual other (none)
patch 117000: recommended revs (none), missing ['05'], actual other ['01']
patch test23: recommended revs ['02', '03'], missing (none), actual other ['01']
patch test_0: recommended revs (none), missing ['02', '03', '01'], actual other (none)
patch test_2: recommended revs ['02', '01'], missing ['03'], actual other (none)
patch testok: recommended revs ['02', '03', '01'], missing (none), actual other (none)

Oops, didn't pyt multiple revs in sort order. Oh well, you can do that if you like.

Regards,
Bengt Richter



More information about the Python-list mailing list