2019-04-19 22:02:41 +02:00
|
|
|
import string
|
2017-04-05 09:12:19 +02:00
|
|
|
from collections import defaultdict
|
2020-06-11 00:54:34 +02:00
|
|
|
from typing import Any, Dict, List, Optional, Tuple
|
|
|
|
|
2021-02-12 08:20:45 +01:00
|
|
|
TOPIC_WITH_BRANCH_TEMPLATE = "{repo} / {branch}"
|
|
|
|
TOPIC_WITH_PR_OR_ISSUE_INFO_TEMPLATE = "{repo} / {type} #{id} {title}"
|
|
|
|
TOPIC_WITH_RELEASE_TEMPLATE = "{repo} / {tag} {title}"
|
2016-10-05 19:21:47 +02:00
|
|
|
|
2021-02-12 08:20:45 +01:00
|
|
|
EMPTY_SHA = "0000000000000000000000000000000000000000"
|
2016-10-06 17:13:22 +02:00
|
|
|
|
2017-03-09 21:25:21 +01:00
|
|
|
COMMITS_LIMIT = 20
|
2021-02-12 08:20:45 +01:00
|
|
|
COMMIT_ROW_TEMPLATE = "* {commit_msg} ([{commit_short_sha}]({commit_url}))\n"
|
2017-11-04 05:34:38 +01:00
|
|
|
COMMITS_MORE_THAN_LIMIT_TEMPLATE = "[and {commits_number} more commit(s)]"
|
|
|
|
COMMIT_OR_COMMITS = "commit{}"
|
2016-10-12 23:27:24 +02:00
|
|
|
|
2023-05-04 17:12:59 +02:00
|
|
|
PUSH_PUSHED_TEXT_WITH_URL = "[{push_type}]({compare_url}) {number_of_commits} {commit_or_commits}"
|
|
|
|
PUSH_PUSHED_TEXT_WITHOUT_URL = "{push_type} {number_of_commits} {commit_or_commits}"
|
2017-10-27 02:47:30 +02:00
|
|
|
|
2021-02-12 08:20:45 +01:00
|
|
|
PUSH_COMMITS_BASE = "{user_name} {pushed_text} to branch {branch_name}."
|
2021-02-12 08:19:30 +01:00
|
|
|
PUSH_COMMITS_MESSAGE_TEMPLATE_WITH_COMMITTERS = (
|
|
|
|
PUSH_COMMITS_BASE
|
|
|
|
+ """ {committers_details}.
|
2017-04-26 02:57:47 +02:00
|
|
|
|
|
|
|
{commits_data}
|
|
|
|
"""
|
2021-02-12 08:19:30 +01:00
|
|
|
)
|
|
|
|
PUSH_COMMITS_MESSAGE_TEMPLATE_WITHOUT_COMMITTERS = (
|
|
|
|
PUSH_COMMITS_BASE
|
|
|
|
+ """
|
2016-09-26 16:32:35 +02:00
|
|
|
|
2016-10-12 23:38:49 +02:00
|
|
|
{commits_data}
|
2016-09-26 16:32:35 +02:00
|
|
|
"""
|
2021-02-12 08:19:30 +01:00
|
|
|
)
|
|
|
|
PUSH_DELETE_BRANCH_MESSAGE_TEMPLATE = (
|
|
|
|
"{user_name} [deleted]({compare_url}) the branch {branch_name}."
|
|
|
|
)
|
|
|
|
PUSH_LOCAL_BRANCH_WITHOUT_COMMITS_MESSAGE_TEMPLATE = (
|
2023-05-04 17:12:59 +02:00
|
|
|
"{user_name} [{push_type}]({compare_url}) the branch {branch_name}."
|
2021-02-12 08:19:30 +01:00
|
|
|
)
|
2022-07-09 12:23:36 +02:00
|
|
|
PUSH_LOCAL_BRANCH_WITHOUT_COMMITS_MESSAGE_WITHOUT_URL_TEMPLATE = (
|
2023-05-04 17:12:59 +02:00
|
|
|
"{user_name} {push_type} the branch {branch_name}."
|
2022-07-09 12:23:36 +02:00
|
|
|
)
|
2017-11-04 05:34:38 +01:00
|
|
|
PUSH_COMMITS_MESSAGE_EXTENSION = "Commits by {}"
|
2017-04-05 09:12:19 +02:00
|
|
|
PUSH_COMMITTERS_LIMIT_INFO = 3
|
2016-09-26 16:32:35 +02:00
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
FORCE_PUSH_COMMITS_MESSAGE_TEMPLATE = (
|
|
|
|
"{user_name} [force pushed]({url}) to branch {branch_name}. Head is now {head}."
|
|
|
|
)
|
2019-05-07 02:51:27 +02:00
|
|
|
CREATE_BRANCH_MESSAGE_TEMPLATE = "{user_name} created [{branch_name}]({url}) branch."
|
|
|
|
CREATE_BRANCH_WITHOUT_URL_MESSAGE_TEMPLATE = "{user_name} created {branch_name} branch."
|
2019-04-19 22:02:41 +02:00
|
|
|
REMOVE_BRANCH_MESSAGE_TEMPLATE = "{user_name} deleted branch {branch_name}."
|
2016-10-05 20:36:17 +02:00
|
|
|
|
2023-06-29 12:24:27 +02:00
|
|
|
ISSUE_LABELED_OR_UNLABELED_MESSAGE_TEMPLATE = (
|
|
|
|
"[{user_name}]({user_url}) {action} the {label_name} label {preposition} [Issue #{id}]({url})."
|
|
|
|
)
|
|
|
|
ISSUE_LABELED_OR_UNLABELED_MESSAGE_TEMPLATE_WITH_TITLE = "[{user_name}]({user_url}) {action} the {label_name} label {preposition} [Issue #{id} {title}]({url})."
|
2023-06-02 22:22:01 +02:00
|
|
|
|
2023-06-13 15:48:40 +02:00
|
|
|
ISSUE_MILESTONED_OR_DEMILESTONED_MESSAGE_TEMPLATE = "[{user_name}]({user_url}) {action} milestone [{milestone_name}]({milestone_url}) {preposition} [issue #{id}]({url})."
|
|
|
|
ISSUE_MILESTONED_OR_DEMILESTONED_MESSAGE_TEMPLATE_WITH_TITLE = "[{user_name}]({user_url}) {action} milestone [{milestone_name}]({milestone_url}) {preposition} [issue #{id} {title}]({url})."
|
|
|
|
|
2017-11-04 05:34:38 +01:00
|
|
|
PULL_REQUEST_OR_ISSUE_MESSAGE_TEMPLATE = "{user_name} {action} [{type}{id}]({url})"
|
2021-02-12 08:19:30 +01:00
|
|
|
PULL_REQUEST_OR_ISSUE_MESSAGE_TEMPLATE_WITH_TITLE = (
|
|
|
|
"{user_name} {action} [{type}{id} {title}]({url})"
|
|
|
|
)
|
2017-11-04 05:34:38 +01:00
|
|
|
PULL_REQUEST_OR_ISSUE_ASSIGNEE_INFO_TEMPLATE = "(assigned to {assignee})"
|
2023-03-29 08:05:23 +02:00
|
|
|
PULL_REQUEST_REVIEWER_INFO_TEMPLATE = "(assigned reviewers: {reviewer})"
|
2019-04-19 22:02:41 +02:00
|
|
|
PULL_REQUEST_BRANCH_INFO_TEMPLATE = "from `{target}` to `{base}`"
|
2016-10-27 21:43:15 +02:00
|
|
|
|
2017-11-04 05:34:38 +01:00
|
|
|
CONTENT_MESSAGE_TEMPLATE = "\n~~~ quote\n{message}\n~~~"
|
2016-10-27 21:43:15 +02:00
|
|
|
|
2017-11-04 05:34:38 +01:00
|
|
|
COMMITS_COMMENT_MESSAGE_TEMPLATE = "{user_name} {action} on [{sha}]({url})"
|
2016-10-11 18:53:20 +02:00
|
|
|
|
2017-11-04 05:34:38 +01:00
|
|
|
PUSH_TAGS_MESSAGE_TEMPLATE = """{user_name} {action} tag {tag}"""
|
|
|
|
TAG_WITH_URL_TEMPLATE = "[{tag_name}]({tag_url})"
|
|
|
|
TAG_WITHOUT_URL_TEMPLATE = "{tag_name}"
|
2016-11-08 22:12:22 +01:00
|
|
|
|
2020-05-11 08:58:53 +02:00
|
|
|
RELEASE_MESSAGE_TEMPLATE = "{user_name} {action} release [{release_name}]({url}) for tag {tagname}."
|
2017-04-05 09:12:19 +02:00
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2023-03-29 08:05:23 +02:00
|
|
|
def get_assignee_string(assignees: List[Dict[str, Any]]) -> str:
|
|
|
|
assignees_string = ""
|
|
|
|
if len(assignees) == 1:
|
|
|
|
assignees_string = "{username}".format(**assignees[0])
|
|
|
|
else:
|
2023-07-31 22:52:35 +02:00
|
|
|
usernames = [a["username"] for a in assignees]
|
2023-03-29 08:05:23 +02:00
|
|
|
|
|
|
|
assignees_string = ", ".join(usernames[:-1]) + " and " + usernames[-1]
|
|
|
|
return assignees_string
|
|
|
|
|
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
def get_push_commits_event_message(
|
|
|
|
user_name: str,
|
|
|
|
compare_url: Optional[str],
|
|
|
|
branch_name: str,
|
|
|
|
commits_data: List[Dict[str, Any]],
|
|
|
|
is_truncated: bool = False,
|
|
|
|
deleted: bool = False,
|
2023-05-04 17:12:59 +02:00
|
|
|
force_push: Optional[bool] = False,
|
2021-02-12 08:19:30 +01:00
|
|
|
) -> str:
|
2017-05-16 04:38:25 +02:00
|
|
|
if not commits_data and deleted:
|
|
|
|
return PUSH_DELETE_BRANCH_MESSAGE_TEMPLATE.format(
|
|
|
|
user_name=user_name,
|
|
|
|
compare_url=compare_url,
|
python: Use trailing commas consistently.
Automatically generated by the following script, based on the output
of lint with flake8-comma:
import re
import sys
last_filename = None
last_row = None
lines = []
for msg in sys.stdin:
m = re.match(
r"\x1b\[35mflake8 \|\x1b\[0m \x1b\[1;31m(.+):(\d+):(\d+): (\w+)", msg
)
if m:
filename, row_str, col_str, err = m.groups()
row, col = int(row_str), int(col_str)
if filename == last_filename:
assert last_row != row
else:
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
with open(filename) as f:
lines = f.readlines()
last_filename = filename
last_row = row
line = lines[row - 1]
if err in ["C812", "C815"]:
lines[row - 1] = line[: col - 1] + "," + line[col - 1 :]
elif err in ["C819"]:
assert line[col - 2] == ","
lines[row - 1] = line[: col - 2] + line[col - 1 :].lstrip(" ")
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-04-10 05:23:40 +02:00
|
|
|
branch_name=branch_name,
|
2017-05-16 04:38:25 +02:00
|
|
|
)
|
|
|
|
|
2023-05-04 17:12:59 +02:00
|
|
|
push_type = "force pushed" if force_push else "pushed"
|
2017-05-17 02:19:33 +02:00
|
|
|
if not commits_data and not deleted:
|
2022-07-09 12:23:36 +02:00
|
|
|
if compare_url:
|
|
|
|
return PUSH_LOCAL_BRANCH_WITHOUT_COMMITS_MESSAGE_TEMPLATE.format(
|
2023-05-04 17:12:59 +02:00
|
|
|
push_type=push_type,
|
2022-07-09 12:23:36 +02:00
|
|
|
user_name=user_name,
|
|
|
|
compare_url=compare_url,
|
|
|
|
branch_name=branch_name,
|
|
|
|
)
|
|
|
|
return PUSH_LOCAL_BRANCH_WITHOUT_COMMITS_MESSAGE_WITHOUT_URL_TEMPLATE.format(
|
2023-05-04 17:12:59 +02:00
|
|
|
push_type=push_type,
|
2017-05-17 02:19:33 +02:00
|
|
|
user_name=user_name,
|
python: Use trailing commas consistently.
Automatically generated by the following script, based on the output
of lint with flake8-comma:
import re
import sys
last_filename = None
last_row = None
lines = []
for msg in sys.stdin:
m = re.match(
r"\x1b\[35mflake8 \|\x1b\[0m \x1b\[1;31m(.+):(\d+):(\d+): (\w+)", msg
)
if m:
filename, row_str, col_str, err = m.groups()
row, col = int(row_str), int(col_str)
if filename == last_filename:
assert last_row != row
else:
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
with open(filename) as f:
lines = f.readlines()
last_filename = filename
last_row = row
line = lines[row - 1]
if err in ["C812", "C815"]:
lines[row - 1] = line[: col - 1] + "," + line[col - 1 :]
elif err in ["C819"]:
assert line[col - 2] == ","
lines[row - 1] = line[: col - 2] + line[col - 1 :].lstrip(" ")
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-04-10 05:23:40 +02:00
|
|
|
branch_name=branch_name,
|
2017-05-17 02:19:33 +02:00
|
|
|
)
|
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
pushed_message_template = (
|
|
|
|
PUSH_PUSHED_TEXT_WITH_URL if compare_url else PUSH_PUSHED_TEXT_WITHOUT_URL
|
|
|
|
)
|
2017-04-05 09:12:19 +02:00
|
|
|
|
|
|
|
pushed_text_message = pushed_message_template.format(
|
2023-05-04 17:12:59 +02:00
|
|
|
push_type=push_type,
|
2017-04-05 09:12:19 +02:00
|
|
|
compare_url=compare_url,
|
|
|
|
number_of_commits=len(commits_data),
|
2021-02-12 08:20:45 +01:00
|
|
|
commit_or_commits=COMMIT_OR_COMMITS.format("s" if len(commits_data) > 1 else ""),
|
2021-02-12 08:19:30 +01:00
|
|
|
)
|
2016-09-26 16:32:35 +02:00
|
|
|
|
python: Convert assignment type annotations to Python 3.6 style.
This commit was split by tabbott; this piece covers the vast majority
of files in Zulip, but excludes scripts/, tools/, and puppet/ to help
ensure we at least show the right error messages for Xenial systems.
We can likely further refine the remaining pieces with some testing.
Generated by com2ann, with whitespace fixes and various manual fixes
for runtime issues:
- invoiced_through: Optional[LicenseLedger] = models.ForeignKey(
+ invoiced_through: Optional["LicenseLedger"] = models.ForeignKey(
-_apns_client: Optional[APNsClient] = None
+_apns_client: Optional["APNsClient"] = None
- notifications_stream: Optional[Stream] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
- signup_notifications_stream: Optional[Stream] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
+ notifications_stream: Optional["Stream"] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
+ signup_notifications_stream: Optional["Stream"] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
- author: Optional[UserProfile] = models.ForeignKey('UserProfile', blank=True, null=True, on_delete=CASCADE)
+ author: Optional["UserProfile"] = models.ForeignKey('UserProfile', blank=True, null=True, on_delete=CASCADE)
- bot_owner: Optional[UserProfile] = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
+ bot_owner: Optional["UserProfile"] = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
- default_sending_stream: Optional[Stream] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
- default_events_register_stream: Optional[Stream] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
+ default_sending_stream: Optional["Stream"] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
+ default_events_register_stream: Optional["Stream"] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
-descriptors_by_handler_id: Dict[int, ClientDescriptor] = {}
+descriptors_by_handler_id: Dict[int, "ClientDescriptor"] = {}
-worker_classes: Dict[str, Type[QueueProcessingWorker]] = {}
-queues: Dict[str, Dict[str, Type[QueueProcessingWorker]]] = {}
+worker_classes: Dict[str, Type["QueueProcessingWorker"]] = {}
+queues: Dict[str, Dict[str, Type["QueueProcessingWorker"]]] = {}
-AUTH_LDAP_REVERSE_EMAIL_SEARCH: Optional[LDAPSearch] = None
+AUTH_LDAP_REVERSE_EMAIL_SEARCH: Optional["LDAPSearch"] = None
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-04-22 01:09:50 +02:00
|
|
|
committers_items: List[Tuple[str, int]] = get_all_committers(commits_data)
|
2017-04-26 02:57:47 +02:00
|
|
|
if len(committers_items) == 1 and user_name == committers_items[0][0]:
|
|
|
|
return PUSH_COMMITS_MESSAGE_TEMPLATE_WITHOUT_COMMITTERS.format(
|
|
|
|
user_name=user_name,
|
|
|
|
pushed_text=pushed_text_message,
|
|
|
|
branch_name=branch_name,
|
|
|
|
commits_data=get_commits_content(commits_data, is_truncated),
|
|
|
|
).rstrip()
|
|
|
|
else:
|
|
|
|
committers_details = "{} ({})".format(*committers_items[0])
|
|
|
|
|
|
|
|
for name, number_of_commits in committers_items[1:-1]:
|
2020-06-09 00:25:09 +02:00
|
|
|
committers_details = f"{committers_details}, {name} ({number_of_commits})"
|
2017-04-26 02:57:47 +02:00
|
|
|
|
|
|
|
if len(committers_items) > 1:
|
|
|
|
committers_details = "{} and {} ({})".format(committers_details, *committers_items[-1])
|
|
|
|
|
|
|
|
return PUSH_COMMITS_MESSAGE_TEMPLATE_WITH_COMMITTERS.format(
|
|
|
|
user_name=user_name,
|
|
|
|
pushed_text=pushed_text_message,
|
|
|
|
branch_name=branch_name,
|
|
|
|
committers_details=PUSH_COMMITS_MESSAGE_EXTENSION.format(committers_details),
|
|
|
|
commits_data=get_commits_content(commits_data, is_truncated),
|
|
|
|
).rstrip()
|
2016-10-05 20:36:17 +02:00
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
|
|
|
def get_force_push_commits_event_message(
|
|
|
|
user_name: str, url: str, branch_name: str, head: str
|
|
|
|
) -> str:
|
2016-10-05 20:36:17 +02:00
|
|
|
return FORCE_PUSH_COMMITS_MESSAGE_TEMPLATE.format(
|
|
|
|
user_name=user_name,
|
|
|
|
url=url,
|
|
|
|
branch_name=branch_name,
|
python: Use trailing commas consistently.
Automatically generated by the following script, based on the output
of lint with flake8-comma:
import re
import sys
last_filename = None
last_row = None
lines = []
for msg in sys.stdin:
m = re.match(
r"\x1b\[35mflake8 \|\x1b\[0m \x1b\[1;31m(.+):(\d+):(\d+): (\w+)", msg
)
if m:
filename, row_str, col_str, err = m.groups()
row, col = int(row_str), int(col_str)
if filename == last_filename:
assert last_row != row
else:
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
with open(filename) as f:
lines = f.readlines()
last_filename = filename
last_row = row
line = lines[row - 1]
if err in ["C812", "C815"]:
lines[row - 1] = line[: col - 1] + "," + line[col - 1 :]
elif err in ["C819"]:
assert line[col - 2] == ","
lines[row - 1] = line[: col - 2] + line[col - 1 :].lstrip(" ")
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-04-10 05:23:40 +02:00
|
|
|
head=head,
|
2016-10-05 20:36:17 +02:00
|
|
|
)
|
2016-10-06 15:26:47 +02:00
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2019-03-03 17:44:33 +01:00
|
|
|
def get_create_branch_event_message(user_name: str, url: Optional[str], branch_name: str) -> str:
|
|
|
|
if url is None:
|
|
|
|
return CREATE_BRANCH_WITHOUT_URL_MESSAGE_TEMPLATE.format(
|
|
|
|
user_name=user_name,
|
|
|
|
branch_name=branch_name,
|
|
|
|
)
|
2017-03-16 08:28:13 +01:00
|
|
|
return CREATE_BRANCH_MESSAGE_TEMPLATE.format(
|
|
|
|
user_name=user_name,
|
|
|
|
url=url,
|
|
|
|
branch_name=branch_name,
|
|
|
|
)
|
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2018-05-10 19:13:36 +02:00
|
|
|
def get_remove_branch_event_message(user_name: str, branch_name: str) -> str:
|
2016-10-06 15:26:47 +02:00
|
|
|
return REMOVE_BRANCH_MESSAGE_TEMPLATE.format(
|
|
|
|
user_name=user_name,
|
|
|
|
branch_name=branch_name,
|
|
|
|
)
|
2016-10-11 18:53:20 +02:00
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
|
|
|
def get_pull_request_event_message(
|
2023-03-16 00:52:45 +01:00
|
|
|
*,
|
2021-02-12 08:19:30 +01:00
|
|
|
user_name: str,
|
|
|
|
action: str,
|
|
|
|
url: str,
|
|
|
|
number: Optional[int] = None,
|
|
|
|
target_branch: Optional[str] = None,
|
|
|
|
base_branch: Optional[str] = None,
|
|
|
|
message: Optional[str] = None,
|
|
|
|
assignee: Optional[str] = None,
|
|
|
|
assignees: Optional[List[Dict[str, Any]]] = None,
|
2023-03-29 08:05:23 +02:00
|
|
|
reviewer: Optional[str] = None,
|
2021-02-12 08:20:45 +01:00
|
|
|
type: str = "PR",
|
2021-02-12 08:19:30 +01:00
|
|
|
title: Optional[str] = None,
|
|
|
|
) -> str:
|
2018-07-13 21:28:16 +02:00
|
|
|
kwargs = {
|
2021-02-12 08:20:45 +01:00
|
|
|
"user_name": user_name,
|
|
|
|
"action": action,
|
|
|
|
"type": type,
|
|
|
|
"url": url,
|
|
|
|
"id": f" #{number}" if number is not None else "",
|
|
|
|
"title": title,
|
2018-07-13 21:28:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if title is not None:
|
|
|
|
main_message = PULL_REQUEST_OR_ISSUE_MESSAGE_TEMPLATE_WITH_TITLE.format(**kwargs)
|
|
|
|
else:
|
|
|
|
main_message = PULL_REQUEST_OR_ISSUE_MESSAGE_TEMPLATE.format(**kwargs)
|
|
|
|
|
2023-03-28 20:25:22 +02:00
|
|
|
if target_branch and base_branch:
|
|
|
|
branch_info = PULL_REQUEST_BRANCH_INFO_TEMPLATE.format(
|
|
|
|
target=target_branch,
|
|
|
|
base=base_branch,
|
|
|
|
)
|
|
|
|
main_message = f"{main_message} {branch_info}"
|
|
|
|
|
2018-12-20 23:31:05 +01:00
|
|
|
if assignees:
|
2023-03-29 08:05:23 +02:00
|
|
|
assignee_string = get_assignee_string(assignees)
|
2019-04-19 22:02:41 +02:00
|
|
|
assignee_info = PULL_REQUEST_OR_ISSUE_ASSIGNEE_INFO_TEMPLATE.format(
|
2023-03-29 08:05:23 +02:00
|
|
|
assignee=assignee_string
|
2021-02-12 08:19:30 +01:00
|
|
|
)
|
2018-12-20 23:31:05 +01:00
|
|
|
|
|
|
|
elif assignee:
|
2021-02-12 08:19:30 +01:00
|
|
|
assignee_info = PULL_REQUEST_OR_ISSUE_ASSIGNEE_INFO_TEMPLATE.format(assignee=assignee)
|
2023-03-29 08:05:23 +02:00
|
|
|
|
|
|
|
elif reviewer:
|
|
|
|
assignee_info = PULL_REQUEST_REVIEWER_INFO_TEMPLATE.format(reviewer=reviewer)
|
|
|
|
|
|
|
|
if assignees or assignee or reviewer:
|
2020-06-09 00:25:09 +02:00
|
|
|
main_message = f"{main_message} {assignee_info}"
|
2016-10-11 18:53:20 +02:00
|
|
|
|
2021-02-12 08:20:45 +01:00
|
|
|
punctuation = ":" if message else "."
|
2023-01-18 02:59:37 +01:00
|
|
|
if (
|
|
|
|
assignees
|
|
|
|
or assignee
|
|
|
|
or (target_branch and base_branch)
|
|
|
|
or title is None
|
2019-04-19 22:02:41 +02:00
|
|
|
# Once we get here, we know that the message ends with a title
|
|
|
|
# which could already have punctuation at the end
|
2023-01-18 02:59:37 +01:00
|
|
|
or title[-1] not in string.punctuation
|
|
|
|
):
|
|
|
|
main_message = f"{main_message}{punctuation}"
|
2019-04-19 22:02:41 +02:00
|
|
|
|
2016-10-19 15:57:57 +02:00
|
|
|
if message:
|
2021-02-12 08:20:45 +01:00
|
|
|
main_message += "\n" + CONTENT_MESSAGE_TEMPLATE.format(message=message)
|
2016-10-11 18:53:20 +02:00
|
|
|
return main_message.rstrip()
|
2016-10-12 23:38:49 +02:00
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
|
|
|
def get_issue_event_message(
|
2023-03-16 20:36:47 +01:00
|
|
|
*,
|
2021-02-12 08:19:30 +01:00
|
|
|
user_name: str,
|
|
|
|
action: str,
|
|
|
|
url: str,
|
|
|
|
number: Optional[int] = None,
|
|
|
|
message: Optional[str] = None,
|
|
|
|
assignee: Optional[str] = None,
|
|
|
|
assignees: Optional[List[Dict[str, Any]]] = None,
|
|
|
|
title: Optional[str] = None,
|
|
|
|
) -> str:
|
2016-10-19 15:57:57 +02:00
|
|
|
return get_pull_request_event_message(
|
2023-03-16 00:52:45 +01:00
|
|
|
user_name=user_name,
|
|
|
|
action=action,
|
|
|
|
url=url,
|
|
|
|
number=number,
|
2016-10-19 15:57:57 +02:00
|
|
|
message=message,
|
|
|
|
assignee=assignee,
|
2018-12-20 23:31:05 +01:00
|
|
|
assignees=assignees,
|
2021-05-10 07:02:14 +02:00
|
|
|
type="issue",
|
2018-07-13 21:28:16 +02:00
|
|
|
title=title,
|
2016-10-19 15:57:57 +02:00
|
|
|
)
|
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2023-06-02 22:22:01 +02:00
|
|
|
def get_issue_labeled_or_unlabeled_event_message(
|
|
|
|
user_name: str,
|
|
|
|
action: str,
|
|
|
|
url: str,
|
|
|
|
number: int,
|
|
|
|
label_name: str,
|
|
|
|
user_url: str,
|
|
|
|
title: Optional[str] = None,
|
|
|
|
) -> str:
|
|
|
|
args = {
|
|
|
|
"user_name": user_name,
|
|
|
|
"action": action,
|
|
|
|
"url": url,
|
|
|
|
"id": number,
|
|
|
|
"label_name": label_name,
|
|
|
|
"user_url": user_url,
|
|
|
|
"title": title,
|
|
|
|
"preposition": "to" if action == "added" else "from",
|
|
|
|
}
|
|
|
|
if title is not None:
|
|
|
|
return ISSUE_LABELED_OR_UNLABELED_MESSAGE_TEMPLATE_WITH_TITLE.format(**args)
|
|
|
|
return ISSUE_LABELED_OR_UNLABELED_MESSAGE_TEMPLATE.format(**args)
|
|
|
|
|
|
|
|
|
2023-06-13 15:48:40 +02:00
|
|
|
def get_issue_milestoned_or_demilestoned_event_message(
|
|
|
|
user_name: str,
|
|
|
|
action: str,
|
|
|
|
url: str,
|
|
|
|
number: int,
|
|
|
|
milestone_name: str,
|
|
|
|
milestone_url: str,
|
|
|
|
user_url: str,
|
|
|
|
title: Optional[str] = None,
|
|
|
|
) -> str:
|
|
|
|
args = {
|
|
|
|
"user_name": user_name,
|
|
|
|
"action": action,
|
|
|
|
"url": url,
|
|
|
|
"id": number,
|
|
|
|
"milestone_name": milestone_name,
|
|
|
|
"milestone_url": milestone_url,
|
|
|
|
"user_url": user_url,
|
|
|
|
"title": title,
|
|
|
|
"preposition": "to" if action == "added" else "from",
|
|
|
|
}
|
|
|
|
if title is not None:
|
|
|
|
return ISSUE_MILESTONED_OR_DEMILESTONED_MESSAGE_TEMPLATE_WITH_TITLE.format(**args)
|
|
|
|
return ISSUE_MILESTONED_OR_DEMILESTONED_MESSAGE_TEMPLATE.format(**args)
|
|
|
|
|
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
def get_push_tag_event_message(
|
2021-02-12 08:20:45 +01:00
|
|
|
user_name: str, tag_name: str, tag_url: Optional[str] = None, action: str = "pushed"
|
2021-02-12 08:19:30 +01:00
|
|
|
) -> str:
|
2016-11-08 22:12:22 +01:00
|
|
|
if tag_url:
|
|
|
|
tag_part = TAG_WITH_URL_TEMPLATE.format(tag_name=tag_name, tag_url=tag_url)
|
|
|
|
else:
|
|
|
|
tag_part = TAG_WITHOUT_URL_TEMPLATE.format(tag_name=tag_name)
|
2019-04-19 22:02:41 +02:00
|
|
|
|
|
|
|
message = PUSH_TAGS_MESSAGE_TEMPLATE.format(
|
2016-11-08 22:12:22 +01:00
|
|
|
user_name=user_name,
|
|
|
|
action=action,
|
python: Use trailing commas consistently.
Automatically generated by the following script, based on the output
of lint with flake8-comma:
import re
import sys
last_filename = None
last_row = None
lines = []
for msg in sys.stdin:
m = re.match(
r"\x1b\[35mflake8 \|\x1b\[0m \x1b\[1;31m(.+):(\d+):(\d+): (\w+)", msg
)
if m:
filename, row_str, col_str, err = m.groups()
row, col = int(row_str), int(col_str)
if filename == last_filename:
assert last_row != row
else:
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
with open(filename) as f:
lines = f.readlines()
last_filename = filename
last_row = row
line = lines[row - 1]
if err in ["C812", "C815"]:
lines[row - 1] = line[: col - 1] + "," + line[col - 1 :]
elif err in ["C819"]:
assert line[col - 2] == ","
lines[row - 1] = line[: col - 2] + line[col - 1 :].lstrip(" ")
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-04-10 05:23:40 +02:00
|
|
|
tag=tag_part,
|
2016-11-08 22:12:22 +01:00
|
|
|
)
|
|
|
|
|
2019-04-19 22:02:41 +02:00
|
|
|
if tag_name[-1] not in string.punctuation:
|
2021-02-12 08:20:45 +01:00
|
|
|
message = f"{message}."
|
2019-04-19 22:02:41 +02:00
|
|
|
|
|
|
|
return message
|
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
|
|
|
def get_commits_comment_action_message(
|
|
|
|
user_name: str, action: str, commit_url: str, sha: str, message: Optional[str] = None
|
|
|
|
) -> str:
|
2016-10-27 21:43:15 +02:00
|
|
|
content = COMMITS_COMMENT_MESSAGE_TEMPLATE.format(
|
|
|
|
user_name=user_name,
|
|
|
|
action=action,
|
|
|
|
sha=get_short_sha(sha),
|
python: Use trailing commas consistently.
Automatically generated by the following script, based on the output
of lint with flake8-comma:
import re
import sys
last_filename = None
last_row = None
lines = []
for msg in sys.stdin:
m = re.match(
r"\x1b\[35mflake8 \|\x1b\[0m \x1b\[1;31m(.+):(\d+):(\d+): (\w+)", msg
)
if m:
filename, row_str, col_str, err = m.groups()
row, col = int(row_str), int(col_str)
if filename == last_filename:
assert last_row != row
else:
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
with open(filename) as f:
lines = f.readlines()
last_filename = filename
last_row = row
line = lines[row - 1]
if err in ["C812", "C815"]:
lines[row - 1] = line[: col - 1] + "," + line[col - 1 :]
elif err in ["C819"]:
assert line[col - 2] == ","
lines[row - 1] = line[: col - 2] + line[col - 1 :].lstrip(" ")
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-04-10 05:23:40 +02:00
|
|
|
url=commit_url,
|
2016-10-27 21:43:15 +02:00
|
|
|
)
|
2021-02-12 08:20:45 +01:00
|
|
|
punctuation = ":" if message else "."
|
|
|
|
content = f"{content}{punctuation}"
|
2019-04-19 22:02:41 +02:00
|
|
|
if message:
|
2016-10-27 21:43:15 +02:00
|
|
|
content += CONTENT_MESSAGE_TEMPLATE.format(
|
python: Use trailing commas consistently.
Automatically generated by the following script, based on the output
of lint with flake8-comma:
import re
import sys
last_filename = None
last_row = None
lines = []
for msg in sys.stdin:
m = re.match(
r"\x1b\[35mflake8 \|\x1b\[0m \x1b\[1;31m(.+):(\d+):(\d+): (\w+)", msg
)
if m:
filename, row_str, col_str, err = m.groups()
row, col = int(row_str), int(col_str)
if filename == last_filename:
assert last_row != row
else:
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
with open(filename) as f:
lines = f.readlines()
last_filename = filename
last_row = row
line = lines[row - 1]
if err in ["C812", "C815"]:
lines[row - 1] = line[: col - 1] + "," + line[col - 1 :]
elif err in ["C819"]:
assert line[col - 2] == ","
lines[row - 1] = line[: col - 2] + line[col - 1 :].lstrip(" ")
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-04-10 05:23:40 +02:00
|
|
|
message=message,
|
2016-10-27 21:43:15 +02:00
|
|
|
)
|
2019-04-19 22:02:41 +02:00
|
|
|
|
2016-10-27 21:43:15 +02:00
|
|
|
return content
|
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
|
|
|
def get_commits_content(commits_data: List[Dict[str, Any]], is_truncated: bool = False) -> str:
|
2021-02-12 08:20:45 +01:00
|
|
|
commits_content = ""
|
2016-10-12 23:38:49 +02:00
|
|
|
for commit in commits_data[:COMMITS_LIMIT]:
|
|
|
|
commits_content += COMMIT_ROW_TEMPLATE.format(
|
2021-02-12 08:20:45 +01:00
|
|
|
commit_short_sha=get_short_sha(commit["sha"]),
|
|
|
|
commit_url=commit.get("url"),
|
|
|
|
commit_msg=commit["message"].partition("\n")[0],
|
2016-10-12 23:38:49 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
if len(commits_data) > COMMITS_LIMIT:
|
|
|
|
commits_content += COMMITS_MORE_THAN_LIMIT_TEMPLATE.format(
|
python: Use trailing commas consistently.
Automatically generated by the following script, based on the output
of lint with flake8-comma:
import re
import sys
last_filename = None
last_row = None
lines = []
for msg in sys.stdin:
m = re.match(
r"\x1b\[35mflake8 \|\x1b\[0m \x1b\[1;31m(.+):(\d+):(\d+): (\w+)", msg
)
if m:
filename, row_str, col_str, err = m.groups()
row, col = int(row_str), int(col_str)
if filename == last_filename:
assert last_row != row
else:
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
with open(filename) as f:
lines = f.readlines()
last_filename = filename
last_row = row
line = lines[row - 1]
if err in ["C812", "C815"]:
lines[row - 1] = line[: col - 1] + "," + line[col - 1 :]
elif err in ["C819"]:
assert line[col - 2] == ","
lines[row - 1] = line[: col - 2] + line[col - 1 :].lstrip(" ")
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-04-10 05:23:40 +02:00
|
|
|
commits_number=len(commits_data) - COMMITS_LIMIT,
|
2016-11-09 18:50:10 +01:00
|
|
|
)
|
|
|
|
elif is_truncated:
|
|
|
|
commits_content += COMMITS_MORE_THAN_LIMIT_TEMPLATE.format(
|
2021-02-12 08:20:45 +01:00
|
|
|
commits_number="",
|
|
|
|
).replace(" ", " ")
|
2016-10-12 23:38:49 +02:00
|
|
|
return commits_content.rstrip()
|
2016-10-27 21:43:15 +02:00
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
|
|
|
def get_release_event_message(
|
|
|
|
user_name: str, action: str, tagname: str, release_name: str, url: str
|
|
|
|
) -> str:
|
2020-05-11 08:58:53 +02:00
|
|
|
content = RELEASE_MESSAGE_TEMPLATE.format(
|
|
|
|
user_name=user_name,
|
|
|
|
action=action,
|
|
|
|
tagname=tagname,
|
|
|
|
release_name=release_name,
|
python: Use trailing commas consistently.
Automatically generated by the following script, based on the output
of lint with flake8-comma:
import re
import sys
last_filename = None
last_row = None
lines = []
for msg in sys.stdin:
m = re.match(
r"\x1b\[35mflake8 \|\x1b\[0m \x1b\[1;31m(.+):(\d+):(\d+): (\w+)", msg
)
if m:
filename, row_str, col_str, err = m.groups()
row, col = int(row_str), int(col_str)
if filename == last_filename:
assert last_row != row
else:
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
with open(filename) as f:
lines = f.readlines()
last_filename = filename
last_row = row
line = lines[row - 1]
if err in ["C812", "C815"]:
lines[row - 1] = line[: col - 1] + "," + line[col - 1 :]
elif err in ["C819"]:
assert line[col - 2] == ","
lines[row - 1] = line[: col - 2] + line[col - 1 :].lstrip(" ")
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-04-10 05:23:40 +02:00
|
|
|
url=url,
|
2020-05-11 08:58:53 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
return content
|
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2018-05-10 19:13:36 +02:00
|
|
|
def get_short_sha(sha: str) -> str:
|
2022-11-07 21:15:53 +01:00
|
|
|
return sha[:11]
|
2017-04-05 09:12:19 +02:00
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2017-11-05 11:15:10 +01:00
|
|
|
def get_all_committers(commits_data: List[Dict[str, Any]]) -> List[Tuple[str, int]]:
|
python: Convert assignment type annotations to Python 3.6 style.
This commit was split by tabbott; this piece covers the vast majority
of files in Zulip, but excludes scripts/, tools/, and puppet/ to help
ensure we at least show the right error messages for Xenial systems.
We can likely further refine the remaining pieces with some testing.
Generated by com2ann, with whitespace fixes and various manual fixes
for runtime issues:
- invoiced_through: Optional[LicenseLedger] = models.ForeignKey(
+ invoiced_through: Optional["LicenseLedger"] = models.ForeignKey(
-_apns_client: Optional[APNsClient] = None
+_apns_client: Optional["APNsClient"] = None
- notifications_stream: Optional[Stream] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
- signup_notifications_stream: Optional[Stream] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
+ notifications_stream: Optional["Stream"] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
+ signup_notifications_stream: Optional["Stream"] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
- author: Optional[UserProfile] = models.ForeignKey('UserProfile', blank=True, null=True, on_delete=CASCADE)
+ author: Optional["UserProfile"] = models.ForeignKey('UserProfile', blank=True, null=True, on_delete=CASCADE)
- bot_owner: Optional[UserProfile] = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
+ bot_owner: Optional["UserProfile"] = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
- default_sending_stream: Optional[Stream] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
- default_events_register_stream: Optional[Stream] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
+ default_sending_stream: Optional["Stream"] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
+ default_events_register_stream: Optional["Stream"] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
-descriptors_by_handler_id: Dict[int, ClientDescriptor] = {}
+descriptors_by_handler_id: Dict[int, "ClientDescriptor"] = {}
-worker_classes: Dict[str, Type[QueueProcessingWorker]] = {}
-queues: Dict[str, Dict[str, Type[QueueProcessingWorker]]] = {}
+worker_classes: Dict[str, Type["QueueProcessingWorker"]] = {}
+queues: Dict[str, Dict[str, Type["QueueProcessingWorker"]]] = {}
-AUTH_LDAP_REVERSE_EMAIL_SEARCH: Optional[LDAPSearch] = None
+AUTH_LDAP_REVERSE_EMAIL_SEARCH: Optional["LDAPSearch"] = None
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-04-22 01:09:50 +02:00
|
|
|
committers: Dict[str, int] = defaultdict(int)
|
2017-04-05 09:12:19 +02:00
|
|
|
|
|
|
|
for commit in commits_data:
|
2021-02-12 08:20:45 +01:00
|
|
|
committers[commit["name"]] += 1
|
2017-04-05 09:12:19 +02:00
|
|
|
|
2017-04-21 20:44:37 +02:00
|
|
|
# Sort by commit count, breaking ties alphabetically.
|
python: Convert assignment type annotations to Python 3.6 style.
This commit was split by tabbott; this piece covers the vast majority
of files in Zulip, but excludes scripts/, tools/, and puppet/ to help
ensure we at least show the right error messages for Xenial systems.
We can likely further refine the remaining pieces with some testing.
Generated by com2ann, with whitespace fixes and various manual fixes
for runtime issues:
- invoiced_through: Optional[LicenseLedger] = models.ForeignKey(
+ invoiced_through: Optional["LicenseLedger"] = models.ForeignKey(
-_apns_client: Optional[APNsClient] = None
+_apns_client: Optional["APNsClient"] = None
- notifications_stream: Optional[Stream] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
- signup_notifications_stream: Optional[Stream] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
+ notifications_stream: Optional["Stream"] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
+ signup_notifications_stream: Optional["Stream"] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
- author: Optional[UserProfile] = models.ForeignKey('UserProfile', blank=True, null=True, on_delete=CASCADE)
+ author: Optional["UserProfile"] = models.ForeignKey('UserProfile', blank=True, null=True, on_delete=CASCADE)
- bot_owner: Optional[UserProfile] = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
+ bot_owner: Optional["UserProfile"] = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
- default_sending_stream: Optional[Stream] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
- default_events_register_stream: Optional[Stream] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
+ default_sending_stream: Optional["Stream"] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
+ default_events_register_stream: Optional["Stream"] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
-descriptors_by_handler_id: Dict[int, ClientDescriptor] = {}
+descriptors_by_handler_id: Dict[int, "ClientDescriptor"] = {}
-worker_classes: Dict[str, Type[QueueProcessingWorker]] = {}
-queues: Dict[str, Dict[str, Type[QueueProcessingWorker]]] = {}
+worker_classes: Dict[str, Type["QueueProcessingWorker"]] = {}
+queues: Dict[str, Dict[str, Type["QueueProcessingWorker"]]] = {}
-AUTH_LDAP_REVERSE_EMAIL_SEARCH: Optional[LDAPSearch] = None
+AUTH_LDAP_REVERSE_EMAIL_SEARCH: Optional["LDAPSearch"] = None
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-04-22 01:09:50 +02:00
|
|
|
committers_items: List[Tuple[str, int]] = sorted(
|
2021-02-12 08:19:30 +01:00
|
|
|
committers.items(),
|
|
|
|
key=lambda item: (-item[1], item[0]),
|
python: Convert assignment type annotations to Python 3.6 style.
This commit was split by tabbott; this piece covers the vast majority
of files in Zulip, but excludes scripts/, tools/, and puppet/ to help
ensure we at least show the right error messages for Xenial systems.
We can likely further refine the remaining pieces with some testing.
Generated by com2ann, with whitespace fixes and various manual fixes
for runtime issues:
- invoiced_through: Optional[LicenseLedger] = models.ForeignKey(
+ invoiced_through: Optional["LicenseLedger"] = models.ForeignKey(
-_apns_client: Optional[APNsClient] = None
+_apns_client: Optional["APNsClient"] = None
- notifications_stream: Optional[Stream] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
- signup_notifications_stream: Optional[Stream] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
+ notifications_stream: Optional["Stream"] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
+ signup_notifications_stream: Optional["Stream"] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
- author: Optional[UserProfile] = models.ForeignKey('UserProfile', blank=True, null=True, on_delete=CASCADE)
+ author: Optional["UserProfile"] = models.ForeignKey('UserProfile', blank=True, null=True, on_delete=CASCADE)
- bot_owner: Optional[UserProfile] = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
+ bot_owner: Optional["UserProfile"] = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
- default_sending_stream: Optional[Stream] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
- default_events_register_stream: Optional[Stream] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
+ default_sending_stream: Optional["Stream"] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
+ default_events_register_stream: Optional["Stream"] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
-descriptors_by_handler_id: Dict[int, ClientDescriptor] = {}
+descriptors_by_handler_id: Dict[int, "ClientDescriptor"] = {}
-worker_classes: Dict[str, Type[QueueProcessingWorker]] = {}
-queues: Dict[str, Dict[str, Type[QueueProcessingWorker]]] = {}
+worker_classes: Dict[str, Type["QueueProcessingWorker"]] = {}
+queues: Dict[str, Dict[str, Type["QueueProcessingWorker"]]] = {}
-AUTH_LDAP_REVERSE_EMAIL_SEARCH: Optional[LDAPSearch] = None
+AUTH_LDAP_REVERSE_EMAIL_SEARCH: Optional["LDAPSearch"] = None
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-04-22 01:09:50 +02:00
|
|
|
)
|
|
|
|
committers_values: List[int] = [c_i[1] for c_i in committers_items]
|
2017-04-05 09:12:19 +02:00
|
|
|
|
|
|
|
if len(committers) > PUSH_COMMITTERS_LIMIT_INFO:
|
|
|
|
others_number_of_commits = sum(committers_values[PUSH_COMMITTERS_LIMIT_INFO:])
|
|
|
|
committers_items = committers_items[:PUSH_COMMITTERS_LIMIT_INFO]
|
2021-02-12 08:20:45 +01:00
|
|
|
committers_items.append(("others", others_number_of_commits))
|
2017-04-05 09:12:19 +02:00
|
|
|
|
|
|
|
return committers_items
|