Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions snap/snapcraft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ environment:
PYTHONPATH: "$PYTHONPATH:$SNAP/usr/lib/python3/dist-packages"
# prevent lstopo from hanging on 26.04
HWLOC_COMPONENTS: "-gl"
PYTHONOPTIMIZE: '1'
Comment thread
tomli380576 marked this conversation as resolved.

layout:
# this combined with the 'cp' in the install hook
Expand Down
3 changes: 2 additions & 1 deletion src/bugit_v2/apps/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,8 @@ def main(
):
sudo_devmode_check()
ensure_all_directories_exist()
assert ctx.command.name in ("lp", "jira", "local")
if ctx.command.name not in ("lp", "jira", "local"):
raise RuntimeError(f"Unexpected command name: {ctx.command.name!r}")

if checkbox_submission:
print(f"Decompressing checkbox submission at {checkbox_submission}")
Expand Down
30 changes: 20 additions & 10 deletions src/bugit_v2/bug_report_submitters/jira_submitter.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,8 @@ def project_exists(self, project_name: str) -> None:
https://hostname.com/jira/software/c/projects/NAME
:return: true if the project exists
"""
assert self.jira, "Jira client is not initialized"
if not self.jira:
raise JiraSubmitterError("Jira client is not initialized")
try:
self.jira.project(id=project_name)
except Exception:
Expand All @@ -186,7 +187,8 @@ def assignee_exists_and_unique(self, assignee: str) -> str:
:param assignee: the email of the assignee or some form of ID
:return: exists and unique
"""
assert self.jira, "Jira client is not initialized"
if not self.jira:
raise JiraSubmitterError("Jira client is not initialized")

query_result = self.jira.search_users(query=assignee)
if len(query_result) == 0:
Expand All @@ -198,7 +200,8 @@ def assignee_exists_and_unique(self, assignee: str) -> str:
return query_result[0].accountId # pyright: ignore[reportAny]

def all_components_exist(self, project: str, components: Sequence[str]) -> None:
assert self.jira, "Jira client is not initialized"
if not self.jira:
raise JiraSubmitterError("Jira client is not initialized")
# the @translate_args decorator confuses the type checker
query_result = cast(list[Component], self.jira.project_components(project))
for wanted_component in components:
Expand All @@ -214,7 +217,8 @@ def all_components_exist(self, project: str, components: Sequence[str]) -> None:

@override
def bug_exists(self, bug_id: str) -> bool:
assert self.auth
if not self.auth:
raise JiraSubmitterError("Missing auth credentials")

try:
if not self.jira:
Expand Down Expand Up @@ -273,8 +277,10 @@ def submit(

bug_dict["description"] = content_str

assert self.auth, "Missing auth credentials"
assert JIRA_SERVER_ADDRESS, "JIRA_SERVER is not specified!"
if not self.auth:
raise JiraSubmitterError("Missing auth credentials")
if not JIRA_SERVER_ADDRESS:
raise JiraSubmitterError("JIRA_SERVER is not specified!")

yield "Starting Jira authentication..."
self.jira = JIRA(
Expand Down Expand Up @@ -330,17 +336,21 @@ def get_cached_credentials(self) -> JiraBasicAuth | None:
def upload_attachment(
self, attachment_file: Path, filename: str | None = None
) -> None:
assert self.jira
assert self.issue
if not self.jira:
raise JiraSubmitterError("Jira client is not initialized")
if not self.issue:
raise JiraSubmitterError("Nothing has been submitted to Jira yet")
# .add_attachment has a decorator that confuses the typechecker
# go to its definition to see the expected arguments
self.jira.add_attachment(self.issue.id, str(attachment_file), filename)

@property
@override
def bug_url(self) -> str:
assert self.jira
assert self.issue, "Nothing has been submitted to Jira yet"
if not self.jira:
raise JiraSubmitterError("Jira client is not initialized")
if not self.issue:
raise JiraSubmitterError("Nothing has been submitted to Jira yet")
return f"{self.jira.server_url}/browse/{self.issue.key}"

@override
Expand Down
51 changes: 33 additions & 18 deletions src/bugit_v2/bug_report_submitters/launchpad_submitter.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@
)
LP_APP_NAME = os.getenv("BUGIT_APP_NAME", "bugit-v2")

assert SERVICE_ROOT in VALID_SERVICE_ROOTS
if SERVICE_ROOT not in VALID_SERVICE_ROOTS:
raise RuntimeError(
"Invalid APPORT_LAUNCHPAD_INSTANCE, "
f"expected one of {VALID_SERVICE_ROOTS}, but got {SERVICE_ROOT}"
)


@final
Expand Down Expand Up @@ -167,11 +171,13 @@ def on_mount(self):

@work(thread=True)
def main_auth_sequence(self):
assert SERVICE_ROOT in VALID_SERVICE_ROOTS, (
"Invalid APPORT_LAUNCHPAD_INSTANCE, "
f"expected one of {VALID_SERVICE_ROOTS}, but got {SERVICE_ROOT}"
)
assert LP_APP_NAME, "BUGIT_APP_NAME was not specified"
if SERVICE_ROOT not in VALID_SERVICE_ROOTS:
raise RuntimeError(
"Invalid APPORT_LAUNCHPAD_INSTANCE, "
f"expected one of {VALID_SERVICE_ROOTS}, but got {SERVICE_ROOT}"
)
if not LP_APP_NAME:
raise RuntimeError("BUGIT_APP_NAME was not specified")

log_widget = self.query_exactly_one("#lp_login_stdout", RichLog)
auth_engine = GraphicalAuthorizeRequestTokenWithURL(
Expand Down Expand Up @@ -244,7 +250,8 @@ class LaunchpadSubmitter(BugReportSubmitter[Path]):
lp_bug_object: Any | None = None # TODO: make a wrapper for this

def check_project_existence(self, project_name: str) -> Any:
assert self.lp_client
if not self.lp_client:
raise RuntimeError("Launchpad client is not initialized")
try:
# type checker freaks out here
# since launchpad lib wants unknown member access + index access
Expand All @@ -259,7 +266,8 @@ def check_project_existence(self, project_name: str) -> Any:
raise ValueError(error_message)

def check_assignee_existence(self, assignee: str) -> Any:
assert self.lp_client
if not self.lp_client:
raise RuntimeError("Launchpad client is not initialized")
try:
return self.lp_client.people[ # pyright: ignore[reportIndexIssue, reportOptionalSubscript, reportUnknownVariableType]
assignee
Expand All @@ -269,7 +277,8 @@ def check_assignee_existence(self, assignee: str) -> Any:
raise ValueError(error_message)

def check_series_existence(self, series: str) -> Any:
assert self.lp_client
if not self.lp_client:
raise RuntimeError("Launchpad client is not initialized")
try:
return self.lp_client.project.getSeries( # pyright: ignore[reportAttributeAccessIssue, reportOptionalMemberAccess, reportUnknownVariableType]
name=series
Expand All @@ -286,12 +295,15 @@ def bug_exists(self, bug_id: str) -> bool:
def submit(
self, bug_report: BugReport
) -> Generator[str | AdvanceMessage, None, None]:
assert SERVICE_ROOT in VALID_SERVICE_ROOTS, (
"Invalid APPORT_LAUNCHPAD_INSTANCE, "
f"expected one of {VALID_SERVICE_ROOTS}, but got {SERVICE_ROOT}"
)
assert LP_APP_NAME, "BUGIT_APP_NAME was not specified"
assert LP_AUTH_FILE_PATH.exists(), "At this point auth should already be valid"
if SERVICE_ROOT not in VALID_SERVICE_ROOTS:
raise RuntimeError(
"Invalid APPORT_LAUNCHPAD_INSTANCE, "
f"expected one of {VALID_SERVICE_ROOTS}, but got {SERVICE_ROOT}"
)
if not LP_APP_NAME:
raise RuntimeError("BUGIT_APP_NAME was not specified")
if not LP_AUTH_FILE_PATH.exists():
raise RuntimeError("At this point auth should already be valid")

yield f"Logging into Launchpad: {SERVICE_ROOT}"
try:
Expand Down Expand Up @@ -368,7 +380,8 @@ def submit(
bug_report.project # index access also has a side effect
],
)
assert self.lp_bug_object, "Unexpected null bug"
if not self.lp_bug_object:
raise RuntimeError("Unexpected null bug")
# https://documentation.ubuntu.com/launchpad/user/explanation/launchpad-api/launchpadlib/#persistent-references-to-launchpad-objects
yield AdvanceMessage(
f"Created bug: {self.lp_bug_object!s}" # pyright: ignore[reportUnknownArgumentType]
Expand Down Expand Up @@ -399,7 +412,8 @@ def submit(
def upload_attachment(
self, attachment_file: Path, filename: str | None = None
) -> str | None:
assert self.lp_bug_object, "No launchpad bug has been created or fetched"
if not self.lp_bug_object:
raise RuntimeError("No launchpad bug has been created or fetched")
with open(attachment_file, "rb") as f:
# this might explode on low memory systems
# but idk how to work around it
Expand All @@ -412,7 +426,8 @@ def upload_attachment(
@property
@override
def bug_url(self) -> str:
assert self.lp_bug_object, "No launchpad bug has been created or fetched"
if not self.lp_bug_object:
raise RuntimeError("No launchpad bug has been created or fetched")
match SERVICE_ROOT:
case "production":
return f"{LPNET_WEB_ROOT}bugs/{self.lp_bug_object.id}"
Expand Down
11 changes: 8 additions & 3 deletions src/bugit_v2/bug_report_submitters/local_file_submitter.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,14 @@ def get_cached_credentials(self) -> None:
@property
@override
def bug_url(self) -> str:
assert self.archive_path, "Report archive not created"
if not self.archive_path:
raise FileNotFoundError("Report archive not created")
return str(self.archive_path)

@override
def finalize(self) -> str:
assert self.archive_name, "Unexpected call before archive name was determined"
if not self.archive_name:
raise RuntimeError("Unexpected call before archive name was determined")

working_dir = Path(self.working_dir.name)

Expand All @@ -126,7 +128,10 @@ def finalize(self) -> str:
format="gztar",
)
)
assert self.archive_path.exists()
if not self.archive_path.exists():
raise FileNotFoundError(
f"Archive {self.archive_path} was not created as expected"
)
self.finalize_ok = True
return f"The bug report archive is at {self.archive_path}"
except Exception as e:
Expand Down
21 changes: 14 additions & 7 deletions src/bugit_v2/bug_report_submitters/mock_jira.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ def project_exists(self, project_name: str) -> None:
https://hostname.com/jira/software/c/projects/NAME
:return: true if the project exists
"""
assert self.jira, "Jira object is not initialized"
if not self.jira:
raise JiraSubmitterError("Jira object is not initialized")
try:
self.jira.project(id=project_name)
except Exception:
Expand All @@ -66,7 +67,8 @@ def assignee_exists_and_unique(self, assignee: str) -> None:
:param assignee: the email of the assignee or some form of ID
:return: exists and unique
"""
assert self.jira, "Jira object is not initialized"
if not self.jira:
raise JiraSubmitterError("Jira object is not initialized")

query_result = self.jira.search_users(query=assignee)
if len(query_result) == 0:
Expand All @@ -75,7 +77,8 @@ def assignee_exists_and_unique(self, assignee: str) -> None:
raise JiraSubmitterError(f"Assignee '{assignee}' isn't unique!")

def all_components_exist(self, project: str, components: Sequence[str]) -> None:
assert self.jira, "Jira object is not initialized"
if not self.jira:
raise JiraSubmitterError("Jira object is not initialized")
# the @translate_args decorator confuses the type checker
query_result = cast(list[Component], self.jira.project_components(project))
for wanted_component in components:
Expand All @@ -89,7 +92,8 @@ def all_components_exist(self, project: str, components: Sequence[str]) -> None:

@override
def bug_exists(self, bug_id: str) -> bool:
assert self.auth
if not self.auth:
raise JiraSubmitterError("Missing auth credentials")

try:
if not self.jira:
Expand Down Expand Up @@ -123,8 +127,10 @@ def submit(
"issuetype": {"name": "Bug"},
}

assert self.auth, "Missing auth credentials"
assert JIRA_SERVER_ADDRESS, "JIRA_SERVER is not specified!"
if not self.auth:
raise JiraSubmitterError("Missing auth credentials")
if not JIRA_SERVER_ADDRESS:
raise JiraSubmitterError("JIRA_SERVER is not specified!")

yield "Starting Jira authentication..."
self.jira = JIRA(
Expand Down Expand Up @@ -190,7 +196,8 @@ def upload_attachment(
@property
@override
def bug_url(self) -> str:
assert self.mock_issue
if not self.mock_issue:
raise JiraSubmitterError("Nothing has been submitted to Jira yet")
return "http://example.com/"

@override
Expand Down
24 changes: 15 additions & 9 deletions src/bugit_v2/bug_report_submitters/mock_lp.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ class MockLaunchpadSubmitter(BugReportSubmitter[Path]):
auth_modal = LaunchpadAuthModal

def check_project_existence(self, project_name: str) -> Any:
assert self.lp_client
if not self.lp_client:
raise RuntimeError("Launchpad client is not initialized")
try:
# type checker freaks out here
# since launchpad lib wants unknown member access + index access
Expand All @@ -55,7 +56,8 @@ def check_project_existence(self, project_name: str) -> Any:
raise ValueError(error_message)

def check_assignee_existence(self, assignee: str) -> Any:
assert self.lp_client
if not self.lp_client:
raise RuntimeError("Launchpad client is not initialized")
try:
return self.lp_client.people[ # pyright: ignore[reportIndexIssue, reportOptionalSubscript, reportUnknownVariableType]
assignee
Expand All @@ -65,7 +67,8 @@ def check_assignee_existence(self, assignee: str) -> Any:
raise ValueError(error_message)

def check_series_existence(self, series: str) -> Any:
assert self.lp_client
if not self.lp_client:
raise RuntimeError("Launchpad client is not initialized")
try:
return self.lp_client.project.getSeries( # pyright: ignore[reportAttributeAccessIssue, reportOptionalMemberAccess, reportUnknownVariableType]
name=series
Expand All @@ -83,12 +86,15 @@ def submit(
self, bug_report: BugReport
) -> Generator[str | AdvanceMessage, None, None]:

assert SERVICE_ROOT in VALID_SERVICE_ROOTS, (
"Invalid APPORT_LAUNCHPAD_INSTANCE, "
f"expected one of {VALID_SERVICE_ROOTS}, but got {SERVICE_ROOT}"
)
assert LP_APP_NAME, "BUGIT_APP_NAME was not specified"
assert LP_AUTH_FILE_PATH.exists(), "At this point auth should already be valid"
if SERVICE_ROOT not in VALID_SERVICE_ROOTS:
raise RuntimeError(
"Invalid APPORT_LAUNCHPAD_INSTANCE, "
f"expected one of {VALID_SERVICE_ROOTS}, but got {SERVICE_ROOT}"
)
if not LP_APP_NAME:
raise RuntimeError("BUGIT_APP_NAME was not specified")
if not LP_AUTH_FILE_PATH.exists():
raise RuntimeError("At this point auth should already be valid")

yield f"Logging into Launchpad: {SERVICE_ROOT}"
try:
Expand Down
3 changes: 2 additions & 1 deletion src/bugit_v2/checkbox_utils/checkbox_exec.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ async def checkbox_exec(
:return: whatever subprocess.run returns
"""
checkbox_info = get_checkbox_info()
assert checkbox_info, "Unable to find checkbox on this DUT"
if not checkbox_info:
raise RuntimeError("Unable to find checkbox on this DUT")

logger.info(f"Checkbox args: {checkbox_args}")
if additional_env:
Expand Down
5 changes: 4 additions & 1 deletion src/bugit_v2/checkbox_utils/submission_extractor.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@
def read_simple_submission(submission_path: Path) -> SimpleCheckboxSubmission:
with tarfile.open(submission_path, "r:xz") as f:
json_io_reader = f.extractfile("submission.json")
assert json_io_reader, f"submission.json does not exist in {submission_path}"
if not json_io_reader:
raise FileNotFoundError(
f"submission.json does not exist in {submission_path}"
)
Comment thread
tomli380576 marked this conversation as resolved.
return SimpleCheckboxSubmission(
submission_path.absolute(),
BaseSimpleCheckboxSubmission.model_validate(
Expand Down
3 changes: 2 additions & 1 deletion src/bugit_v2/components/confirm_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,6 @@ def on_mount(self) -> None:
self.query_exactly_one(f"#{self.focus_id_on_mount}", Button).focus()

def on_button_pressed(self, event: Button.Pressed) -> None:
assert event.button.id
if not event.button.id:
raise RuntimeError("Button pressed without an id")
self.dismiss(cast(T, event.button.id))
3 changes: 2 additions & 1 deletion src/bugit_v2/components/file_picker.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,8 @@ def on_mount(self):

@on(Button.Pressed, ".delete_selection")
def delete_file_from_list(self, event: Button.Pressed):
assert event.button.name is not None
if event.button.name is None:
raise RuntimeError("Delete button is missing its file name")
try:
self._chosen_files.remove(Path(event.button.name))
self.post_message(self.FilesUpdated(list(self._chosen_files)))
Expand Down
Loading