Consolidate API access check and folder listing into single request#179
Consolidate API access check and folder listing into single request#179
Conversation
|
😎 Merged manually by @abhimehro - details. |
|
👋 Development Partner is reviewing this PR. Will provide feedback shortly. |
Co-authored-by: abhimehro <84992105+abhimehro@users.noreply.github.com>
|
👋 Development Partner is reviewing this PR. Will provide feedback shortly. |
|
👋 Development Partner is reviewing this PR. Will provide feedback shortly. |
| mock_response.raise_for_status.return_value = None | ||
|
|
||
| result = m.verify_access_and_get_folders(mock_client, "valid_profile") | ||
| assert result == {"Folder A": "id_a", "Folder B": "id_b"} |
Check notice
Code scanning / Bandit
Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test
| monkeypatch.setattr(m, "log", mock_log) | ||
|
|
||
| assert m.check_api_access(mock_client, "invalid_token") is False | ||
| assert m.verify_access_and_get_folders(mock_client, "invalid_token") is None |
Check notice
Code scanning / Bandit
Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test
| monkeypatch.setattr(m, "log", mock_log) | ||
|
|
||
| assert m.check_api_access(mock_client, "forbidden_profile") is False | ||
| assert m.verify_access_and_get_folders(mock_client, "forbidden_profile") is None |
Check notice
Code scanning / Bandit
Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test
| monkeypatch.setattr(m, "log", mock_log) | ||
|
|
||
| assert m.check_api_access(mock_client, "missing_profile") is False | ||
| assert m.verify_access_and_get_folders(mock_client, "missing_profile") is None |
Check notice
Code scanning / Bandit
Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test
| monkeypatch.setattr(m, "MAX_RETRIES", 2) | ||
|
|
||
| assert m.check_api_access(mock_client, "profile") is False | ||
| assert m.verify_access_and_get_folders(mock_client, "profile") is None |
Check notice
Code scanning / Bandit
Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test
|
|
||
| assert m.check_api_access(mock_client, "profile") is False | ||
| assert m.verify_access_and_get_folders(mock_client, "profile") is None | ||
| assert mock_client.get.call_count == 2 |
Check notice
Code scanning / Bandit
Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test
| monkeypatch.setattr(m, "MAX_RETRIES", 2) | ||
|
|
||
| assert m.check_api_access(mock_client, "profile") is False | ||
| assert m.verify_access_and_get_folders(mock_client, "profile") is None |
Check notice
Code scanning / Bandit
Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test
|
|
||
| assert m.check_api_access(mock_client, "profile") is False | ||
| assert m.verify_access_and_get_folders(mock_client, "profile") is None | ||
| assert mock_client.get.call_count == 2 |
Check notice
Code scanning / Bandit
Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test
| assert mock_log.error.called | ||
| assert "Network failure" in str(mock_log.error.call_args) | ||
| error_msg = str(mock_log.error.call_args) | ||
| assert "Network error" in error_msg or "access verification" in error_msg |
Check notice
Code scanning / Bandit
Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test
| mock_response.raise_for_status.return_value = None | ||
|
|
||
| result = m.verify_access_and_get_folders(mock_client, "valid_profile") | ||
| assert result == {"Folder A": "id_a", "Folder B": "id_b"} |
Check notice
Code scanning / Bandit (reported by Codacy)
Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test
| monkeypatch.setattr(m, "log", mock_log) | ||
|
|
||
| assert m.check_api_access(mock_client, "invalid_token") is False | ||
| assert m.verify_access_and_get_folders(mock_client, "invalid_token") is None |
Check notice
Code scanning / Bandit (reported by Codacy)
Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test
| monkeypatch.setattr(m, "log", mock_log) | ||
|
|
||
| assert m.check_api_access(mock_client, "forbidden_profile") is False | ||
| assert m.verify_access_and_get_folders(mock_client, "forbidden_profile") is None |
Check notice
Code scanning / Bandit (reported by Codacy)
Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test
| monkeypatch.setattr(m, "log", mock_log) | ||
|
|
||
| assert m.check_api_access(mock_client, "missing_profile") is False | ||
| assert m.verify_access_and_get_folders(mock_client, "missing_profile") is None |
Check notice
Code scanning / Bandit (reported by Codacy)
Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test
| monkeypatch.setattr(m, "MAX_RETRIES", 2) | ||
|
|
||
| assert m.check_api_access(mock_client, "profile") is False | ||
| assert m.verify_access_and_get_folders(mock_client, "profile") is None |
Check notice
Code scanning / Bandit (reported by Codacy)
Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test
|
|
||
| assert m.check_api_access(mock_client, "profile") is False | ||
| assert m.verify_access_and_get_folders(mock_client, "profile") is None | ||
| assert mock_client.get.call_count == 2 |
Check notice
Code scanning / Bandit (reported by Codacy)
Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test
| monkeypatch.setattr(m, "MAX_RETRIES", 2) | ||
|
|
||
| assert m.check_api_access(mock_client, "profile") is False | ||
| assert m.verify_access_and_get_folders(mock_client, "profile") is None |
Check notice
Code scanning / Bandit (reported by Codacy)
Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test
|
|
||
| assert m.check_api_access(mock_client, "profile") is False | ||
| assert m.verify_access_and_get_folders(mock_client, "profile") is None | ||
| assert mock_client.get.call_count == 2 |
Check notice
Code scanning / Bandit (reported by Codacy)
Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test
| assert mock_log.error.called | ||
| assert "Network failure" in str(mock_log.error.call_args) | ||
| error_msg = str(mock_log.error.call_args) | ||
| assert "Network error" in error_msg or "access verification" in error_msg |
Check notice
Code scanning / Bandit (reported by Codacy)
Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. Note test
|
|
||
| body = data.get("body") | ||
| if not isinstance(body, dict): | ||
| log.error( |
Check warning
Code scanning / Pylint (reported by Codacy)
Too many return statements (8/6) Warning
|
|
||
| body = data.get("body") | ||
| if not isinstance(body, dict): | ||
| log.error( |
Check warning
Code scanning / Pylint (reported by Codacy)
Too many branches (17/12) Warning
|
|
||
| body = data.get("body") | ||
| if not isinstance(body, dict): | ||
| log.error( |
Check warning
Code scanning / Pylint (reported by Codacy)
Too many local variables (17/15) Warning
| body = data.get("body") | ||
| if not isinstance(body, dict): | ||
| log.error( | ||
| "Failed to parse folders data: expected 'body' to be an object, " |
Check warning
Code scanning / Pylint (reported by Codacy)
Wrong hanging indentation before block (add 4 spaces). Warning
| f"{Colors.FAIL} Please check your token at: https://controld.com/account/manage-account{Colors.ENDC}" | ||
| ) | ||
| elif code == 403: | ||
| log.critical( |
Check warning
Code scanning / Pylint (reported by Codacy)
Variable name "f" doesn't conform to snake_case naming style Warning
| return None | ||
|
|
||
|
|
||
| def get_all_existing_rules( |
Check warning
Code scanning / Pylint (reported by Codacy)
Line too long (121/100) Warning
| # Case 7: check_api_access handles success and errors correctly | ||
| def test_check_api_access_success(monkeypatch): | ||
| # Case 7: verify_access_and_get_folders handles success and errors correctly | ||
| def test_verify_access_and_get_folders_success(monkeypatch): |
Check warning
Code scanning / Pylint (reported by Codacy)
Missing function docstring Warning test
| assert result == {"Folder A": "id_a", "Folder B": "id_b"} | ||
|
|
||
|
|
||
| def test_verify_access_and_get_folders_401(monkeypatch): |
Check warning
Code scanning / Pylint (reported by Codacy)
Missing function docstring Warning test
|
|
||
|
|
||
| def test_check_api_access_403(monkeypatch): | ||
| def test_verify_access_and_get_folders_403(monkeypatch): |
Check warning
Code scanning / Pylint (reported by Codacy)
Missing function docstring Warning test
|
|
||
|
|
||
| def test_check_api_access_404(monkeypatch): | ||
| def test_verify_access_and_get_folders_404(monkeypatch): |
Check warning
Code scanning / Pylint (reported by Codacy)
Missing function docstring Warning test
|
|
||
|
|
||
| def test_check_api_access_404(monkeypatch): | ||
| def test_verify_access_and_get_folders_404(monkeypatch): |
Check warning
Code scanning / Pylintpython3 (reported by Codacy)
Missing function or method docstring Warning test
|
|
||
|
|
||
| def test_check_api_access_403(monkeypatch): | ||
| def test_verify_access_and_get_folders_403(monkeypatch): |
Check warning
Code scanning / Pylintpython3 (reported by Codacy)
Missing function or method docstring Warning test
| assert result == {"Folder A": "id_a", "Folder B": "id_b"} | ||
|
|
||
|
|
||
| def test_verify_access_and_get_folders_401(monkeypatch): |
Check warning
Code scanning / Pylintpython3 (reported by Codacy)
Missing function or method docstring Warning test
| # Case 7: check_api_access handles success and errors correctly | ||
| def test_check_api_access_success(monkeypatch): | ||
| # Case 7: verify_access_and_get_folders handles success and errors correctly | ||
| def test_verify_access_and_get_folders_success(monkeypatch): |
Check warning
Code scanning / Pylintpython3 (reported by Codacy)
Missing function or method docstring Warning test
|
|
||
| existing_folders = list_existing_folders(client, profile_id) | ||
| if not no_delete: | ||
| deletion_occurred = False |
Check warning
Code scanning / Pylintpython3 (reported by Codacy)
Line too long (121/100) Warning
|
|
||
| # Only process entries that are dicts and have the required keys. | ||
| result: Dict[str, str] = {} | ||
| for f in folders: |
Check warning
Code scanning / Pylintpython3 (reported by Codacy)
Too many return statements (8/6) Warning
|
|
||
| # Only process entries that are dicts and have the required keys. | ||
| result: Dict[str, str] = {} | ||
| for f in folders: |
Check warning
Code scanning / Pylintpython3 (reported by Codacy)
Too many branches (17/12) Warning
| return False | ||
|
|
||
| existing_folders = list_existing_folders(client, profile_id) | ||
| if not no_delete: |
Check notice
Code scanning / Pylintpython3 (reported by Codacy)
Use lazy % formatting in logging functions Note
main.py
Outdated
Check notice
Code scanning / Pylintpython3 (reported by Codacy)
Use lazy % formatting in logging functions Note
main.py
Outdated
Check notice
Code scanning / Pylintpython3 (reported by Codacy)
Use lazy % formatting in logging functions Note
There was a problem hiding this comment.
Pull request overview
This PR reduces Control D API latency by consolidating the access check and folder listing into a single /groups request via a new helper, and updates tests/docs accordingly.
Changes:
- Add
verify_access_and_get_folders()to combine access verification + folder map retrieval in one call (with retry logic). - Update
sync_profile()and parallel deletion tests to use the combined helper instead ofcheck_api_access()+list_existing_folders(). - Update unit tests and documentation to reflect the new helper and behavior.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
main.py |
Introduces verify_access_and_get_folders() and switches sync_profile() to the single-call approach. |
test_main.py |
Replaces check_api_access tests with coverage for verify_access_and_get_folders (success, auth errors, retry, network errors). |
tests/test_parallel_deletion.py |
Updates mocks to use verify_access_and_get_folders() so deletion tests match the new call flow. |
WARP.md |
Documents the new helper and updated workflow in the API helper section. |
| log.warning( | ||
| "Request failed (attempt %d/%d). Retrying in %ds...", | ||
| attempt + 1, | ||
| MAX_RETRIES, | ||
| wait_time, | ||
| ) |
There was a problem hiding this comment.
The retry log message uses a %d placeholder for wait_time, but wait_time can be a float (e.g., if RETRY_DELAY is configured/overridden as a non-integer for faster retries). Using %d will raise a formatting TypeError at runtime. Consider switching to %s/%.3f (or explicitly casting) so retries can't crash due to logging format mismatch.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
👋 Development Partner is reviewing this PR. Will provide feedback shortly. |
|
👋 Development Partner is reviewing this PR. Will provide feedback shortly. |
Consolidates open PR #178 which was blocked by linting violations. The core change reduces API latency by combining two sequential requests into one.
Changes
API optimization
check_api_access()+list_existing_folders()sequence withverify_access_and_get_folders()/groupsendpoint validates access and returns folder mapBefore:
After:
Linting fixes from original PR
e→errfor exception handlersPost-merge cleanup
copilot/review-open-pull-requests,copilot/refactor-pull-request-170Original prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.