add new cpv_sort_key() function
authorZac Medico <zmedico@gentoo.org>
Thu, 2 Dec 2010 03:56:44 +0000 (19:56 -0800)
committerZac Medico <zmedico@gentoo.org>
Sat, 4 Dec 2010 06:27:39 +0000 (22:27 -0800)
pym/portage/tests/versions/test_cpv_sort_key.py [new file with mode: 0644]
pym/portage/versions.py

diff --git a/pym/portage/tests/versions/test_cpv_sort_key.py b/pym/portage/tests/versions/test_cpv_sort_key.py
new file mode 100644 (file)
index 0000000..857af17
--- /dev/null
@@ -0,0 +1,16 @@
+# Copyright 2010 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+from portage.tests import TestCase
+from portage.versions import cpv_sort_key
+
+class CpvSortKeyTestCase(TestCase):
+
+       def testCpvSortKey(self):
+
+               tests = [ (( "a", "b", "a/b-2", "a/a-1", "a/b-1"),
+                       ( "a", "a/a-1", "a/b-1", "a/b-2", "b")),
+               ]
+
+               for test in tests:
+                       self.assertEqual( tuple(sorted(test[0], key=cpv_sort_key())), test[1] )
index 8ac32eb243ada6e97c072d66a607fcc486158c04..d3271a7620d34ce86e4aeb41f3019c3e91b232ee 100644 (file)
@@ -4,13 +4,17 @@
 
 __all__ = [
        'best', 'catpkgsplit', 'catsplit',
-       'cpv_getkey', 'cpv_getversion', 'pkgcmp',  'pkgsplit',
+       'cpv_getkey', 'cpv_getversion', 'cpv_sort_key', 'pkgcmp',  'pkgsplit',
        'ververify', 'vercmp'
 ]
 
 import re
 import warnings
 
+import portage
+portage.proxy.lazyimport.lazyimport(globals(),
+       'portage.util:cmp_sort_key'
+)
 from portage.localization import _
 
 # \w is [a-zA-Z0-9_]
@@ -342,6 +346,44 @@ def cpv_getversion(mycpv):
                return None
        return mycpv[len(cp+"-"):]
 
+def cpv_sort_key():
+       """
+       Create an object for sorting cpvs, to be useed as the 'key' parameter
+       in places like list.sort() or sorted(). This calls catpkgsplit() once for
+       each cpv and caches the result. If a given cpv is invalid or two cpvs
+       have different category/package names, then plain string (> and <)
+       comparison is used.
+
+       @rtype: key object for sorting
+       @return: object for use as the 'key' parameter in places like
+               list.sort() or sorted()
+       """
+
+       split_cache = {}
+
+       def cmp_cpv(cpv1, cpv2):
+
+               split1 = split_cache.get(cpv1, False)
+               if split1 is False:
+                       split1 = catpkgsplit(cpv1)
+                       if split1 is not None:
+                               split1 = (split1[:2], '-'.join(split1[2:]))
+                       split_cache[cpv1] = split1
+
+               split2 = split_cache.get(cpv2, False)
+               if split2 is False:
+                       split2 = catpkgsplit(cpv2)
+                       if split2 is not None:
+                               split2 = (split2[:2], '-'.join(split2[2:]))
+                       split_cache[cpv2] = split2
+
+               if split1 is None or split2 is None or split1[0] != split2[0]:
+                       return (cpv1 > cpv2) - (cpv1 < cpv2)
+
+               return vercmp(split1[1], split2[1])
+
+       return cmp_sort_key(cmp_cpv)
+
 def catsplit(mydep):
         return mydep.split("/", 1)