File: MilestoneOperation.py

package info (click to toggle)
trac 1.6-2~bpo12%2B1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-backports
  • size: 26,624 kB
  • sloc: python: 81,903; javascript: 2,219; makefile: 561; sh: 92; xml: 12
file content (112 lines) | stat: -rw-r--r-- 4,177 bytes parent folder | download | duplicates (2)
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
# -*- coding: utf-8 -*-
#
# Copyright (C) 2012-2023 Edgewall Software
# Copyright (C) 2012 Franz Mayer <franz.mayer@gefasoft.de>
# All rights reserved.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://trac.edgewall.org/wiki/TracLicense.
#
# This software consists of voluntary contributions made by many
# individuals. For the exact contribution history, see the revision
# history and logs, available at https://trac.edgewall.org/.

from trac.core import Component, implements
from trac.resource import ResourceNotFound
from trac.ticket.api import ITicketActionController
from trac.ticket.default_workflow import ConfigurableTicketWorkflow
from trac.ticket.model import Milestone
from trac.util import to_list
from trac.util.translation import _
from trac.web.chrome import add_warning

revision = "$Rev$"
url = "$URL$"


class MilestoneOperation(Component):
    """Sets milestone for specified resolutions.

    Example:
    {{{#!ini
    [ticket-workflow]
    resolve.operations = set_resolution,set_milestone
    resolve.milestone = invalid,wontfix,duplicate,worksforme -> rejected
    }}}

    When setting resolution to `duplicate` the milestone will
    automatically change to `rejected`. If user changes milestone
    manually when resolving the ticket, this workflow operation has
    ''no effect''.

    Don't forget to add `MilestoneOperation` to the `workflow` option
    in the `[ticket]` section of TracIni. When added to the default
    value of `workflow`, the line will look like this:
    {{{#!ini
    [ticket]
    workflow = ConfigurableTicketWorkflow,MilestoneOperation
    }}}
    """

    implements(ITicketActionController)

    def get_ticket_actions(self, req, ticket):
        controller = ConfigurableTicketWorkflow(self.env)
        return controller.get_actions_by_operation_for_req(req, ticket,
                                                           'set_milestone')

    def get_all_status(self):
        return []

    def render_ticket_action_control(self, req, ticket, action):
        actions = ConfigurableTicketWorkflow(self.env).actions
        label = actions[action]['label']
        hint = None
        old_milestone = ticket._old.get('milestone')
        if old_milestone is None:
            resolutions, milestone = \
                self._get_resolutions_and_milestone(action)
            if resolutions:
                try:
                    Milestone(self.env, milestone)
                except ResourceNotFound:
                    pass
                else:
                    res_hint = ', '.join("'%s'" % r for r in resolutions)
                    hint = _("For resolution %(resolutions)s the milestone "
                             "will be set to '%(milestone)s'.",
                             resolutions=res_hint, milestone=milestone)
        return label, None, hint

    def get_ticket_changes(self, req, ticket, action):
        old_milestone = ticket._old.get('milestone')
        if old_milestone is None:
            new_milestone = self._get_resolutions_and_milestone(action)[1]
            try:
                Milestone(self.env, new_milestone)
            except ResourceNotFound:
                add_warning(req, _("Milestone %(name)s does not exist.",
                                   name=new_milestone))
            else:
                self.log.info("Changed milestone from %s to %s",
                              old_milestone, new_milestone)
                return {'milestone': new_milestone}
        return {}

    def apply_action_side_effects(self, req, ticket, action):
        pass

    def _get_resolutions_and_milestone(self, action):
        transitions = self.config.get('ticket-workflow', action + '.milestone')
        milestone = None
        resolutions = []
        try:
            transition = to_list(transitions, sep='->')
        except ValueError:
            pass
        else:
            if len(transition) == 2:
                resolutions = to_list(transition[0])
                milestone = transition[1]
        return resolutions, milestone