11from __future__ import annotations
22
3- from functools import update_wrapper
3+ from functools import wraps
44from typing import (
55 Any ,
6- Callable ,
76 Coroutine ,
87 Generator ,
98 Protocol ,
2322# ============================================================================
2423# DESIGN NOTES:
2524#
26- # The async connect function uses a two-layer wrapper to support both:
25+ # The async connect function uses a wrapper to support both:
2726# 1. Direct awaiting: conn = await connect(...)
2827# 2. Async context manager: async with connect(...) as conn:
2928#
29+ # connect: A function decorated with @wraps(SnowflakeConnection.__init__) that
30+ # preserves metadata for IDE support, type checking, and introspection.
31+ # Returns a _AsyncConnectContextManager instance when called.
32+ #
3033# _AsyncConnectContextManager: Implements __await__ and __aenter__/__aexit__
3134# to support both patterns on the same awaitable.
3235#
33- # _AsyncConnectWrapper: A callable class that preserves SnowflakeConnection
34- # metadata via @preserve_metadata decorator for IDE support, type checking,
35- # and introspection. Returns _AsyncConnectContextManager instances when called .
36+ # The @wraps decorator ensures that connect() has the same signature and
37+ # documentation as SnowflakeConnection.__init__, making it behave identically
38+ # to the sync snowflake.connector.connect function from an introspection POV .
3639#
3740# Metadata preservation is critical for IDE autocomplete, static type checkers,
3841# and documentation generation to work correctly on the async connect function.
@@ -95,35 +98,6 @@ async def __aexit__(
9598 ...
9699
97100
98- def preserve_metadata (
99- source : type , * , override_name : str | None = None
100- ) -> Callable [[T ], T ]:
101- """Decorator to copy metadata from a source class to class instances.
102-
103- Copies __wrapped__, __doc__, __module__, __annotations__ etc. to instances
104- during their initialization, allowing instances to be introspected like the
105- source class's __init__.
106-
107- Args:
108- source: Class to copy metadata from (uses its __init__).
109- override_name: Optional name override for instances.
110- """
111-
112- def decorator (cls : T ) -> T :
113- metadata_source = source .__init__
114- original_init = cls .__init__
115-
116- def new_init (self : Any ) -> None :
117- update_wrapper (self , metadata_source , updated = [])
118- if override_name :
119- self .__name__ = override_name
120- self .__qualname__ = override_name
121- original_init (self )
122-
123- cls .__init__ = new_init
124- return cls
125-
126- return decorator
127101
128102
129103class _AsyncConnectContextManager (HybridCoroutineContextManager [SnowflakeConnection ]):
@@ -177,31 +151,21 @@ async def __aexit__(self, exc_type: Any, exc: Any, tb: Any) -> None:
177151 return None
178152
179153
180- @preserve_metadata (SnowflakeConnection , override_name = "connect" )
181- class _AsyncConnectWrapper :
182- """Preserves SnowflakeConnection.__init__ metadata for async connect function .
154+ @wraps (SnowflakeConnection . __init__ )
155+ def Connect ( ** kwargs : Any ) -> HybridCoroutineContextManager [ SnowflakeConnection ] :
156+ """Create and connect to a Snowflake connection asynchronously .
183157
184- This wrapper enables introspection tools and IDEs to see the same signature
185- as the synchronous snowflake.connector.connect function.
158+ Returns an awaitable that can also be used as an async context manager.
159+ Supports both patterns:
160+ - conn = await connect(...)
161+ - async with connect(...) as conn:
186162 """
163+ async def _connect_coro () -> SnowflakeConnection :
164+ conn = SnowflakeConnection (** kwargs )
165+ await conn .connect ()
166+ return conn
187167
188- def __call__ (
189- self , ** kwargs : Any
190- ) -> HybridCoroutineContextManager [SnowflakeConnection ]:
191- """Create and connect to a Snowflake connection asynchronously.
192-
193- Returns an awaitable that can also be used as an async context manager.
194- Supports both patterns:
195- - conn = await connect(...)
196- - async with connect(...) as conn:
197- """
198-
199- async def _connect_coro () -> SnowflakeConnection :
200- conn = SnowflakeConnection (** kwargs )
201- await conn .connect ()
202- return conn
203-
204- return _AsyncConnectContextManager (_connect_coro ())
168+ return _AsyncConnectContextManager (_connect_coro ())
205169
206170
207- connect = _AsyncConnectWrapper ()
171+ connect = Connect
0 commit comments