Skip to content

Commit

Permalink
chore: update type annotations in template, io and inputs modules (#3593
Browse files Browse the repository at this point in the history
)

* refactor(input_mixin.py): update typing annotations for variables to use union types for better clarity and compatibility with Python 3.10
refactor(inputs.py): update typing annotations for variables to use union types and import necessary modules for compatibility with Python 3.10

* refactor(base.py): remove unnecessary imports and update typing for fields in Input and Output classes
feat(base.py): add support for specifying field types more explicitly in Input and Output classes
feat(frontend_node/base.py): enhance typing and field definitions in FrontendNode class
feat(frontend_node/custom_components.py): improve typing and field definitions in CustomComponentFrontendNode and ComponentFrontendNode classes
feat(template/base.py): update typing for fields in Template class and remove unnecessary imports

* refactor(inputs): remove unnecessary Optional import from typing in input_mixin.py and inputs.py files to improve code readability and maintainability

* refactor(schema.py): change 'Type' to 'type' for consistency in type annotations
refactor(schema.py): change 'list' to 'List' and 'Literal' to 'literal' for correct type hinting in create_input_schema function

* test: fix tests

---------

Co-authored-by: italojohnny <italojohnnydosanjos@gmail.com>
  • Loading branch information
ogabrielluiz and italojohnny authored Aug 28, 2024
1 parent 3e19a3f commit 1883710
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 63 deletions.
22 changes: 11 additions & 11 deletions src/backend/base/langflow/inputs/input_mixin.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from enum import Enum
from typing import Annotated, Any, Optional
from typing import Annotated, Any

from pydantic import BaseModel, ConfigDict, Field, PlainSerializer, field_validator, model_serializer

Expand Down Expand Up @@ -50,27 +50,27 @@ class BaseInputMixin(BaseModel, validate_assignment=True): # type: ignore
value: Any = ""
"""The value of the field. Default is an empty string."""

display_name: Optional[str] = None
display_name: str | None = None
"""Display name of the field. Defaults to None."""

advanced: bool = False
"""Specifies if the field will an advanced parameter (hidden). Defaults to False."""

input_types: Optional[list[str]] = None
input_types: list[str] | None = None
"""List of input types for the handle when the field has more than one type. Default is an empty list."""

dynamic: bool = False
"""Specifies if the field is dynamic. Defaults to False."""

info: Optional[str] = ""
info: str | None = ""
"""Additional information about the field to be shown in the tooltip. Defaults to an empty string."""

real_time_refresh: Optional[bool] = None
real_time_refresh: bool | None = None
"""Specifies if the field should have real time refresh. `refresh_button` must be False. Defaults to None."""

refresh_button: Optional[bool] = None
refresh_button: bool | None = None
"""Specifies if the field should have a refresh button. Defaults to False."""
refresh_button_text: Optional[str] = None
refresh_button_text: str | None = None
"""Specifies the text for the refresh button. Defaults to None."""

title_case: bool = False
Expand Down Expand Up @@ -116,7 +116,7 @@ class DatabaseLoadMixin(BaseModel):

# Specific mixin for fields needing file interaction
class FileMixin(BaseModel):
file_path: Optional[str] = Field(default="")
file_path: str | None = Field(default="")
file_types: list[str] = Field(default=[], alias="fileTypes")

@field_validator("file_types")
Expand All @@ -134,11 +134,11 @@ def validate_file_types(cls, v):


class RangeMixin(BaseModel):
range_spec: Optional[RangeSpec] = None
range_spec: RangeSpec | None = None


class DropDownMixin(BaseModel):
options: Optional[list[str]] = None
options: list[str] | None = None
"""List of options for the field. Only used when is_list=True. Default is an empty list."""
combobox: CoalesceBool = False
"""Variable that defines if the user can insert custom values in the dropdown."""
Expand All @@ -149,7 +149,7 @@ class MultilineMixin(BaseModel):


class TableMixin(BaseModel):
table_schema: Optional[TableSchema | list[Column]] = None
table_schema: TableSchema | list[Column] | None = None

@field_validator("table_schema")
@classmethod
Expand Down
9 changes: 5 additions & 4 deletions src/backend/base/langflow/inputs/inputs.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import warnings
from typing import Any, AsyncIterator, Iterator, Optional, Union, get_args
from typing import Any, Union, get_args
from collections.abc import AsyncIterator, Iterator

from pydantic import Field, field_validator

Expand Down Expand Up @@ -379,7 +380,7 @@ class NestedDictInput(BaseInputMixin, ListableInputMixin, MetadataTraceMixin, In
"""

field_type: SerializableFieldTypes = FieldTypes.NESTED_DICT
value: Optional[dict | Data] = {}
value: dict | Data | None = {}


class DictInput(BaseInputMixin, ListableInputMixin, InputTraceMixin):
Expand All @@ -395,7 +396,7 @@ class DictInput(BaseInputMixin, ListableInputMixin, InputTraceMixin):
"""

field_type: SerializableFieldTypes = FieldTypes.DICT
value: Optional[dict] = {}
value: dict | None = {}


class DropdownInput(BaseInputMixin, DropDownMixin, MetadataTraceMixin):
Expand Down Expand Up @@ -465,7 +466,7 @@ class FileInput(BaseInputMixin, ListableInputMixin, FileMixin, MetadataTraceMixi

class DefaultPromptField(Input):
name: str
display_name: Optional[str] = None
display_name: str | None = None
field_type: str = "str"

advanced: bool = False
Expand Down
8 changes: 4 additions & 4 deletions src/backend/base/langflow/io/schema.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from typing import TYPE_CHECKING, List, Literal, Type
from typing import TYPE_CHECKING, Literal

from pydantic import BaseModel, Field, create_model

from langflow.inputs.inputs import FieldTypes

_convert_field_type_to_type: dict[FieldTypes, Type] = {
_convert_field_type_to_type: dict[FieldTypes, type] = {
FieldTypes.TEXT: str,
FieldTypes.INTEGER: int,
FieldTypes.FLOAT: float,
Expand All @@ -20,7 +20,7 @@
from langflow.inputs.inputs import InputTypes


def create_input_schema(inputs: list["InputTypes"]) -> Type[BaseModel]:
def create_input_schema(inputs: list["InputTypes"]) -> type[BaseModel]:
if not isinstance(inputs, list):
raise TypeError("inputs must be a list of Inputs")
fields = {}
Expand All @@ -35,7 +35,7 @@ def create_input_schema(inputs: list["InputTypes"]) -> Type[BaseModel]:

field_type = eval(literal_string, {"Literal": Literal}) # type: ignore
if hasattr(input_model, "is_list") and input_model.is_list:
field_type = List[field_type] # type: ignore
field_type = list[field_type] # type: ignore
if input_model.name:
name = input_model.name.replace("_", " ").title()
elif input_model.display_name:
Expand Down
33 changes: 17 additions & 16 deletions src/backend/base/langflow/template/field/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
from typing import GenericAlias # type: ignore
from typing import _GenericAlias # type: ignore
from typing import _UnionGenericAlias # type: ignore
from typing import Any, Callable, Optional, Union
from typing import Any
from collections.abc import Callable

from pydantic import BaseModel, ConfigDict, Field, field_serializer, field_validator, model_serializer, model_validator

Expand Down Expand Up @@ -46,42 +47,42 @@ class Input(BaseModel):
file_types: list[str] = Field(default=[], serialization_alias="fileTypes")
"""List of file types associated with the field . Default is an empty list."""

file_path: Optional[str] = ""
file_path: str | None = ""
"""The file path of the field if it is a file. Defaults to None."""

password: bool = False
"""Specifies if the field is a password. Defaults to False."""

options: Optional[Union[list[str], Callable]] = None
options: list[str] | Callable | None = None
"""List of options for the field. Only used when is_list=True. Default is an empty list."""

name: Optional[str] = None
name: str | None = None
"""Name of the field. Default is an empty string."""

display_name: Optional[str] = None
display_name: str | None = None
"""Display name of the field. Defaults to None."""

advanced: bool = False
"""Specifies if the field will an advanced parameter (hidden). Defaults to False."""

input_types: Optional[list[str]] = None
input_types: list[str] | None = None
"""List of input types for the handle when the field has more than one type. Default is an empty list."""

dynamic: bool = False
"""Specifies if the field is dynamic. Defaults to False."""

info: Optional[str] = ""
info: str | None = ""
"""Additional information about the field to be shown in the tooltip. Defaults to an empty string."""

real_time_refresh: Optional[bool] = None
real_time_refresh: bool | None = None
"""Specifies if the field should have real time refresh. `refresh_button` must be False. Defaults to None."""

refresh_button: Optional[bool] = None
refresh_button: bool | None = None
"""Specifies if the field should have a refresh button. Defaults to False."""
refresh_button_text: Optional[str] = None
refresh_button_text: str | None = None
"""Specifies the text for the refresh button. Defaults to None."""

range_spec: Optional[RangeSpec] = Field(default=None, serialization_alias="rangeSpec")
range_spec: RangeSpec | None = Field(default=None, serialization_alias="rangeSpec")
"""Range specification for the field. Defaults to None."""

load_from_db: bool = False
Expand Down Expand Up @@ -161,22 +162,22 @@ class Output(BaseModel):
types: list[str] = Field(default=[])
"""List of output types for the field."""

selected: Optional[str] = Field(default=None)
selected: str | None = Field(default=None)
"""The selected output type for the field."""

name: str = Field(description="The name of the field.")
"""The name of the field."""

hidden: Optional[bool] = Field(default=None)
hidden: bool | None = Field(default=None)
"""Dictates if the field is hidden."""

display_name: Optional[str] = Field(default=None)
display_name: str | None = Field(default=None)
"""The display name of the field."""

method: Optional[str] = Field(default=None)
method: str | None = Field(default=None)
"""The method to use for the output."""

value: Optional[Any] = Field(default=UNDEFINED)
value: Any | None = Field(default=UNDEFINED)

cache: bool = Field(default=True)

Expand Down
33 changes: 16 additions & 17 deletions src/backend/base/langflow/template/frontend_node/base.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from collections import defaultdict
from typing import Dict, List, Optional, Union

from pydantic import BaseModel, field_serializer, model_serializer

Expand All @@ -11,46 +10,46 @@ class FrontendNode(BaseModel):
_format_template: bool = True
template: Template
"""Template for the frontend node."""
description: Optional[str] = None
description: str | None = None
"""Description of the frontend node."""
icon: Optional[str] = None
icon: str | None = None
"""Icon of the frontend node."""
is_input: Optional[bool] = None
is_input: bool | None = None
"""Whether the frontend node is used as an input when processing the Graph.
If True, there should be a field named 'input_value'."""
is_output: Optional[bool] = None
is_output: bool | None = None
"""Whether the frontend node is used as an output when processing the Graph.
If True, there should be a field named 'input_value'."""
is_composition: Optional[bool] = None
is_composition: bool | None = None
"""Whether the frontend node is used for composition."""
base_classes: List[str]
base_classes: list[str]
"""List of base classes for the frontend node."""
name: str = ""
"""Name of the frontend node."""
display_name: Optional[str] = ""
display_name: str | None = ""
"""Display name of the frontend node."""
documentation: str = ""
"""Documentation of the frontend node."""
custom_fields: Optional[Dict] = defaultdict(list)
custom_fields: dict | None = defaultdict(list)
"""Custom fields of the frontend node."""
output_types: List[str] = []
output_types: list[str] = []
"""List of output types for the frontend node."""
full_path: Optional[str] = None
full_path: str | None = None
"""Full path of the frontend node."""
pinned: bool = False
"""Whether the frontend node is pinned."""
conditional_paths: List[str] = []
conditional_paths: list[str] = []
"""List of conditional paths for the frontend node."""
frozen: bool = False
"""Whether the frontend node is frozen."""
outputs: List[Output] = []
outputs: list[Output] = []
"""List of output fields for the frontend node."""

field_order: list[str] = []
"""Order of the fields in the frontend node."""
beta: bool = False
"""Whether the frontend node is in beta."""
error: Optional[str] = None
error: str | None = None
"""Error message for the frontend node."""
edited: bool = False
"""Whether the frontend node has been edited."""
Expand All @@ -60,7 +59,7 @@ def set_documentation(self, documentation: str) -> None:
self.documentation = documentation

@field_serializer("base_classes")
def process_base_classes(self, base_classes: List[str]) -> List[str]:
def process_base_classes(self, base_classes: list[str]) -> list[str]:
"""Removes unwanted base classes from the list of base classes."""

sorted_base_classes = sorted(list(set(base_classes)), key=lambda x: x.lower())
Expand Down Expand Up @@ -156,14 +155,14 @@ def validate_attributes(self) -> None:
input_overlap_str = ", ".join(map(lambda x: f"'{x}'", input_overlap))
error_message += f"Input names {input_overlap_str} are reserved attributes."

def add_base_class(self, base_class: Union[str, List[str]]) -> None:
def add_base_class(self, base_class: str | list[str]) -> None:
"""Adds a base class to the frontend node."""
if isinstance(base_class, str):
self.base_classes.append(base_class)
elif isinstance(base_class, list):
self.base_classes.extend(base_class)

def add_output_type(self, output_type: Union[str, List[str]]) -> None:
def add_output_type(self, output_type: str | list[str]) -> None:
"""Adds an output type to the frontend node."""
if isinstance(output_type, str):
self.output_types.append(output_type)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from typing import Optional

from langflow.template.field.base import Input
from langflow.template.frontend_node.base import FrontendNode
from langflow.template.template.base import Template
Expand Down Expand Up @@ -47,7 +45,7 @@ def build(self, param: Data) -> Data:
class CustomComponentFrontendNode(FrontendNode):
_format_template: bool = False
name: str = "CustomComponent"
display_name: Optional[str] = "CustomComponent"
display_name: str | None = "CustomComponent"
beta: bool = False
template: Template = Template(
type_name="CustomComponent",
Expand All @@ -65,14 +63,14 @@ class CustomComponentFrontendNode(FrontendNode):
)
],
)
description: Optional[str] = None
description: str | None = None
base_classes: list[str] = []


class ComponentFrontendNode(FrontendNode):
_format_template: bool = False
name: str = "Component"
display_name: Optional[str] = "Component"
display_name: str | None = "Component"
beta: bool = False
template: Template = Template(
type_name="Component",
Expand All @@ -90,5 +88,5 @@ class ComponentFrontendNode(FrontendNode):
)
],
)
description: Optional[str] = None
description: str | None = None
base_classes: list[str] = []
5 changes: 3 additions & 2 deletions src/backend/base/langflow/template/template/base.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from typing import Callable, Union, cast
from typing import cast
from collections.abc import Callable

from pydantic import BaseModel, Field, model_serializer

Expand All @@ -13,7 +14,7 @@ class Template(BaseModel):

def process_fields(
self,
format_field_func: Union[Callable, None] = None,
format_field_func: Callable | None = None,
):
if format_field_func:
for field in self.fields:
Expand Down
Loading

0 comments on commit 1883710

Please sign in to comment.