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
2 changes: 1 addition & 1 deletion fastfuels_sdk/client_library/api_spec.json

Large diffs are not rendered by default.

136 changes: 101 additions & 35 deletions fastfuels_sdk/client_library/models/tree_inventory.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,37 +23,69 @@
from typing_extensions import Annotated
from fastfuels_sdk.client_library.models.feature_type import FeatureType
from fastfuels_sdk.client_library.models.job_status import JobStatus
from fastfuels_sdk.client_library.models.tree_inventory_modification import TreeInventoryModification
from fastfuels_sdk.client_library.models.tree_inventory_source import TreeInventorySource
from fastfuels_sdk.client_library.models.tree_inventory_treatment import TreeInventoryTreatment
from fastfuels_sdk.client_library.models.processing_error import ProcessingError
from fastfuels_sdk.client_library.models.tree_inventory_modification import (
TreeInventoryModification,
)
from fastfuels_sdk.client_library.models.tree_inventory_source import (
TreeInventorySource,
)
from fastfuels_sdk.client_library.models.tree_inventory_treatment import (
TreeInventoryTreatment,
)
from fastfuels_sdk.client_library.models.tree_map_source import TreeMapSource
from fastfuels_sdk.client_library.models.upload_response import UploadResponse
from typing import Optional, Set
from typing_extensions import Self


class TreeInventory(BaseModel):
"""
TreeInventory
""" # noqa: E501
""" # noqa: E501

sources: List[TreeInventorySource]
tree_map: Optional[TreeMapSource] = Field(default=None, alias="TreeMap")
modifications: Optional[Annotated[List[TreeInventoryModification], Field(max_length=1000)]] = Field(default=None, description="List of modifications to apply to the tree inventory data")
treatments: Optional[Annotated[List[TreeInventoryTreatment], Field(max_length=1000)]] = Field(default=None, description="List of silvicultural treatments to apply.")
feature_masks: Optional[List[FeatureType]] = Field(default=None, description="List of Features to mask tree inventory data. This has the effect of removing trees that intersect with the feature.", alias="featureMasks")
modifications: Optional[
Annotated[List[TreeInventoryModification], Field(max_length=1000)]
] = Field(
default=None,
description="List of modifications to apply to the tree inventory data",
)
treatments: Optional[
Annotated[List[TreeInventoryTreatment], Field(max_length=1000)]
] = Field(default=None, description="List of silvicultural treatments to apply.")
feature_masks: Optional[List[FeatureType]] = Field(
default=None,
description="List of Features to mask tree inventory data. This has the effect of removing trees that intersect with the feature.",
alias="featureMasks",
)
status: Optional[JobStatus] = None
created_on: Optional[datetime] = Field(default=None, alias="createdOn")
modified_on: Optional[datetime] = Field(default=None, alias="modifiedOn")
checksum: Optional[StrictStr] = None
file: Optional[UploadResponse] = None
__properties: ClassVar[List[str]] = ["sources", "TreeMap", "modifications", "treatments", "featureMasks", "status", "createdOn", "modifiedOn", "checksum", "file"]
error: Optional[ProcessingError] = None
__properties: ClassVar[List[str]] = [
"sources",
"TreeMap",
"modifications",
"treatments",
"featureMasks",
"status",
"createdOn",
"modifiedOn",
"checksum",
"file",
"error",
]

model_config = ConfigDict(
populate_by_name=True,
validate_assignment=True,
protected_namespaces=(),
)


def to_str(self) -> str:
"""Returns the string representation of the model using alias"""
return pprint.pformat(self.model_dump(by_alias=True))
Expand All @@ -78,59 +110,66 @@ def to_dict(self) -> Dict[str, Any]:
were set at model initialization. Other fields with value `None`
are ignored.
"""
excluded_fields: Set[str] = set([
])
excluded_fields: Set[str] = set([])

_dict = self.model_dump(
mode='json',
mode="json",
by_alias=True,
exclude=excluded_fields,
exclude_none=True,
)
# override the default output from pydantic by calling `to_dict()` of tree_map
if self.tree_map:
_dict['TreeMap'] = self.tree_map.to_dict()
_dict["TreeMap"] = self.tree_map.to_dict()
# override the default output from pydantic by calling `to_dict()` of each item in modifications (list)
_items = []
if self.modifications:
for _item_modifications in self.modifications:
if _item_modifications:
_items.append(_item_modifications.to_dict())
_dict['modifications'] = _items
_dict["modifications"] = _items
# override the default output from pydantic by calling `to_dict()` of each item in treatments (list)
_items = []
if self.treatments:
for _item_treatments in self.treatments:
if _item_treatments:
_items.append(_item_treatments.to_dict())
_dict['treatments'] = _items
_dict["treatments"] = _items
# override the default output from pydantic by calling `to_dict()` of file
if self.file:
_dict['file'] = self.file.to_dict()
_dict["file"] = self.file.to_dict()
# override the default output from pydantic by calling `to_dict()` of error
if self.error:
_dict["error"] = self.error.to_dict()
# set to None if tree_map (nullable) is None
# and model_fields_set contains the field
if self.tree_map is None and "tree_map" in self.model_fields_set:
_dict['TreeMap'] = None
_dict["TreeMap"] = None

# set to None if created_on (nullable) is None
# and model_fields_set contains the field
if self.created_on is None and "created_on" in self.model_fields_set:
_dict['createdOn'] = None
_dict["createdOn"] = None

# set to None if modified_on (nullable) is None
# and model_fields_set contains the field
if self.modified_on is None and "modified_on" in self.model_fields_set:
_dict['modifiedOn'] = None
_dict["modifiedOn"] = None

# set to None if checksum (nullable) is None
# and model_fields_set contains the field
if self.checksum is None and "checksum" in self.model_fields_set:
_dict['checksum'] = None
_dict["checksum"] = None

# set to None if file (nullable) is None
# and model_fields_set contains the field
if self.file is None and "file" in self.model_fields_set:
_dict['file'] = None
_dict["file"] = None

# set to None if error (nullable) is None
# and model_fields_set contains the field
if self.error is None and "error" in self.model_fields_set:
_dict["error"] = None

return _dict

Expand All @@ -143,18 +182,45 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
if not isinstance(obj, dict):
return cls.model_validate(obj)

_obj = cls.model_validate({
"sources": obj.get("sources"),
"TreeMap": TreeMapSource.from_dict(obj["TreeMap"]) if obj.get("TreeMap") is not None else None,
"modifications": [TreeInventoryModification.from_dict(_item) for _item in obj["modifications"]] if obj.get("modifications") is not None else None,
"treatments": [TreeInventoryTreatment.from_dict(_item) for _item in obj["treatments"]] if obj.get("treatments") is not None else None,
"featureMasks": obj.get("featureMasks"),
"status": obj.get("status"),
"createdOn": obj.get("createdOn"),
"modifiedOn": obj.get("modifiedOn"),
"checksum": obj.get("checksum"),
"file": UploadResponse.from_dict(obj["file"]) if obj.get("file") is not None else None
})
_obj = cls.model_validate(
{
"sources": obj.get("sources"),
"TreeMap": (
TreeMapSource.from_dict(obj["TreeMap"])
if obj.get("TreeMap") is not None
else None
),
"modifications": (
[
TreeInventoryModification.from_dict(_item)
for _item in obj["modifications"]
]
if obj.get("modifications") is not None
else None
),
"treatments": (
[
TreeInventoryTreatment.from_dict(_item)
for _item in obj["treatments"]
]
if obj.get("treatments") is not None
else None
),
"featureMasks": obj.get("featureMasks"),
"status": obj.get("status"),
"createdOn": obj.get("createdOn"),
"modifiedOn": obj.get("modifiedOn"),
"checksum": obj.get("checksum"),
"file": (
UploadResponse.from_dict(obj["file"])
if obj.get("file") is not None
else None
),
"error": (
ProcessingError.from_dict(obj["error"])
if obj.get("error") is not None
else None
),
}
)
return _obj


15 changes: 2 additions & 13 deletions fastfuels_sdk/client_library/models/upload_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

from pydantic import BaseModel, ConfigDict, StrictStr
from typing import Any, ClassVar, Dict, List, Optional
from fastfuels_sdk.client_library.models.processing_error import ProcessingError
from typing import Optional, Set
from typing_extensions import Self

Expand All @@ -32,8 +31,7 @@ class UploadResponse(BaseModel):
url: Optional[StrictStr] = None
headers: Optional[Dict[str, StrictStr]] = None
curl: Optional[StrictStr] = None
error: Optional[ProcessingError] = None
__properties: ClassVar[List[str]] = ["message", "method", "url", "headers", "curl", "error"]
__properties: ClassVar[List[str]] = ["message", "method", "url", "headers", "curl"]

model_config = ConfigDict(
populate_by_name=True,
Expand Down Expand Up @@ -74,9 +72,6 @@ def to_dict(self) -> Dict[str, Any]:
exclude=excluded_fields,
exclude_none=True,
)
# override the default output from pydantic by calling `to_dict()` of error
if self.error:
_dict['error'] = self.error.to_dict()
# set to None if message (nullable) is None
# and model_fields_set contains the field
if self.message is None and "message" in self.model_fields_set:
Expand All @@ -102,11 +97,6 @@ def to_dict(self) -> Dict[str, Any]:
if self.curl is None and "curl" in self.model_fields_set:
_dict['curl'] = None

# set to None if error (nullable) is None
# and model_fields_set contains the field
if self.error is None and "error" in self.model_fields_set:
_dict['error'] = None

return _dict

@classmethod
Expand All @@ -123,8 +113,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
"method": obj.get("method"),
"url": obj.get("url"),
"headers": obj.get("headers"),
"curl": obj.get("curl"),
"error": ProcessingError.from_dict(obj["error"]) if obj.get("error") is not None else None
"curl": obj.get("curl")
})
return _obj

Expand Down
12 changes: 11 additions & 1 deletion fastfuels_sdk/exports.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

# Internal imports
from fastfuels_sdk.api import get_client
from fastfuels_sdk.utils import format_processing_error
from fastfuels_sdk.client_library.models import Export as ExportModel
from fastfuels_sdk.client_library.api import (
TreeInventoryApi,
Expand Down Expand Up @@ -168,7 +169,16 @@ def wait_until_completed(

while export.status != "completed":
if export.status == "failed":
raise RuntimeError("Export processing failed.")
error_msg = "Export processing failed."

# Extract detailed error information if available
error_obj = getattr(export, "error", None)
if error_obj:
error_details = format_processing_error(error_obj)
if error_details:
error_msg = f"{error_msg}\n\n{error_details}"

raise RuntimeError(error_msg)
if elapsed_time >= timeout:
raise TimeoutError(
f"Timed out waiting for export to finish after {timeout} seconds."
Expand Down
24 changes: 22 additions & 2 deletions fastfuels_sdk/features.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

# Internal imports
from fastfuels_sdk.api import get_client
from fastfuels_sdk.utils import format_processing_error
from fastfuels_sdk.client_library.api import (
FeaturesApi,
RoadFeatureApi,
Expand Down Expand Up @@ -560,7 +561,16 @@ def wait_until_completed(
road_feature = self.get(in_place=in_place if in_place else False)
while road_feature.status != "completed":
if road_feature.status == "failed":
raise RuntimeError("Road feature processing failed.")
error_msg = "Road feature processing failed."

# Extract detailed error information if available
error_obj = getattr(road_feature, "error", None)
if error_obj:
error_details = format_processing_error(error_obj)
if error_details:
error_msg = f"{error_msg}\n\n{error_details}"

raise RuntimeError(error_msg)
if elapsed_time >= timeout:
raise TimeoutError("Timed out waiting for road features to finish.")
sleep(step)
Expand Down Expand Up @@ -709,7 +719,17 @@ def wait_until_completed(
water_feature = self.get(in_place=in_place if in_place else False)
while water_feature.status != "completed":
if water_feature.status == "failed":
raise RuntimeError("Water feature processing failed.")
error_msg = "Water feature processing failed."

# Extract detailed error information if available
# Check for error in multiple possible locations
error_obj = getattr(water_feature, "error", None)
if error_obj:
error_details = format_processing_error(error_obj)
if error_details:
error_msg = f"{error_msg}\n\n{error_details}"

raise RuntimeError(error_msg)
if elapsed_time >= timeout:
raise TimeoutError("Timed out waiting for water features to finish.")
sleep(step)
Expand Down
12 changes: 11 additions & 1 deletion fastfuels_sdk/grids/feature_grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

# Internal imports
from fastfuels_sdk.api import get_client
from fastfuels_sdk.utils import format_processing_error
from fastfuels_sdk.client_library.api import FeatureGridApi
from fastfuels_sdk.client_library.models import (
FeatureGrid as FeatureGridModel,
Expand Down Expand Up @@ -159,7 +160,16 @@ def wait_until_completed(

while feature_grid.status != "completed":
if feature_grid.status == "failed":
raise RuntimeError("Feature grid processing failed.")
error_msg = "Feature grid processing failed."

# Extract detailed error information if available
error_obj = getattr(feature_grid, "error", None)
if error_obj:
error_details = format_processing_error(error_obj)
if error_details:
error_msg = f"{error_msg}\n\n{error_details}"

raise RuntimeError(error_msg)
if elapsed_time >= timeout:
raise TimeoutError("Timed out waiting for feature grid to finish.")
sleep(step)
Expand Down
12 changes: 11 additions & 1 deletion fastfuels_sdk/grids/surface_grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

# Internal imports
from fastfuels_sdk.api import get_client
from fastfuels_sdk.utils import format_processing_error
from fastfuels_sdk.exports import Export
from fastfuels_sdk.client_library.api import SurfaceGridApi
from fastfuels_sdk.client_library.models import (
Expand Down Expand Up @@ -160,7 +161,16 @@ def wait_until_completed(

while surface_grid.status != "completed":
if surface_grid.status == "failed":
raise RuntimeError("Surface grid processing failed.")
error_msg = "Surface grid processing failed."

# Extract detailed error information if available
error_obj = getattr(surface_grid, "error", None)
if error_obj:
error_details = format_processing_error(error_obj)
if error_details:
error_msg = f"{error_msg}\n\n{error_details}"

raise RuntimeError(error_msg)
if elapsed_time >= timeout:
raise TimeoutError("Timed out waiting for surface grid to finish.")
sleep(step)
Expand Down
Loading
Loading