057f77c54b2999de1a2207e52dd3f382a28e423f
[gentoolkit.git] / pym / gentoolkit / keyword.py
1 #!/usr/bin/python
2 #
3 # Copyright(c) 2004-2010, Gentoo Foundation
4 #
5 # Licensed under the GNU General Public License, v2
6 #
7 # $Header$
8
9 """Provides common methods on Gentoo GLEP 53 keywords.
10
11 http://www.gentoo.org/proj/en/glep/glep-0053.html
12 """
13
14 __all__ = (
15         'Keyword',
16         'compare_strs',
17         'reduce_keywords',
18         'determine_keyword'
19 )
20
21 # =======
22 # Imports
23 # =======
24
25
26 # =======
27 # Classes
28 # =======
29
30 class Keyword(object):
31         """Provides common methods on a GLEP 53 keyword."""
32
33         def __init__(self, keyword):
34                 self.keyword = keyword
35                 arch, sep, os = keyword.partition('-')
36                 self.arch = arch
37                 self.os = os
38
39         def __eq__(self, other):
40                 if not isinstance(other, self.__class__):
41                         return False
42                 return self.keyword == other.keyword
43
44         def __ne__(self, other):
45                 return not self == other
46
47         def __lt__(self, other):
48                 if not isinstance(other, self.__class__):
49                         raise TypeError("other isn't of %s type, is %s" % (
50                                 self.__class__, other.__class__)
51                         )
52                 if self.os < other.os:
53                         return True
54                 return self.arch < other.arch
55
56         def __le__(self, other):
57                 return self == other or self < other
58
59         def __gt__(self, other):
60                 return not self <= other
61
62         def __ge__(self, other):
63                 return self == other or self > other
64
65         def __str__(self):
66                 return self.keyword
67
68         def __repr__(self):
69                 return "<{0.__class__.__name__} {0.keyword!r}>".format(self)
70
71 # =========
72 # Functions
73 # =========
74
75 def compare_strs(kw1, kw2):
76         """Similar to the builtin cmp, but for keyword strings. Usually called
77         as: keyword_list.sort(keyword.compare_strs)
78
79         An alternative is to use the Keyword descriptor directly:
80         >>> kwds = sorted(Keyword(x) for x in keyword_list)
81
82         @see: >>> help(cmp)
83         """
84
85         kw1_arch, sep, kw1_os = kw1.partition('-')
86         kw2_arch, sep, kw2_os = kw2.partition('-')
87         if kw1_arch != kw2_arch:
88                 if kw1_os != kw2_os:
89                         return -1 if kw1_os < kw2_os else 1
90                 return -1 if kw1_arch < kw2_arch else 1
91         if kw1_os == kw2_os:
92                 return 0
93         return -1 if kw1_os < kw2_os else 1
94
95
96 def reduce_keywords(keywords):
97         """Reduce a list of keywords to a unique set of stable keywords.
98
99         Example usage:
100                 >>> reduce_keywords(['~amd64', 'x86', '~x86'])
101                 set(['amd64', 'x86'])
102
103         @type keywords: array
104         @rtype: set
105         """
106         return set(x.lstrip('~') for x in keywords)
107
108
109 abs_keywords = reduce_keywords
110
111
112 # FIXME: this is unclear
113 # dj, how about 'deduce_keyword'
114 # I was trying to avoid a 2nd use of determine_keyword name (in analyse.lib)
115 # but that one is a little different and not suitable for this task.
116 def determine_keyword(arch, accepted, keywords):
117         """Determine a keyword from matching a dep's KEYWORDS
118         list against the ARCH & ACCEPT_KEYWORDS provided.
119
120         @type arch: string
121         @param arch: portage.settings["ARCH"]
122         @type accepted: string
123         @param accepted: portage.settings["ACCEPT_KEYWORDS"]
124         @type keywords: string
125         @param keywords: the pkg ebuilds keywords
126         """
127         if not keywords:
128                 return ''
129         keys = keywords.split()
130         if arch in keys:
131                 return arch
132         keyworded = "~" + arch
133         if keyworded in keys:
134                 return keyworded
135         match = list(set(accepted.split(" ")).intersection(keys))
136         if len(match) > 1:
137                 if arch in match:
138                         return arch
139                 if keyworded in match:
140                         return keyworded
141                 return 'unknown'
142         if match:
143                 return match[0]
144         return 'unknown'