Format, lint, type

This commit is contained in:
Abel Luck 2022-12-01 14:20:37 +00:00
parent a1ae717c8f
commit c925079e8b
8 changed files with 159 additions and 91 deletions

View file

@ -1,18 +1,14 @@
import re
import attr
import logging
from typing import Any, Tuple
from jinja2 import TemplateNotFound
import re
from typing import Any, List, Tuple
from mautrix.types import (EventType, RoomID, StateEvent, Membership, MessageType, JSON,
TextMessageEventContent, Format, ReactionEventContent, RelationType)
import attr
from jinja2 import TemplateNotFound
from mautrix.types import Format, MessageType, TextMessageEventContent
from mautrix.util.formatter import parse_html
from ..util.template import TemplateManager, TemplateUtil
from .types import EventParse, OTHER_ENUMS, Action
from ..common import COLOR_ALARM, COLOR_OK, COLOR_UNKNOWN
from .types import OTHER_ENUMS, Action, EventParse # type: ignore
spaces = re.compile(" +")
space = " "
@ -21,22 +17,23 @@ space = " "
messages = TemplateManager("gitlab", "messages")
templates = TemplateManager("gitlab", "mixins")
async def parse_event(x_gitlab_event: str, payload: Any) -> Tuple[str, str]:
async def parse_event(x_gitlab_event: str, payload: Any) -> List[Tuple[str, str]]:
evt = EventParse[x_gitlab_event].deserialize(payload)
print("processing", evt)
try:
tpl = messages[evt.template_name]
except TemplateNotFound as e:
except TemplateNotFound:
msg = f"Received unhandled gitlab event type {x_gitlab_event}"
logging.info(msg)
logging.info(payload)
return [(msg, msg)]
logging.error(msg)
logging.debug(payload)
return []
aborted = False
def abort() -> None:
nonlocal aborted
aborted = True
base_args = {
**{field.key: field for field in Action if field.key.isupper()},
**OTHER_ENUMS,
@ -45,14 +42,13 @@ async def parse_event(x_gitlab_event: str, payload: Any) -> Tuple[str, str]:
msgs = []
for subevt in evt.preprocess():
print("preprocessing", subevt)
args = {
**attr.asdict(subevt, recurse=False),
**{key: getattr(subevt, key) for key in subevt.event_properties},
"abort": abort,
**base_args,
**base_args, # type: ignore
}
args["templates"] = templates.proxy(args)
args["templates"] = templates.proxy(args) # type: ignore
html = tpl.render(**args)
if not html or aborted:
@ -60,11 +56,15 @@ async def parse_event(x_gitlab_event: str, payload: Any) -> Tuple[str, str]:
continue
html = spaces.sub(space, html.strip())
content = TextMessageEventContent(msgtype=MessageType.TEXT, format=Format.HTML,
formatted_body=html, body=await parse_html(html))
content = TextMessageEventContent(
msgtype=MessageType.TEXT,
format=Format.HTML,
formatted_body=html,
body=await parse_html(html),
)
content["xyz.maubot.gitlab.webhook"] = {
"event_type": x_gitlab_event,
**subevt.meta,
}
msgs.append((content.body, content.formatted_body))
return msgs
return msgs

View file

@ -1,3 +1,4 @@
# type: ignore
# gitlab - A GitLab client and webhook receiver for maubot
# Copyright (C) 2019 Lorenz Steinert
# Copyright (C) 2021 Tulir Asokan
@ -14,22 +15,27 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from typing import List, Union, Dict, Optional, Type, NewType, ClassVar, Tuple, Iterable
from datetime import datetime
from typing import ClassVar, Dict, Iterable, List, NewType, Optional, Tuple, Type, Union
from jinja2 import TemplateNotFound
from attr import dataclass
from yarl import URL
import attr
from mautrix.types import JSON, ExtensibleEnum, SerializableAttrs, serializer, deserializer
from attr import dataclass
from jinja2 import TemplateNotFound
from mautrix.types import (
JSON,
ExtensibleEnum,
SerializableAttrs,
deserializer,
serializer,
)
from yarl import URL
from ..util.contrast import contrast, hex_to_rgb
@serializer(datetime)
def datetime_serializer(dt: datetime) -> JSON:
return dt.strftime('%Y-%m-%dT%H:%M:%S%z')
return dt.strftime("%Y-%m-%dT%H:%M:%S%z")
@deserializer(datetime)
@ -93,9 +99,12 @@ class GitlabLabel(SerializableAttrs):
@property
def foreground_color(self) -> str:
return (self.white_hex
if contrast(hex_to_rgb(self.color), self.white_rgb) >= self.contrast_threshold
else self.black_hex)
return (
self.white_hex
if contrast(hex_to_rgb(self.color), self.white_rgb)
>= self.contrast_threshold
else self.black_hex
)
@dataclass
@ -133,7 +142,7 @@ class GitlabUser(SerializableAttrs):
def __hash__(self) -> int:
return self.id
def __eq__(self, other: 'GitlabUser') -> bool:
def __eq__(self, other: "GitlabUser") -> bool:
if not isinstance(other, GitlabUser):
return False
return self.id == other.id
@ -221,7 +230,7 @@ class GitlabSource(SerializableAttrs):
http_url: Optional[str] = None
GitlabTarget = NewType('GitlabTarget', GitlabSource)
GitlabTarget = NewType("GitlabTarget", GitlabSource)
class GitlabChangeWrapper:
@ -600,7 +609,7 @@ class GitlabBuild(SerializableAttrs):
@dataclass
class GitlabEvent:
def preprocess(self) -> List['GitlabEvent']:
def preprocess(self) -> List["GitlabEvent"]:
return [self]
@property
@ -641,9 +650,14 @@ class GitlabPushEvent(SerializableAttrs, GitlabEvent):
@property
def user(self) -> GitlabUser:
return GitlabUser(id=self.user_id, name=self.user_name, email=self.user_email,
username=self.user_username, avatar_url=self.user_avatar,
web_url=f"{self.project.gitlab_base_url}/{self.user_username}")
return GitlabUser(
id=self.user_id,
name=self.user_name,
email=self.user_email,
username=self.user_username,
avatar_url=self.user_avatar,
web_url=f"{self.project.gitlab_base_url}/{self.user_username}",
)
@property
def template_name(self) -> str:
@ -651,8 +665,15 @@ class GitlabPushEvent(SerializableAttrs, GitlabEvent):
@property
def event_properties(self) -> Iterable[str]:
return ("user", "is_new_ref", "is_deleted_ref", "ref_name", "ref_type", "ref_url",
"diff_url")
return (
"user",
"is_new_ref",
"is_deleted_ref",
"ref_name",
"ref_type",
"ref_url",
"diff_url",
)
@property
def diff_url(self) -> str:
@ -695,7 +716,9 @@ class GitlabPushEvent(SerializableAttrs, GitlabEvent):
return f"push-{self.project_id}-{self.checkout_sha}-{self.ref_name}"
def split_updates(evt: Union['GitlabIssueEvent', 'GitlabMergeRequestEvent']) -> List[GitlabEvent]:
def split_updates(
evt: Union["GitlabIssueEvent", "GitlabMergeRequestEvent"]
) -> List[GitlabEvent]:
if not evt.changes:
return [evt]
output = []
@ -704,7 +727,9 @@ def split_updates(evt: Union['GitlabIssueEvent', 'GitlabMergeRequestEvent']) ->
for field in attr.fields(GitlabChanges):
value = getattr(evt.changes, field.name)
if value:
output.append(attr.evolve(evt, changes=GitlabChanges(**{field.name: value})))
output.append(
attr.evolve(evt, changes=GitlabChanges(**{field.name: value}))
)
return output
@ -719,7 +744,7 @@ class GitlabIssueEvent(SerializableAttrs, GitlabEvent):
labels: Optional[List[GitlabLabel]] = None
changes: Optional[GitlabChanges] = None
def preprocess(self) -> List['GitlabIssueEvent']:
def preprocess(self) -> List["GitlabIssueEvent"]:
users_to_mutate = [self.user]
if self.changes and self.changes.assignees:
users_to_mutate += self.changes.assignees.previous
@ -737,7 +762,7 @@ class GitlabIssueEvent(SerializableAttrs, GitlabEvent):
@property
def event_properties(self) -> Iterable[str]:
return "action",
return ("action",)
@property
def action(self) -> Action:
@ -757,7 +782,7 @@ class GitlabCommentEvent(SerializableAttrs, GitlabEvent):
issue: Optional[GitlabIssue] = None
snippet: Optional[GitlabSnippet] = None
def preprocess(self) -> List['GitlabCommentEvent']:
def preprocess(self) -> List["GitlabCommentEvent"]:
self.user.web_url = f"{self.project.gitlab_base_url}/{self.user.username}"
return [self]
@ -776,7 +801,7 @@ class GitlabMergeRequestEvent(SerializableAttrs, GitlabEvent):
labels: List[GitlabLabel]
changes: GitlabChanges
def preprocess(self) -> List['GitlabMergeRequestEvent']:
def preprocess(self) -> List["GitlabMergeRequestEvent"]:
users_to_mutate = [self.user]
if self.changes and self.changes.assignees:
users_to_mutate += self.changes.assignees.previous
@ -792,7 +817,7 @@ class GitlabMergeRequestEvent(SerializableAttrs, GitlabEvent):
@property
def event_properties(self) -> Iterable[str]:
return "action",
return ("action",)
@property
def action(self) -> Action:
@ -807,7 +832,7 @@ class GitlabWikiPageEvent(SerializableAttrs, GitlabEvent):
wiki: GitlabWiki
object_attributes: GitlabWikiPageAttributes
def preprocess(self) -> List['GitlabWikiPageEvent']:
def preprocess(self) -> List["GitlabWikiPageEvent"]:
self.user.web_url = f"{self.project.gitlab_base_url}/{self.user.username}"
return [self]
@ -862,7 +887,7 @@ class GitlabJobEvent(SerializableAttrs, GitlabEvent):
repository: GitlabRepository
runner: Optional[GitlabRunner]
def preprocess(self) -> List['GitlabJobEvent']:
def preprocess(self) -> List["GitlabJobEvent"]:
base_url = str(URL(self.repository.homepage).with_path(""))
self.user.web_url = f"{base_url}/{self.user.username}"
return [self]
@ -894,20 +919,22 @@ class GitlabJobEvent(SerializableAttrs, GitlabEvent):
@property
def event_properties(self) -> Iterable[str]:
return "build_url",
return ("build_url",)
@property
def build_url(self) -> str:
return f"{self.repository.homepage}/-/jobs/{self.build_id}"
GitlabEventType = Union[Type[GitlabPushEvent],
Type[GitlabIssueEvent],
Type[GitlabCommentEvent],
Type[GitlabMergeRequestEvent],
Type[GitlabWikiPageEvent],
Type[GitlabPipelineEvent],
Type[GitlabJobEvent]]
GitlabEventType = Union[
Type[GitlabPushEvent],
Type[GitlabIssueEvent],
Type[GitlabCommentEvent],
Type[GitlabMergeRequestEvent],
Type[GitlabWikiPageEvent],
Type[GitlabPipelineEvent],
Type[GitlabJobEvent],
]
EventParse: Dict[str, GitlabEventType] = {
"Push Hook": GitlabPushEvent,
@ -919,7 +946,7 @@ EventParse: Dict[str, GitlabEventType] = {
"Merge Request Hook": GitlabMergeRequestEvent,
"Wiki Page Hook": GitlabWikiPageEvent,
"Pipeline Hook": GitlabPipelineEvent,
"Job Hook": GitlabJobEvent
"Job Hook": GitlabJobEvent,
}
OTHER_ENUMS = {