Skip to content

🧹 [Code Health Improvement] Simplify verify_access_and_get_folders#805

Open
abhimehro wants to merge 2 commits into
mainfrom
chore/simplify-verify-access-8559911743973236436
Open

🧹 [Code Health Improvement] Simplify verify_access_and_get_folders#805
abhimehro wants to merge 2 commits into
mainfrom
chore/simplify-verify-access-8559911743973236436

Conversation

@abhimehro
Copy link
Copy Markdown
Owner

@abhimehro abhimehro commented May 14, 2026

🎯 What: Simplified deeply nested logic in verify_access_and_get_folders by extracting JSON parsing to _parse_folders_response and error logging to _log_auth_error.
💡 Why: Reduces cyclomatic complexity and improves maintainability by decomposing a Brain Method into logical sub-steps.
Verification: Verified safe via full regression test suite (uv run pytest tests/) and linter (ruff).
Result: Enhanced readability without altering behavior.


PR created automatically by Jules for task 8559911743973236436 started by @abhimehro


Open in Devin Review

Co-authored-by: abhimehro <84992105+abhimehro@users.noreply.github.com>
@google-labs-jules
Copy link
Copy Markdown

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

Copilot AI review requested due to automatic review settings May 14, 2026 14:26
@trunk-io
Copy link
Copy Markdown

trunk-io Bot commented May 14, 2026

Merging to main in this repository is managed by Trunk.

  • To merge this pull request, check the box to the left or comment /trunk merge below.

After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here

@cursor
Copy link
Copy Markdown

cursor Bot commented May 14, 2026

PR Summary

Low Risk
Low risk refactor that only extracts existing response-parsing and 401/403/404 logging logic into helpers; primary risk is minor behavior drift in error handling if the helpers are called differently.

Overview
Simplifies verify_access_and_get_folders by extracting response-shape validation and folder mapping into _parse_folders_response, and consolidating 401/403/404 messaging into _log_auth_error.

Behavior is intended to remain the same, but the access check now delegates JSON parsing and auth-related logging to these helpers, reducing nesting and cyclomatic complexity.

Reviewed by Cursor Bugbot for commit d89d876. Configure here.

Copy link
Copy Markdown

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 3 potential issues.

Open in Devin Review

Comment thread main.py
Comment thread main.py Outdated
Comment on lines +1786 to +1807
def _log_auth_error(code: int, profile_id: str) -> None:
if code == 401:
log.critical(
f"{Colors.FAIL}❌ Authentication Failed: The API Token is invalid.{Colors.ENDC}"
)
log.critical(
f"{Colors.FAIL} Please check your token at: https://controld.com/account/manage-account{Colors.ENDC}"
)
elif code == 403:
log.critical(
"%s🚫 Access Denied: Token lacks permission for Profile %s.%s",
Colors.FAIL,
sanitize_for_log(profile_id),
Colors.ENDC,
)
elif code == 404:
log.critical(
f"{Colors.FAIL}🔍 Profile Not Found: The ID '{sanitize_for_log(profile_id)}' does not exist.{Colors.ENDC}"
)
log.critical(
f"{Colors.FAIL} Please verify the Profile ID from your Control D Dashboard URL.{Colors.ENDC}"
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Info: Inconsistent logging style between 401/404 (f-string) and 403 (%-formatting) in _log_auth_error

The _log_auth_error function uses f-string interpolation for the 401 and 404 branches (main.py:1789, main.py:1803) but uses %s-style lazy formatting for the 403 branch (main.py:1796-1800). This inconsistency was inherited from the original inline code in verify_access_and_get_folders, so it's pre-existing rather than introduced by this PR. It's not a bug (both styles work), but it's worth noting for consistency if the author is already touching this code.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread main.py
Comment on lines 1895 to 1899
try:
data = resp.json()

# Ensure we got the expected top-level JSON structure.
# We defensively validate types here so that unexpected but valid
# JSON (e.g., a list or a scalar) doesn't cause AttributeError/TypeError
# and cause the operation to fail unexpectedly.
if not isinstance(data, dict):
log.error(
"Failed to parse folders data: expected JSON object at top level, "
f"got {type(data).__name__}"
)
return None

body = data.get("body")
if not isinstance(body, dict):
log.error(
"Failed to parse folders data: expected 'body' to be an object, "
f"got {type(body).__name__ if body is not None else 'None'}"
)
return None

folders = body.get("groups", [])
if not isinstance(folders, list):
log.error(
"Failed to parse folders data: expected 'body[\"groups\"]' to be a list, "
f"got {type(folders).__name__}"
)
return None

# Only process entries that are dicts and have the required keys.
result: dict[str, str] = {}
for f in folders:
if not isinstance(f, dict):
# Skip non-dict entries instead of crashing; this protects
# against partial data corruption or unexpected API changes.
continue
name = f.get("group")
pk = f.get("PK")
# Skip entries with empty or None values for required fields
if not name or not pk:
continue

pk_str = str(pk)
if not validate_folder_id(pk_str):
continue

result[str(name).strip()] = pk_str

return result
return _parse_folders_response(resp.json())
except (ValueError, TypeError, AttributeError) as err:
# As a final safeguard, catch any remaining parsing/shape errors so
# that a malformed response cannot crash the caller.
log.error("Failed to parse folders data: %s", sanitize_for_log(err))
return None
Copy link
Copy Markdown

@devin-ai-integration devin-ai-integration Bot May 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Info: Refactoring correctly preserves original behavior

The extraction of parsing logic into _parse_folders_response and auth error logging into _log_auth_error is a faithful refactor. The call at main.py:1896 (return _parse_folders_response(resp.json())) correctly replaces the old inline parsing, and the except clause at line 1897 still catches ValueError/TypeError/AttributeError from resp.json() (which can throw if the response body isn't valid JSON). The _parse_folders_response function itself doesn't raise these exceptions (it returns None on bad input), so the try/except only guards the resp.json() call, which is the correct behavior.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

codescene-delta-analysis[bot]

This comment was marked as outdated.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Co-authored-by: abhimehro <84992105+abhimehro@users.noreply.github.com>
Copy link
Copy Markdown

@codescene-delta-analysis codescene-delta-analysis Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gates Passed
6 Quality Gates Passed

See analysis details in CodeScene

Quality Gate Profile: Pay Down Tech Debt
Install CodeScene MCP: safeguard and uplift AI-generated code. Catch issues early with our IDE extension and CLI tool.

Copy link
Copy Markdown

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 new potential issues.

Open in Devin Review

Comment thread main.py
Comment on lines +1786 to +1808
def _log_auth_error(code: int, profile_id: str) -> None:
if code == 401:
log.critical(
f"{Colors.FAIL}❌ Authentication Failed: The API Token is invalid.{Colors.ENDC}"
)
log.critical(
f"{Colors.FAIL} Please check your token at: https://controld.com/account/manage-account{Colors.ENDC}"
)
elif code == 403:
log.critical(
"%s🚫 Access Denied: Token lacks permission for Profile %s.%s",
Colors.FAIL,
sanitize_for_log(profile_id),
Colors.ENDC,
)
elif code == 404:
log.critical(
f"{Colors.FAIL}🔍 Profile Not Found: The ID '{sanitize_for_log(profile_id)}' does not exist.{Colors.ENDC}"
)
log.critical(
f"{Colors.FAIL} Please verify the Profile ID from your Control D Dashboard URL.{Colors.ENDC}"
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚩 check_api_access does not use the new _log_auth_error helper

The new _log_auth_error helper at main.py:1786 centralizes auth error logging for 401/403/404 codes. However, check_api_access at main.py:1666 still uses its own inline logging for the same error codes. Additionally, check_api_access at line 1689 does NOT sanitize profile_id in the 403 f-string (f"...Profile {profile_id}...") whereas the extracted _log_auth_error at line 1796-1800 does use sanitize_for_log(profile_id). This is a pre-existing inconsistency that the refactoring didn't address — both functions handle the same error codes but only one sanitizes the profile ID for the 403 case.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread main.py
Comment on lines +1741 to +1743
def _parse_folders_response(data: dict) -> dict[str, str] | None:
# Ensure we got the expected top-level JSON structure.
if not isinstance(data, dict):
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Info: Type hint data: dict is narrower than actual input from resp.json()

The _parse_folders_response parameter is typed data: dict but resp.json() can return any JSON type (list, str, int, None, etc.). The function correctly handles this at runtime via the isinstance(data, dict) check on line 1743, and from __future__ import annotations (line 16) makes the annotation a string at runtime so no TypeError occurs. However, the type hint is misleading — Any would be more accurate and would prevent a type checker from flagging callers that pass non-dict values (which is the intended defensive use case).

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants