8
8
import warnings
9
9
from collections import defaultdict
10
10
from copy import copy
11
- from typing import DefaultDict , Literal , Mapping , Optional , TypedDict
11
+ from typing import DefaultDict , Literal , Mapping , Optional
12
12
from urllib .parse import ParseResult , urlparse
13
13
14
- from pydantic import BaseModel , Extra , Field , validator
14
+ from pydantic import BaseModel , ConfigDict , Extra , Field , RootModel , field_validator
15
+ from typing_extensions import TypedDict
15
16
16
17
from jbi import Operation , steps
17
18
from jbi .errors import ActionNotFoundError
@@ -40,8 +41,9 @@ class ActionSteps(BaseModel):
40
41
"create_comment" ,
41
42
]
42
43
43
- @validator ("*" )
44
- def validate_steps (cls , function_names ): # pylint: disable=no-self-argument
44
+ @field_validator ("*" )
45
+ @classmethod
46
+ def validate_steps (cls , function_names : list [str ]):
45
47
"""Validate that all configure step functions exist in the steps module"""
46
48
47
49
invalid_functions = [
@@ -69,7 +71,7 @@ class ActionParams(BaseModel):
69
71
jira_project_key : str
70
72
steps : ActionSteps = ActionSteps ()
71
73
jira_components : JiraComponents = JiraComponents ()
72
- labels_brackets : str = Field ( "no" , enum = ["yes" , "no" , "both" ])
74
+ labels_brackets : Literal ["yes" , "no" , "both" ] = "no"
73
75
status_map : dict [str , str ] = {}
74
76
resolution_map : dict [str , str ] = {}
75
77
issue_type_map : dict [str , str ] = {"task" : "Task" , "defect" : "Bug" }
@@ -91,23 +93,24 @@ def jira_project_key(self):
91
93
return self .parameters .jira_project_key
92
94
93
95
94
- class Actions (BaseModel ):
96
+ class Actions (RootModel ):
95
97
"""
96
98
Actions is the container model for the list of actions in the configuration file
97
99
"""
98
100
99
- __root__ : list [Action ] = Field (..., min_items = 1 )
101
+ root : list [Action ] = Field (..., min_length = 1 )
100
102
101
103
@functools .cached_property
102
104
def by_tag (self ) -> Mapping [str , Action ]:
103
105
"""Build mapping of actions by lookup tag."""
104
- return {action .whiteboard_tag : action for action in self .__root__ }
106
+ # pylint: disable-next=not-an-iterable
107
+ return {action .whiteboard_tag : action for action in self .root }
105
108
106
109
def __iter__ (self ):
107
- return iter (self .__root__ )
110
+ return iter (self .root ) # pylint: disable=not-an-iterable
108
111
109
112
def __len__ (self ):
110
- return len (self .__root__ )
113
+ return len (self .root )
111
114
112
115
def __getitem__ (self , item ):
113
116
return self .by_tag [item ]
@@ -119,12 +122,12 @@ def get(self, tag: Optional[str]) -> Optional[Action]:
119
122
@functools .cached_property
120
123
def configured_jira_projects_keys (self ) -> set [str ]:
121
124
"""Return the list of Jira project keys from all configured actions"""
122
- return {action .jira_project_key for action in self .__root__ }
125
+ # pylint: disable-next=not-an-iterable
126
+ return {action .jira_project_key for action in self .root }
123
127
124
- @validator ("__root__" )
125
- def validate_actions ( # pylint: disable=no-self-argument
126
- cls , actions : list [Action ]
127
- ):
128
+ @field_validator ("root" )
129
+ @classmethod
130
+ def validate_actions (cls , actions : list [Action ]):
128
131
"""
129
132
Inspect the list of actions:
130
133
- Validate that lookup tags are uniques
@@ -143,10 +146,7 @@ def validate_actions( # pylint: disable=no-self-argument
143
146
144
147
return actions
145
148
146
- class Config :
147
- """Pydantic configuration"""
148
-
149
- keep_untouched = (functools .cached_property ,)
149
+ model_config = ConfigDict (ignored_types = (functools .cached_property ,))
150
150
151
151
152
152
class BugzillaWebhookUser (BaseModel ):
@@ -169,48 +169,49 @@ class BugzillaWebhookEvent(BaseModel):
169
169
"""Bugzilla Event Object"""
170
170
171
171
action : str
172
- time : Optional [datetime .datetime ]
173
- user : Optional [BugzillaWebhookUser ]
174
- changes : Optional [list [BugzillaWebhookEventChange ]]
175
- target : Optional [str ]
176
- routing_key : Optional [str ]
172
+ time : Optional [datetime .datetime ] = None
173
+ user : Optional [BugzillaWebhookUser ] = None
174
+ changes : Optional [list [BugzillaWebhookEventChange ]] = None
175
+ target : Optional [str ] = None
176
+ routing_key : Optional [str ] = None
177
177
178
178
def changed_fields (self ) -> list [str ]:
179
179
"""Returns the names of changed fields in a bug"""
180
+ # pylint: disable-next=not-an-iterable
180
181
return [c .field for c in self .changes ] if self .changes else []
181
182
182
183
183
184
class BugzillaWebhookComment (BaseModel ):
184
185
"""Bugzilla Comment Object"""
185
186
186
- body : Optional [str ]
187
- id : Optional [int ]
188
- number : Optional [int ]
189
- is_private : Optional [bool ]
190
- creation_time : Optional [datetime .datetime ]
187
+ body : Optional [str ] = None
188
+ id : Optional [int ] = None
189
+ number : Optional [int ] = None
190
+ is_private : Optional [bool ] = None
191
+ creation_time : Optional [datetime .datetime ] = None
191
192
192
193
193
194
class BugzillaBug (BaseModel ):
194
195
"""Bugzilla Bug Object"""
195
196
196
197
id : int
197
- is_private : Optional [bool ]
198
- type : Optional [str ]
199
- product : Optional [str ]
200
- component : Optional [str ]
201
- whiteboard : Optional [str ]
202
- keywords : Optional [list ]
203
- flags : Optional [list ]
204
- groups : Optional [list ]
205
- status : Optional [str ]
206
- resolution : Optional [str ]
207
- see_also : Optional [list ]
208
- summary : Optional [str ]
209
- severity : Optional [str ]
210
- priority : Optional [str ]
211
- creator : Optional [str ]
212
- assigned_to : Optional [str ]
213
- comment : Optional [BugzillaWebhookComment ]
198
+ is_private : Optional [bool ] = None
199
+ type : Optional [str ] = None
200
+ product : Optional [str ] = None
201
+ component : Optional [str ] = None
202
+ whiteboard : Optional [str ] = None
203
+ keywords : Optional [list ] = None
204
+ flags : Optional [list ] = None
205
+ groups : Optional [list ] = None
206
+ status : Optional [str ] = None
207
+ resolution : Optional [str ] = None
208
+ see_also : Optional [list ] = None
209
+ summary : Optional [str ] = None
210
+ severity : Optional [str ] = None
211
+ priority : Optional [str ] = None
212
+ creator : Optional [str ] = None
213
+ assigned_to : Optional [str ] = None
214
+ comment : Optional [BugzillaWebhookComment ] = None
214
215
215
216
@property
216
217
def product_component (self ) -> str :
@@ -297,8 +298,8 @@ class BugzillaComment(BaseModel):
297
298
class BugzillaApiResponse (BaseModel ):
298
299
"""Bugzilla Response Object"""
299
300
300
- faults : Optional [list ]
301
- bugs : Optional [list [BugzillaBug ]]
301
+ faults : Optional [list ] = None
302
+ bugs : Optional [list [BugzillaBug ]] = None
302
303
303
304
304
305
class BugzillaWebhook (BaseModel ):
@@ -326,7 +327,7 @@ def slug(self):
326
327
class BugzillaWebhooksResponse (BaseModel ):
327
328
"""Bugzilla Webhooks List Response Object"""
328
329
329
- webhooks : Optional [list [BugzillaWebhook ]]
330
+ webhooks : Optional [list [BugzillaWebhook ]] = None
330
331
331
332
332
333
class Context (BaseModel ):
@@ -341,8 +342,8 @@ class JiraContext(Context):
341
342
"""Logging context about Jira"""
342
343
343
344
project : str
344
- issue : Optional [str ]
345
- labels : Optional [list [str ]]
345
+ issue : Optional [str ] = None
346
+ labels : Optional [list [str ]] = None
346
347
347
348
348
349
BugId = TypedDict ("BugId" , {"id" : Optional [int ]})
@@ -354,7 +355,7 @@ class RunnerContext(Context, extra=Extra.forbid):
354
355
rid : str
355
356
operation : Operation
356
357
event : BugzillaWebhookEvent
357
- action : Optional [Action ]
358
+ action : Optional [Action ] = None
358
359
bug : BugId | BugzillaBug
359
360
360
361
@@ -364,7 +365,7 @@ class ActionContext(Context, extra=Extra.forbid):
364
365
action : Action
365
366
rid : str
366
367
operation : Operation
367
- current_step : Optional [str ]
368
+ current_step : Optional [str ] = None
368
369
event : BugzillaWebhookEvent
369
370
jira : JiraContext
370
371
bug : BugzillaBug
0 commit comments