55from collections .abc import Iterable , Mapping
66from dataclasses import dataclass
77from enum import Enum
8- from importlib .util import find_spec
98from typing import Any , ClassVar , Final , Literal , Protocol , cast , runtime_checkable
109
1110from typing_extensions import TypeVar , dataclass_transform
1211
13-
14- def module_available (module_name : str ) -> bool :
15- """Return True if the given module spec can be resolved.
16-
17- Args:
18- module_name: Dotted path for the module to locate.
19-
20- Returns:
21- True if the module can be resolved, False otherwise.
22- """
23-
24- try :
25- return find_spec (module_name ) is not None
26- except ModuleNotFoundError :
27- return False
12+ from sqlspec .utils .dependencies import dependency_flag , module_available
2813
2914
3015@runtime_checkable
@@ -131,12 +116,10 @@ class FailFastStub:
131116 BaseModel = _RealBaseModel
132117 TypeAdapter = _RealTypeAdapter
133118 FailFast = _RealFailFast
134- PYDANTIC_INSTALLED = True # pyright: ignore[reportConstantRedefinition]
135119except ImportError :
136120 BaseModel = BaseModelStub # type: ignore[assignment,misc]
137121 TypeAdapter = TypeAdapterStub # type: ignore[assignment,misc]
138122 FailFast = FailFastStub # type: ignore[assignment,misc]
139- PYDANTIC_INSTALLED = False # pyright: ignore[reportConstantRedefinition]
140123
141124# Always define stub types for msgspec
142125
@@ -184,21 +167,17 @@ class UnsetTypeStub(enum.Enum):
184167 UnsetType = _RealUnsetType
185168 UNSET = _REAL_UNSET
186169 convert = _real_convert
187- MSGSPEC_INSTALLED = True # pyright: ignore[reportConstantRedefinition]
188170except ImportError :
189171 Struct = StructStub # type: ignore[assignment,misc]
190172 UnsetType = UnsetTypeStub # type: ignore[assignment,misc]
191173 UNSET = UNSET_STUB # type: ignore[assignment] # pyright: ignore[reportConstantRedefinition]
192174 convert = convert_stub
193- MSGSPEC_INSTALLED = False # pyright: ignore[reportConstantRedefinition]
194175
195176
196177try :
197178 import orjson # noqa: F401
198-
199- ORJSON_INSTALLED = True # pyright: ignore[reportConstantRedefinition]
200179except ImportError :
201- ORJSON_INSTALLED = False # pyright : ignore[reportConstantRedefinition ]
180+ orjson = None # type : ignore[assignment ]
202181
203182
204183# Always define stub type for DTOData
@@ -228,10 +207,8 @@ def as_builtins(self) -> Any:
228207 from litestar .dto .data_structures import DTOData as _RealDTOData # pyright: ignore[reportUnknownVariableType]
229208
230209 DTOData = _RealDTOData
231- LITESTAR_INSTALLED = True # pyright: ignore[reportConstantRedefinition]
232210except ImportError :
233211 DTOData = DTODataStub # type: ignore[assignment,misc]
234- LITESTAR_INSTALLED = False # pyright: ignore[reportConstantRedefinition]
235212
236213
237214# Always define stub types for attrs
@@ -290,21 +267,17 @@ def attrs_has_stub(*args: Any, **kwargs: Any) -> bool: # noqa: ARG001
290267 attrs_field = _real_attrs_field
291268 attrs_fields = _real_attrs_fields
292269 attrs_has = _real_attrs_has
293- ATTRS_INSTALLED = True # pyright: ignore[reportConstantRedefinition]
294270except ImportError :
295271 AttrsInstance = AttrsInstanceStub # type: ignore[misc]
296272 attrs_asdict = attrs_asdict_stub
297273 attrs_define = attrs_define_stub
298274 attrs_field = attrs_field_stub
299275 attrs_fields = attrs_fields_stub
300276 attrs_has = attrs_has_stub # type: ignore[assignment]
301- ATTRS_INSTALLED = False # pyright: ignore[reportConstantRedefinition]
302277
303278try :
304279 from cattrs import structure as cattrs_structure
305280 from cattrs import unstructure as cattrs_unstructure
306-
307- CATTRS_INSTALLED = True # pyright: ignore[reportConstantRedefinition]
308281except ImportError :
309282
310283 def cattrs_unstructure (* args : Any , ** kwargs : Any ) -> Any : # noqa: ARG001
@@ -315,8 +288,6 @@ def cattrs_structure(*args: Any, **kwargs: Any) -> Any: # noqa: ARG001
315288 """Placeholder implementation"""
316289 return {}
317290
318- CATTRS_INSTALLED = False # pyright: ignore[reportConstantRedefinition] # pyright: ignore[reportConstantRedefinition]
319-
320291
321292class EmptyEnum (Enum ):
322293 """A sentinel enum used as placeholder."""
@@ -433,16 +404,12 @@ def __iter__(self) -> "Iterable[Any]":
433404 from pyarrow import RecordBatchReader as ArrowRecordBatchReader
434405 from pyarrow import Schema as ArrowSchema
435406 from pyarrow import Table as ArrowTable
436-
437- PYARROW_INSTALLED = True
438407except ImportError :
439408 ArrowTable = ArrowTableResult # type: ignore[assignment,misc]
440409 ArrowRecordBatch = ArrowRecordBatchResult # type: ignore[assignment,misc]
441410 ArrowSchema = ArrowSchemaProtocol # type: ignore[assignment,misc]
442411 ArrowRecordBatchReader = ArrowRecordBatchReaderProtocol # type: ignore[assignment,misc]
443412
444- PYARROW_INSTALLED = False # pyright: ignore[reportConstantRedefinition]
445-
446413
447414@runtime_checkable
448415class PandasDataFrameProtocol (Protocol ):
@@ -472,20 +439,15 @@ def __getitem__(self, key: Any) -> Any:
472439
473440try :
474441 from pandas import DataFrame as PandasDataFrame
475-
476- PANDAS_INSTALLED = True
477442except ImportError :
478443 PandasDataFrame = PandasDataFrameProtocol # type: ignore[assignment,misc]
479- PANDAS_INSTALLED = False
480444
481445
482446try :
483447 from polars import DataFrame as PolarsDataFrame
484448
485- POLARS_INSTALLED = True
486449except ImportError :
487450 PolarsDataFrame = PolarsDataFrameProtocol # type: ignore[assignment,misc]
488- POLARS_INSTALLED = False
489451
490452
491453@runtime_checkable
@@ -514,8 +476,6 @@ def tolist(self) -> "list[Any]":
514476 StatusCode ,
515477 Tracer , # pyright: ignore[reportMissingImports, reportAssignmentType]
516478 )
517-
518- OPENTELEMETRY_INSTALLED = True # pyright: ignore[reportConstantRedefinition]
519479except ImportError :
520480 # Define shims for when opentelemetry is not installed
521481
@@ -578,7 +538,6 @@ def get_tracer_provider(self) -> Any: # pragma: no cover
578538 trace = _TraceModule () # type: ignore[assignment]
579539 StatusCode = trace .StatusCode # type: ignore[misc]
580540 Status = trace .Status # type: ignore[misc]
581- OPENTELEMETRY_INSTALLED = False # pyright: ignore[reportConstantRedefinition] # pyright: ignore[reportConstantRedefinition]
582541
583542
584543try :
@@ -587,8 +546,6 @@ def get_tracer_provider(self) -> Any: # pragma: no cover
587546 Gauge , # pyright: ignore[reportAssignmentType]
588547 Histogram , # pyright: ignore[reportAssignmentType]
589548 )
590-
591- PROMETHEUS_INSTALLED = True # pyright: ignore[reportConstantRedefinition]
592549except ImportError :
593550 # Define shims for when prometheus_client is not installed
594551
@@ -636,8 +593,6 @@ class Histogram(_Metric): # type: ignore[no-redef]
636593 def labels (self , * labelvalues : str , ** labelkwargs : str ) -> _MetricInstance :
637594 return _MetricInstance () # pragma: no cover
638595
639- PROMETHEUS_INSTALLED = False # pyright: ignore[reportConstantRedefinition] # pyright: ignore[reportConstantRedefinition]
640-
641596
642597try :
643598 import aiosql # pyright: ignore[reportMissingImports, reportAssignmentType]
@@ -651,8 +606,6 @@ def labels(self, *labelvalues: str, **labelkwargs: str) -> _MetricInstance:
651606 from aiosql .types import ( # pyright: ignore[reportMissingImports, reportAssignmentType]
652607 SyncDriverAdapterProtocol as AiosqlSyncProtocol , # pyright: ignore[reportMissingImports, reportAssignmentType]
653608 )
654-
655- AIOSQL_INSTALLED = True # pyright: ignore[reportConstantRedefinition]
656609except ImportError :
657610 # Define shims for when aiosql is not installed
658611
@@ -723,16 +676,25 @@ async def insert_update_delete(self, conn: Any, query_name: str, sql: str, param
723676 async def insert_update_delete_many (self , conn : Any , query_name : str , sql : str , parameters : Any ) -> None : ...
724677 async def insert_returning (self , conn : Any , query_name : str , sql : str , parameters : Any ) -> "Any | None" : ...
725678
726- AIOSQL_INSTALLED = False # pyright: ignore[reportConstantRedefinition] # pyright: ignore[reportConstantRedefinition]
727-
728-
729- FSSPEC_INSTALLED = module_available ("fsspec" )
730- NUMPY_INSTALLED = module_available ("numpy" )
731- OBSTORE_INSTALLED = module_available ("obstore" )
732- PGVECTOR_INSTALLED = module_available ("pgvector" )
733679
734- CLOUD_SQL_CONNECTOR_INSTALLED = module_available ("google.cloud.sql.connector" )
735- ALLOYDB_CONNECTOR_INSTALLED = module_available ("google.cloud.alloydb.connector" )
680+ AIOSQL_INSTALLED = dependency_flag ("aiosql" )
681+ ATTRS_INSTALLED = dependency_flag ("attrs" )
682+ CATTRS_INSTALLED = dependency_flag ("cattrs" )
683+ CLOUD_SQL_CONNECTOR_INSTALLED = dependency_flag ("google.cloud.sql.connector" )
684+ FSSPEC_INSTALLED = dependency_flag ("fsspec" )
685+ LITESTAR_INSTALLED = dependency_flag ("litestar" )
686+ MSGSPEC_INSTALLED = dependency_flag ("msgspec" )
687+ NUMPY_INSTALLED = dependency_flag ("numpy" )
688+ OBSTORE_INSTALLED = dependency_flag ("obstore" )
689+ OPENTELEMETRY_INSTALLED = dependency_flag ("opentelemetry" )
690+ ORJSON_INSTALLED = dependency_flag ("orjson" )
691+ PANDAS_INSTALLED = dependency_flag ("pandas" )
692+ PGVECTOR_INSTALLED = dependency_flag ("pgvector" )
693+ POLARS_INSTALLED = dependency_flag ("polars" )
694+ PROMETHEUS_INSTALLED = dependency_flag ("prometheus_client" )
695+ PYARROW_INSTALLED = dependency_flag ("pyarrow" )
696+ PYDANTIC_INSTALLED = dependency_flag ("pydantic" )
697+ ALLOYDB_CONNECTOR_INSTALLED = dependency_flag ("google.cloud.alloydb.connector" )
736698
737699__all__ = (
738700 "AIOSQL_INSTALLED" ,
0 commit comments