diff --git a/libs/labelbox/src/labelbox/schema/workflow/nodes/done_node.py b/libs/labelbox/src/labelbox/schema/workflow/nodes/done_node.py index fce1d3bd6..2c2e2c3cc 100644 --- a/libs/labelbox/src/labelbox/schema/workflow/nodes/done_node.py +++ b/libs/labelbox/src/labelbox/schema/workflow/nodes/done_node.py @@ -2,7 +2,7 @@ import logging from typing import Dict, List, Any, Optional -from pydantic import Field, field_validator +from pydantic import Field, field_validator, ConfigDict from labelbox.schema.workflow.base import BaseWorkflowNode from labelbox.schema.workflow.enums import ( @@ -57,6 +57,8 @@ class DoneNode(BaseWorkflowNode): and will not flow to any other nodes in the workflow. """ + model_config = ConfigDict(extra="ignore") + label: str = Field(default="Done", max_length=50) definition_id: WorkflowDefinitionId = Field( default=WorkflowDefinitionId.Done, frozen=True, alias="definitionId" diff --git a/libs/labelbox/src/labelbox/schema/workflow/nodes/initial_labeling_node.py b/libs/labelbox/src/labelbox/schema/workflow/nodes/initial_labeling_node.py index 1adff2e2b..5de2af0d6 100644 --- a/libs/labelbox/src/labelbox/schema/workflow/nodes/initial_labeling_node.py +++ b/libs/labelbox/src/labelbox/schema/workflow/nodes/initial_labeling_node.py @@ -2,7 +2,7 @@ import logging from typing import Dict, List, Any, Optional, Literal, Union -from pydantic import Field, field_validator, model_validator +from pydantic import Field, field_validator, model_validator, ConfigDict from labelbox.schema.workflow.base import BaseWorkflowNode from labelbox.schema.workflow.enums import ( @@ -59,6 +59,8 @@ class InitialLabelingNode(BaseWorkflowNode): and cannot have incoming connections from other nodes. """ + model_config = ConfigDict(extra="ignore") + label: str = Field( default="Initial labeling task", frozen=True, max_length=50 ) diff --git a/libs/labelbox/src/labelbox/schema/workflow/nodes/initial_rework_node.py b/libs/labelbox/src/labelbox/schema/workflow/nodes/initial_rework_node.py index fca96aeb0..fb86f8e80 100644 --- a/libs/labelbox/src/labelbox/schema/workflow/nodes/initial_rework_node.py +++ b/libs/labelbox/src/labelbox/schema/workflow/nodes/initial_rework_node.py @@ -2,7 +2,7 @@ import logging from typing import Dict, List, Any, Optional, Literal, Union -from pydantic import Field, field_validator, model_validator +from pydantic import Field, field_validator, model_validator, ConfigDict from labelbox.schema.workflow.base import BaseWorkflowNode from labelbox.schema.workflow.enums import ( @@ -66,6 +66,8 @@ class InitialReworkNode(BaseWorkflowNode): to ensure proper routing in the Labelbox platform. """ + model_config = ConfigDict(extra="ignore") + label: str = Field( default="Rework (all rejected)", frozen=True, max_length=50 ) diff --git a/libs/labelbox/src/labelbox/schema/workflow/nodes/logic_node.py b/libs/labelbox/src/labelbox/schema/workflow/nodes/logic_node.py index 1457a7227..6b53437cb 100644 --- a/libs/labelbox/src/labelbox/schema/workflow/nodes/logic_node.py +++ b/libs/labelbox/src/labelbox/schema/workflow/nodes/logic_node.py @@ -6,7 +6,7 @@ import logging from typing import Dict, List, Any, Optional, Literal -from pydantic import Field, model_validator, field_validator +from pydantic import Field, model_validator, field_validator, ConfigDict from labelbox.schema.workflow.base import BaseWorkflowNode from labelbox.schema.workflow.enums import ( @@ -27,6 +27,7 @@ class LogicNode(BaseWorkflowNode): + model_config = ConfigDict(extra="ignore") """Logic node. One or more instances possible. One input, two outputs (if/else).""" label: str = Field( diff --git a/libs/labelbox/src/labelbox/schema/workflow/nodes/review_node.py b/libs/labelbox/src/labelbox/schema/workflow/nodes/review_node.py index 4c51d38c0..3f1861cf1 100644 --- a/libs/labelbox/src/labelbox/schema/workflow/nodes/review_node.py +++ b/libs/labelbox/src/labelbox/schema/workflow/nodes/review_node.py @@ -2,7 +2,7 @@ import logging from typing import Dict, List, Any, Optional, Literal, Union -from pydantic import Field, field_validator, model_validator +from pydantic import Field, field_validator, model_validator, ConfigDict from labelbox.schema.workflow.base import BaseWorkflowNode from labelbox.schema.workflow.enums import ( @@ -69,6 +69,8 @@ class ReviewNode(BaseWorkflowNode): which default to "and" logic. This allows more flexible routing. """ + model_config = ConfigDict(extra="ignore") + label: str = Field(default="Review task", max_length=50) # For ReviewNode, filter_logic defaults to "or" filter_logic: Literal["and", "or"] = Field( diff --git a/libs/labelbox/src/labelbox/schema/workflow/nodes/rework_node.py b/libs/labelbox/src/labelbox/schema/workflow/nodes/rework_node.py index 079e4b434..5e6ddf5e8 100644 --- a/libs/labelbox/src/labelbox/schema/workflow/nodes/rework_node.py +++ b/libs/labelbox/src/labelbox/schema/workflow/nodes/rework_node.py @@ -2,7 +2,7 @@ import logging from typing import Dict, List, Any, Optional, Literal -from pydantic import Field, field_validator +from pydantic import Field, field_validator, ConfigDict from labelbox.schema.workflow.base import BaseWorkflowNode from labelbox.schema.workflow.enums import ( @@ -17,6 +17,7 @@ class ReworkNode(BaseWorkflowNode): + model_config = ConfigDict(extra="ignore") """ Terminal rework node for sending work back for corrections. diff --git a/libs/labelbox/src/labelbox/schema/workflow/workflow.py b/libs/labelbox/src/labelbox/schema/workflow/workflow.py index 4af0f9e25..55682ff58 100644 --- a/libs/labelbox/src/labelbox/schema/workflow/workflow.py +++ b/libs/labelbox/src/labelbox/schema/workflow/workflow.py @@ -283,10 +283,13 @@ def get_nodes(self) -> List[BaseWorkflowNode]: node_kwargs["config"] = node_data["config"] if "customFields" in node_data: - node_kwargs["customFields"] = node_data["customFields"] + # Handle customFields being None by converting to empty dict + custom_fields = node_data["customFields"] + if custom_fields is None: + custom_fields = {} + node_kwargs["customFields"] = custom_fields # Extract instructions from customFields if available - custom_fields = node_data["customFields"] if ( isinstance(custom_fields, dict) and "description" in custom_fields