1# This Source Code Form is subject to the terms of the Mozilla Public
2# License, v. 2.0. If a copy of the MPL was not distributed with this
3# file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5from __future__ import absolute_import, print_function, unicode_literals
6
7import attr
8
9
10@attr.s
11class Task(object):
12    """
13    Representation of a task in a TaskGraph.  Each Task has, at creation:
14
15    - kind: the name of the task kind
16    - label; the label for this task
17    - attributes: a dictionary of attributes for this task (used for filtering)
18    - task: the task definition (JSON-able dictionary)
19    - optimization: optimization to apply to the task (see taskgraph.optimize)
20    - dependencies: tasks this one depends on, in the form {name: label}, for example
21      {'build': 'build-linux64/opt', 'docker-image': 'build-docker-image-desktop-test'}
22
23    And later, as the task-graph processing proceeds:
24
25    - task_id -- TaskCluster taskId under which this task will be created
26
27    This class is just a convenience wrapper for the data type and managing
28    display, comparison, serialization, etc. It has no functionality of its own.
29    """
30
31    kind = attr.ib()
32    label = attr.ib()
33    attributes = attr.ib()
34    task = attr.ib()
35    task_id = attr.ib(default=None, init=False)
36    optimization = attr.ib(default=None)
37    dependencies = attr.ib(factory=dict)
38    release_artifacts = attr.ib(
39        converter=attr.converters.optional(frozenset),
40        default=None,
41    )
42
43    def __attrs_post_init__(self):
44        self.attributes['kind'] = self.kind
45
46    def to_json(self):
47        rv = {
48            'kind': self.kind,
49            'label': self.label,
50            'attributes': self.attributes,
51            'dependencies': self.dependencies,
52            'optimization': self.optimization,
53            'task': self.task,
54        }
55        if self.task_id:
56            rv['task_id'] = self.task_id
57        if self.release_artifacts:
58            rv['release_artifacts'] = sorted(self.release_artifacts)
59        return rv
60
61    @classmethod
62    def from_json(cls, task_dict):
63        """
64        Given a data structure as produced by taskgraph.to_json, re-construct
65        the original Task object.  This is used to "resume" the task-graph
66        generation process, for example in Action tasks.
67        """
68        rv = cls(
69            kind=task_dict['kind'],
70            label=task_dict['label'],
71            attributes=task_dict['attributes'],
72            task=task_dict['task'],
73            optimization=task_dict['optimization'],
74            dependencies=task_dict.get('dependencies'),
75            release_artifacts=task_dict.get('release-artifacts'),
76        )
77        if 'task_id' in task_dict:
78            rv.task_id = task_dict['task_id']
79        return rv
80