@@ -52,7 +52,7 @@ class SupportsDuckdbTemplate(Protocol):
5252 """Something that can be converted into a Template by implementing the __duckdb_template__ method."""
5353
5454 def __duckdb_template__ (
55- self , / , ** future_kwargs
55+ self , / , ** future_kwargs : object
5656 ) -> (
5757 str
5858 | IntoInterpolation
@@ -153,7 +153,7 @@ def template(*parts: str | IntoInterpolation | Param | SupportsDuckdbTemplate |
153153 >>> t.compile()
154154 CompiledSql(sql='SELECT * FROM users WHERE id = $p0_id', params={'p0_id': 123})
155155 """ # noqa: E501
156- expanded = []
156+ expanded : list [ str | IntoInterpolation ] = []
157157 for part in parts :
158158 expanded .extend (_expand_part (part ))
159159 return SqlTemplate (* expanded )
@@ -170,7 +170,7 @@ def compile(*part: str | IntoInterpolation | Param | SupportsDuckdbTemplate | ob
170170 return t .compile ()
171171
172172
173- def _is_iterable_nonstring (value : object ) -> TypeIs [Iterable ]:
173+ def _is_iterable_nonstring (value : object ) -> TypeIs [Iterable [ object ] ]:
174174 return isinstance (value , Iterable ) and not isinstance (value , str | bytes )
175175
176176
@@ -206,7 +206,12 @@ def _expand_part(part: object) -> Iterable[str | IntoInterpolation]:
206206class ParamInterpolation :
207207 """A simple wrapper that implements the IntoInterpolation protocol for a given Param."""
208208
209- def __init__ (self , param : Param ): # noqa: ANN204
209+ value : object
210+ expression : str | None
211+ conversion : Literal ["s" , "r" , "a" ] | None
212+ format_spec : str
213+
214+ def __init__ (self , param : Param ) -> None :
210215 self .value = param
211216 self .expression = param .name
212217 self .conversion = None
@@ -251,6 +256,7 @@ def _resolve_interpolation(interp: IntoInterpolation) -> Iterable[str | Param]:
251256 #
252257 # Follow Python's f-string semantics: apply conversion first, then format_spec.
253258 # e.g. {x!r:.10} means format(repr(x), ".10")
259+ converted : str | None
254260 if interp .conversion == "s" :
255261 converted = str (value )
256262 elif interp .conversion == "r" :
@@ -314,7 +320,8 @@ class SqlTemplate:
314320 def __init__ (self , * parts : str | IntoInterpolation ) -> None :
315321 for part in parts :
316322 if not isinstance (part , str | IntoInterpolation ):
317- msg = f"Unexpected part type in SqlTemplate: { type (part ).__name__ } . Expected str or IntoInterpolation."
323+ # Guard for untyped callers; mypy considers this unreachable given the declared parameter type.
324+ msg = f"Unexpected part type in SqlTemplate: { type (part ).__name__ } . Expected str or IntoInterpolation." # type: ignore[unreachable]
318325 raise TypeError (msg )
319326 self .strings , self .interpolations = parse_parts (parts )
320327
@@ -391,7 +398,8 @@ def parse_parts(parts: Iterable[str | T]) -> tuple[tuple[str, ...], tuple[T, ...
391398
392399 This merges adjacent strings and ensuring that the number of strings is one more than the number of others.
393400 """
394- strings , others = [], []
401+ strings : list [str ] = []
402+ others : list [T ] = []
395403 last_thing : Literal ["string" , "other" ] | None = None
396404 for part in parts :
397405 if isinstance (part , str ):
@@ -421,7 +429,7 @@ def parse_parts(parts: Iterable[str | T]) -> tuple[tuple[str, ...], tuple[T, ...
421429def compile_parts (parts : Iterable [str | Param ], / ) -> CompiledSql :
422430 """Compile parts into a final SQL string with named parameter placeholders, and a list of Params."""
423431 sql_parts : list [str ] = []
424- params_items = []
432+ params_items : list [ tuple [ str , object ]] = []
425433
426434 def next_name (suffix : str | None = None ) -> str :
427435 # still count exact params in the count, so we get p0, my_param, p2, p3, my_param_2, p5, etc
0 commit comments