Skip to content

Commit 4c97ed3

Browse files
bashtageKevin Sheppard
and
Kevin Sheppard
authored
ENH: Improve sql io api (#229)
* ENH: Improve sql io api * TYP: Finish typing sql * TYP: Improve type accuracy Add sqlalchemy Fix small issues in initial pass * TST: Add tests for sql * TST: Fix tests on windows * TST: Fix tests on windows * MAINT: Fix dep and add comment Co-authored-by: Kevin Sheppard <kevin.sheppard@gmail.com>
1 parent f73002f commit 4c97ed3

File tree

5 files changed

+204
-178
lines changed

5 files changed

+204
-178
lines changed

pandas-stubs/core/frame.pyi

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2000,18 +2000,6 @@ class DataFrame(NDFrame, OpsMixin):
20002000
compression: CompressionOptions = ...,
20012001
protocol: int = ...,
20022002
) -> None: ...
2003-
def to_sql(
2004-
self,
2005-
name: _str,
2006-
con,
2007-
schema: _str | None = ...,
2008-
if_exists: _str = ...,
2009-
index: _bool = ...,
2010-
index_label: _str | Sequence[_str] | None = ...,
2011-
chunksize: int | None = ...,
2012-
dtype: dict | Scalar | None = ...,
2013-
method: _str | Callable | None = ...,
2014-
) -> None: ...
20152003
@overload
20162004
def to_string(
20172005
self,

pandas-stubs/core/generic.pyi

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
import sqlite3
12
from typing import (
23
Any,
34
Callable,
45
ClassVar,
56
Hashable,
7+
Iterable,
68
Literal,
79
Mapping,
810
Sequence,
@@ -13,13 +15,15 @@ import numpy as np
1315
from pandas.core.base import PandasObject
1416
from pandas.core.indexes.base import Index
1517
import pandas.core.indexing as indexing
18+
import sqlalchemy.engine
1619

1720
from pandas._typing import (
1821
S1,
1922
ArrayLike,
2023
Axis,
2124
CompressionOptions,
2225
Dtype,
26+
DtypeArg,
2327
FilePath,
2428
FilePathOrBuffer,
2529
FileWriteMode,
@@ -29,17 +33,18 @@ from pandas._typing import (
2933
HashableT,
3034
HDFCompLib,
3135
IgnoreRaise,
36+
IndexLabel,
3237
Level,
3338
NDFrameT,
3439
ReplaceMethod,
35-
Scalar,
3640
SeriesAxisType,
3741
SortKind,
3842
StorageOptions,
3943
T,
4044
)
4145

4246
from pandas.io.pytables import HDFStore
47+
from pandas.io.sql import SQLTable
4348

4449
_bool = bool
4550
_str = str
@@ -152,15 +157,17 @@ class NDFrame(PandasObject, indexing.IndexingMixin):
152157
def to_sql(
153158
self,
154159
name: _str,
155-
con,
160+
con: str | sqlalchemy.engine.Connection | sqlite3.Connection,
156161
schema: _str | None = ...,
157-
if_exists: _str = ...,
162+
if_exists: Literal["fail", "replace", "append"] = ...,
158163
index: _bool = ...,
159-
index_label: _str | Sequence[_str] | None = ...,
164+
index_label: IndexLabel = ...,
160165
chunksize: int | None = ...,
161-
dtype: dict | Scalar | None = ...,
162-
method: _str | Callable | None = ...,
163-
) -> None: ...
166+
dtype: DtypeArg | None = ...,
167+
method: Literal["multi"]
168+
| Callable[[SQLTable, Any, list[str], Iterable], int | None]
169+
| None = ...,
170+
) -> int | None: ...
164171
def to_pickle(
165172
self,
166173
path: _str,

pandas-stubs/io/sql.pyi

Lines changed: 114 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -1,191 +1,146 @@
1+
import sqlite3
12
from typing import (
23
Any,
3-
Mapping,
4-
Sequence,
4+
Callable,
5+
Generator,
6+
Iterable,
7+
Literal,
8+
overload,
59
)
610

711
from pandas.core.base import PandasObject
812
from pandas.core.frame import DataFrame
13+
import sqlalchemy.engine
14+
15+
from pandas._typing import (
16+
DtypeArg,
17+
npt,
18+
)
919

1020
class DatabaseError(IOError): ...
1121

12-
def execute(sql, con, cur=..., params=...): ...
22+
@overload
1323
def read_sql_table(
1424
table_name: str,
15-
con,
25+
con: str | sqlalchemy.engine.Connection | sqlite3.Connection,
1626
schema: str | None = ...,
17-
index_col: str | Sequence[str] | None = ...,
27+
index_col: str | list[str] | None = ...,
1828
coerce_float: bool = ...,
19-
parse_dates: Sequence[str] | Mapping[str, str] | None = ...,
20-
columns: Sequence[str] | None = ...,
21-
chunksize: int | None = ...,
29+
parse_dates: list[str] | dict[str, str] | dict[str, dict[str, Any]] | None = ...,
30+
columns: list[str] | None = ...,
31+
*,
32+
chunksize: int,
33+
) -> Generator[DataFrame, None, None]: ...
34+
@overload
35+
def read_sql_table(
36+
table_name: str,
37+
con: str | sqlalchemy.engine.Connection | sqlite3.Connection,
38+
schema: str | None = ...,
39+
index_col: str | list[str] | None = ...,
40+
coerce_float: bool = ...,
41+
parse_dates: list[str] | dict[str, str] | dict[str, dict[str, Any]] | None = ...,
42+
columns: list[str] | None = ...,
43+
chunksize: None = ...,
2244
) -> DataFrame: ...
45+
@overload
2346
def read_sql_query(
24-
sql,
25-
con,
26-
schema: str | None = ...,
27-
index_col: str | Sequence[str] | None = ...,
47+
sql: str,
48+
con: str | sqlalchemy.engine.Connection | sqlite3.Connection,
49+
index_col: str | list[str] | None = ...,
2850
coerce_float: bool = ...,
29-
params=...,
30-
parse_dates: Sequence[str] | Mapping[str, str] | None = ...,
31-
chunksize: int | None = ...,
51+
params: list[str] | tuple[str, ...] | dict[str, str] | None = ...,
52+
parse_dates: list[str] | dict[str, str] | dict[str, dict[str, Any]] | None = ...,
53+
*,
54+
chunksize: int,
55+
dtype: DtypeArg | None = ...,
56+
) -> Generator[DataFrame, None, None]: ...
57+
@overload
58+
def read_sql_query(
59+
sql: str,
60+
con: str | sqlalchemy.engine.Connection | sqlite3.Connection,
61+
index_col: str | list[str] | None = ...,
62+
coerce_float: bool = ...,
63+
params: list[str] | tuple[str, ...] | dict[str, str] | None = ...,
64+
parse_dates: list[str] | dict[str, str] | dict[str, dict[str, Any]] | None = ...,
65+
chunksize: None = ...,
66+
dtype: DtypeArg | None = ...,
3267
) -> DataFrame: ...
68+
@overload
69+
def read_sql(
70+
sql: str,
71+
con: str | sqlalchemy.engine.Connection | sqlite3.Connection,
72+
index_col: str | list[str] | None = ...,
73+
coerce_float: bool = ...,
74+
params: list[str] | tuple[str, ...] | dict[str, str] | None = ...,
75+
parse_dates: list[str] | dict[str, str] | dict[str, dict[str, Any]] | None = ...,
76+
columns: list[str] = ...,
77+
*,
78+
chunksize: int,
79+
) -> Generator[DataFrame, None, None]: ...
80+
@overload
3381
def read_sql(
34-
sql: str | Any,
35-
con: str | Any,
36-
index_col: str | Sequence[str] | None = ...,
82+
sql: str,
83+
con: str | sqlalchemy.engine.Connection | sqlite3.Connection,
84+
index_col: str | list[str] | None = ...,
3785
coerce_float: bool = ...,
38-
params: Sequence[str] | tuple[str, ...] | Mapping[str, str] | None = ...,
39-
parse_dates: Sequence[str]
40-
| Mapping[str, str]
41-
| Mapping[str, Mapping[str, Any]]
42-
| None = ...,
43-
columns: Sequence[str] = ...,
44-
chunksize: int = ...,
86+
params: list[str] | tuple[str, ...] | dict[str, str] | None = ...,
87+
parse_dates: list[str] | dict[str, str] | dict[str, dict[str, Any]] | None = ...,
88+
columns: list[str] = ...,
89+
chunksize: None = ...,
4590
) -> DataFrame: ...
46-
def to_sql(
47-
frame,
48-
name,
49-
con,
50-
schema=...,
51-
if_exists: str = ...,
52-
index: bool = ...,
53-
index_label=...,
54-
chunksize=...,
55-
dtype=...,
56-
method=...,
57-
) -> None: ...
58-
def has_table(table_name, con, schema=...): ...
59-
60-
table_exists = has_table
61-
62-
def pandasSQL_builder(con, schema=..., meta=..., is_cursor: bool = ...): ...
63-
64-
class SQLTable(PandasObject):
65-
name = ...
66-
pd_sql = ...
67-
prefix = ...
68-
frame = ...
69-
index = ...
70-
schema = ...
71-
if_exists = ...
72-
keys = ...
73-
dtype = ...
74-
table = ...
75-
def __init__(
76-
self,
77-
name,
78-
pandas_sql_engine,
79-
frame=...,
80-
index: bool = ...,
81-
if_exists: str = ...,
82-
prefix: str = ...,
83-
index_label=...,
84-
schema=...,
85-
keys=...,
86-
dtype=...,
87-
) -> None: ...
88-
def exists(self): ...
89-
def sql_schema(self): ...
90-
def create(self) -> None: ...
91-
def insert_data(self): ...
92-
def insert(self, chunksize=..., method=...) -> None: ...
93-
def read(
94-
self, coerce_float: bool = ..., parse_dates=..., columns=..., chunksize=...
95-
): ...
9691

9792
class PandasSQL(PandasObject):
98-
def read_sql(self, *args, **kwargs) -> None: ...
93+
def read_sql(self, *args, **kwargs): ...
9994
def to_sql(
10095
self,
101-
frame,
102-
name,
103-
if_exists: str = ...,
96+
frame: DataFrame,
97+
name: str,
98+
if_exists: Literal["fail", "replace", "append"] = ...,
10499
index: bool = ...,
105100
index_label=...,
106-
schema=...,
101+
schema: str | None = ...,
107102
chunksize=...,
108-
dtype=...,
109-
method=...,
110-
) -> None: ...
103+
dtype: DtypeArg | None = ...,
104+
method: Literal["multi"]
105+
| Callable[[SQLTable, Any, list[str], Iterable], int | None]
106+
| None = ...,
107+
) -> int | None: ...
111108

112-
class SQLDatabase(PandasSQL):
113-
connectable = ...
114-
meta = ...
115-
def __init__(self, engine, schema=..., meta=...) -> None: ...
116-
def run_transaction(self) -> None: ...
117-
def execute(self, *args, **kwargs): ...
118-
def read_table(
119-
self,
120-
table_name,
121-
index_col=...,
122-
coerce_float: bool = ...,
123-
parse_dates=...,
124-
columns=...,
125-
schema=...,
126-
chunksize=...,
127-
): ...
128-
def read_query(
129-
self,
130-
sql,
131-
index_col=...,
132-
coerce_float: bool = ...,
133-
parse_dates=...,
134-
params=...,
135-
chunksize=...,
136-
): ...
137-
def to_sql(
109+
class SQLTable(PandasObject):
110+
name: str
111+
pd_sql: PandasSQL # pandas SQL interface
112+
prefix: str
113+
frame: DataFrame | None
114+
index: list[str]
115+
schema: str
116+
if_exists: Literal["fail", "replace", "append"]
117+
keys: list[str]
118+
dtype: DtypeArg | None
119+
table: Any # sqlalchemy.Table
120+
def __init__(
138121
self,
139-
frame,
140-
name,
141-
if_exists: str = ...,
142-
index: bool = ...,
143-
index_label=...,
144-
schema=...,
145-
chunksize=...,
146-
dtype=...,
147-
method=...,
122+
name: str,
123+
pandas_sql_engine: PandasSQL,
124+
frame: DataFrame | None = ...,
125+
index: bool | str | list[str] | None = ...,
126+
if_exists: Literal["fail", "replace", "append"] = ...,
127+
prefix: str = ...,
128+
index_label: str | list[str] | None = ...,
129+
schema: str | None = ...,
130+
keys: str | list[str] | None = ...,
131+
dtype: DtypeArg | None = ...,
148132
) -> None: ...
149-
@property
150-
def tables(self): ...
151-
def has_table(self, name, schema=...): ...
152-
def get_table(self, table_name, schema=...): ...
153-
def drop_table(self, table_name, schema=...) -> None: ...
154-
155-
class SQLiteTable(SQLTable):
156-
def __init__(self, *args, **kwargs): ...
157-
def sql_schema(self): ...
158-
def insert_statement(self): ...
159-
160-
class SQLiteDatabase(PandasSQL):
161-
is_cursor = ...
162-
con = ...
163-
def __init__(self, con, is_cursor: bool = ...) -> None: ...
164-
def run_transaction(self) -> None: ...
165-
def execute(self, *args, **kwargs): ...
166-
def read_query(
133+
def exists(self) -> bool: ...
134+
def sql_schema(self) -> str: ...
135+
def create(self) -> None: ...
136+
def insert_data(self) -> tuple[list[str], list[npt.NDArray]]: ...
137+
def insert(
138+
self, chunksize: int | None = ..., method: str | None = ...
139+
) -> int | None: ...
140+
def read(
167141
self,
168-
sql,
169-
index_col=...,
170142
coerce_float: bool = ...,
171-
params=...,
172-
parse_dates=...,
173-
chunksize=...,
174-
): ...
175-
def to_sql(
176-
self,
177-
frame,
178-
name,
179-
if_exists: str = ...,
180-
index: bool = ...,
181-
index_label=...,
182-
schema=...,
183-
chunksize=...,
184-
dtype=...,
185-
method=...,
186-
) -> None: ...
187-
def has_table(self, name, schema=...): ...
188-
def get_table(self, table_name, schema=...) -> None: ...
189-
def drop_table(self, name, schema=...) -> None: ...
190-
191-
def get_schema(frame, name, keys=..., con=..., dtype=...): ...
143+
parse_dates: bool | list[str] | None = ...,
144+
columns: list[str] | None = ...,
145+
chunksize: int | None = ...,
146+
) -> DataFrame | Generator[DataFrame, None, None]: ...

0 commit comments

Comments
 (0)