"""Type guard functions for runtime type checking in SQLSpec.
This module provides type-safe runtime checks that help the type checker
understand type narrowing, replacing defensive hasattr() and duck typing patterns.
"""
import inspect
import sys
from collections.abc import Sequence
from collections.abc import Set as AbstractSet
from dataclasses import Field
from dataclasses import fields as dataclasses_fields
from dataclasses import is_dataclass as dataclasses_is_dataclass
from typing import TYPE_CHECKING, Any, Literal, cast
from sqlglot import exp
from typing_extensions import is_typeddict
from sqlspec._typing import Empty
from sqlspec.protocols import (
DictProtocol,
HasExpressionAndParametersProtocol,
HasExpressionAndSQLProtocol,
HasExpressionProtocol,
HasMigrationConfigProtocol,
HasParameterBuilderProtocol,
HasSQLGlotExpressionProtocol,
HasStatementConfigFactoryProtocol,
HasValueProtocol,
SupportsArrowResults,
WithMethodProtocol,
)
from sqlspec.typing import (
ATTRS_INSTALLED,
LITESTAR_INSTALLED,
MSGSPEC_INSTALLED,
PYDANTIC_INSTALLED,
DataclassProtocol,
Struct,
)
from sqlspec.utils.text import camelize, kebabize, pascalize
if TYPE_CHECKING:
from typing import TypeGuard
from sqlspec._typing import AttrsInstanceStub, BaseModelStub, DTODataStub, StructStub
from sqlspec.core import StatementFilter
from sqlspec.core.parameters import TypedParameter
from sqlspec.protocols import (
ArrowTableStatsProtocol,
AsyncDeleteProtocol,
AsyncReadableProtocol,
AsyncReadBytesProtocol,
AsyncWriteBytesProtocol,
CursorMetadataProtocol,
HasAddListenerProtocol,
HasAsDictProtocol,
HasConfigProtocol,
HasConnectionConfigProtocol,
HasDatabaseUrlAndBindKeyProtocol,
HasErrorsProtocol,
HasExtensionConfigProtocol,
HasFieldNameProtocol,
HasFilterAttributesProtocol,
HasGetDataProtocol,
HasLastRowIdProtocol,
HasNameProtocol,
HasNotifiesProtocol,
HasRowcountProtocol,
HasSqliteErrorProtocol,
HasSqlStateProtocol,
HasStatementTypeProtocol,
HasTracerProviderProtocol,
HasTypeCodeProtocol,
HasTypecodeProtocol,
HasTypecodeSizedProtocol,
HasWhereProtocol,
MappingLikeProtocol,
NotificationProtocol,
PipelineCapableProtocol,
QueryResultProtocol,
ReadableProtocol,
SpanAttributeProtocol,
SupportsArrayProtocol,
SupportsCloseProtocol,
SupportsDtypeStrProtocol,
SupportsJsonTypeProtocol,
)
from sqlspec.typing import SupportedSchemaModel
__all__ = (
"dataclass_to_dict",
"expression_has_limit",
"extract_dataclass_fields",
"extract_dataclass_items",
"get_initial_expression",
"get_literal_parent",
"get_msgspec_rename_config",
"get_node_expressions",
"get_node_this",
"get_param_style_and_name",
"get_value_attribute",
"has_add_listener",
"has_array_interface",
"has_arrow_table_stats",
"has_asdict_method",
"has_config_attribute",
"has_connection_config",
"has_cursor_metadata",
"has_database_url_and_bind_key",
"has_dict_attribute",
"has_dtype_str",
"has_errors",
"has_expression_and_parameters",
"has_expression_and_sql",
"has_expression_attr",
"has_expressions_attribute",
"has_extension_config",
"has_field_name",
"has_filter_attributes",
"has_get_data",
"has_lastrowid",
"has_migration_config",
"has_name",
"has_notifies",
"has_parameter_builder",
"has_parent_attribute",
"has_pipeline_capability",
"has_query_result_metadata",
"has_rowcount",
"has_span_attribute",
"has_sqlglot_expression",
"has_sqlite_error",
"has_sqlstate",
"has_statement_config_factory",
"has_statement_type",
"has_this_attribute",
"has_tracer_provider",
"has_type_code",
"has_typecode",
"has_typecode_and_len",
"has_value_attribute",
"has_with_method",
"is_async_readable",
"is_attrs_instance",
"is_attrs_instance_with_field",
"is_attrs_instance_without_field",
"is_attrs_schema",
"is_copy_statement",
"is_dataclass",
"is_dataclass_instance",
"is_dataclass_with_field",
"is_dataclass_without_field",
"is_dict",
"is_dict_row",
"is_dict_with_field",
"is_dict_without_field",
"is_dto_data",
"is_expression",
"is_iterable_parameters",
"is_local_path",
"is_mapping_like",
"is_msgspec_struct",
"is_msgspec_struct_with_field",
"is_msgspec_struct_without_field",
"is_notification",
"is_number_literal",
"is_pydantic_model",
"is_pydantic_model_with_field",
"is_pydantic_model_without_field",
"is_readable",
"is_schema",
"is_schema_or_dict",
"is_schema_or_dict_with_field",
"is_schema_or_dict_without_field",
"is_schema_with_field",
"is_schema_without_field",
"is_statement_filter",
"is_string_literal",
"is_typed_dict",
"is_typed_parameter",
"resolve_row_format",
"supports_arrow_results",
"supports_async_delete",
"supports_async_read_bytes",
"supports_async_write_bytes",
"supports_close",
"supports_json_type",
"supports_where",
)
def is_readable(obj: Any) -> "TypeGuard[ReadableProtocol]":
"""Check if an object is readable (has a read method)."""
try:
return callable(obj.read)
except AttributeError:
return False