Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
115 changes: 112 additions & 3 deletions src/gfwapiclient/base/models.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
"""Global Fishing Watch (GFW) API Python Client - Base Models."""

from typing import ClassVar
from enum import Enum
from typing import Any, ClassVar, Optional

from pydantic import AliasGenerator, ConfigDict
from pydantic import AliasGenerator, ConfigDict, Field, field_validator
from pydantic import BaseModel as PydanticBaseModel
from pydantic.alias_generators import to_camel


__all__ = ["BaseModel"]
__all__ = ["BaseModel", "Region", "RegionDataset"]


class BaseModel(PydanticBaseModel):
Expand Down Expand Up @@ -47,3 +48,111 @@ class BaseModel(PydanticBaseModel):
use_enum_values=True,
validate_default=True,
)


class RegionDataset(str, Enum):
"""Regions API dataset.

For more details on the Regions API supported datasets, please refer
to the official Global Fishing Watch API documentation:

See: https://globalfishingwatch.org/our-apis/documentation#regions

Attributes:
PUBLIC_EEZ_AREAS (str):
Exclusive Economic Zone (EEZ) regions dataset.

PUBLIC_MPA_ALL (str):
Marine Protected Area (MPA) regions dataset.

PUBLIC_RFMO (str):
Regional Fisheries Management Organization (RFMO) regions dataset.
"""

PUBLIC_EEZ_AREAS = "public-eez-areas"
PUBLIC_MPA_ALL = "public-mpa-all"
PUBLIC_RFMO = "public-rfmo"


class Region(BaseModel):
"""Region of interest.

Represents a predefined geographic region (or area) of interest supported by
the Global Fishing Watch APIs, including:

- Exclusive Economic Zones (EEZ)
- Marine Protected Areas (MPA)
- Regional Fisheries Management Organizations (RFMO)

The predefined region (or area) of interest are used in other API endpoints when:

- Create a report of a specified region.
See: https://globalfishingwatch.org/our-apis/documentation#create-a-report-of-a-specified-region

- Get All Events:
See: https://globalfishingwatch.org/our-apis/documentation#get-all-events-post-endpoint

- Create a Bulk Report.
See https://globalfishingwatch.org/our-apis/documentation#create-a-bulk-report

For more details on the predefined region (or area) of interest, please refer
to the official Global Fishing Watch API documentation:

See: https://globalfishingwatch.org/our-apis/documentation#regions

For more details on the predefined region (or area) of interest data caveats,
please refer to the official Global Fishing Watch API documentation:

See: https://globalfishingwatch.org/our-apis/documentation#exclusive-economic-zone-boundaries-definition

See: https://globalfishingwatch.org/our-apis/documentation#marine-protected-area-boundaries-definition

See: https://globalfishingwatch.org/our-apis/documentation#what-does-it-mean-if-an-event-is-within-a-specific-geographic-area-such-as-an-eez-mpa-or-rfmo

See: https://globalfishingwatch.org/our-apis/documentation#how-does-gfw-calculate-that-an-event-has-a-publicly-listed-authorization

See: https://globalfishingwatch.org/our-apis/documentation#insights-api-rfmo-iuu-vessel-list

See: https://globalfishingwatch.org/our-apis/documentation#exclusive-economic-zone-boundaries-definitions

See: https://globalfishingwatch.org/our-apis/documentation#marine-protected-area-boundaries-definition-2

Attributes:
dataset (Optional[RegionDataset]):
Dataset name (or ID) containing the region of interest (e.g.,
`"public-eez-areas"`).

id (Optional[str]):
Unique identifier (ID) for the region of interest (e.g., `"8466"`).
"""

dataset: Optional[RegionDataset] = Field(None, alias="dataset")
id: Optional[str] = Field(None, alias="id")

@field_validator(
"id",
mode="before",
)
@classmethod
def normalize_id(cls, value: Any) -> Optional[Any]:
"""Normalize the region identifier (ID) to a string.

Ensures the `id` field is consistently represented as a string.
Empty or whitespace-only values are normalized to `None`.

Args:
value (Any):
The raw region `id` value to validate.

Returns:
Optional[Any]:
The normalized region string `id`, or `None` if the value
is empty or missing.
"""
if isinstance(value, int):
return str(value)

if isinstance(value, str) and value.strip() == "":
return None

return value
16 changes: 4 additions & 12 deletions src/gfwapiclient/resources/bulk_downloads/base/models/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
"""

from enum import Enum
from typing import Any, Optional, Union
from typing import Any

from pydantic import Field

from gfwapiclient.base.models import BaseModel
from gfwapiclient.base.models import BaseModel, Region


__all__ = [
Expand Down Expand Up @@ -85,7 +85,7 @@ class BulkReportGeometry(BaseModel):
coordinates: Any = Field(...)


class BulkReportRegion(BaseModel):
class BulkReportRegion(Region):
"""Bulk report region of interest.

Represents a predefined area of interest used for filtering bulk report data.
Expand All @@ -96,17 +96,9 @@ class BulkReportRegion(BaseModel):
See: https://globalfishingwatch.org/our-apis/documentation#bulk-report-body-only-for-post-request

See: https://globalfishingwatch.org/our-apis/documentation#regions

Attributes:
dataset (Optional[str]):
Dataset containing the region of interest (e.g. `"public-eez-areas"`).

id (Optional[Union[str, int]]):
Region of interest identifier (ID) (e.g. `8466`).
"""

dataset: Optional[str] = Field(None, alias="dataset")
id: Optional[Union[str, int]] = Field(None, alias="id")
pass


class BulkReportFileType(str, Enum):
Expand Down
19 changes: 10 additions & 9 deletions src/gfwapiclient/resources/events/base/models/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from pydantic import Field

from gfwapiclient.base.models import BaseModel
from gfwapiclient.base.models import BaseModel, Region
from gfwapiclient.http.models.request import RequestBody


Expand Down Expand Up @@ -101,19 +101,20 @@ class EventGeometry(BaseModel):
coordinates: Any = Field(...)


class EventRegion(BaseModel):
class EventRegion(Region):
"""Region where the events occur.

Attributes:
dataset (str):
The dataset containing the region.
Represents a predefined area of interest used for filtering events data.

For more details on the Events API supported regions, please refer to the
official Global Fishing Watch API documentation:

See: https://globalfishingwatch.org/our-apis/documentation#events-post-body-parameters

id (str):
The region ID.
See: https://globalfishingwatch.org/our-apis/documentation#regions
"""

dataset: str = Field(...)
id: str = Field(...)
pass


class EventBaseBody(RequestBody):
Expand Down
13 changes: 7 additions & 6 deletions src/gfwapiclient/resources/fourwings/report/models/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from pydantic import Field

from gfwapiclient.base.models import BaseModel
from gfwapiclient.base.models import BaseModel, Region, RegionDataset
from gfwapiclient.http.models import RequestBody, RequestParams


Expand Down Expand Up @@ -228,18 +228,20 @@ class FourWingsGeometry(BaseModel):
coordinates: Any = Field(...)


class FourWingsReportRegion(BaseModel):
class FourWingsReportRegion(Region):
"""4Wings report region of interest.

Represents a predefined region of interest used for filtering report data.
Represents a predefined region of interest used for filtering 4Wings report data.

For more details on the 4Wings API supported report regions, please
refer to the official Global Fishing Watch API documentation:

See: https://globalfishingwatch.org/our-apis/documentation#report-body-only-for-post-request

See: https://globalfishingwatch.org/our-apis/documentation#regions

Attributes:
dataset (Optional[str]):
dataset (Optional[RegionDataset]):
Dataset containing the region.

id (Optional[str]):
Expand All @@ -255,8 +257,7 @@ class FourWingsReportRegion(BaseModel):
Value for the buffer distance.
"""

dataset: Optional[str] = Field(None, alias="dataset")
id: Optional[str] = Field(None, alias="id")
dataset: Optional[RegionDataset] = Field(None, alias="dataset")
buffer_operation: Optional[FourWingsReportBufferOperation] = Field(
None, alias="bufferOperation"
)
Expand Down
2 changes: 2 additions & 0 deletions src/gfwapiclient/resources/references/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@

See: https://globalfishingwatch.org/our-apis/documentation#how-does-gfw-calculate-that-an-event-has-a-publicly-listed-authorization

See: https://globalfishingwatch.org/our-apis/documentation#insights-api-rfmo-iuu-vessel-list

See: https://globalfishingwatch.org/our-apis/documentation#exclusive-economic-zone-boundaries-definitions

See: https://globalfishingwatch.org/our-apis/documentation#marine-protected-area-boundaries-definition-2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@

See: https://globalfishingwatch.org/our-apis/documentation#how-does-gfw-calculate-that-an-event-has-a-publicly-listed-authorization

See: https://globalfishingwatch.org/our-apis/documentation#insights-api-rfmo-iuu-vessel-list

See: https://globalfishingwatch.org/our-apis/documentation#exclusive-economic-zone-boundaries-definitions

See: https://globalfishingwatch.org/our-apis/documentation#marine-protected-area-boundaries-definition-2
Expand Down
26 changes: 12 additions & 14 deletions src/gfwapiclient/resources/references/regions/models/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from pydantic import Field

from gfwapiclient.base.models import Region, RegionDataset
from gfwapiclient.http.models import Result, ResultItem


Expand All @@ -17,21 +18,21 @@
]


class EEZRegionItem(ResultItem):
class EEZRegionItem(Region, ResultItem):
"""Exclusive Economic Zone (EEZ) region item.

Represents single EEZ region item returned by the EEZ regions API endpoint.

Attributes:
id (Optional[int]):
id (Optional[str]):
Unique identifier for the EEZ region. Used in 4Wings, Events and
Bulk Download API queries.

label (Optional[str]):
Human-readable name of the EEZ region.

iso3 (Optional[str]):
ISO 3166-1 alpha-3 country code (`null` for joint regimes and
ISO 3166-1 alpha-3 country code (`None` for joint regimes and
overlapping claims).

iso_sov_1 (Optional[str]):
Expand All @@ -46,18 +47,17 @@ class EEZRegionItem(ResultItem):
territory_1 (Optional[str]):
Territory name.

dataset (str):
dataset (Optional[RegionDataset]):
Dataset name or ID. Used in 4Wings, Events and Bulk Download API queries.
"""

id: Optional[int] = Field(None)
label: Optional[str] = Field(None)
iso3: Optional[str] = Field(None)
iso_sov_1: Optional[str] = Field(None, alias="isoSov1")
iso_sov_2: Optional[str] = Field(None, alias="isoSov2")
iso_sov_3: Optional[str] = Field(None, alias="isoSov3")
territory_1: Optional[str] = Field(None, alias="territory1")
dataset: Optional[str] = Field("public-eez-areas")
dataset: Optional[RegionDataset] = Field(RegionDataset.PUBLIC_EEZ_AREAS)


class EEZRegionResult(Result[EEZRegionItem]):
Expand Down Expand Up @@ -92,7 +92,7 @@ def __init__(self, data: List[EEZRegionItem]) -> None:
super().__init__(data=data)


class MPARegionItem(ResultItem):
class MPARegionItem(Region, ResultItem):
"""Marine Protected Area (MPA) region item.

Represents single MPA region item returned by the MPA regions API endpoint.
Expand All @@ -105,13 +105,12 @@ class MPARegionItem(ResultItem):
label (Optional[str]):
Name and designation of the Marine Protected Area.

dataset (str):
dataset (Optional[RegionDataset]):
Dataset name or ID. Used in 4Wings, Events and Bulk Download API queries.
"""

id: Optional[str] = Field(None)
label: Optional[str] = Field(None)
dataset: Optional[str] = Field("public-mpa-all")
dataset: Optional[RegionDataset] = Field(RegionDataset.PUBLIC_MPA_ALL)


class MPARegionResult(Result[MPARegionItem]):
Expand Down Expand Up @@ -146,7 +145,7 @@ def __init__(self, data: List[MPARegionItem]) -> None:
super().__init__(data=data)


class RFMORegionItem(ResultItem):
class RFMORegionItem(Region, ResultItem):
"""Regional Fisheries Management Organization (RFMO) region item.

Represents single RFMO region item returned by the RFMO regions API endpoint.
Expand All @@ -162,14 +161,13 @@ class RFMORegionItem(ResultItem):
id_ (Optional[str]):
Duplicate identifier field (matches id and label).

dataset (str):
dataset (Optional[RegionDataset]):
Dataset name or ID. Used in 4Wings, Events and Bulk Download API queries.
"""

id: Optional[str] = Field(None)
label: Optional[str] = Field(None)
id_: Optional[str] = Field(None, alias="ID")
dataset: Optional[str] = Field("public-rfmo")
dataset: Optional[RegionDataset] = Field(RegionDataset.PUBLIC_RFMO)


class RFMORegionResult(Result[RFMORegionItem]):
Expand Down
4 changes: 4 additions & 0 deletions src/gfwapiclient/resources/references/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ class ReferenceResource(BaseResource):

See: https://globalfishingwatch.org/our-apis/documentation#how-does-gfw-calculate-that-an-event-has-a-publicly-listed-authorization

See: https://globalfishingwatch.org/our-apis/documentation#insights-api-rfmo-iuu-vessel-list

See: https://globalfishingwatch.org/our-apis/documentation#exclusive-economic-zone-boundaries-definitions

See: https://globalfishingwatch.org/our-apis/documentation#marine-protected-area-boundaries-definition-2
Expand Down Expand Up @@ -138,6 +140,8 @@ async def get_rfmo_regions(self, **kwargs: Dict[str, Any]) -> RFMORegionResult:

See: https://globalfishingwatch.org/our-apis/documentation#how-does-gfw-calculate-that-an-event-has-a-publicly-listed-authorization

See: https://globalfishingwatch.org/our-apis/documentation#insights-api-rfmo-iuu-vessel-list

Args:
**kwargs (Dict[str, Any]):
Additional keyword arguments to pass to the RFMO region endpoint's request.
Expand Down
Loading