aboutsummaryrefslogtreecommitdiffstats
path: root/import_issues.py
diff options
context:
space:
mode:
authorMatěj Cepl <mcepl@cepl.eu>2024-05-05 09:25:47 +0200
committerMatěj Cepl <mcepl@cepl.eu>2024-05-05 09:34:33 +0200
commita293240f40bd4c33285820f41eab6a07d295442d (patch)
tree067c7f90dde33fc1d947eb2b3eab3cb3b90e0dca /import_issues.py
parent91d4e6e2f57e84fdfbac56e6cf835f6eceaec6fc (diff)
downloadlazygl2srht-a293240f40bd4c33285820f41eab6a07d295442d.tar.gz
chore: blacken the filesent
Formatting produced by Black is commonly agreed one, and it simplifies life a lot. Add black to your pre-commit hook.
Diffstat (limited to 'import_issues.py')
-rwxr-xr-ximport_issues.py306
1 files changed, 179 insertions, 127 deletions
diff --git a/import_issues.py b/import_issues.py
index 666644e..13c06ea 100755
--- a/import_issues.py
+++ b/import_issues.py
@@ -138,8 +138,10 @@ from typing import Dict, List, Optional
ID_RE = re.compile(r'^[0-9]+$')
-logging.basicConfig(format='%(levelname)s:%(funcName)s:%(message)s',
- level=logging.DEBUG)
+logging.basicConfig(
+ format='%(levelname)s:%(funcName)s:%(message)s',
+ level=logging.DEBUG,
+)
log = logging.getLogger()
email_count = 0
@@ -155,25 +157,27 @@ def read_id_map_file(file_path: Path) -> Dict[int, str]:
line_num = 0
for row in reader:
line_num += 1
- assert len(row) == 2 and ID_RE.search(row[0]) and row[1], \
- f"Row {line_num} of {file_path} is not in the form <ID>,<NAME>: {row!r}"
+ assert (
+ len(row) == 2 and ID_RE.search(row[0]) and row[1]
+ ), f"Row {line_num} of {file_path} is not in the form <ID>,<NAME>: {row!r}"
new_id = int(row[0])
- assert new_id not in result, \
- f"ID {new_id} appears multiple times in {file_path}."
+ assert (
+ new_id not in result
+ ), f"ID {new_id} appears multiple times in {file_path}."
result[new_id] = row[1]
return result
def do_mail(
- *,
- smtp,
- smtp_delay: float,
- mode: str,
- frm: str,
- to: str,
- body: str,
- subject: Optional[str] = None,
+ *,
+ smtp,
+ smtp_delay: float,
+ mode: str,
+ frm: str,
+ to: str,
+ body: str,
+ subject: Optional[str] = None,
):
global email_count
email_count += 1
@@ -217,23 +221,23 @@ def do_mail(
def open_ticket(
- *,
- smtp,
- smtp_delay: float,
- mode: str,
- srht_owner: str,
- srht_tracker: str,
- frm: str,
- title: str,
- body: str,
- created_by: Optional[str],
- created_at: str,
- closed_at: Optional[str],
- is_closed: bool,
- is_confidential: bool,
- label_names: List[str],
- milestone_name: Optional[str],
- gitlab_ticket_url: str,
+ *,
+ smtp,
+ smtp_delay: float,
+ mode: str,
+ srht_owner: str,
+ srht_tracker: str,
+ frm: str,
+ title: str,
+ body: str,
+ created_by: Optional[str],
+ created_at: str,
+ closed_at: Optional[str],
+ is_closed: bool,
+ is_confidential: bool,
+ label_names: List[str],
+ milestone_name: Optional[str],
+ gitlab_ticket_url: str,
) -> int:
global issue_count
@@ -279,14 +283,14 @@ def open_ticket(
def file_missing_ticket(
- *,
- smtp,
- smtp_delay: float,
- mode: str,
- srht_owner: str,
- srht_tracker: str,
- frm: str,
- issue_id: int,
+ *,
+ smtp,
+ smtp_delay: float,
+ mode: str,
+ srht_owner: str,
+ srht_tracker: str,
+ frm: str,
+ issue_id: int,
):
global issue_count
@@ -318,20 +322,20 @@ def file_missing_ticket(
def send_comment(
- *,
- smtp,
- smtp_delay: float,
- mode: str,
- srht_owner: str,
- srht_tracker: str,
- frm: str,
- issue_id: int,
- body: str,
- author_name: str,
- created_at: str,
- last_edited_at: str,
- is_system: bool,
- is_confidential: bool,
+ *,
+ smtp,
+ smtp_delay: float,
+ mode: str,
+ srht_owner: str,
+ srht_tracker: str,
+ frm: str,
+ issue_id: int,
+ body: str,
+ author_name: str,
+ created_at: str,
+ last_edited_at: str,
+ is_system: bool,
+ is_confidential: bool,
):
lines = []
pheaders = []
@@ -368,16 +372,16 @@ def send_comment(
def close_ticket(
- *,
- smtp,
- smtp_delay: float,
- mode: str,
- srht_owner: str,
- srht_tracker: str,
- frm: str,
- issue_id: int,
- closed_at: Optional[str],
- is_closed: bool,
+ *,
+ smtp,
+ smtp_delay: float,
+ mode: str,
+ srht_owner: str,
+ srht_tracker: str,
+ frm: str,
+ issue_id: int,
+ closed_at: Optional[str],
+ is_closed: bool,
):
lines = []
@@ -401,39 +405,47 @@ def close_ticket(
def run(
- *,
- smtp,
- smtp_delay: float,
- mode: str,
- srht_owner: str,
- srht_tracker: str,
- frm: str,
- export_dir_path: Path,
- gitlab_project_url: str,
- labels_file_path: Optional[Path],
- skip_unknown_labels: bool,
- users_file_path: Optional[Path],
- skip_unknown_users: bool,
- skip_missing_issues: bool,
- create_missing_issues: bool,
- include_confidential: bool,
- skip_confidential: bool,
+ *,
+ smtp,
+ smtp_delay: float,
+ mode: str,
+ srht_owner: str,
+ srht_tracker: str,
+ frm: str,
+ export_dir_path: Path,
+ gitlab_project_url: str,
+ labels_file_path: Optional[Path],
+ skip_unknown_labels: bool,
+ users_file_path: Optional[Path],
+ skip_unknown_users: bool,
+ skip_missing_issues: bool,
+ create_missing_issues: bool,
+ include_confidential: bool,
+ skip_confidential: bool,
):
- label_ids_to_names: Optional[Dict[int, str]] = \
- read_id_map_file(labels_file_path) if labels_file_path else None
- user_ids_to_names: Optional[Dict[int, str]] = \
+ label_ids_to_names: Optional[Dict[int, str]] = (
+ read_id_map_file(labels_file_path)
+ if labels_file_path
+ else None
+ )
+ user_ids_to_names: Optional[Dict[int, str]] = (
read_id_map_file(users_file_path) if users_file_path else None
+ )
# TODO Might be able to automatically map note.events.author_id to
# note.author.name for a subset of relevant users.
milestone_jsons = []
- with open(export_dir_path / 'milestones.ndjson') as milestones_file:
+ with open(
+ export_dir_path / 'milestones.ndjson'
+ ) as milestones_file:
for line in milestones_file:
milestone_jsons.append(json.loads(line))
milestone_ids_to_titles = {}
for milestone_json in milestone_jsons:
- milestone_ids_to_titles[milestone_json['iid']] = milestone_json['title']
+ milestone_ids_to_titles[milestone_json['iid']] = (
+ milestone_json['title']
+ )
issue_jsons = []
with open(export_dir_path / 'issues.ndjson') as issues_file:
@@ -441,7 +453,9 @@ def run(
issue_jsons.append(json.loads(line))
if skip_confidential:
- issue_jsons = [x for x in issue_jsons if not x.get('confidential')]
+ issue_jsons = [
+ x for x in issue_jsons if not x.get('confidential')
+ ]
for issue_json in issue_jsons:
issue_json['notes'] = [
n
@@ -451,8 +465,7 @@ def run(
elif not include_confidential:
have_confidential_issues = any(
- x.get('confidential')
- for x in issue_jsons
+ x.get('confidential') for x in issue_jsons
)
have_confidential_notes = any(
n.get('confidential')
@@ -464,21 +477,27 @@ def run(
confidential_types.append('issues')
if have_confidential_notes:
confidential_types.append('notes')
- assert not (have_confidential_issues or have_confidential_notes), \
- f"Found confidential {' and '.join(confidential_types)}; please " \
- f"decide whether these should all be included, then pass either " \
- f"--include-confidential or --skip-confidential, or edit " \
+ assert not (
+ have_confidential_issues or have_confidential_notes
+ ), (
+ f"Found confidential {' and '.join(confidential_types)}; please "
+ f"decide whether these should all be included, then pass either "
+ f"--include-confidential or --skip-confidential, or edit "
f"issues.ndjson for more fine-grained control."
+ )
issue_jsons.sort(key=lambda x: x['iid'])
max_issue_id = max(x['iid'] for x in issue_jsons)
present_issue_id_set = {x['iid'] for x in issue_jsons}
- missing_issue_ids = set(range(1, max_issue_id + 1)) - present_issue_id_set
- if missing_issue_ids and not (skip_missing_issues or create_missing_issues):
+ missing_issue_ids = (
+ set(range(1, max_issue_id + 1)) - present_issue_id_set
+ )
+ if missing_issue_ids and not (
+ skip_missing_issues or create_missing_issues
+ ):
if skip_confidential:
- because_confidential_msg = \
- " (possibly because some confidential issues were excluded)"
+ because_confidential_msg = " (possibly because some confidential issues were excluded)"
else:
because_confidential_msg = ""
@@ -531,9 +550,10 @@ def run(
elif author_id in user_ids_to_names:
created_by = user_ids_to_names[author_id]
else:
- assert skip_unknown_users, \
- f"Unknown author #{author_id} of ticket #{gitlab_issue_id}, " \
+ assert skip_unknown_users, (
+ f"Unknown author #{author_id} of ticket #{gitlab_issue_id}, "
f"please add to the users file."
+ )
created_by = None
srht_issue_id = open_ticket(
@@ -550,17 +570,23 @@ def run(
closed_at=issue_json['closed_at'],
is_closed=(issue_json['state'] == 'closed'),
is_confidential=(issue_json.get('confidential') is True),
- label_names=[x['label']['title'] for x in issue_json['label_links']],
- milestone_name=issue_json.get('milestone', {}).get('title') or None,
+ label_names=[
+ x['label']['title'] for x in issue_json['label_links']
+ ],
+ milestone_name=issue_json.get('milestone', {}).get(
+ 'title'
+ )
+ or None,
gitlab_ticket_url=f"{gitlab_project_url}/-/issues/{gitlab_issue_id}",
)
if not skip_missing_issues:
- assert srht_issue_id == gitlab_issue_id, \
- f"Internal error, srht_issue_id {srht_issue_id} != " \
- f"gitlab_issue_id {gitlab_issue_id} " \
- f"(skip_missing_issues={skip_missing_issues}, " \
+ assert srht_issue_id == gitlab_issue_id, (
+ f"Internal error, srht_issue_id {srht_issue_id} != "
+ f"gitlab_issue_id {gitlab_issue_id} "
+ f"(skip_missing_issues={skip_missing_issues}, "
f"create_missing_issues={create_missing_issues})."
+ )
issue_id_map[gitlab_issue_id] = srht_issue_id
@@ -568,29 +594,40 @@ def run(
for issue_json in issue_jsons:
for note_json in issue_json['notes']:
- system_action = note_json.get('system_note_metadata', {}).get('action', None)
+ system_action = note_json.get(
+ 'system_note_metadata', {}
+ ).get('action', None)
body = note_json['note']
# The "Removed" part is a guess here, don't know if that actually shows up.
if label_ids_to_names is not None and (
- system_action == 'label' or re.search(r'^(Added|Removed) ~[0-9]+ label', body)
+ system_action == 'label'
+ or re.search(r'^(Added|Removed) ~[0-9]+ label', body)
):
+
def expand_label(ref):
ref_num = int(ref.group(1))
if ref_num in label_ids_to_names:
return label_ids_to_names[ref_num]
- assert skip_unknown_labels, \
- f"Unknown label #{ref_num}, please add to the labels file."
- return ref.group(0) # Return the original "~id" string.
+ assert (
+ skip_unknown_labels
+ ), f"Unknown label #{ref_num}, please add to the labels file."
+ return ref.group(
+ 0
+ ) # Return the original "~id" string.
body = re.sub(r'~([0-9]+)', expand_label, body)
- if system_action == 'milestone' or re.search(r'^Milestone changed to %[0-9]+$', body):
+ if system_action == 'milestone' or re.search(
+ r'^Milestone changed to %[0-9]+$', body
+ ):
+
def expand_milestone(ref):
ref_num = int(ref.group(1))
- assert ref_num in milestone_ids_to_titles, \
- f"Unknown milestone #{ref_num}."
+ assert (
+ ref_num in milestone_ids_to_titles
+ ), f"Unknown milestone #{ref_num}."
return milestone_ids_to_titles[ref_num]
body = re.sub(r'%([0-9]+)', expand_milestone, body)
@@ -770,8 +807,9 @@ def main():
export_dir = args['export_dir']
assert export_dir, f"Must have a exported project directory."
export_dir_path = Path(export_dir)
- assert export_dir_path.is_dir(), \
- f"Project directory is not a directory: {export_dir_path}"
+ assert (
+ export_dir_path.is_dir()
+ ), f"Project directory is not a directory: {export_dir_path}"
mode = args['mode']
frm = args['from']
@@ -779,39 +817,53 @@ def main():
labels_file = args['labels_file']
skip_labels = args['skip_labels']
skip_unknown_labels = args['skip_unknown_labels']
- assert labels_file or skip_labels, \
- f"One of --labels-file or --skip-labels must be provided."
+ assert (
+ labels_file or skip_labels
+ ), f"One of --labels-file or --skip-labels must be provided."
users_file = args['users_file']
skip_users = args['skip_users']
skip_unknown_users = args['skip_unknown_users']
- assert skip_users or users_file, \
- f"One of --users-file or --skip-users must be provided."
+ assert (
+ skip_users or users_file
+ ), f"One of --users-file or --skip-users must be provided."
skip_missing_issues = args['skip_missing_issues']
create_missing_issues = args['create_missing_issues']
- assert not (skip_missing_issues and create_missing_issues), \
- f"Can accept at most one of --skip-missing-issues and --create-missing-issues."
+ assert not (
+ skip_missing_issues and create_missing_issues
+ ), f"Can accept at most one of --skip-missing-issues and --create-missing-issues."
include_confidential = args['include_confidential']
skip_confidential = args['skip_confidential']
- assert not (include_confidential and skip_confidential), \
- f"Can accept at most one of --include-confidential and --skip-confidential."
+ assert not (
+ include_confidential and skip_confidential
+ ), f"Can accept at most one of --include-confidential and --skip-confidential."
if mode == 'print':
smtp = None
elif mode == 'send':
smtp_ssl = args['smtp_ssl']
smtp_starttls = args['smtp_starttls']
- smtp_host = args['smtp_host'] or os.environ.get('SMTP_HOST', 'localhost')
- smtp_port = args['smtp_port'] or os.environ.get('SMTP_PORT', 465 if smtp_ssl else 25)
- smtp_user = args['smtp_user'] or os.environ.get('SMTP_USER', None)
- smtp_password = args['smtp_password'] or os.environ.get('SMTP_PASSWORD', None)
+ smtp_host = args['smtp_host'] or os.environ.get(
+ 'SMTP_HOST', 'localhost'
+ )
+ smtp_port = args['smtp_port'] or os.environ.get(
+ 'SMTP_PORT', 465 if smtp_ssl else 25
+ )
+ smtp_user = args['smtp_user'] or os.environ.get(
+ 'SMTP_USER', None
+ )
+ smtp_password = args['smtp_password'] or os.environ.get(
+ 'SMTP_PASSWORD', None
+ )
assert smtp_user, f"No SMTP user given."
assert smtp_password, f"No SMTP password given."
- log.info(f"Connecting to {smtp_host}:{smtp_port}, user {smtp_user!r}.")
+ log.info(
+ f"Connecting to {smtp_host}:{smtp_port}, user {smtp_user!r}."
+ )
if smtp_ssl:
smtp = smtplib.SMTP_SSL(host=smtp_host, port=smtp_port)