aboutsummaryrefslogtreecommitdiff
blob: b28db6a64e7d872a02deaf9f83b4cb8d28c0d830 (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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
    g_collections.py
    ~~~~~~~~~~~~~~~~
    
    Customized classes of standard python data types
    for use withing g-sorcery for custom formatted string output
    substitution in our ebuild templates and classes for storing
    information about packages and dependencies.
    
    :copyright: (c) 2013 by Brian Dolbec
    :copyright: (c) 2013 by Jauhien Piatlicki
    :license: GPL-2, see LICENSE for more details.
"""

import portage

class elist(list):
    '''Custom list type which adds a customized __str__()
    and takes an optional separator argument

    elist() -> new empty elist
    elist(iterable) -> new elist initialized from iterable's items
    elist(separator='\\n\\t') -> new empty elist with
        newline & tab indented str(x) output
    elist(iterable, ' ') -> new elist initialized from iterable's items
        with space separated str(x) output
    '''

    __slots__ = ('_sep_')

    def __init__(self, iterable=None, separator=' '):
        '''
        iterable: initialize from iterable's items
        separator: string used to join list members with for __str__()
        '''
        list.__init__(self, iterable or [])
        self._sep_ = separator

    def __str__(self):
        '''Custom output function
        'x.__str__() <==> str(separator.join(x))'
        '''
        return self._sep_.join(map(str, self))


class serializable_elist(object):
    """
    A JSON serializable version of elist.
    """

    __slots__ = ('data')
    
    def __init__(self, iterable=None, separator=' '):
        '''
        iterable: initialize from iterable's items
        separator: string used to join list members with for __str__()
        '''
        self.data = elist(iterable or [], separator)

    def __iter__(self):
        return iter(self.data)

    def __str__(self):
        '''Custom output function
        '''
        return str(self.data)

    def append(self, x):
        self.data.append(x)

    def serialize(self):
        return {"separator": self.data._sep_, "data" : self.data}

    @classmethod
    def deserialize(cls, value):
        return serializable_elist(value["data"], separator = value["separator"])


#todo: replace Package with something better

class Package(object):
    """
    Class to store full package name: category/package-version
    """
    __slots__ = ('category', 'name', 'version')

    def __init__(self, category, package, version):
        self.category = category
        self.name = package
        self.version = version

    def __str__(self):
        return self.category + '/' + self.name + '-' + self.version

    def __eq__(self, other):
        return self.category == other.category and \
            self.name == other.name and \
            self.version == other.version

    def __hash__(self):
        return hash(self.category + self.name + self.version)

    def serialize(self):
        return [self.category, self.name, self.version]

    @classmethod
    def deserialize(cls, value):
        return Package(*value)


#todo equality operator for Dependency, as it can be used in backend dependency solving algorithm

class Dependency(object):
    """
    Class to store a dependency. Uses portage Atom.
    """

    __slots__ = ('atom', 'category', 'package', 'version', 'operator')

    def __init__(self, category, package, version="", operator=""):
        atom_str = operator + category + "/" + package
        if version:            
            atom_str += "-" + str(version)
        object.__setattr__(self, "atom", portage.dep.Atom(atom_str))
        object.__setattr__(self, "category", category)
        object.__setattr__(self, "package", package)
        object.__setattr__(self, "version", version)
        object.__setattr__(self, "operator", operator)

    def __setattr__(self, name, value):
        raise AttributeError("Dependency instances are immutable",
                             self.__class__, name, value)

    def __str__(self):
        return str(self.atom)

    def serialize(self):
        return str(self)

    @classmethod
    def deserialize(cls, value):
        atom = portage.dep.Atom(value)
        operator = portage.dep.get_operator(atom)
        cpv = portage.dep.dep_getcpv(atom)
        category, rest = portage.catsplit(cpv)

        if operator:
            package, version, revision = portage.pkgsplit(rest)
        else:
            package = rest
            version = ""
            operator = ""

        return Dependency(category, package, version, operator)