Completed
Push — master ( 889440...e965d2 )
by Dieter
01:16
created

BuildJob.add_property()   A

Complexity

Conditions 1

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 1
dl 0
loc 9
rs 9.6666
1
# vim: set expandtab sw=4 ts=4:
2
"""
3
Gather build related data.
4
5
Copyright (C) 2014-2016 Dieter Adriaenssens <[email protected]>
6
7
This file is part of buildtimetrend/python-lib
8
<https://github.com/buildtimetrend/python-lib/>
9
10
This program is free software: you can redistribute it and/or modify
11
it under the terms of the GNU Affero General Public License as published by
12
the Free Software Foundation, either version 3 of the License, or
13
any later version.
14
15
This program is distributed in the hope that it will be useful,
16
but WITHOUT ANY WARRANTY; without even the implied warranty of
17
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
GNU Affero General Public License for more details.
19
20
You should have received a copy of the GNU Affero General Public License
21
along with this program. If not, see <http://www.gnu.org/licenses/>.
22
"""
23
24
import copy
25
from lxml import etree
26
from buildtimetrend import logger
27
from buildtimetrend.settings import Settings
28
from buildtimetrend.stages import Stages
29
from buildtimetrend.collection import Collection
30
from buildtimetrend.tools import split_isotimestamp
31
32
33
class BuildJob(object):
34
35
    """Gather build job related data."""
36
37
    def __init__(self, csv_filename=None, end_timestamp=None):
38
        """Initialize instance."""
39
        self.properties = Collection()
40
        self.stages = Stages()
41
        if end_timestamp is not None:
42
            self.stages.set_end_timestamp(end_timestamp)
43
        if csv_filename is not None:
44
            self.stages.read_csv(csv_filename)
45
46
    def add_stages(self, stages):
47
        """
48
        Add a Stages instance.
49
50
        Parameters :
51
        - stages : Stages instance
52
        """
53
        if isinstance(stages, Stages):
54
            self.stages = stages
55
56
    def add_stage(self, stage):
57
        """
58
        Add a Stage instance.
59
60
        Parameters :
61
        - stage : Stage instance
62
        """
63
        self.stages.add_stage(stage)
64
65
    def add_property(self, name, value):
66
        """
67
        Add a build property.
68
69
        Parameters :
70
        - name : Property name
71
        - value : Property value
72
        """
73
        self.properties.add_item(name, value)
74
75
    def get_property(self, name):
76
        """
77
        Get a build property value.
78
79
        Parameters :
80
        - name : Property name
81
        """
82
        return self.properties.get_item(name)
83
84
    def get_properties(self):
85
        """Return build properties."""
86
        # copy values of properties
87
        data = self.properties.get_items()
88
89
        # add total duration
90
        # use total stage duration if it is defined
91
        # else, calculate duration from stage duration
92
        if "duration" not in data:
93
            data["duration"] = self.stages.total_duration()
94
95
        # add started_at of first stage if it is defined
96
        # and if it is not set in properties
97
        if self.stages.started_at is not None and "started_at" not in data:
98
            data["started_at"] = self.stages.started_at
99
100
        # add finished_at of last stage if it is defined
101
        # and if it is not set in properties
102
        if self.stages.finished_at is not None and "finished_at" not in data:
103
            data["finished_at"] = self.stages.finished_at
104
105
        return data
106
107
    def set_started_at(self, isotimestamp):
108
        """
109
        Set timestamp when build started.
110
111
        Parameters :
112
        - isotimestamp : timestamp in iso format when build started
113
        """
114
        try:
115
            self.add_property("started_at", split_isotimestamp(isotimestamp))
116
        except (TypeError, ValueError) as msg:
117
            logger.warning(
118
                "isotimestamp expected when setting started_at : %s", msg
119
            )
120
121
    def set_finished_at(self, isotimestamp):
122
        """
123
        Set timestamp when build finished.
124
125
        Parameters :
126
        - isotimestamp : timestamp in iso format when build started
127
        """
128
        try:
129
            self.add_property("finished_at", split_isotimestamp(isotimestamp))
130
        except (TypeError, ValueError) as msg:
131
            logger.warning(
132
                "isotimestamp expected when setting finished_at : %s", msg
133
            )
134
135
    def load_properties_from_settings(self):
136
        """Load build properties from settings."""
137
        self.load_property_from_settings("build")
138
        self.load_property_from_settings("job")
139
        self.load_property_from_settings("branch")
140
        self.load_property_from_settings("ci_platform")
141
        self.load_property_from_settings("build_trigger")
142
        self.load_property_from_settings("pull_request")
143
        self.load_property_from_settings("result")
144
        self.load_property_from_settings("build_matrix")
145
        self.add_property("repo", Settings().get_project_name())
146
147
    def load_property_from_settings(self, property_name, setting_name=None):
148
        """
149
        Load the value of a setting and set it as a build property.
150
151
        Parameters
152
        - property_name : name of the build property
153
        - setting_name : name of the setting (takes property_name if not set)
154
        """
155
        if setting_name is None:
156
            setting_name = property_name
157
158
        value = Settings().get_setting(setting_name)
159
160
        if value is not None:
161
            self.add_property(property_name, value)
162
163
    def to_dict(self):
164
        """Return object as dictionary."""
165
        # get build properties
166
        data = self.get_properties()
167
168
        # add stages
169
        if isinstance(self.stages, Stages):
170
            data["stages"] = self.stages.stages
171
172
        return data
173
174
    def stages_to_list(self):
175
        """Return list of stages, all containing the build properties."""
176
        if isinstance(self.stages, Stages):
177
            # create list to be returned
178
            data = []
179
180
            # get build properties
181
            build_properties = self.get_properties()
182
183
            # iterate all stages
184
            for stage in self.stages.stages:
185
                temp = {}
186
                # copy stage data
187
                temp["stage"] = copy.deepcopy(stage)
188
                # copy values of properties
189
                # check if collection is empty
190
                if build_properties:
191
                    temp["job"] = build_properties
192
                data.append(temp)
193
194
        return data
195
196
    def to_xml(self):
197
        """Generate XML object of a BuildJob instance."""
198
        root = etree.Element("build")
199
200
        # add properties
201
        for key in self.properties.get_items():
202
            root.set(str(key), str(self.properties.get_item(key)))
203
204
        # add stages
205
        if isinstance(self.stages, Stages):
206
            root.append(self.stages.to_xml())
207
208
        return root
209
210
    def to_xml_string(self):
211
        """Generate XML string of a BuildJob instance."""
212
        return etree.tostring(self.to_xml(), pretty_print=True)
213