aboutsummaryrefslogtreecommitdiff
blob: da4ada2be3bfe5e9c32743d14833cb32468ce96f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# Copyright(c) 2004-2010, Gentoo Foundation
#
# Licensed under the GNU General Public License, v2

"""Provides common methods on Gentoo GLEP 53 keywords.

http://www.gentoo.org/proj/en/glep/glep-0053.html
"""

__all__ = ("Keyword", "compare_strs", "reduce_keywords", "determine_keyword")

# =======
# Imports
# =======


# =======
# Classes
# =======


class Keyword:
    """Provides common methods on a GLEP 53 keyword."""

    def __init__(self, keyword):
        self.keyword = keyword
        arch, sep, os = keyword.partition("-")
        self.arch = arch
        self.os = os

    def __eq__(self, other):
        if not isinstance(other, self.__class__):
            return False
        return self.keyword == other.keyword

    def __ne__(self, other):
        return not self == other

    def __lt__(self, other):
        if not isinstance(other, self.__class__):
            raise TypeError(
                f"other isn't of {self.__class__} type, is {other.__class__}"
            )
        if self.os < other.os:
            return True
        return self.arch < other.arch

    def __le__(self, other):
        return self == other or self < other

    def __gt__(self, other):
        return not self <= other

    def __ge__(self, other):
        return self == other or self > other

    def __str__(self):
        return self.keyword

    def __repr__(self):
        return "<{0.__class__.__name__} {0.keyword!r}>".format(self)


# =========
# Functions
# =========


def compare_strs(kw1, kw2):
    """Similar to the builtin cmp, but for keyword strings. Usually called
    as: keyword_list.sort(keyword.compare_strs)

    An alternative is to use the Keyword descriptor directly:
    >>> keyword_list = ['~x86', '~amd64', 'x86']
    >>> kwds = sorted(Keyword(x) for x in keyword_list)

    @see: >>> help(cmp)
    """

    kw1_arch, sep, kw1_os = kw1.partition("-")
    kw2_arch, sep, kw2_os = kw2.partition("-")
    if kw1_arch != kw2_arch:
        if kw1_os != kw2_os:
            return -1 if kw1_os < kw2_os else 1
        return -1 if kw1_arch < kw2_arch else 1
    if kw1_os == kw2_os:
        return 0
    return -1 if kw1_os < kw2_os else 1


def reduce_keywords(keywords):
    """Reduce a list of keywords to a unique set of stable keywords.

    Example usage:
            >>> kw = reduce_keywords(['~amd64', 'x86', '~x86'])
            >>> isinstance(kw, set)
            True
            >>> sorted(kw)
            ['amd64', 'x86']

    @type keywords: array
    @rtype: set
    """
    return {x.lstrip("~") for x in keywords}


abs_keywords = reduce_keywords


# FIXME: this is unclear
# dj, how about 'deduce_keyword'
# I was trying to avoid a 2nd use of determine_keyword name (in analyse.lib)
# but that one is a little different and not suitable for this task.
def determine_keyword(arch, accepted, keywords):
    """Determine a keyword from matching a dep's KEYWORDS
    list against the ARCH & ACCEPT_KEYWORDS provided.

    @type arch: string
    @param arch: portage.settings["ARCH"]
    @type accepted: string
    @param accepted: portage.settings["ACCEPT_KEYWORDS"]
    @type keywords: string
    @param keywords: the pkg ebuilds keywords
    """
    if not keywords:
        return ""
    keys = keywords.split()
    if arch in keys:
        return arch
    keyworded = "~" + arch
    if keyworded in keys:
        return keyworded
    match = list(set(accepted.split(" ")).intersection(keys))
    if len(match) > 1:
        if arch in match:
            return arch
        if keyworded in match:
            return keyworded
        return "unknown"
    if match:
        return match[0]
    return "unknown"