Skip to content

Commit 6d237f6

Browse files
committed
Update type annotations in cursor.py
1 parent 6aaab60 commit 6d237f6

File tree

1 file changed

+140
-42
lines changed

1 file changed

+140
-42
lines changed

aioodbc/cursor.py

Lines changed: 140 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from __future__ import annotations
22

3+
from typing import Any, Callable, Coroutine, List, Optional, Tuple, TypeVar
4+
35
import pyodbc
46

57
from .log import logger
@@ -8,6 +10,9 @@
810
__all__ = ["Cursor"]
911

1012

13+
_T = TypeVar("_T")
14+
15+
1116
class Cursor:
1217
"""Cursors represent a database cursor (and map to ODBC HSTMTs), which
1318
is used to manage the context of a fetch operation.
@@ -17,13 +22,23 @@ class Cursor:
1722
the other cursors.
1823
"""
1924

20-
def __init__(self, pyodbc_cursor: pyodbc.Cursor, connection, echo=False):
25+
def __init__(
26+
self,
27+
pyodbc_cursor: pyodbc.Cursor,
28+
connection: Connection,
29+
echo: bool = False,
30+
) -> None:
2131
self._conn = connection
2232
self._impl: pyodbc.Cursor = pyodbc_cursor
2333
self._loop = connection.loop
2434
self._echo: bool = echo
2535

26-
async def _run_operation(self, func, *args, **kwargs):
36+
async def _run_operation(
37+
self,
38+
func: Callable[..., _T],
39+
*args: Any,
40+
**kwargs: Any,
41+
) -> _T:
2742
# execute func in thread pool of attached to cursor connection
2843
if not self._conn:
2944
raise pyodbc.OperationalError("Cursor is closed.")
@@ -37,17 +52,17 @@ async def _run_operation(self, func, *args, **kwargs):
3752
raise
3853

3954
@property
40-
def echo(self):
55+
def echo(self) -> bool:
4156
"""Return echo mode status."""
4257
return self._echo
4358

4459
@property
45-
def connection(self):
60+
def connection(self) -> Optional[Connection]:
4661
"""Cursors database connection"""
4762
return self._conn
4863

4964
@property
50-
def autocommit(self):
65+
def autocommit(self) -> bool:
5166
"""Show autocommit mode for current database session. True if
5267
connection is in autocommit mode; False otherwse. The default
5368
is False.
@@ -56,12 +71,12 @@ def autocommit(self):
5671
return self._conn.autocommit
5772

5873
@autocommit.setter
59-
def autocommit(self, value):
74+
def autocommit(self, value: bool) -> None:
6075
assert self._conn is not None # mypy
6176
self._conn.autocommit = value
6277

6378
@property
64-
def rowcount(self):
79+
def rowcount(self) -> int:
6580
"""The number of rows modified by the previous DDL statement.
6681
6782
This is -1 if no SQL has been executed or if the number of rows is
@@ -73,7 +88,7 @@ def rowcount(self):
7388
return self._impl.rowcount
7489

7590
@property
76-
def description(self):
91+
def description(self) -> Tuple[Tuple[str, Any, int, int, int, int, bool]]:
7792
"""This read-only attribute is a list of 7-item tuples, each
7893
containing (name, type_code, display_size, internal_size, precision,
7994
scale, null_ok).
@@ -91,23 +106,23 @@ def description(self):
91106
return self._impl.description
92107

93108
@property
94-
def closed(self):
109+
def closed(self) -> bool:
95110
"""Read only property indicates if cursor has been closed"""
96111
return self._conn is None
97112

98113
@property
99-
def arraysize(self):
114+
def arraysize(self) -> int:
100115
"""This read/write attribute specifies the number of rows to fetch
101116
at a time with .fetchmany() . It defaults to 1 meaning to fetch a
102117
single row at a time.
103118
"""
104119
return self._impl.arraysize
105120

106121
@arraysize.setter
107-
def arraysize(self, size):
122+
def arraysize(self, size: int) -> None:
108123
self._impl.arraysize = size
109124

110-
async def close(self):
125+
async def close(self) -> None:
111126
"""Close the cursor now (rather than whenever __del__ is called).
112127
113128
The cursor will be unusable from this point forward; an Error
@@ -119,7 +134,7 @@ async def close(self):
119134
await self._run_operation(self._impl.close)
120135
self._conn = None
121136

122-
async def execute(self, sql, *params):
137+
async def execute(self, sql: str, *params: Any) -> Cursor:
123138
"""Executes the given operation substituting any markers with
124139
the given parameters.
125140
@@ -136,7 +151,7 @@ async def execute(self, sql, *params):
136151
await self._run_operation(self._impl.execute, sql, *params)
137152
return self
138153

139-
def executemany(self, sql, *params):
154+
def executemany(self, sql: str, *params: Any) -> Coroutine[Any, Any, None]:
140155
"""Prepare a database query or command and then execute it against
141156
all parameter sequences found in the sequence seq_of_params.
142157
@@ -157,7 +172,7 @@ async def setoutputsize(self, *args, **kwargs):
157172
"""Does nothing, required by DB API."""
158173
return None
159174

160-
def fetchone(self):
175+
def fetchone(self) -> Coroutine[Any, Any, Optional[pyodbc.Row]]:
161176
"""Returns the next row or None when no more data is available.
162177
163178
A ProgrammingError exception is raised if no SQL has been executed
@@ -167,7 +182,7 @@ def fetchone(self):
167182
fut = self._run_operation(self._impl.fetchone)
168183
return fut
169184

170-
def fetchall(self):
185+
def fetchall(self) -> Coroutine[Any, Any, List[pyodbc.Row]]:
171186
"""Returns a list of all remaining rows.
172187
173188
Since this reads all rows into memory, it should not be used if
@@ -181,7 +196,7 @@ def fetchall(self):
181196
fut = self._run_operation(self._impl.fetchall)
182197
return fut
183198

184-
def fetchmany(self, size=0):
199+
def fetchmany(self, size: int = 0) -> Coroutine[Any, Any, List[pyodbc.Row]]:
185200
"""Returns a list of remaining rows, containing no more than size
186201
rows, used to process results in chunks. The list will be empty when
187202
there are no more rows.
@@ -200,7 +215,7 @@ def fetchmany(self, size=0):
200215
fut = self._run_operation(self._impl.fetchmany, size)
201216
return fut
202217

203-
def nextset(self):
218+
def nextset(self) -> Coroutine[Any, Any, bool]:
204219
"""This method will make the cursor skip to the next available
205220
set, discarding any remaining rows from the current set.
206221
@@ -214,7 +229,13 @@ def nextset(self):
214229
fut = self._run_operation(self._impl.nextset)
215230
return fut
216231

217-
def tables(self, **kw):
232+
def tables(
233+
self,
234+
table: Optional[str] = None,
235+
catalog: Optional[str] = None,
236+
schema: Optional[str] = None,
237+
tableType: Optional[str] = None,
238+
) -> Coroutine[Any, Any, pyodbc.Cursor]:
218239
"""Creates a result set of tables in the database that match the
219240
given criteria.
220241
@@ -223,10 +244,22 @@ def tables(self, **kw):
223244
:param schema: the schmea name
224245
:param tableType: one of TABLE, VIEW, SYSTEM TABLE ...
225246
"""
226-
fut = self._run_operation(self._impl.tables, **kw)
247+
fut = self._run_operation(
248+
self._impl.tables,
249+
table=table,
250+
catalog=catalog,
251+
schema=schema,
252+
tableType=tableType,
253+
)
227254
return fut
228255

229-
def columns(self, **kw):
256+
def columns(
257+
self,
258+
table: Optional[str] = None,
259+
catalog: Optional[str] = None,
260+
schema: Optional[str] = None,
261+
column: Optional[str] = None,
262+
) -> Coroutine[Any, Any, pyodbc.Cursor]:
230263
"""Creates a results set of column names in specified tables by
231264
executing the ODBC SQLColumns function. Each row fetched has the
232265
following columns.
@@ -236,10 +269,23 @@ def columns(self, **kw):
236269
:param schema: the schmea name
237270
:param column: string search pattern for column names.
238271
"""
239-
fut = self._run_operation(self._impl.columns, **kw)
272+
fut = self._run_operation(
273+
self._impl.columns,
274+
table=table,
275+
catalog=catalog,
276+
schema=schema,
277+
column=column,
278+
)
240279
return fut
241280

242-
def statistics(self, table, catalog=None, schema=None, unique=False, quick=True):
281+
def statistics(
282+
self,
283+
table: str,
284+
catalog: Optional[str] = None,
285+
schema: Optional[str] = None,
286+
unique: bool = False,
287+
quick: bool = True,
288+
) -> Coroutine[Any, Any, pyodbc.Cursor]:
243289
"""Creates a results set of statistics about a single table and
244290
the indexes associated with the table by executing SQLStatistics.
245291
@@ -262,8 +308,12 @@ def statistics(self, table, catalog=None, schema=None, unique=False, quick=True)
262308
return fut
263309

264310
def rowIdColumns(
265-
self, table, catalog=None, schema=None, nullable=True # nopep8
266-
):
311+
self,
312+
table: str,
313+
catalog: Optional[str] = None,
314+
schema: Optional[str] = None,
315+
nullable: bool = True,
316+
) -> Coroutine[Any, Any, pyodbc.Cursor]:
267317
"""Executes SQLSpecialColumns with SQL_BEST_ROWID which creates a
268318
result set of columns that uniquely identify a row
269319
"""
@@ -277,8 +327,12 @@ def rowIdColumns(
277327
return fut
278328

279329
def rowVerColumns(
280-
self, table, catalog=None, schema=None, nullable=True # nopep8
281-
):
330+
self,
331+
table: str,
332+
catalog: Optional[str] = None,
333+
schema: Optional[str] = None,
334+
nullable: bool = True,
335+
) -> Coroutine[Any, Any, pyodbc.Cursor]:
282336
"""Executes SQLSpecialColumns with SQL_ROWVER which creates a
283337
result set of columns that are automatically updated when any
284338
value in the row is updated.
@@ -292,68 +346,112 @@ def rowVerColumns(
292346
)
293347
return fut
294348

295-
def primaryKeys(self, table, catalog=None, schema=None): # nopep8
349+
def primaryKeys(
350+
self,
351+
table: str,
352+
catalog: Optional[str] = None,
353+
schema: Optional[str] = None,
354+
) -> Coroutine[Any, Any, pyodbc.Cursor]:
296355
"""Creates a result set of column names that make up the primary key
297356
for a table by executing the SQLPrimaryKeys function."""
298357
fut = self._run_operation(
299358
self._impl.primaryKeys, table, catalog=catalog, schema=schema
300359
)
301360
return fut
302361

303-
def foreignKeys(self, *a, **kw): # nopep8
362+
def foreignKeys(
363+
self,
364+
table: Optional[str] = None,
365+
catalog: Optional[str] = None,
366+
schema: Optional[str] = None,
367+
foreignTable: Optional[str] = None,
368+
foreignCatalog: Optional[str] = None,
369+
foreignSchema: Optional[str] = None,
370+
) -> Coroutine[Any, Any, pyodbc.Cursor]:
304371
"""Executes the SQLForeignKeys function and creates a result set
305372
of column names that are foreign keys in the specified table (columns
306373
in the specified table that refer to primary keys in other tables)
307374
or foreign keys in other tables that refer to the primary key in
308375
the specified table.
309376
"""
310-
fut = self._run_operation(self._impl.foreignKeys, *a, **kw)
377+
fut = self._run_operation(
378+
self._impl.foreignKeys,
379+
table=table,
380+
catalog=catalog,
381+
schema=schema,
382+
foreignTable=foreignTable,
383+
foreignCatalog=foreignCatalog,
384+
foreignSchema=foreignSchema,
385+
)
311386
return fut
312387

313-
def getTypeInfo(self, sql_type): # nopep8
388+
def getTypeInfo(
389+
self,
390+
sql_type: Optional[int] = None,
391+
) -> Coroutine[Any, Any, pyodbc.Cursor]:
314392
"""Executes SQLGetTypeInfo a creates a result set with information
315393
about the specified data type or all data types supported by the
316394
ODBC driver if not specified.
317395
"""
318396
fut = self._run_operation(self._impl.getTypeInfo, sql_type)
319397
return fut
320398

321-
def procedures(self, *a, **kw):
399+
def procedures(
400+
self,
401+
procedure: Optional[str] = None,
402+
catalog: Optional[str] = None,
403+
schema: Optional[str] = None,
404+
) -> Coroutine[Any, Any, pyodbc.Cursor]:
322405
"""Executes SQLProcedures and creates a result set of information
323406
about the procedures in the data source.
324407
"""
325-
fut = self._run_operation(self._impl.procedures, *a, **kw)
408+
fut = self._run_operation(
409+
self._impl.procedures,
410+
procedure=procedure,
411+
catalog=catalog,
412+
schema=schema,
413+
)
326414
return fut
327415

328-
def procedureColumns(self, *a, **kw): # nopep8
329-
fut = self._run_operation(self._impl.procedureColumns, *a, **kw)
416+
def procedureColumns(
417+
self,
418+
procedure: Optional[str] = None,
419+
catalog: Optional[str] = None,
420+
schema: Optional[str] = None,
421+
) -> Coroutine[Any, Any, pyodbc.Cursor]:
422+
fut = self._run_operation(
423+
self._impl.procedureColumns,
424+
procedure=procedure,
425+
catalog=catalog,
426+
schema=schema,
427+
)
330428
return fut
331429

332-
def skip(self, count):
430+
def skip(self, count: int) -> Coroutine[Any, Any, None]:
333431
fut = self._run_operation(self._impl.skip, count)
334432
return fut
335433

336-
def commit(self):
434+
def commit(self) -> Coroutine[Any, Any, None]:
337435
fut = self._run_operation(self._impl.commit)
338436
return fut
339437

340-
def rollback(self):
438+
def rollback(self) -> Coroutine[Any, Any, None]:
341439
fut = self._run_operation(self._impl.rollback)
342440
return fut
343441

344-
def __aiter__(self):
442+
def __aiter__(self) -> Cursor:
345443
return self
346444

347-
async def __anext__(self):
445+
async def __anext__(self) -> pyodbc.Row:
348446
ret = await self.fetchone()
349447
if ret is not None:
350448
return ret
351449
else:
352450
raise StopAsyncIteration
353451

354-
async def __aenter__(self):
452+
async def __aenter__(self) -> Cursor:
355453
return self
356454

357-
async def __aexit__(self, exc_type, exc_val, exc_tb):
455+
async def __aexit__(self, exc_type, exc_val, exc_tb) -> None:
358456
await self.close()
359457
return

0 commit comments

Comments
 (0)