1
1
import datetime
2
2
import logging
3
- from typing import Optional , TypedDict
3
+ from typing import Any , Optional , TypedDict
4
4
from urllib .parse import ParseResult , urlparse
5
5
6
- from pydantic import BaseModel , TypeAdapter
6
+ from pydantic import (
7
+ AwareDatetime ,
8
+ BaseModel ,
9
+ TypeAdapter ,
10
+ ValidationError ,
11
+ ValidationInfo ,
12
+ ValidatorFunctionWrapHandler ,
13
+ )
14
+ from pydantic .functional_validators import WrapValidator
15
+ from typing_extensions import Annotated
7
16
8
17
logger = logging .getLogger (__name__ )
9
18
JIRA_HOSTNAMES = ("jira" , "atlassian" )
10
19
11
20
BugId = TypedDict ("BugId" , {"id" : Optional [int ]})
12
21
13
22
23
+ def maybe_add_timezone (
24
+ v : Any , handler : ValidatorFunctionWrapHandler , info : ValidationInfo
25
+ ):
26
+ if isinstance (v , str ):
27
+ try :
28
+ return handler (v )
29
+ except ValidationError :
30
+ return handler (v + "+00:00" )
31
+ assert isinstance (v , datetime .datetime ), "must be a datetime here"
32
+ v = v .replace (tzinfo = datetime .timezone .utc )
33
+ return v
34
+
35
+
36
+ SmartAwareDatetime = Annotated [AwareDatetime , WrapValidator (maybe_add_timezone )]
37
+
38
+
14
39
class WebhookUser (BaseModel , frozen = True ):
15
40
"""Bugzilla User Object"""
16
41
@@ -31,7 +56,7 @@ class WebhookEvent(BaseModel, frozen=True):
31
56
"""Bugzilla Event Object"""
32
57
33
58
action : str
34
- time : datetime . datetime
59
+ time : SmartAwareDatetime
35
60
user : Optional [WebhookUser ] = None
36
61
changes : Optional [list [WebhookEventChange ]] = None
37
62
target : Optional [str ] = None
@@ -50,7 +75,7 @@ class WebhookComment(BaseModel, frozen=True):
50
75
id : Optional [int ] = None
51
76
number : Optional [int ] = None
52
77
is_private : Optional [bool ] = None
53
- creation_time : Optional [datetime . datetime ] = None
78
+ creation_time : Optional [SmartAwareDatetime ] = None
54
79
55
80
56
81
class Bug (BaseModel , frozen = True ):
0 commit comments