From 207d18e61dae1a0ba03b7a07bb9c1d8737387687 Mon Sep 17 00:00:00 2001 From: BURG3R5 <77491630+BURG3R5@users.noreply.github.com> Date: Fri, 24 Dec 2021 19:40:09 +0530 Subject: [PATCH 1/6] conf: Add linting using Pylint to CI. --- .github/workflows/ci.yml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f917096..e3e0844 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,17 +7,28 @@ jobs: runs-on: ubuntu-latest steps: + # Setup - name: Checkout code uses: actions/checkout@v2 + - name: Set up Python uses: actions/setup-python@v2 with: python-version: "3.10" + - name: Install dependencies run: | python -m pip install --upgrade pip pip install -r requirements.txt - - name: Lint with black + + # Lint + - name: Lint with Black run: | pip install black black --check . + + - name: Lint with Pylint + run: | + pip install pylint + touch __init__.py + pylint `pwd` --fail-under=5 From ce5cbcf80d2eff3bad000bc3d7f4ad7fd4493fd2 Mon Sep 17 00:00:00 2001 From: BURG3R5 <77491630+BURG3R5@users.noreply.github.com> Date: Fri, 24 Dec 2021 19:42:48 +0530 Subject: [PATCH 2/6] conf: Remove githooks. --- .githooks/commit-msg | 16 ---------------- .githooks/pre-commit | 25 ------------------------- README.md | 14 ++++---------- 3 files changed, 4 insertions(+), 51 deletions(-) delete mode 100644 .githooks/commit-msg delete mode 100644 .githooks/pre-commit diff --git a/.githooks/commit-msg b/.githooks/commit-msg deleted file mode 100644 index 5e46509..0000000 --- a/.githooks/commit-msg +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -MSG="$1" - -if ! grep -qE "^(bfix|chor|conf|docs|feat|ptch|rfac): " "$MSG";then - echo "Incorrect commit message." - echo "Start your message with either" - echo " - 'feat: '" - echo " - 'ptch: '" - echo " - 'bfix: '" - echo " - 'rfac: '" - echo " - 'chor: '" - echo " - 'docs: '" - echo " - 'conf: '" - exit 1 -fi diff --git a/.githooks/pre-commit b/.githooks/pre-commit deleted file mode 100644 index 92b1f93..0000000 --- a/.githooks/pre-commit +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - -. venv/Scripts/activate - -# If no changes, exit cleanly. -changed=$(git diff --cached --name-only) -if [[ -z "$changed" ]]; then - exit 0 -fi - -# If merge markers in changelist, throw error. -echo "$changed" | xargs egrep '^[><=]{7}( |$)' -H -I --line-number -if [ $? == 0 ]; then - echo "WARNING: You have merge markers in the above files. Fix them before committing." - exit 1 -fi - -# If wrongly formatted Python files in directory, throw error. -black --check . -if [ $? == 1 ]; then - echo "WARNING: Some Python files in the working directory are not properly formatted." - exit 1 -fi - -deactivate diff --git a/README.md b/README.md index c9ea6b0..77a8294 100644 --- a/README.md +++ b/README.md @@ -54,16 +54,10 @@ $ pip install -r requirements.txt ``` Or, if your system contains both Python 2 and Python 3, use `pip3`. -#### 5. Enable Git hooks - -``` -$ git config --local --add core.hooksPath .githooks -``` - -#### 6. Get the environment variables from another contributor -#### 7. [Download and configure ngrok](https://betterprogramming.pub/ngrok-make-your-localhost-accessible-to-anyone-333b99e44b07) -#### 8. Send your generated URL to MDG org admins -#### 9. Run the bot +#### 5. Get the environment variables from another contributor +#### 6. [Download and configure ngrok](https://betterprogramming.pub/ngrok-make-your-localhost-accessible-to-anyone-333b99e44b07) +#### 7. Send your generated URL to MDG org admins +#### 8. Run the bot ``` $ python main.py From 2f77fd793255003e7ee9f7b1d7a75de29218b318 Mon Sep 17 00:00:00 2001 From: BURG3R5 <77491630+BURG3R5@users.noreply.github.com> Date: Fri, 24 Dec 2021 20:18:57 +0530 Subject: [PATCH 3/6] conf: Add `*.pyc` pattern to `.gitignore`. --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index e9dc610..035836a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .env .idea venv -**__pycache__** +*.pyc +__init__.py From 1432a76ea87405ed4ef4fbea53b8b5e0d39e97d0 Mon Sep 17 00:00:00 2001 From: BURG3R5 <77491630+BURG3R5@users.noreply.github.com> Date: Fri, 24 Dec 2021 23:51:02 +0530 Subject: [PATCH 4/6] rfac: Refactor for code quality. --- .github/workflows/ci.yml | 2 +- github_parsers.py | 1 + main.py | 3 +- models/github.py | 1 + slack_bot.py | 306 +++++++++++++++++++++------------------ utils.py | 3 +- 6 files changed, 171 insertions(+), 145 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e3e0844..0899738 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,4 +31,4 @@ jobs: run: | pip install pylint touch __init__.py - pylint `pwd` --fail-under=5 + pylint `pwd` --fail-under=5 --disable=too-few-public-methods,fixme diff --git a/github_parsers.py b/github_parsers.py index 5959b97..9475b40 100644 --- a/github_parsers.py +++ b/github_parsers.py @@ -37,6 +37,7 @@ def parse(event_type, raw_json) -> GitHubEvent: event_type=event_type, json=json, ) + raise ValueError(f"Undefined event: {raw_json}") # Helper classes: diff --git a/main.py b/main.py index dc7719a..b954299 100644 --- a/main.py +++ b/main.py @@ -30,10 +30,11 @@ def manage_github_events(): @post("/slack/commands") -def manage_slack_commands(): +def manage_slack_commands() -> Optional[dict]: response: Optional[dict] = bot.run(raw_json=request.forms) if response is not None: return response + return None bot: SlackBot = SlackBot() diff --git a/models/github.py b/models/github.py index 3e098f6..6076914 100644 --- a/models/github.py +++ b/models/github.py @@ -71,6 +71,7 @@ def __init__(self, name: str, **kwargs): self.link = kwargs.get("link", f"https://github.com/{name}") +# pylint: disable-next=too-many-instance-attributes class GitHubEvent: def __init__(self, event_type: EventType, repo: Repository, **kwargs): self.type = event_type diff --git a/slack_bot.py b/slack_bot.py index 5438d21..58c19de 100644 --- a/slack_bot.py +++ b/slack_bot.py @@ -1,6 +1,6 @@ import os from pathlib import Path -from typing import Optional +from typing import Optional, Any from bottle import MultiDict from dotenv import load_dotenv @@ -57,12 +57,11 @@ def inform(self, event: GitHubEvent) -> None: def calculate_channels(self, repo: str, event_type: EventType) -> list[str]: if repo not in self.subscriptions: return [] - else: - correct_channels: list[str] = [] - for channel in self.subscriptions[repo]: - if channel.is_subscribed_to(event=event_type): - correct_channels += [channel.name] - return correct_channels + correct_channels: list[str] = [] + for channel in self.subscriptions[repo]: + if channel.is_subscribed_to(event=event_type): + correct_channels += [channel.name] + return correct_channels @staticmethod def compose_message(event: GitHubEvent) -> tuple[str, Optional[str]]: @@ -71,7 +70,10 @@ def compose_message(event: GitHubEvent) -> tuple[str, Optional[str]]: # TODO: Beautify messages. if event.type == EventType.branch_created: - message = f"{event.repo.name}::\tBranch created by {event.user.name}: `{event.branch.name}`." + message = ( + f"{event.repo.name}::\t" + f"Branch created by {event.user.name}: `{event.branch.name}`." + ) elif event.type == EventType.issue_opened: message = ( f"{event.repo.name}::\t" @@ -92,9 +94,17 @@ def compose_message(event: GitHubEvent) -> tuple[str, Optional[str]]: ) elif event.type == EventType.push: if len(event.commits) == 1: - message = f"{event.user.name} pushed to {event.branch.name}, one new commit:\n>{event.commits[0]}" + message = ( + f"{event.user.name} pushed to " + f"{event.branch.name}," + f" one new commit:\n>{event.commits[0]}" + ) else: - message = f"{event.user.name} pushed to {event.branch.name}, {len(event.commits)} new commits:" + message = ( + f"{event.user.name} pushed to " + f"{event.branch.name}, " + f"{len(event.commits)} new commits:" + ) for i, commit in enumerate(event.commits): message += f"\n>{i}. {commit.message}" elif event.type == EventType.review: @@ -125,152 +135,166 @@ def run(self, raw_json: MultiDict) -> Optional[dict]: current_channel: str = "#" + json["channel_name"] command: str = json["command"] args: list[str] = json["text"].split() - repo: Optional[str] = args[0] if len(args) > 0 else None - if command == "/subscribe": - new_events: set[EventType] = { - SlackBot.convert_str_to_event_type(arg) for arg in args[1:] - } - if repo in self.subscriptions: - channels: set[Channel] = self.subscriptions[repo] - channel: Optional[Channel] = None - for subscribed_channel in channels: - if subscribed_channel.name == current_channel: - channel = subscribed_channel - if channel is None: - # If this channel has not subscribed to any events - # from this repo, add a subscription. - channels.add( - Channel( - name=current_channel, - events=new_events, - ) - ) - self.subscriptions[repo] = channels - else: - # If this channel has subscribed to some events - # from this repo, update the list of events. - old_events: set[EventType] = channel.events - self.subscriptions[repo].remove(channel) - self.subscriptions[repo].add( - Channel( - name=current_channel, - events=(old_events.union(new_events)), - ) - ) - else: - # If no one has subscribed to this repo, add a repo entry. - self.subscriptions[repo] = { - Channel( - name=current_channel, - events=new_events, - ) - } - elif command == "/unsubscribe" and repo in self.subscriptions: + if command == "/subscribe" and len(args) > 0: + self.run_subscribe_command(current_channel=current_channel, args=args) + elif command == "/unsubscribe" and len(args) > 0: + self.run_unsubscribe_command(current_channel=current_channel, args=args) + elif command == "/list": + return self.run_list_command(current_channel=current_channel) + elif command == "/help": + return self.run_help_command() + return None + + def run_subscribe_command(self, current_channel: str, args: list[str]): + repo: [str] = args[0] + new_events: set[EventType] = { + SlackBot.convert_str_to_event_type(arg) for arg in args[1:] + } + if repo in self.subscriptions: channels: set[Channel] = self.subscriptions[repo] channel: Optional[Channel] = None for subscribed_channel in channels: if subscribed_channel.name == current_channel: channel = subscribed_channel - if channel is not None: + if channel is None: + # If this channel has not subscribed to any events + # from this repo, add a subscription. + channels.add( + Channel( + name=current_channel, + events=new_events, + ) + ) + self.subscriptions[repo] = channels + else: # If this channel has subscribed to some events # from this repo, update the list of events. - events = channel.events - for arg in args[1:]: - event: EventType = SlackBot.convert_str_to_event_type(arg) - try: - events.remove(event) - except KeyError: - # This means that the user tried to unsubscribe from - # an event that wasn't subscribed to in the first place. - pass + old_events: set[EventType] = channel.events self.subscriptions[repo].remove(channel) - if len(events) != 0: - self.subscriptions[repo].add( - Channel( - name=current_channel, - events=events, - ) + self.subscriptions[repo].add( + Channel( + name=current_channel, + events=(old_events.union(new_events)), ) - elif command == "/list": - blocks: list[dict] = [] - for repo in self.subscriptions.keys(): - channels: set[Channel] = self.subscriptions[repo] - channel: Optional[Channel] = None - for subscribed_channel in channels: - if subscribed_channel.name == current_channel: - channel = subscribed_channel - if channel is None: - continue - events_string = ", ".join(event.name for event in channel.events) - blocks += [ - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": f"*{repo}*\n{events_string}", - }, - }, - { - "type": "divider", - }, - ] - return { - "response_type": "in_channel", - "blocks": blocks, + ) + else: + # If no one has subscribed to this repo, add a repo entry. + self.subscriptions[repo] = { + Channel( + name=current_channel, + events=new_events, + ) } - elif command == "/help": - # TODO: Prettify events section. - return { - "response_type": "ephemeral", - "blocks": [ - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": ( - "*Commands*\n" - "1. `/subscribe [ ...]`\n" - "2. `/unsubsribe [ ...]`\n" - "3. `/list`\n" - "4. `/help`" - ), - }, + + def run_unsubscribe_command(self, current_channel: str, args: list[str]): + repo: [str] = args[0] + channels: set[Channel] = self.subscriptions[repo] + channel: Optional[Channel] = None + for subscribed_channel in channels: + if subscribed_channel.name == current_channel: + channel = subscribed_channel + if channel is not None: + # If this channel has subscribed to some events + # from this repo, update the list of events. + events = channel.events + for arg in args[1:]: + event: EventType = SlackBot.convert_str_to_event_type(arg) + try: + events.remove(event) + except KeyError: + # This means that the user tried to unsubscribe from + # an event that wasn't subscribed to in the first place. + pass + self.subscriptions[repo].remove(channel) + if len(events) != 0: + self.subscriptions[repo].add( + Channel( + name=current_channel, + events=events, + ) + ) + + def run_list_command(self, current_channel: str) -> dict[str, Any]: + blocks: list[dict] = [] + for repo, channels in self.subscriptions.items(): + channel: Optional[Channel] = None + for subscribed_channel in channels: + if subscribed_channel.name == current_channel: + channel = subscribed_channel + if channel is None: + continue + events_string = ", ".join(event.name for event in channel.events) + blocks += [ + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": f"*{repo}*\n{events_string}", }, - {"type": "divider"}, - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": ( - "*Events*\n" - "GitHub events are abbreviated as follows:\n" - "1. `bc`: branch_created\n" - "2. `bd`: branch_deleted\n" - "3. `tc`: tag_created\n" - "4. `td`: tag_deleted\n" - "5. `prc`: pull_closed\n" - "6. `prm`: pull_merged\n" - "7. `pro`: pull_opened\n" - "8. `prr`: pull_ready\n" - "9. `io`: issue_opened\n" - "10. `ic`: issue_closed\n" - "11. `rv`: review\n" - "12. `rc`: review_comment\n" - "13. `cc`: commit_comment\n" - "14. `fk`: fork\n" - "15. `p`: push\n" - "16. `rl`: release\n" - "17. `sa`: star_added\n" - "18. `sr`: star_removed\n" - ), - }, + }, + { + "type": "divider", + }, + ] + return { + "response_type": "in_channel", + "blocks": blocks, + } + + @staticmethod + def run_help_command() -> dict[str, Any]: + # TODO: Prettify events section. + return { + "response_type": "ephemeral", + "blocks": [ + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": ( + "*Commands*\n" + "1. `/subscribe [ ...]`\n" + "2. `/unsubsribe [ ...]`\n" + "3. `/list`\n" + "4. `/help`" + ), }, - ], - } - return + }, + {"type": "divider"}, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": ( + "*Events*\n" + "GitHub events are abbreviated as follows:\n" + "1. `bc`: branch_created\n" + "2. `bd`: branch_deleted\n" + "3. `tc`: tag_created\n" + "4. `td`: tag_deleted\n" + "5. `prc`: pull_closed\n" + "6. `prm`: pull_merged\n" + "7. `pro`: pull_opened\n" + "8. `prr`: pull_ready\n" + "9. `io`: issue_opened\n" + "10. `ic`: issue_closed\n" + "11. `rv`: review\n" + "12. `rc`: review_comment\n" + "13. `cc`: commit_comment\n" + "14. `fk`: fork\n" + "15. `p`: push\n" + "16. `rl`: release\n" + "17. `sa`: star_added\n" + "18. `sr`: star_removed\n" + ), + }, + }, + ], + } @staticmethod def convert_str_to_event_type(event_name: str) -> EventType: for event_type in EventType: if event_type.value == event_name: return event_type + raise ValueError("Event not in enum") diff --git a/utils.py b/utils.py index 209827b..c170e1d 100644 --- a/utils.py +++ b/utils.py @@ -29,8 +29,7 @@ def get(k): for key in keys: if key in self.data: return get(key) - else: - return keys[0].upper() + return keys[0].upper() @staticmethod def from_multi_dict(multi_dict: MultiDict): From 91b9e208b0bb7100ddd544b1c4ca855c32001bb8 Mon Sep 17 00:00:00 2001 From: BURG3R5 <77491630+BURG3R5@users.noreply.github.com> Date: Thu, 10 Feb 2022 13:44:05 +0530 Subject: [PATCH 5/6] chor: Remove unnecessary `raise`s and simplify loops. --- github_parsers.py | 7 ++++--- main.py | 5 +++-- slack_bot.py | 45 ++++++++++++++++++++++++++++++--------------- 3 files changed, 37 insertions(+), 20 deletions(-) diff --git a/github_parsers.py b/github_parsers.py index 9475b40..b3514e0 100644 --- a/github_parsers.py +++ b/github_parsers.py @@ -1,5 +1,5 @@ from abc import ABC, abstractmethod -from typing import Type +from typing import Type, Optional from models.github import Commit, EventType, GitHubEvent, Ref, User, Repository from models.link import Link @@ -8,7 +8,7 @@ class GitHubPayloadParser: @staticmethod - def parse(event_type, raw_json) -> GitHubEvent: + def parse(event_type, raw_json) -> Optional[GitHubEvent]: json: JSON = JSON(raw_json) event_parsers: list[Type[EventParser]] = [ BranchCreateEventParser, @@ -37,7 +37,8 @@ def parse(event_type, raw_json) -> GitHubEvent: event_type=event_type, json=json, ) - raise ValueError(f"Undefined event: {raw_json}") + print(f"Undefined event: {raw_json}") + return None # Helper classes: diff --git a/main.py b/main.py index b954299..ce73896 100644 --- a/main.py +++ b/main.py @@ -22,11 +22,12 @@ def test_post(): @post("/github/events") def manage_github_events(): - event: GitHubEvent = GitHubPayloadParser.parse( + event: Optional[GitHubEvent] = GitHubPayloadParser.parse( event_type=request.headers["X-GitHub-Event"], raw_json=request.json, ) - bot.inform(event) + if event is not None: + bot.inform(event) @post("/slack/commands") diff --git a/slack_bot.py b/slack_bot.py index 58c19de..9454cab 100644 --- a/slack_bot.py +++ b/slack_bot.py @@ -150,12 +150,18 @@ def run_subscribe_command(self, current_channel: str, args: list[str]): new_events: set[EventType] = { SlackBot.convert_str_to_event_type(arg) for arg in args[1:] } + # Remove all the entries which do not correspond to a correct [EventType]. + new_events -= [None] if repo in self.subscriptions: channels: set[Channel] = self.subscriptions[repo] - channel: Optional[Channel] = None - for subscribed_channel in channels: - if subscribed_channel.name == current_channel: - channel = subscribed_channel + channel: Optional[Channel] = next( + ( + subscribed_channel + for subscribed_channel in channels + if subscribed_channel.name == current_channel + ), + None, + ) if channel is None: # If this channel has not subscribed to any events # from this repo, add a subscription. @@ -189,16 +195,20 @@ def run_subscribe_command(self, current_channel: str, args: list[str]): def run_unsubscribe_command(self, current_channel: str, args: list[str]): repo: [str] = args[0] channels: set[Channel] = self.subscriptions[repo] - channel: Optional[Channel] = None - for subscribed_channel in channels: - if subscribed_channel.name == current_channel: - channel = subscribed_channel + channel: Optional[Channel] = next( + ( + subscribed_channel + for subscribed_channel in channels + if subscribed_channel.name == current_channel + ), + None, + ) if channel is not None: # If this channel has subscribed to some events # from this repo, update the list of events. events = channel.events for arg in args[1:]: - event: EventType = SlackBot.convert_str_to_event_type(arg) + event: Optional[EventType] = SlackBot.convert_str_to_event_type(arg) try: events.remove(event) except KeyError: @@ -217,10 +227,14 @@ def run_unsubscribe_command(self, current_channel: str, args: list[str]): def run_list_command(self, current_channel: str) -> dict[str, Any]: blocks: list[dict] = [] for repo, channels in self.subscriptions.items(): - channel: Optional[Channel] = None - for subscribed_channel in channels: - if subscribed_channel.name == current_channel: - channel = subscribed_channel + channel: Optional[Channel] = next( + ( + subscribed_channel + for subscribed_channel in channels + if subscribed_channel.name == current_channel + ), + None, + ) if channel is None: continue events_string = ", ".join(event.name for event in channel.events) @@ -293,8 +307,9 @@ def run_help_command() -> dict[str, Any]: } @staticmethod - def convert_str_to_event_type(event_name: str) -> EventType: + def convert_str_to_event_type(event_name: str) -> Optional[EventType]: for event_type in EventType: if event_type.value == event_name: return event_type - raise ValueError("Event not in enum") + print("Event not in enum") + return None From a33600e296e667969da333928692d5fff9f1b125 Mon Sep 17 00:00:00 2001 From: BURG3R5 <77491630+BURG3R5@users.noreply.github.com> Date: Sat, 19 Feb 2022 11:01:20 +0530 Subject: [PATCH 6/6] chor: Replace `Optional` typing with `|`-based typing. --- github_parsers.py | 4 ++-- main.py | 12 ++++-------- models/github.py | 30 +++++++++++++++--------------- models/link.py | 5 +---- slack_bot.py | 20 ++++++++++---------- 5 files changed, 32 insertions(+), 39 deletions(-) diff --git a/github_parsers.py b/github_parsers.py index b3514e0..9bdbde3 100644 --- a/github_parsers.py +++ b/github_parsers.py @@ -1,5 +1,5 @@ from abc import ABC, abstractmethod -from typing import Type, Optional +from typing import Type from models.github import Commit, EventType, GitHubEvent, Ref, User, Repository from models.link import Link @@ -8,7 +8,7 @@ class GitHubPayloadParser: @staticmethod - def parse(event_type, raw_json) -> Optional[GitHubEvent]: + def parse(event_type, raw_json) -> GitHubEvent | None: json: JSON = JSON(raw_json) event_parsers: list[Type[EventParser]] = [ BranchCreateEventParser, diff --git a/main.py b/main.py index ce73896..92ee37d 100644 --- a/main.py +++ b/main.py @@ -1,5 +1,3 @@ -from typing import Optional - from bottle import post, run, request, get from github_parsers import GitHubPayloadParser @@ -22,7 +20,7 @@ def test_post(): @post("/github/events") def manage_github_events(): - event: Optional[GitHubEvent] = GitHubPayloadParser.parse( + event: GitHubEvent | None = GitHubPayloadParser.parse( event_type=request.headers["X-GitHub-Event"], raw_json=request.json, ) @@ -31,11 +29,9 @@ def manage_github_events(): @post("/slack/commands") -def manage_slack_commands() -> Optional[dict]: - response: Optional[dict] = bot.run(raw_json=request.forms) - if response is not None: - return response - return None +def manage_slack_commands() -> dict | None: + response: dict | None = bot.run(raw_json=request.forms) + return response bot: SlackBot = SlackBot() diff --git a/models/github.py b/models/github.py index 6076914..f090556 100644 --- a/models/github.py +++ b/models/github.py @@ -1,5 +1,5 @@ import enum -from typing import Optional, Literal +from typing import Literal from models.link import Link @@ -7,9 +7,9 @@ class Commit: def __init__( self, - message: Optional[str] = None, - sha: Optional[str] = None, - link: Optional[str] = None, + message: str | None = None, + sha: str | None = None, + link: str | None = None, ): self.message = message self.sha = sha @@ -55,14 +55,14 @@ def __init__( **kwargs, ): self.name = name - self.link: Optional[str] = kwargs.get("link", None) + self.link: str | None = kwargs.get("link", None) self.type = ref_type class Repository: def __init__(self, name: str, **kwargs): self.name = name - self.link: Optional[str] = kwargs.get("link", None) + self.link: str | None = kwargs.get("link", None) class User: @@ -77,16 +77,16 @@ def __init__(self, event_type: EventType, repo: Repository, **kwargs): self.type = event_type self.repo = repo - self.number: Optional[int] = kwargs.get("number", None) + self.number: int | None = kwargs.get("number", None) - self.status: Optional[str] = kwargs.get("status", None) - self.title: Optional[str] = kwargs.get("title", None) + self.status: str | None = kwargs.get("status", None) + self.title: str | None = kwargs.get("title", None) - self.branch: Optional[Ref] = kwargs.get("branch", None) - self.user: Optional[User] = kwargs.get("user", None) + self.branch: Ref | None = kwargs.get("branch", None) + self.user: User | None = kwargs.get("user", None) - self.comments: Optional[list[str]] = kwargs.get("comments", None) + self.comments: list[str] | None = kwargs.get("comments", None) - self.commits: Optional[list[Commit]] = kwargs.get("commits", None) - self.links: Optional[list[Link]] = kwargs.get("links", None) - self.reviewers: Optional[list[User]] = kwargs.get("reviewers", None) + self.commits: list[Commit] | None = kwargs.get("commits", None) + self.links: list[Link] | None = kwargs.get("links", None) + self.reviewers: list[User] | None = kwargs.get("reviewers", None) diff --git a/models/link.py b/models/link.py index 28923e5..401431c 100644 --- a/models/link.py +++ b/models/link.py @@ -1,8 +1,5 @@ -from typing import Optional - - class Link: - def __init__(self, url: Optional[str] = None, text: Optional[str] = None): + def __init__(self, url: str | None = None, text: str | None = None): self.url = url self.text = text diff --git a/slack_bot.py b/slack_bot.py index 9454cab..b65ada9 100644 --- a/slack_bot.py +++ b/slack_bot.py @@ -1,6 +1,6 @@ import os from pathlib import Path -from typing import Optional, Any +from typing import Any from bottle import MultiDict from dotenv import load_dotenv @@ -64,9 +64,9 @@ def calculate_channels(self, repo: str, event_type: EventType) -> list[str]: return correct_channels @staticmethod - def compose_message(event: GitHubEvent) -> tuple[str, Optional[str]]: + def compose_message(event: GitHubEvent) -> tuple[str, str | None]: message: str = "" - details: Optional[str] = None + details: str | None = None # TODO: Beautify messages. if event.type == EventType.branch_created: @@ -116,7 +116,7 @@ def compose_message(event: GitHubEvent) -> tuple[str, Optional[str]]: return message, details - def send_message(self, channel: str, message: str, details: Optional[str]) -> None: + def send_message(self, channel: str, message: str, details: str | None) -> None: if details is None: print(f"Sending {message} to {channel}") self.client.chat_postMessage(channel=channel, text=message) @@ -130,7 +130,7 @@ def send_message(self, channel: str, message: str, details: Optional[str]) -> No ) # Slash commands related methods - def run(self, raw_json: MultiDict) -> Optional[dict]: + def run(self, raw_json: MultiDict) -> str | None: json: JSON = JSON.from_multi_dict(raw_json) current_channel: str = "#" + json["channel_name"] command: str = json["command"] @@ -154,7 +154,7 @@ def run_subscribe_command(self, current_channel: str, args: list[str]): new_events -= [None] if repo in self.subscriptions: channels: set[Channel] = self.subscriptions[repo] - channel: Optional[Channel] = next( + channel: Channel | None = next( ( subscribed_channel for subscribed_channel in channels @@ -195,7 +195,7 @@ def run_subscribe_command(self, current_channel: str, args: list[str]): def run_unsubscribe_command(self, current_channel: str, args: list[str]): repo: [str] = args[0] channels: set[Channel] = self.subscriptions[repo] - channel: Optional[Channel] = next( + channel: Channel | None = next( ( subscribed_channel for subscribed_channel in channels @@ -208,7 +208,7 @@ def run_unsubscribe_command(self, current_channel: str, args: list[str]): # from this repo, update the list of events. events = channel.events for arg in args[1:]: - event: Optional[EventType] = SlackBot.convert_str_to_event_type(arg) + event: EventType | None = SlackBot.convert_str_to_event_type(arg) try: events.remove(event) except KeyError: @@ -227,7 +227,7 @@ def run_unsubscribe_command(self, current_channel: str, args: list[str]): def run_list_command(self, current_channel: str) -> dict[str, Any]: blocks: list[dict] = [] for repo, channels in self.subscriptions.items(): - channel: Optional[Channel] = next( + channel: Channel | None = next( ( subscribed_channel for subscribed_channel in channels @@ -307,7 +307,7 @@ def run_help_command() -> dict[str, Any]: } @staticmethod - def convert_str_to_event_type(event_name: str) -> Optional[EventType]: + def convert_str_to_event_type(event_name: str) -> EventType | None: for event_type in EventType: if event_type.value == event_name: return event_type