From 8911d0c2d31736087f2e27899fc580c9b7e3d664 Mon Sep 17 00:00:00 2001 From: scaleway-bot Date: Tue, 30 Sep 2025 11:10:47 +0000 Subject: [PATCH] feat: update generated APIs --- .../environmental_footprint/__init__.py | 2 + .../v1alpha1/__init__.py | 33 +++ .../environmental_footprint/v1alpha1/api.py | 152 +++++++++++ .../v1alpha1/marshalling.py | 244 +++++++++++++++++ .../environmental_footprint/v1alpha1/types.py | 248 ++++++++++++++++++ .../environmental_footprint/__init__.py | 2 + .../v1alpha1/__init__.py | 33 +++ .../environmental_footprint/v1alpha1/api.py | 152 +++++++++++ .../v1alpha1/marshalling.py | 244 +++++++++++++++++ .../environmental_footprint/v1alpha1/types.py | 248 ++++++++++++++++++ 10 files changed, 1358 insertions(+) create mode 100644 scaleway-async/scaleway_async/environmental_footprint/__init__.py create mode 100644 scaleway-async/scaleway_async/environmental_footprint/v1alpha1/__init__.py create mode 100644 scaleway-async/scaleway_async/environmental_footprint/v1alpha1/api.py create mode 100644 scaleway-async/scaleway_async/environmental_footprint/v1alpha1/marshalling.py create mode 100644 scaleway-async/scaleway_async/environmental_footprint/v1alpha1/types.py create mode 100644 scaleway/scaleway/environmental_footprint/__init__.py create mode 100644 scaleway/scaleway/environmental_footprint/v1alpha1/__init__.py create mode 100644 scaleway/scaleway/environmental_footprint/v1alpha1/api.py create mode 100644 scaleway/scaleway/environmental_footprint/v1alpha1/marshalling.py create mode 100644 scaleway/scaleway/environmental_footprint/v1alpha1/types.py diff --git a/scaleway-async/scaleway_async/environmental_footprint/__init__.py b/scaleway-async/scaleway_async/environmental_footprint/__init__.py new file mode 100644 index 000000000..8b74a5ed7 --- /dev/null +++ b/scaleway-async/scaleway_async/environmental_footprint/__init__.py @@ -0,0 +1,2 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. diff --git a/scaleway-async/scaleway_async/environmental_footprint/v1alpha1/__init__.py b/scaleway-async/scaleway_async/environmental_footprint/v1alpha1/__init__.py new file mode 100644 index 000000000..4354e9c93 --- /dev/null +++ b/scaleway-async/scaleway_async/environmental_footprint/v1alpha1/__init__.py @@ -0,0 +1,33 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import ProductCategory +from .types import ReportType +from .types import ServiceCategory +from .types import Impact +from .types import SkuImpact +from .types import ZoneImpact +from .types import RegionImpact +from .types import ProjectImpact +from .types import ImpactDataResponse +from .types import ImpactReportAvailability +from .types import UserApiDownloadImpactReportRequest +from .types import UserApiGetImpactDataRequest +from .types import UserApiGetImpactReportAvailabilityRequest +from .api import EnvironmentalFootprintV1Alpha1UserAPI + +__all__ = [ + "ProductCategory", + "ReportType", + "ServiceCategory", + "Impact", + "SkuImpact", + "ZoneImpact", + "RegionImpact", + "ProjectImpact", + "ImpactDataResponse", + "ImpactReportAvailability", + "UserApiDownloadImpactReportRequest", + "UserApiGetImpactDataRequest", + "UserApiGetImpactReportAvailabilityRequest", + "EnvironmentalFootprintV1Alpha1UserAPI", +] diff --git a/scaleway-async/scaleway_async/environmental_footprint/v1alpha1/api.py b/scaleway-async/scaleway_async/environmental_footprint/v1alpha1/api.py new file mode 100644 index 000000000..543a60dfb --- /dev/null +++ b/scaleway-async/scaleway_async/environmental_footprint/v1alpha1/api.py @@ -0,0 +1,152 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from datetime import datetime +from typing import Optional + +from scaleway_core.api import API +from scaleway_core.bridge import ( + ScwFile, + unmarshal_ScwFile, +) +from .types import ( + ProductCategory, + ReportType, + ServiceCategory, + ImpactDataResponse, + ImpactReportAvailability, + UserApiDownloadImpactReportRequest, +) +from .marshalling import ( + unmarshal_ImpactDataResponse, + unmarshal_ImpactReportAvailability, + marshal_UserApiDownloadImpactReportRequest, +) + + +class EnvironmentalFootprintV1Alpha1UserAPI(API): + """ + Access and download impact reports and impact data for your Scaleway projects. Our API provides key metrics such as estimated carbon emissions and water usage to help monitor your environmental footprint. + """ + + async def get_impact_report_availability( + self, + *, + organization_id: Optional[str] = None, + start_date: Optional[datetime] = None, + end_date: Optional[datetime] = None, + ) -> ImpactReportAvailability: + """ + Get available impact reports. + Returns a list of dates of available impact reports. + :param organization_id: The UUID of the Organization for which you want to download a report. + :param start_date: Start date of the search period (ISO 8601 format, with time in UTC, `YYYY-MM-DDTHH:MM:SSZ`). The date is inclusive. + :param end_date: End date of the search period (ISO 8601 format, with time in UTC, `YYYY-MM-DDTHH:MM:SSZ`). The date is exclusive. Defaults to today's date. + :return: :class:`ImpactReportAvailability ` + + Usage: + :: + + result = await api.get_impact_report_availability() + """ + + res = self._request( + "GET", + "/environmental-footprint/v1alpha1/reports/availability", + params={ + "end_date": end_date, + "organization_id": organization_id + or self.client.default_organization_id, + "start_date": start_date, + }, + ) + + self._throw_on_error(res) + return unmarshal_ImpactReportAvailability(res.json()) + + async def download_impact_report( + self, + *, + organization_id: Optional[str] = None, + date: Optional[datetime] = None, + type_: Optional[ReportType] = None, + ) -> ScwFile: + """ + Download PDF impact report. + Download a Scaleway impact PDF report with detailed impact data for your Scaleway projects. + :param organization_id: The UUID of the Organization for which you want to download a report. + :param date: The start date of the period for which you want to download a report (ISO 8601 format, e.g., 2025-05-01T00:00:00Z). + :param type_: Type of report to download (e.g., monthly). Defaults to monthly. + :return: :class:`ScwFile ` + + Usage: + :: + + result = await api.download_impact_report() + """ + + res = self._request( + "POST", + "/environmental-footprint/v1alpha1/reports/download", + body=marshal_UserApiDownloadImpactReportRequest( + UserApiDownloadImpactReportRequest( + organization_id=organization_id, + date=date, + type_=type_, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_ScwFile(res.json()) + + async def get_impact_data( + self, + *, + organization_id: Optional[str] = None, + start_date: Optional[datetime] = None, + end_date: Optional[datetime] = None, + regions: Optional[list[str]] = None, + zones: Optional[list[str]] = None, + project_ids: Optional[list[str]] = None, + service_categories: Optional[list[ServiceCategory]] = None, + product_categories: Optional[list[ProductCategory]] = None, + ) -> ImpactDataResponse: + """ + Retrieve detailed impact data. + Retrieve detailed impact data for your Scaleway projects within a specified date range. Filter by project ID, region, zone, service category, and/or product category. + :param organization_id: The UUID of the Organization for which you want to download a report. + :param start_date: Start date (inclusive) of the period for which you want to retrieve impact data (ISO 8601 format, e.g., 2025-05-01T00:00:00Z). + :param end_date: End date (exclusive) of the period for which you want to retrieve impact data (ISO 8601 format, with time in UTC, `YYYY-MM-DDTHH:MM:SSZ`). Defaults to today's date. + :param regions: List of regions to filter by (\"fr-par\"). Defaults to all regions. + :param zones: List of zones to filter by (\"fr-par-1\"). Defaults to all zones. + :param project_ids: List of Project IDs to filter by. Defaults to all Projects in the Organization. + :param service_categories: List of service categories to filter by. Defaults to all service categories. + :param product_categories: List of product categories to filter by. Defaults to all product categories. + :return: :class:`ImpactDataResponse ` + + Usage: + :: + + result = await api.get_impact_data() + """ + + res = self._request( + "GET", + "/environmental-footprint/v1alpha1/data/query", + params={ + "end_date": end_date, + "organization_id": organization_id + or self.client.default_organization_id, + "product_categories": product_categories, + "project_ids": project_ids, + "regions": regions, + "service_categories": service_categories, + "start_date": start_date, + "zones": zones, + }, + ) + + self._throw_on_error(res) + return unmarshal_ImpactDataResponse(res.json()) diff --git a/scaleway-async/scaleway_async/environmental_footprint/v1alpha1/marshalling.py b/scaleway-async/scaleway_async/environmental_footprint/v1alpha1/marshalling.py new file mode 100644 index 000000000..548836019 --- /dev/null +++ b/scaleway-async/scaleway_async/environmental_footprint/v1alpha1/marshalling.py @@ -0,0 +1,244 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from .types import ( + ProductCategory, + ServiceCategory, + Impact, + SkuImpact, + ZoneImpact, + RegionImpact, + ProjectImpact, + ImpactDataResponse, + ImpactReportAvailability, + UserApiDownloadImpactReportRequest, +) + + +def unmarshal_Impact(data: Any) -> Impact: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Impact' failed as data isn't a dictionary." + ) + + args: dict[str, Any] = {} + + field = data.get("kg_co2_equivalent", None) + if field is not None: + args["kg_co2_equivalent"] = field + else: + args["kg_co2_equivalent"] = 0.0 + + field = data.get("m3_water_usage", None) + if field is not None: + args["m3_water_usage"] = field + else: + args["m3_water_usage"] = 0.0 + + return Impact(**args) + + +def unmarshal_SkuImpact(data: Any) -> SkuImpact: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SkuImpact' failed as data isn't a dictionary." + ) + + args: dict[str, Any] = {} + + field = data.get("sku", None) + if field is not None: + args["sku"] = field + else: + args["sku"] = None + + field = data.get("service_category", None) + if field is not None: + args["service_category"] = field + else: + args["service_category"] = ServiceCategory.UNKNOWN_SERVICE_CATEGORY + + field = data.get("product_category", None) + if field is not None: + args["product_category"] = field + else: + args["product_category"] = ProductCategory.UNKNOWN_PRODUCT_CATEGORY + + field = data.get("total_sku_impact", None) + if field is not None: + args["total_sku_impact"] = unmarshal_Impact(field) + else: + args["total_sku_impact"] = None + + return SkuImpact(**args) + + +def unmarshal_ZoneImpact(data: Any) -> ZoneImpact: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ZoneImpact' failed as data isn't a dictionary." + ) + + args: dict[str, Any] = {} + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + else: + args["zone"] = None + + field = data.get("skus", None) + if field is not None: + args["skus"] = ( + [unmarshal_SkuImpact(v) for v in field] if field is not None else None + ) + else: + args["skus"] = [] + + field = data.get("total_zone_impact", None) + if field is not None: + args["total_zone_impact"] = unmarshal_Impact(field) + else: + args["total_zone_impact"] = None + + return ZoneImpact(**args) + + +def unmarshal_RegionImpact(data: Any) -> RegionImpact: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RegionImpact' failed as data isn't a dictionary." + ) + + args: dict[str, Any] = {} + + field = data.get("region", None) + if field is not None: + args["region"] = field + else: + args["region"] = None + + field = data.get("zones", None) + if field is not None: + args["zones"] = ( + [unmarshal_ZoneImpact(v) for v in field] if field is not None else None + ) + else: + args["zones"] = [] + + field = data.get("total_region_impact", None) + if field is not None: + args["total_region_impact"] = unmarshal_Impact(field) + else: + args["total_region_impact"] = None + + return RegionImpact(**args) + + +def unmarshal_ProjectImpact(data: Any) -> ProjectImpact: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ProjectImpact' failed as data isn't a dictionary." + ) + + args: dict[str, Any] = {} + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + else: + args["project_id"] = None + + field = data.get("regions", None) + if field is not None: + args["regions"] = ( + [unmarshal_RegionImpact(v) for v in field] if field is not None else None + ) + else: + args["regions"] = [] + + field = data.get("total_project_impact", None) + if field is not None: + args["total_project_impact"] = unmarshal_Impact(field) + else: + args["total_project_impact"] = None + + return ProjectImpact(**args) + + +def unmarshal_ImpactDataResponse(data: Any) -> ImpactDataResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ImpactDataResponse' failed as data isn't a dictionary." + ) + + args: dict[str, Any] = {} + + field = data.get("projects", None) + if field is not None: + args["projects"] = ( + [unmarshal_ProjectImpact(v) for v in field] if field is not None else None + ) + else: + args["projects"] = [] + + field = data.get("start_date", None) + if field is not None: + args["start_date"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["start_date"] = None + + field = data.get("end_date", None) + if field is not None: + args["end_date"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["end_date"] = None + + field = data.get("total_impact", None) + if field is not None: + args["total_impact"] = unmarshal_Impact(field) + else: + args["total_impact"] = None + + return ImpactDataResponse(**args) + + +def unmarshal_ImpactReportAvailability(data: Any) -> ImpactReportAvailability: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ImpactReportAvailability' failed as data isn't a dictionary." + ) + + args: dict[str, Any] = {} + + field = data.get("month_summary_reports", None) + if field is not None: + args["month_summary_reports"] = field + else: + args["month_summary_reports"] = None + + return ImpactReportAvailability(**args) + + +def marshal_UserApiDownloadImpactReportRequest( + request: UserApiDownloadImpactReportRequest, + defaults: ProfileDefaults, +) -> dict[str, Any]: + output: dict[str, Any] = {} + + if request.organization_id is not None: + output["organization_id"] = request.organization_id + else: + output["organization_id"] = defaults.default_organization_id + + if request.date is not None: + output["date"] = request.date.isoformat() + + if request.type_ is not None: + output["type"] = request.type_ + + return output diff --git a/scaleway-async/scaleway_async/environmental_footprint/v1alpha1/types.py b/scaleway-async/scaleway_async/environmental_footprint/v1alpha1/types.py new file mode 100644 index 000000000..79a683f85 --- /dev/null +++ b/scaleway-async/scaleway_async/environmental_footprint/v1alpha1/types.py @@ -0,0 +1,248 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass, field +from datetime import datetime +from enum import Enum +from typing import Optional + +from scaleway_core.bridge import ( + Region as ScwRegion, + Zone as ScwZone, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class ProductCategory(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_PRODUCT_CATEGORY = "unknown_product_category" + APPLE_SILICON = "apple_silicon" + BLOCK_STORAGE = "block_storage" + DEDIBOX = "dedibox" + ELASTIC_METAL = "elastic_metal" + INSTANCES = "instances" + OBJECT_STORAGE = "object_storage" + + def __str__(self) -> str: + return str(self.value) + + +class ReportType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_REPORT_TYPE = "unknown_report_type" + MONTHLY = "monthly" + YEARLY = "yearly" + + def __str__(self) -> str: + return str(self.value) + + +class ServiceCategory(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SERVICE_CATEGORY = "unknown_service_category" + BAREMETAL = "baremetal" + COMPUTE = "compute" + STORAGE = "storage" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class Impact: + kg_co2_equivalent: float + """ + The estimated carbon emissions in kilograms of CO₂ equivalent (kgCO₂e). + """ + + m3_water_usage: float + """ + The estimated water consumption in cubic meters (m³). + """ + + +@dataclass +class SkuImpact: + sku: str + """ + Unique ID of the combination of product, region and zone. + """ + + service_category: ServiceCategory + """ + The service category associated with this SKU. + """ + + product_category: ProductCategory + """ + The product category associated with this SKU. + """ + + total_sku_impact: Optional[Impact] = None + """ + The total estimated impact for this SKU during the given period. + """ + + +@dataclass +class ZoneImpact: + zone: ScwZone + """ + ID of the zone. + """ + + skus: list[SkuImpact] + """ + List of estimated impact values per SKU. + """ + + total_zone_impact: Optional[Impact] = None + """ + The total estimated impact for this zone across all given service categories, and product categories during the given period. + """ + + +@dataclass +class RegionImpact: + region: ScwRegion + """ + ID of the region. + """ + + zones: list[ZoneImpact] + """ + List of estimated impact values per zone. + """ + + total_region_impact: Optional[Impact] = None + """ + The total estimated impact for this region across all given zones, service categories, and product categories during the given period. + """ + + +@dataclass +class ProjectImpact: + project_id: str + """ + ID of the project. + """ + + regions: list[RegionImpact] + """ + List of estimated impact values per region. + """ + + total_project_impact: Optional[Impact] = None + """ + The total estimated impact for this Project across all given regions, zones, service categories, and product categories during the given period. + """ + + +@dataclass +class ImpactDataResponse: + projects: list[ProjectImpact] + """ + List of estimated impact values per Project. + """ + + start_date: Optional[datetime] = None + """ + Start date of the impact data period (inclusive). + """ + + end_date: Optional[datetime] = None + """ + End date of the impact data period (exclusive). + """ + + total_impact: Optional[Impact] = None + """ + The total estimated impact across all given Projects, regions, zones, service categories, and product categories during the given period. + """ + + +@dataclass +class ImpactReportAvailability: + month_summary_reports: list[datetime] + """ + The list of calendar months for which impact reports are available. + """ + + +@dataclass +class UserApiDownloadImpactReportRequest: + organization_id: Optional[str] = None + """ + The UUID of the Organization for which you want to download a report. + """ + + date: Optional[datetime] = None + """ + The start date of the period for which you want to download a report (ISO 8601 format, e.g., 2025-05-01T00:00:00Z). + """ + + type_: Optional[ReportType] = ReportType.UNKNOWN_REPORT_TYPE + """ + Type of report to download (e.g., monthly). Defaults to monthly. + """ + + +@dataclass +class UserApiGetImpactDataRequest: + organization_id: Optional[str] = None + """ + The UUID of the Organization for which you want to download a report. + """ + + start_date: Optional[datetime] = None + """ + Start date (inclusive) of the period for which you want to retrieve impact data (ISO 8601 format, e.g., 2025-05-01T00:00:00Z). + """ + + end_date: Optional[datetime] = None + """ + End date (exclusive) of the period for which you want to retrieve impact data (ISO 8601 format, with time in UTC, `YYYY-MM-DDTHH:MM:SSZ`). Defaults to today's date. + """ + + regions: Optional[list[str]] = field(default_factory=list) + """ + List of regions to filter by (\"fr-par\"). Defaults to all regions. + """ + + zones: Optional[list[str]] = field(default_factory=list) + """ + List of zones to filter by (\"fr-par-1\"). Defaults to all zones. + """ + + project_ids: Optional[list[str]] = field(default_factory=list) + """ + List of Project IDs to filter by. Defaults to all Projects in the Organization. + """ + + service_categories: Optional[list[ServiceCategory]] = field(default_factory=list) + """ + List of service categories to filter by. Defaults to all service categories. + """ + + product_categories: Optional[list[ProductCategory]] = field(default_factory=list) + """ + List of product categories to filter by. Defaults to all product categories. + """ + + +@dataclass +class UserApiGetImpactReportAvailabilityRequest: + organization_id: Optional[str] = None + """ + The UUID of the Organization for which you want to download a report. + """ + + start_date: Optional[datetime] = None + """ + Start date of the search period (ISO 8601 format, with time in UTC, `YYYY-MM-DDTHH:MM:SSZ`). The date is inclusive. + """ + + end_date: Optional[datetime] = None + """ + End date of the search period (ISO 8601 format, with time in UTC, `YYYY-MM-DDTHH:MM:SSZ`). The date is exclusive. Defaults to today's date. + """ diff --git a/scaleway/scaleway/environmental_footprint/__init__.py b/scaleway/scaleway/environmental_footprint/__init__.py new file mode 100644 index 000000000..8b74a5ed7 --- /dev/null +++ b/scaleway/scaleway/environmental_footprint/__init__.py @@ -0,0 +1,2 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. diff --git a/scaleway/scaleway/environmental_footprint/v1alpha1/__init__.py b/scaleway/scaleway/environmental_footprint/v1alpha1/__init__.py new file mode 100644 index 000000000..4354e9c93 --- /dev/null +++ b/scaleway/scaleway/environmental_footprint/v1alpha1/__init__.py @@ -0,0 +1,33 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from .types import ProductCategory +from .types import ReportType +from .types import ServiceCategory +from .types import Impact +from .types import SkuImpact +from .types import ZoneImpact +from .types import RegionImpact +from .types import ProjectImpact +from .types import ImpactDataResponse +from .types import ImpactReportAvailability +from .types import UserApiDownloadImpactReportRequest +from .types import UserApiGetImpactDataRequest +from .types import UserApiGetImpactReportAvailabilityRequest +from .api import EnvironmentalFootprintV1Alpha1UserAPI + +__all__ = [ + "ProductCategory", + "ReportType", + "ServiceCategory", + "Impact", + "SkuImpact", + "ZoneImpact", + "RegionImpact", + "ProjectImpact", + "ImpactDataResponse", + "ImpactReportAvailability", + "UserApiDownloadImpactReportRequest", + "UserApiGetImpactDataRequest", + "UserApiGetImpactReportAvailabilityRequest", + "EnvironmentalFootprintV1Alpha1UserAPI", +] diff --git a/scaleway/scaleway/environmental_footprint/v1alpha1/api.py b/scaleway/scaleway/environmental_footprint/v1alpha1/api.py new file mode 100644 index 000000000..fa1f35d85 --- /dev/null +++ b/scaleway/scaleway/environmental_footprint/v1alpha1/api.py @@ -0,0 +1,152 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from datetime import datetime +from typing import Optional + +from scaleway_core.api import API +from scaleway_core.bridge import ( + ScwFile, + unmarshal_ScwFile, +) +from .types import ( + ProductCategory, + ReportType, + ServiceCategory, + ImpactDataResponse, + ImpactReportAvailability, + UserApiDownloadImpactReportRequest, +) +from .marshalling import ( + unmarshal_ImpactDataResponse, + unmarshal_ImpactReportAvailability, + marshal_UserApiDownloadImpactReportRequest, +) + + +class EnvironmentalFootprintV1Alpha1UserAPI(API): + """ + Access and download impact reports and impact data for your Scaleway projects. Our API provides key metrics such as estimated carbon emissions and water usage to help monitor your environmental footprint. + """ + + def get_impact_report_availability( + self, + *, + organization_id: Optional[str] = None, + start_date: Optional[datetime] = None, + end_date: Optional[datetime] = None, + ) -> ImpactReportAvailability: + """ + Get available impact reports. + Returns a list of dates of available impact reports. + :param organization_id: The UUID of the Organization for which you want to download a report. + :param start_date: Start date of the search period (ISO 8601 format, with time in UTC, `YYYY-MM-DDTHH:MM:SSZ`). The date is inclusive. + :param end_date: End date of the search period (ISO 8601 format, with time in UTC, `YYYY-MM-DDTHH:MM:SSZ`). The date is exclusive. Defaults to today's date. + :return: :class:`ImpactReportAvailability ` + + Usage: + :: + + result = api.get_impact_report_availability() + """ + + res = self._request( + "GET", + "/environmental-footprint/v1alpha1/reports/availability", + params={ + "end_date": end_date, + "organization_id": organization_id + or self.client.default_organization_id, + "start_date": start_date, + }, + ) + + self._throw_on_error(res) + return unmarshal_ImpactReportAvailability(res.json()) + + def download_impact_report( + self, + *, + organization_id: Optional[str] = None, + date: Optional[datetime] = None, + type_: Optional[ReportType] = None, + ) -> ScwFile: + """ + Download PDF impact report. + Download a Scaleway impact PDF report with detailed impact data for your Scaleway projects. + :param organization_id: The UUID of the Organization for which you want to download a report. + :param date: The start date of the period for which you want to download a report (ISO 8601 format, e.g., 2025-05-01T00:00:00Z). + :param type_: Type of report to download (e.g., monthly). Defaults to monthly. + :return: :class:`ScwFile ` + + Usage: + :: + + result = api.download_impact_report() + """ + + res = self._request( + "POST", + "/environmental-footprint/v1alpha1/reports/download", + body=marshal_UserApiDownloadImpactReportRequest( + UserApiDownloadImpactReportRequest( + organization_id=organization_id, + date=date, + type_=type_, + ), + self.client, + ), + ) + + self._throw_on_error(res) + return unmarshal_ScwFile(res.json()) + + def get_impact_data( + self, + *, + organization_id: Optional[str] = None, + start_date: Optional[datetime] = None, + end_date: Optional[datetime] = None, + regions: Optional[list[str]] = None, + zones: Optional[list[str]] = None, + project_ids: Optional[list[str]] = None, + service_categories: Optional[list[ServiceCategory]] = None, + product_categories: Optional[list[ProductCategory]] = None, + ) -> ImpactDataResponse: + """ + Retrieve detailed impact data. + Retrieve detailed impact data for your Scaleway projects within a specified date range. Filter by project ID, region, zone, service category, and/or product category. + :param organization_id: The UUID of the Organization for which you want to download a report. + :param start_date: Start date (inclusive) of the period for which you want to retrieve impact data (ISO 8601 format, e.g., 2025-05-01T00:00:00Z). + :param end_date: End date (exclusive) of the period for which you want to retrieve impact data (ISO 8601 format, with time in UTC, `YYYY-MM-DDTHH:MM:SSZ`). Defaults to today's date. + :param regions: List of regions to filter by (\"fr-par\"). Defaults to all regions. + :param zones: List of zones to filter by (\"fr-par-1\"). Defaults to all zones. + :param project_ids: List of Project IDs to filter by. Defaults to all Projects in the Organization. + :param service_categories: List of service categories to filter by. Defaults to all service categories. + :param product_categories: List of product categories to filter by. Defaults to all product categories. + :return: :class:`ImpactDataResponse ` + + Usage: + :: + + result = api.get_impact_data() + """ + + res = self._request( + "GET", + "/environmental-footprint/v1alpha1/data/query", + params={ + "end_date": end_date, + "organization_id": organization_id + or self.client.default_organization_id, + "product_categories": product_categories, + "project_ids": project_ids, + "regions": regions, + "service_categories": service_categories, + "start_date": start_date, + "zones": zones, + }, + ) + + self._throw_on_error(res) + return unmarshal_ImpactDataResponse(res.json()) diff --git a/scaleway/scaleway/environmental_footprint/v1alpha1/marshalling.py b/scaleway/scaleway/environmental_footprint/v1alpha1/marshalling.py new file mode 100644 index 000000000..548836019 --- /dev/null +++ b/scaleway/scaleway/environmental_footprint/v1alpha1/marshalling.py @@ -0,0 +1,244 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. + +from typing import Any +from dateutil import parser + +from scaleway_core.profile import ProfileDefaults +from .types import ( + ProductCategory, + ServiceCategory, + Impact, + SkuImpact, + ZoneImpact, + RegionImpact, + ProjectImpact, + ImpactDataResponse, + ImpactReportAvailability, + UserApiDownloadImpactReportRequest, +) + + +def unmarshal_Impact(data: Any) -> Impact: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'Impact' failed as data isn't a dictionary." + ) + + args: dict[str, Any] = {} + + field = data.get("kg_co2_equivalent", None) + if field is not None: + args["kg_co2_equivalent"] = field + else: + args["kg_co2_equivalent"] = 0.0 + + field = data.get("m3_water_usage", None) + if field is not None: + args["m3_water_usage"] = field + else: + args["m3_water_usage"] = 0.0 + + return Impact(**args) + + +def unmarshal_SkuImpact(data: Any) -> SkuImpact: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'SkuImpact' failed as data isn't a dictionary." + ) + + args: dict[str, Any] = {} + + field = data.get("sku", None) + if field is not None: + args["sku"] = field + else: + args["sku"] = None + + field = data.get("service_category", None) + if field is not None: + args["service_category"] = field + else: + args["service_category"] = ServiceCategory.UNKNOWN_SERVICE_CATEGORY + + field = data.get("product_category", None) + if field is not None: + args["product_category"] = field + else: + args["product_category"] = ProductCategory.UNKNOWN_PRODUCT_CATEGORY + + field = data.get("total_sku_impact", None) + if field is not None: + args["total_sku_impact"] = unmarshal_Impact(field) + else: + args["total_sku_impact"] = None + + return SkuImpact(**args) + + +def unmarshal_ZoneImpact(data: Any) -> ZoneImpact: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ZoneImpact' failed as data isn't a dictionary." + ) + + args: dict[str, Any] = {} + + field = data.get("zone", None) + if field is not None: + args["zone"] = field + else: + args["zone"] = None + + field = data.get("skus", None) + if field is not None: + args["skus"] = ( + [unmarshal_SkuImpact(v) for v in field] if field is not None else None + ) + else: + args["skus"] = [] + + field = data.get("total_zone_impact", None) + if field is not None: + args["total_zone_impact"] = unmarshal_Impact(field) + else: + args["total_zone_impact"] = None + + return ZoneImpact(**args) + + +def unmarshal_RegionImpact(data: Any) -> RegionImpact: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'RegionImpact' failed as data isn't a dictionary." + ) + + args: dict[str, Any] = {} + + field = data.get("region", None) + if field is not None: + args["region"] = field + else: + args["region"] = None + + field = data.get("zones", None) + if field is not None: + args["zones"] = ( + [unmarshal_ZoneImpact(v) for v in field] if field is not None else None + ) + else: + args["zones"] = [] + + field = data.get("total_region_impact", None) + if field is not None: + args["total_region_impact"] = unmarshal_Impact(field) + else: + args["total_region_impact"] = None + + return RegionImpact(**args) + + +def unmarshal_ProjectImpact(data: Any) -> ProjectImpact: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ProjectImpact' failed as data isn't a dictionary." + ) + + args: dict[str, Any] = {} + + field = data.get("project_id", None) + if field is not None: + args["project_id"] = field + else: + args["project_id"] = None + + field = data.get("regions", None) + if field is not None: + args["regions"] = ( + [unmarshal_RegionImpact(v) for v in field] if field is not None else None + ) + else: + args["regions"] = [] + + field = data.get("total_project_impact", None) + if field is not None: + args["total_project_impact"] = unmarshal_Impact(field) + else: + args["total_project_impact"] = None + + return ProjectImpact(**args) + + +def unmarshal_ImpactDataResponse(data: Any) -> ImpactDataResponse: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ImpactDataResponse' failed as data isn't a dictionary." + ) + + args: dict[str, Any] = {} + + field = data.get("projects", None) + if field is not None: + args["projects"] = ( + [unmarshal_ProjectImpact(v) for v in field] if field is not None else None + ) + else: + args["projects"] = [] + + field = data.get("start_date", None) + if field is not None: + args["start_date"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["start_date"] = None + + field = data.get("end_date", None) + if field is not None: + args["end_date"] = parser.isoparse(field) if isinstance(field, str) else field + else: + args["end_date"] = None + + field = data.get("total_impact", None) + if field is not None: + args["total_impact"] = unmarshal_Impact(field) + else: + args["total_impact"] = None + + return ImpactDataResponse(**args) + + +def unmarshal_ImpactReportAvailability(data: Any) -> ImpactReportAvailability: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ImpactReportAvailability' failed as data isn't a dictionary." + ) + + args: dict[str, Any] = {} + + field = data.get("month_summary_reports", None) + if field is not None: + args["month_summary_reports"] = field + else: + args["month_summary_reports"] = None + + return ImpactReportAvailability(**args) + + +def marshal_UserApiDownloadImpactReportRequest( + request: UserApiDownloadImpactReportRequest, + defaults: ProfileDefaults, +) -> dict[str, Any]: + output: dict[str, Any] = {} + + if request.organization_id is not None: + output["organization_id"] = request.organization_id + else: + output["organization_id"] = defaults.default_organization_id + + if request.date is not None: + output["date"] = request.date.isoformat() + + if request.type_ is not None: + output["type"] = request.type_ + + return output diff --git a/scaleway/scaleway/environmental_footprint/v1alpha1/types.py b/scaleway/scaleway/environmental_footprint/v1alpha1/types.py new file mode 100644 index 000000000..79a683f85 --- /dev/null +++ b/scaleway/scaleway/environmental_footprint/v1alpha1/types.py @@ -0,0 +1,248 @@ +# This file was automatically generated. DO NOT EDIT. +# If you have any remark or suggestion do not hesitate to open an issue. +from __future__ import annotations + +from dataclasses import dataclass, field +from datetime import datetime +from enum import Enum +from typing import Optional + +from scaleway_core.bridge import ( + Region as ScwRegion, + Zone as ScwZone, +) +from scaleway_core.utils import ( + StrEnumMeta, +) + + +class ProductCategory(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_PRODUCT_CATEGORY = "unknown_product_category" + APPLE_SILICON = "apple_silicon" + BLOCK_STORAGE = "block_storage" + DEDIBOX = "dedibox" + ELASTIC_METAL = "elastic_metal" + INSTANCES = "instances" + OBJECT_STORAGE = "object_storage" + + def __str__(self) -> str: + return str(self.value) + + +class ReportType(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_REPORT_TYPE = "unknown_report_type" + MONTHLY = "monthly" + YEARLY = "yearly" + + def __str__(self) -> str: + return str(self.value) + + +class ServiceCategory(str, Enum, metaclass=StrEnumMeta): + UNKNOWN_SERVICE_CATEGORY = "unknown_service_category" + BAREMETAL = "baremetal" + COMPUTE = "compute" + STORAGE = "storage" + + def __str__(self) -> str: + return str(self.value) + + +@dataclass +class Impact: + kg_co2_equivalent: float + """ + The estimated carbon emissions in kilograms of CO₂ equivalent (kgCO₂e). + """ + + m3_water_usage: float + """ + The estimated water consumption in cubic meters (m³). + """ + + +@dataclass +class SkuImpact: + sku: str + """ + Unique ID of the combination of product, region and zone. + """ + + service_category: ServiceCategory + """ + The service category associated with this SKU. + """ + + product_category: ProductCategory + """ + The product category associated with this SKU. + """ + + total_sku_impact: Optional[Impact] = None + """ + The total estimated impact for this SKU during the given period. + """ + + +@dataclass +class ZoneImpact: + zone: ScwZone + """ + ID of the zone. + """ + + skus: list[SkuImpact] + """ + List of estimated impact values per SKU. + """ + + total_zone_impact: Optional[Impact] = None + """ + The total estimated impact for this zone across all given service categories, and product categories during the given period. + """ + + +@dataclass +class RegionImpact: + region: ScwRegion + """ + ID of the region. + """ + + zones: list[ZoneImpact] + """ + List of estimated impact values per zone. + """ + + total_region_impact: Optional[Impact] = None + """ + The total estimated impact for this region across all given zones, service categories, and product categories during the given period. + """ + + +@dataclass +class ProjectImpact: + project_id: str + """ + ID of the project. + """ + + regions: list[RegionImpact] + """ + List of estimated impact values per region. + """ + + total_project_impact: Optional[Impact] = None + """ + The total estimated impact for this Project across all given regions, zones, service categories, and product categories during the given period. + """ + + +@dataclass +class ImpactDataResponse: + projects: list[ProjectImpact] + """ + List of estimated impact values per Project. + """ + + start_date: Optional[datetime] = None + """ + Start date of the impact data period (inclusive). + """ + + end_date: Optional[datetime] = None + """ + End date of the impact data period (exclusive). + """ + + total_impact: Optional[Impact] = None + """ + The total estimated impact across all given Projects, regions, zones, service categories, and product categories during the given period. + """ + + +@dataclass +class ImpactReportAvailability: + month_summary_reports: list[datetime] + """ + The list of calendar months for which impact reports are available. + """ + + +@dataclass +class UserApiDownloadImpactReportRequest: + organization_id: Optional[str] = None + """ + The UUID of the Organization for which you want to download a report. + """ + + date: Optional[datetime] = None + """ + The start date of the period for which you want to download a report (ISO 8601 format, e.g., 2025-05-01T00:00:00Z). + """ + + type_: Optional[ReportType] = ReportType.UNKNOWN_REPORT_TYPE + """ + Type of report to download (e.g., monthly). Defaults to monthly. + """ + + +@dataclass +class UserApiGetImpactDataRequest: + organization_id: Optional[str] = None + """ + The UUID of the Organization for which you want to download a report. + """ + + start_date: Optional[datetime] = None + """ + Start date (inclusive) of the period for which you want to retrieve impact data (ISO 8601 format, e.g., 2025-05-01T00:00:00Z). + """ + + end_date: Optional[datetime] = None + """ + End date (exclusive) of the period for which you want to retrieve impact data (ISO 8601 format, with time in UTC, `YYYY-MM-DDTHH:MM:SSZ`). Defaults to today's date. + """ + + regions: Optional[list[str]] = field(default_factory=list) + """ + List of regions to filter by (\"fr-par\"). Defaults to all regions. + """ + + zones: Optional[list[str]] = field(default_factory=list) + """ + List of zones to filter by (\"fr-par-1\"). Defaults to all zones. + """ + + project_ids: Optional[list[str]] = field(default_factory=list) + """ + List of Project IDs to filter by. Defaults to all Projects in the Organization. + """ + + service_categories: Optional[list[ServiceCategory]] = field(default_factory=list) + """ + List of service categories to filter by. Defaults to all service categories. + """ + + product_categories: Optional[list[ProductCategory]] = field(default_factory=list) + """ + List of product categories to filter by. Defaults to all product categories. + """ + + +@dataclass +class UserApiGetImpactReportAvailabilityRequest: + organization_id: Optional[str] = None + """ + The UUID of the Organization for which you want to download a report. + """ + + start_date: Optional[datetime] = None + """ + Start date of the search period (ISO 8601 format, with time in UTC, `YYYY-MM-DDTHH:MM:SSZ`). The date is inclusive. + """ + + end_date: Optional[datetime] = None + """ + End date of the search period (ISO 8601 format, with time in UTC, `YYYY-MM-DDTHH:MM:SSZ`). The date is exclusive. Defaults to today's date. + """