archive and unarchive and delete api integration - #39
Conversation
Code Review SummaryI've reviewed PR #39 for the archive, unarchive, and delete API integration. Overall, the implementation is functional but there are several issues that should be addressed: ✅ Positives
|
|
|
||
| payload = json.dumps({"project_id": self.project_id}) | ||
|
|
||
| headers = {"content-type": "application/json"} |
There was a problem hiding this comment.
Inconsistent header casing: The codebase predominantly uses lowercase content-type (see lines 42, 128, 211, 263, 576, 613). Recommend changing to lowercase for consistency:
| headers = {"content-type": "application/json"} | |
| headers = {"content-type": "application/json"} |
|
|
||
|
|
There was a problem hiding this comment.
Code style: Extra blank line here is inconsistent with other methods in this file. Should be removed for consistency.
|
|
||
| def delete(self): |
There was a problem hiding this comment.
Code style: Extra blank line should be removed for consistency with other methods.
| url = f"{constants.BASE_URL}/projects/project/{self.project_id}?client_id={self.client.client_id}&uuid={unique_id}" | ||
|
|
There was a problem hiding this comment.
Code style: Extra blank line should be removed for consistency.
| return self.client.make_request( | ||
| "POST", | ||
| url, | ||
| extra_headers=headers, | ||
| request_id=unique_id, | ||
| data=payload, | ||
| ) |
There was a problem hiding this comment.
Inconsistent response handling: This method returns the raw response, but other similar methods like import_users (line 645) return response.get(\"response\"). Should clarify and document the expected return format. Consider either:
- Extracting nested response for consistency, or
- Documenting why this returns full response object
| return self.client.make_request( | ||
| "DELETE", | ||
| url, | ||
| extra_headers=headers, | ||
| request_id=unique_id, | ||
| ) |
There was a problem hiding this comment.
Missing validation: Consider validating:
- Project exists before attempting deletion
- User has permission to delete
- Project isn't already deleted
Also, response handling: Same issue as archive() - should document if full response or nested data should be returned.
| from unittest.mock import patch, Mock | ||
| import json | ||
| from labellerr.core.projects.image_project import ImageProject | ||
| from labellerr.core.users.base import LabellerrUsers |
There was a problem hiding this comment.
Unused import: LabellerrUsers is imported but never used in this file. Should be removed.
| def test_archive_project(self, project, client): | ||
| """Test archiving a project""" | ||
| mock_response = {"status": "success", "msg": "Project archived"} | ||
|
|
||
| with patch.object(client, "make_request", return_value=mock_response) as mock_req: | ||
| response = project.archive() | ||
|
|
||
| assert response == mock_response | ||
|
|
||
| # Verify the request | ||
| mock_req.assert_called_once() | ||
| args, kwargs = mock_req.call_args | ||
| assert args[0] == "POST" | ||
| assert "/projects/archive" in args[1] | ||
| assert kwargs["data"] is not None | ||
| assert '"project_id": "test_project_id"' in kwargs["data"] |
There was a problem hiding this comment.
Test coverage gap: The test only verifies the request was made, but should also verify:
- The request includes the correct
uuidin the URL - The
request_idparameter matches theuuid - The payload is properly formatted JSON
Consider adding these assertions:
assert kwargs.get(\"request_id\") is not None
assert f\"uuid={kwargs['request_id']}\" in args[1]| # 1. Archive | ||
| print(f"Archiving project {project.project_id}...") | ||
| try: | ||
| project.archive() | ||
| except Exception as e: | ||
| pytest.fail(f"Failed to archive project: {e}") |
There was a problem hiding this comment.
Weak assertions: The test should verify:
- Response status/success indicator
- Response structure matches expected format
- Consider checking project state via a GET request to confirm it's actually archived
Current implementation only checks that no exception was raised, which is insufficient for integration testing.
| print(f"Deleting project {project.project_id}...") | ||
| try: | ||
| project.delete() | ||
| except Exception as e: | ||
| pytest.fail(f"Failed to delete project: {e}") |
There was a problem hiding this comment.
Test completeness: After deleting, the test should:
- Verify the delete response indicates success
- Optionally attempt to fetch the project and verify it returns a 404 or "not found" error
- Check that subsequent operations on the deleted project fail appropriately
This ensures the delete actually worked and wasn't just a no-op.
| from enum import Enum | ||
| from typing import List, Literal | ||
| from uuid import UUID | ||
|
|
||
| from .base import DatasetDataType | ||
| from pydantic import BaseModel, Field, field_validator | ||
|
|
||
|
|
||
| class DataSetScope(StrEnum): | ||
| class DataSetScope(str, Enum): |
There was a problem hiding this comment.
Good fix: Changing from StrEnum (Python 3.11+) to str, Enum is correct for maintaining Python 3.7+ compatibility as specified in pyproject.toml. The behavior is equivalent and this ensures backward compatibility. ✅
| payload = json.dumps({"project_id": self.project_id}) | ||
|
|
||
| headers = {"content-type": "application/json"} | ||
| if self.client.api_key: |
There was a problem hiding this comment.
no need for this check, it will always be there
| """ | ||
| unique_id = str(uuid.uuid4()) | ||
|
|
||
| url = f"{constants.BASE_URL}/projects/project/{self.project_id}?client_id={self.client.client_id}&uuid={unique_id}" |
There was a problem hiding this comment.
i think the url is incorrect
|
|
||
| return self.client.make_request( | ||
| "DELETE", | ||
| url, | ||
| extra_headers=headers, | ||
| request_id=unique_id, | ||
| ) |
There was a problem hiding this comment.
since we don't allow delete http method, lets use POST
No description provided.