/
models.py
125 lines (95 loc) · 4.49 KB
/
models.py
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
"""Database models for integration configuration storage."""
import logging
from django.db import models
from django.utils.translation import gettext_lazy as _
from djblets.conditions import ConditionSet
from djblets.integrations.models import BaseIntegrationConfig
from reviewboard.integrations.base import GetIntegrationManagerMixin
from reviewboard.site.models import LocalSite
logger = logging.getLogger(__name__)
class IntegrationConfig(GetIntegrationManagerMixin, BaseIntegrationConfig):
"""Stored configuration for a particular integration.
This contains configuration settings for a given instance of an
integration, along with state indicating if that integration is to be
enabled and user-specified identifying information.
"""
local_site = models.ForeignKey(
LocalSite,
on_delete=models.CASCADE,
related_name='integration_configs',
blank=True,
null=True)
def load_conditions(self, form_cls, conditions_key='conditions'):
"""Load a set of conditions from the configuration.
This loads and deserializes a set of conditions from the configuration
stored in the provided key. Those conditions can then be matched by the
caller.
If the conditions are not found, this will return ``None``.
If the conditions cannot be deserialized, this will log some diagnostic
output and error messages and return ``None``.
Args:
form_cls (type):
The configuration form class that owns the condition field.
This will generally be ``my_integration.form_cls``,
but can be another form in more complex integrations.
conditions_key (unicode, optional):
The key for the conditions data in the configuration.
Defaults to "conditions".
Returns:
djblets.conditions.conditions.ConditionSet:
The condition set based on the data, if found and if it could be
loaded. Otherwise, ``None`` will be returned.
"""
conditions_data = self.get(conditions_key)
if not conditions_data:
return None
try:
return ConditionSet.deserialize(
form_cls.base_fields[conditions_key].choices,
conditions_data,
choice_kwargs={
'local_site': self.local_site,
'matching': True,
})
except Exception:
logger.exception('Unable to load bad condition set data for '
'integration configuration ID=%s for key="%s"',
self.pk, conditions_key)
logger.debug('Bad conditions data = %r', conditions_data)
return None
def match_conditions(self, form_cls, conditions_key='conditions',
**match_kwargs):
"""Filter configurations based on a review request.
If the configuration contains a ``conditions`` key, and the
configuration form contains a matching field, this will check
the conditions for matches against the review request.
Args:
form_cls (type):
The configuration form class that owns the condition field.
This will generally be ``my_integration.form_cls``,
but can be another form in more complex integrations.
conditions_key (unicode, optional):
The key for the conditions data in the configuration.
Defaults to "conditions".
**match_kwargs (dict):
Keyword arguments to match for the conditions.
Returns:
bool:
``True`` if the specified conditions in the configuration matches
the provided keyword arguments. ``False`` if not.
"""
condition_set = self.load_conditions(form_cls, conditions_key)
if condition_set:
try:
return condition_set.matches(**match_kwargs)
except Exception as e:
logger.exception(
'Unexpected failure when matching conditions for '
'integration configuration ID=%s, config_key=%s, '
'match_kwargs=%r: %s',
self.pk, conditions_key, match_kwargs, e)
return False
class Meta:
db_table = 'integrations_integrationconfig'
verbose_name = _('Integration Configuration')
verbose_name_plural = _('Integration Configurations')