Skip to content

Commit b023763

Browse files
authored
Merge pull request #42 from GlobalFishingWatch/feature/bulk-downloads-list
implement get all bulk reports by user (list) API endpoints and request/response models
2 parents 7c4cc32 + 4dc68f5 commit b023763

File tree

12 files changed

+418
-0
lines changed

12 files changed

+418
-0
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
"""Global Fishing Watch (GFW) API Python Client - Get All Bulk Reports.
2+
3+
This module provides the endpoint and associated functionalities for retrieving details
4+
of multiple previously created bulk reports. It defines the `BulkReportListEndPoint`
5+
class, which handles the construction and execution of API requests, and the parsing
6+
of API responses for Get All Bulk Reports API endpoint.
7+
8+
For detailed information about the Get All Bulk Reports API endpoint, please refer to
9+
the official Global Fishing Watch API documentation:
10+
11+
See: https://globalfishingwatch.org/our-apis/documentation#get-all-bulk-reports-by-user
12+
13+
For more details on the Get All Bulk Reports data caveats, please refer to the
14+
official Global Fishing Watch API documentation:
15+
16+
See: https://globalfishingwatch.org/our-apis/documentation#sar-fixed-infrastructure-data-caveats
17+
"""
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
"""Global Fishing Watch (GFW) API Python Client - Get All Bulk Reports API endpoint."""
2+
3+
from typing import Any, Dict, List, Union
4+
5+
from typing_extensions import override
6+
7+
from gfwapiclient.exceptions.validation import ResultValidationError
8+
from gfwapiclient.http.client import HTTPClient
9+
from gfwapiclient.http.endpoints import GetEndPoint
10+
from gfwapiclient.http.models import RequestBody
11+
from gfwapiclient.resources.bulk_downloads.list.models.request import (
12+
BulkReportListParams,
13+
)
14+
from gfwapiclient.resources.bulk_downloads.list.models.response import (
15+
BulkReportListItem,
16+
BulkReportListResult,
17+
)
18+
19+
20+
__all__ = ["BulkReportListEndPoint"]
21+
22+
23+
class BulkReportListEndPoint(
24+
GetEndPoint[
25+
BulkReportListParams, RequestBody, BulkReportListItem, BulkReportListResult
26+
],
27+
):
28+
"""Get All Bulk Reports API endpoint.
29+
30+
This endpoint retrieves a list of metadata and status of the previously created
31+
bulk reports based on the provided request parameters.
32+
33+
For more details on the Get All Bulk Reports API endpoint, please refer to the
34+
official Global Fishing Watch API documentation:
35+
36+
See: https://globalfishingwatch.org/our-apis/documentation#get-all-bulk-reports-by-user
37+
"""
38+
39+
def __init__(
40+
self,
41+
*,
42+
request_params: BulkReportListParams,
43+
http_client: HTTPClient,
44+
) -> None:
45+
"""Initializes a new `BulkReportListEndPoint`.
46+
47+
Args:
48+
request_params (BulkReportListParams):
49+
The request parameters.
50+
51+
http_client (HTTPClient):
52+
The HTTP client used to make the API call.
53+
"""
54+
super().__init__(
55+
path="bulk-reports",
56+
request_params=request_params,
57+
result_item_class=BulkReportListItem,
58+
result_class=BulkReportListResult,
59+
http_client=http_client,
60+
)
61+
62+
@override
63+
def _transform_response_data(
64+
self,
65+
*,
66+
body: Union[List[Dict[str, Any]], Dict[str, Any]],
67+
) -> Union[List[Dict[str, Any]], Dict[str, Any]]:
68+
"""Transform and reshape response body and yield data.
69+
70+
This method transforms the raw response body from the API into a format
71+
suitable for the `BulkReportListResult` model.
72+
73+
The expected response structure is: `{"entries": [{...}]}`.
74+
75+
Args:
76+
body (Union[List[Dict[str, Any]], Dict[str, Any]]):
77+
The raw response body.
78+
79+
Returns:
80+
Union[List[Dict[str, Any]], Dict[str, Any]]:
81+
The transformed response data.
82+
83+
Raises:
84+
ResultValidationError:
85+
If the response body does not match the expected format.
86+
"""
87+
# expected: {"entries": [{"key": ...}, ...], ...}
88+
if not isinstance(body, dict) or "entries" not in body:
89+
raise ResultValidationError(
90+
message="Expected a list of entries, but got an empty list.",
91+
body=body,
92+
)
93+
94+
# Transforming and reshaping entries
95+
bulk_report_entries: List[Dict[str, Any]] = body.get("entries", [])
96+
transformed_data: List[Dict[str, Any]] = []
97+
98+
# Loop through "entries" list i.e [{"key": ..., ...}, ...]
99+
for bulk_report_entry in bulk_report_entries:
100+
# Append extracted dictionaries, if not empty
101+
if bulk_report_entry:
102+
transformed_data.append(dict(**bulk_report_entry))
103+
104+
return transformed_data
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
"""Global Fishing Watch (GFW) API Python Client - Get All Bulk Reports Models.
2+
3+
This module defines Pydantic data models used for interacting with the
4+
Get All Bulk Reports API endpoint. These models are used to represent
5+
request parameters, and response data when retrieving detailed metadata and status of
6+
multiple previously created bulk report
7+
8+
For detailed information about the Get All Bulk Reports API endpoint, please refer to
9+
the official Global Fishing Watch API documentation:
10+
11+
See: https://globalfishingwatch.org/our-apis/documentation#get-all-bulk-reports-by-user
12+
13+
For more details on the Get All Bulk Reports data caveats, please refer to the
14+
official Global Fishing Watch API documentation:
15+
16+
See: https://globalfishingwatch.org/our-apis/documentation#sar-fixed-infrastructure-data-caveats
17+
"""
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
"""Global Fishing Watch (GFW) API Python Client - Get All Bulk Reports Request Models."""
2+
3+
from typing import Final, Optional
4+
5+
from pydantic import Field
6+
7+
from gfwapiclient.http.models import RequestParams
8+
from gfwapiclient.resources.bulk_downloads.base.models.response import BulkReportStatus
9+
10+
11+
__all__ = ["BulkReportListParams"]
12+
13+
14+
BULK_REPORT_LIST_PARAMS_VALIDATION_ERROR_MESSAGE: Final[str] = (
15+
"Get bulk reports request parameters validation failed."
16+
)
17+
18+
19+
class BulkReportListParams(RequestParams):
20+
"""Request query parameters for Get All Bulk Reports API endpoint.
21+
22+
Represents pagination, sorting, filtering parameters etc. for retrieving
23+
previously created bulk reports.
24+
25+
For more details on the Get All Bulk Reports API endpoint supported
26+
request parameters, please refer to the official Global Fishing Watch API
27+
documentation:
28+
29+
See: https://globalfishingwatch.org/our-apis/documentation#get-all-bulk-reports-by-user
30+
31+
Attributes:
32+
limit (Optional[int]):
33+
Maximum number of bulk reports to return.
34+
Defaults to `99999`.
35+
36+
offset (Optional[int]):
37+
Number of bulk reports to skip before returning results.
38+
Used for pagination. Defaults to `0`.
39+
40+
sort (Optional[str]):
41+
Property to sort the bulk reports by (e.g., `"-createdAt"`).
42+
43+
status (Optional[BulkReportStatus]):
44+
Current status of the bulk report generation process (e.g., `"done"` etc.).
45+
"""
46+
47+
limit: Optional[int] = Field(99999, ge=0, alias="limit")
48+
offset: Optional[int] = Field(0, ge=0, alias="offset")
49+
sort: Optional[str] = Field("-createdAt", alias="sort")
50+
status: Optional[BulkReportStatus] = Field(None, alias="status")
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
"""Global Fishing Watch (GFW) API Python Client - Get All Bulk Reports Response Models."""
2+
3+
from typing import List, Type
4+
5+
from gfwapiclient.http.models import Result
6+
from gfwapiclient.resources.bulk_downloads.base.models.response import BulkReportItem
7+
8+
9+
__all__ = ["BulkReportListItem", "BulkReportListResult"]
10+
11+
12+
class BulkReportListItem(BulkReportItem):
13+
"""Result item for the Get All Bulk Reports API endpoint.
14+
15+
Represents metadata and status of the previously created bulk report.
16+
17+
For more details on the Get All Bulk Reports API endpoint supported
18+
response bodies, please refer to the official Global Fishing Watch API
19+
documentation:
20+
21+
See: https://globalfishingwatch.org/our-apis/documentation#get-all-bulk-reports-by-user
22+
23+
See: https://globalfishingwatch.org/our-apis/documentation#bulk-reports-get-http-response
24+
25+
See: https://globalfishingwatch.org/our-apis/documentation#bulk-report-object-schema
26+
"""
27+
28+
pass
29+
30+
31+
class BulkReportListResult(Result[BulkReportListItem]):
32+
"""Result for the Get All Bulk Reports API endpoint.
33+
34+
For more details on the Get All Bulk Reports API endpoint supported
35+
response bodies, please refer to the official Global Fishing Watch API
36+
documentation:
37+
38+
See: https://globalfishingwatch.org/our-apis/documentation#get-all-bulk-reports-by-user
39+
40+
Attributes:
41+
_result_item_class (Type[BulkReportListItem]):
42+
The model used for individual result items.
43+
44+
_data (BulkReportListItem):
45+
The bulk report item returned in the response.
46+
"""
47+
48+
_result_item_class: Type[BulkReportListItem]
49+
_data: List[BulkReportListItem]
50+
51+
def __init__(self, data: List[BulkReportListItem]) -> None:
52+
"""Initializes a new `BulkReportListResult`.
53+
54+
Args:
55+
data (List[BulkReportListItem]):
56+
The list of bulk report items.
57+
"""
58+
super().__init__(data=data)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"limit": 99999,
3+
"offset": 0,
4+
"sort": "-createdAt",
5+
"status": "done"
6+
}

tests/resources/bulk_downloads/conftest.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,19 @@ def mock_raw_bulk_report_create_request_body(
5454
"bulk_downloads/bulk_report_create_request_body.json"
5555
)
5656
return raw_bulk_report_create_request_body
57+
58+
59+
@pytest.fixture
60+
def mock_raw_bulk_report_list_request_params(
61+
load_json_fixture: Callable[[str], Dict[str, Any]],
62+
) -> Dict[str, Any]:
63+
"""Fixture for mock raw bulk report list request parameters.
64+
65+
Returns:
66+
Dict[str, Any]:
67+
Raw `BulkReportListParams` sample data as dictionary.
68+
"""
69+
raw_bulk_report_list_request_params: Dict[str, Any] = load_json_fixture(
70+
"bulk_downloads/bulk_report_list_request_params.json"
71+
)
72+
return raw_bulk_report_list_request_params
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Tests for `gfwapiclient.resources.bulk_downloads.list`."""
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Tests for `gfwapiclient.resources.bulk_downloads.create.models`."""
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"""Tests for `gfwapiclient.resources.bulk_downloads.list.models.request`."""
2+
3+
from typing import Any, Dict
4+
5+
from gfwapiclient.resources.bulk_downloads.list.models.request import (
6+
BulkReportListParams,
7+
)
8+
9+
10+
def test_bulk_report_list_request_params_serializes_all_fields(
11+
mock_raw_bulk_report_list_request_params: Dict[str, Any],
12+
) -> None:
13+
"""Test that `BulkReportListParams` serializes all fields correctly."""
14+
bulk_report_list_request_params: BulkReportListParams = BulkReportListParams(
15+
**mock_raw_bulk_report_list_request_params
16+
)
17+
assert bulk_report_list_request_params.limit is not None
18+
assert bulk_report_list_request_params.offset is not None
19+
assert bulk_report_list_request_params.sort is not None
20+
assert bulk_report_list_request_params.status is not None
21+
assert bulk_report_list_request_params.to_query_params() is not None

0 commit comments

Comments
 (0)