Skip to content

Commit fcff205

Browse files
committed
✨ Add SQLModel core code
0 parents  commit fcff205

File tree

17 files changed

+1867
-0
lines changed

17 files changed

+1867
-0
lines changed

sqlmodel/__init__.py

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
__version__ = "0.0.1"
2+
3+
# Re-export from SQLAlchemy
4+
from sqlalchemy.engine import create_mock_engine as create_mock_engine
5+
from sqlalchemy.engine import engine_from_config as engine_from_config
6+
from sqlalchemy.inspection import inspect as inspect
7+
from sqlalchemy.schema import BLANK_SCHEMA as BLANK_SCHEMA
8+
from sqlalchemy.schema import CheckConstraint as CheckConstraint
9+
from sqlalchemy.schema import Column as Column
10+
from sqlalchemy.schema import ColumnDefault as ColumnDefault
11+
from sqlalchemy.schema import Computed as Computed
12+
from sqlalchemy.schema import Constraint as Constraint
13+
from sqlalchemy.schema import DDL as DDL
14+
from sqlalchemy.schema import DefaultClause as DefaultClause
15+
from sqlalchemy.schema import FetchedValue as FetchedValue
16+
from sqlalchemy.schema import ForeignKey as ForeignKey
17+
from sqlalchemy.schema import ForeignKeyConstraint as ForeignKeyConstraint
18+
from sqlalchemy.schema import Identity as Identity
19+
from sqlalchemy.schema import Index as Index
20+
from sqlalchemy.schema import MetaData as MetaData
21+
from sqlalchemy.schema import PrimaryKeyConstraint as PrimaryKeyConstraint
22+
from sqlalchemy.schema import Sequence as Sequence
23+
from sqlalchemy.schema import Table as Table
24+
from sqlalchemy.schema import ThreadLocalMetaData as ThreadLocalMetaData
25+
from sqlalchemy.schema import UniqueConstraint as UniqueConstraint
26+
from sqlalchemy.sql import alias as alias
27+
from sqlalchemy.sql import all_ as all_
28+
from sqlalchemy.sql import and_ as and_
29+
from sqlalchemy.sql import any_ as any_
30+
from sqlalchemy.sql import asc as asc
31+
from sqlalchemy.sql import between as between
32+
from sqlalchemy.sql import bindparam as bindparam
33+
from sqlalchemy.sql import case as case
34+
from sqlalchemy.sql import cast as cast
35+
from sqlalchemy.sql import collate as collate
36+
from sqlalchemy.sql import column as column
37+
from sqlalchemy.sql import delete as delete
38+
from sqlalchemy.sql import desc as desc
39+
from sqlalchemy.sql import distinct as distinct
40+
from sqlalchemy.sql import except_ as except_
41+
from sqlalchemy.sql import except_all as except_all
42+
from sqlalchemy.sql import exists as exists
43+
from sqlalchemy.sql import extract as extract
44+
from sqlalchemy.sql import false as false
45+
from sqlalchemy.sql import func as func
46+
from sqlalchemy.sql import funcfilter as funcfilter
47+
from sqlalchemy.sql import insert as insert
48+
from sqlalchemy.sql import intersect as intersect
49+
from sqlalchemy.sql import intersect_all as intersect_all
50+
from sqlalchemy.sql import join as join
51+
from sqlalchemy.sql import LABEL_STYLE_DEFAULT as LABEL_STYLE_DEFAULT
52+
from sqlalchemy.sql import (
53+
LABEL_STYLE_DISAMBIGUATE_ONLY as LABEL_STYLE_DISAMBIGUATE_ONLY,
54+
)
55+
from sqlalchemy.sql import LABEL_STYLE_NONE as LABEL_STYLE_NONE
56+
from sqlalchemy.sql import (
57+
LABEL_STYLE_TABLENAME_PLUS_COL as LABEL_STYLE_TABLENAME_PLUS_COL,
58+
)
59+
from sqlalchemy.sql import lambda_stmt as lambda_stmt
60+
from sqlalchemy.sql import lateral as lateral
61+
from sqlalchemy.sql import literal as literal
62+
from sqlalchemy.sql import literal_column as literal_column
63+
from sqlalchemy.sql import modifier as modifier
64+
from sqlalchemy.sql import not_ as not_
65+
from sqlalchemy.sql import null as null
66+
from sqlalchemy.sql import nulls_first as nulls_first
67+
from sqlalchemy.sql import nulls_last as nulls_last
68+
from sqlalchemy.sql import nullsfirst as nullsfirst
69+
from sqlalchemy.sql import nullslast as nullslast
70+
from sqlalchemy.sql import or_ as or_
71+
from sqlalchemy.sql import outerjoin as outerjoin
72+
from sqlalchemy.sql import outparam as outparam
73+
from sqlalchemy.sql import over as over
74+
from sqlalchemy.sql import subquery as subquery
75+
from sqlalchemy.sql import table as table
76+
from sqlalchemy.sql import tablesample as tablesample
77+
from sqlalchemy.sql import text as text
78+
from sqlalchemy.sql import true as true
79+
from sqlalchemy.sql import tuple_ as tuple_
80+
from sqlalchemy.sql import type_coerce as type_coerce
81+
from sqlalchemy.sql import union as union
82+
from sqlalchemy.sql import union_all as union_all
83+
from sqlalchemy.sql import update as update
84+
from sqlalchemy.sql import values as values
85+
from sqlalchemy.sql import within_group as within_group
86+
from sqlalchemy.types import ARRAY as ARRAY
87+
from sqlalchemy.types import BIGINT as BIGINT
88+
from sqlalchemy.types import BigInteger as BigInteger
89+
from sqlalchemy.types import BINARY as BINARY
90+
from sqlalchemy.types import BLOB as BLOB
91+
from sqlalchemy.types import BOOLEAN as BOOLEAN
92+
from sqlalchemy.types import Boolean as Boolean
93+
from sqlalchemy.types import CHAR as CHAR
94+
from sqlalchemy.types import CLOB as CLOB
95+
from sqlalchemy.types import DATE as DATE
96+
from sqlalchemy.types import Date as Date
97+
from sqlalchemy.types import DATETIME as DATETIME
98+
from sqlalchemy.types import DateTime as DateTime
99+
from sqlalchemy.types import DECIMAL as DECIMAL
100+
from sqlalchemy.types import Enum as Enum
101+
from sqlalchemy.types import FLOAT as FLOAT
102+
from sqlalchemy.types import Float as Float
103+
from sqlalchemy.types import INT as INT
104+
from sqlalchemy.types import INTEGER as INTEGER
105+
from sqlalchemy.types import Integer as Integer
106+
from sqlalchemy.types import Interval as Interval
107+
from sqlalchemy.types import JSON as JSON
108+
from sqlalchemy.types import LargeBinary as LargeBinary
109+
from sqlalchemy.types import NCHAR as NCHAR
110+
from sqlalchemy.types import NUMERIC as NUMERIC
111+
from sqlalchemy.types import Numeric as Numeric
112+
from sqlalchemy.types import NVARCHAR as NVARCHAR
113+
from sqlalchemy.types import PickleType as PickleType
114+
from sqlalchemy.types import REAL as REAL
115+
from sqlalchemy.types import SMALLINT as SMALLINT
116+
from sqlalchemy.types import SmallInteger as SmallInteger
117+
from sqlalchemy.types import String as String
118+
from sqlalchemy.types import TEXT as TEXT
119+
from sqlalchemy.types import Text as Text
120+
from sqlalchemy.types import TIME as TIME
121+
from sqlalchemy.types import Time as Time
122+
from sqlalchemy.types import TIMESTAMP as TIMESTAMP
123+
from sqlalchemy.types import TypeDecorator as TypeDecorator
124+
from sqlalchemy.types import Unicode as Unicode
125+
from sqlalchemy.types import UnicodeText as UnicodeText
126+
from sqlalchemy.types import VARBINARY as VARBINARY
127+
from sqlalchemy.types import VARCHAR as VARCHAR
128+
129+
# Extensions and modifications of SQLAlchemy in SQLModel
130+
from .engine.create import create_engine as create_engine
131+
from .orm.session import Session as Session
132+
from .sql.expression import select as select
133+
from .sql.expression import col as col
134+
from .sql.sqltypes import AutoString as AutoString
135+
136+
# Export SQLModel specifics (equivalent to Pydantic)
137+
from .main import SQLModel as SQLModel
138+
from .main import Field as Field
139+
from .main import Relationship as Relationship

sqlmodel/default.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from typing import Any, TypeVar
2+
3+
4+
class _DefaultPlaceholder:
5+
"""
6+
You shouldn't use this class directly.
7+
8+
It's used internally to recognize when a default value has been overwritten, even
9+
if the overriden default value was truthy.
10+
"""
11+
12+
def __init__(self, value: Any):
13+
self.value = value
14+
15+
def __bool__(self) -> bool:
16+
return bool(self.value)
17+
18+
def __eq__(self, o: object) -> bool:
19+
return isinstance(o, _DefaultPlaceholder) and o.value == self.value
20+
21+
22+
_TDefaultType = TypeVar("_TDefaultType")
23+
24+
25+
def Default(value: _TDefaultType) -> _TDefaultType:
26+
"""
27+
You shouldn't use this function directly.
28+
29+
It's used internally to recognize when a default value has been overwritten, even
30+
if the overriden default value was truthy.
31+
"""
32+
return _DefaultPlaceholder(value) # type: ignore

sqlmodel/engine/__init__.py

Whitespace-only changes.

sqlmodel/engine/create.py

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
import json
2+
import sqlite3
3+
from typing import Any, Callable, Dict, List, Optional, Type, Union
4+
5+
from sqlalchemy import create_engine as _create_engine
6+
from sqlalchemy.engine.url import URL
7+
from sqlalchemy.future import Engine as _FutureEngine
8+
from sqlalchemy.pool import Pool
9+
from typing_extensions import Literal, TypedDict
10+
11+
from ..default import Default, _DefaultPlaceholder
12+
13+
# Types defined in sqlalchemy2-stubs, but can't be imported, so re-define here
14+
15+
_Debug = Literal["debug"]
16+
17+
_IsolationLevel = Literal[
18+
"SERIALIZABLE",
19+
"REPEATABLE READ",
20+
"READ COMMITTED",
21+
"READ UNCOMMITTED",
22+
"AUTOCOMMIT",
23+
]
24+
_ParamStyle = Literal["qmark", "numeric", "named", "format", "pyformat"]
25+
_ResetOnReturn = Literal["rollback", "commit"]
26+
27+
28+
class _SQLiteConnectArgs(TypedDict, total=False):
29+
timeout: float
30+
detect_types: Any
31+
isolation_level: Optional[Literal["DEFERRED", "IMMEDIATE", "EXCLUSIVE"]]
32+
check_same_thread: bool
33+
factory: Type[sqlite3.Connection]
34+
cached_statements: int
35+
uri: bool
36+
37+
38+
_ConnectArgs = Union[_SQLiteConnectArgs, Dict[str, Any]]
39+
40+
41+
# Re-define create_engine to have by default future=True, and assume that's what is used
42+
# Also show the default values used for each parameter, but don't set them unless
43+
# explicitly passed as arguments by the user to prevent errors. E.g. SQLite doesn't
44+
# support pool connection arguments.
45+
def create_engine(
46+
url: Union[str, URL],
47+
*,
48+
connect_args: _ConnectArgs = Default({}), # type: ignore
49+
echo: Union[bool, _Debug] = Default(False),
50+
echo_pool: Union[bool, _Debug] = Default(False),
51+
enable_from_linting: bool = Default(True),
52+
encoding: str = Default("utf-8"),
53+
execution_options: Dict[Any, Any] = Default({}),
54+
future: bool = True,
55+
hide_parameters: bool = Default(False),
56+
implicit_returning: bool = Default(True),
57+
isolation_level: Optional[_IsolationLevel] = Default(None),
58+
json_deserializer: Callable[..., Any] = Default(json.loads),
59+
json_serializer: Callable[..., Any] = Default(json.dumps),
60+
label_length: Optional[int] = Default(None),
61+
logging_name: Optional[str] = Default(None),
62+
max_identifier_length: Optional[int] = Default(None),
63+
max_overflow: int = Default(10),
64+
module: Optional[Any] = Default(None),
65+
paramstyle: Optional[_ParamStyle] = Default(None),
66+
pool: Optional[Pool] = Default(None),
67+
poolclass: Optional[Type[Pool]] = Default(None),
68+
pool_logging_name: Optional[str] = Default(None),
69+
pool_pre_ping: bool = Default(False),
70+
pool_size: int = Default(5),
71+
pool_recycle: int = Default(-1),
72+
pool_reset_on_return: Optional[_ResetOnReturn] = Default("rollback"),
73+
pool_timeout: float = Default(30),
74+
pool_use_lifo: bool = Default(False),
75+
plugins: Optional[List[str]] = Default(None),
76+
query_cache_size: Optional[int] = Default(None),
77+
**kwargs: Any,
78+
) -> _FutureEngine:
79+
current_kwargs: Dict[str, Any] = {
80+
"future": future,
81+
}
82+
if not isinstance(echo, _DefaultPlaceholder):
83+
current_kwargs["echo"] = echo
84+
if not isinstance(echo_pool, _DefaultPlaceholder):
85+
current_kwargs["echo_pool"] = echo_pool
86+
if not isinstance(enable_from_linting, _DefaultPlaceholder):
87+
current_kwargs["enable_from_linting"] = enable_from_linting
88+
if not isinstance(connect_args, _DefaultPlaceholder):
89+
current_kwargs["connect_args"] = connect_args
90+
if not isinstance(encoding, _DefaultPlaceholder):
91+
current_kwargs["encoding"] = encoding
92+
if not isinstance(execution_options, _DefaultPlaceholder):
93+
current_kwargs["execution_options"] = execution_options
94+
if not isinstance(hide_parameters, _DefaultPlaceholder):
95+
current_kwargs["hide_parameters"] = hide_parameters
96+
if not isinstance(implicit_returning, _DefaultPlaceholder):
97+
current_kwargs["implicit_returning"] = implicit_returning
98+
if not isinstance(isolation_level, _DefaultPlaceholder):
99+
current_kwargs["isolation_level"] = isolation_level
100+
if not isinstance(json_deserializer, _DefaultPlaceholder):
101+
current_kwargs["json_deserializer"] = json_deserializer
102+
if not isinstance(json_serializer, _DefaultPlaceholder):
103+
current_kwargs["json_serializer"] = json_serializer
104+
if not isinstance(label_length, _DefaultPlaceholder):
105+
current_kwargs["label_length"] = label_length
106+
if not isinstance(logging_name, _DefaultPlaceholder):
107+
current_kwargs["logging_name"] = logging_name
108+
if not isinstance(max_identifier_length, _DefaultPlaceholder):
109+
current_kwargs["max_identifier_length"] = max_identifier_length
110+
if not isinstance(max_overflow, _DefaultPlaceholder):
111+
current_kwargs["max_overflow"] = max_overflow
112+
if not isinstance(module, _DefaultPlaceholder):
113+
current_kwargs["module"] = module
114+
if not isinstance(paramstyle, _DefaultPlaceholder):
115+
current_kwargs["paramstyle"] = paramstyle
116+
if not isinstance(pool, _DefaultPlaceholder):
117+
current_kwargs["pool"] = pool
118+
if not isinstance(poolclass, _DefaultPlaceholder):
119+
current_kwargs["poolclass"] = poolclass
120+
if not isinstance(pool_logging_name, _DefaultPlaceholder):
121+
current_kwargs["pool_logging_name"] = pool_logging_name
122+
if not isinstance(pool_pre_ping, _DefaultPlaceholder):
123+
current_kwargs["pool_pre_ping"] = pool_pre_ping
124+
if not isinstance(pool_size, _DefaultPlaceholder):
125+
current_kwargs["pool_size"] = pool_size
126+
if not isinstance(pool_recycle, _DefaultPlaceholder):
127+
current_kwargs["pool_recycle"] = pool_recycle
128+
if not isinstance(pool_reset_on_return, _DefaultPlaceholder):
129+
current_kwargs["pool_reset_on_return"] = pool_reset_on_return
130+
if not isinstance(pool_timeout, _DefaultPlaceholder):
131+
current_kwargs["pool_timeout"] = pool_timeout
132+
if not isinstance(pool_use_lifo, _DefaultPlaceholder):
133+
current_kwargs["pool_use_lifo"] = pool_use_lifo
134+
if not isinstance(plugins, _DefaultPlaceholder):
135+
current_kwargs["plugins"] = plugins
136+
if not isinstance(query_cache_size, _DefaultPlaceholder):
137+
current_kwargs["query_cache_size"] = query_cache_size
138+
current_kwargs.update(kwargs)
139+
return _create_engine(url, **current_kwargs)

sqlmodel/engine/result.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
from typing import Generic, Iterator, List, Optional, TypeVar
2+
3+
from sqlalchemy.engine.result import Result as _Result
4+
from sqlalchemy.engine.result import ScalarResult as _ScalarResult
5+
6+
_T = TypeVar("_T")
7+
8+
9+
class ScalarResult(_ScalarResult, Generic[_T]):
10+
def all(self) -> List[_T]:
11+
return super().all()
12+
13+
def partitions(self, size: Optional[int] = None) -> Iterator[List[_T]]:
14+
return super().partitions(size)
15+
16+
def fetchall(self) -> List[_T]:
17+
return super().fetchall()
18+
19+
def fetchmany(self, size: Optional[int] = None) -> List[_T]:
20+
return super().fetchmany(size)
21+
22+
def __iter__(self) -> Iterator[_T]:
23+
return super().__iter__()
24+
25+
def __next__(self) -> _T:
26+
return super().__next__()
27+
28+
def first(self) -> Optional[_T]:
29+
return super().first()
30+
31+
def one_or_none(self) -> Optional[_T]:
32+
return super().one_or_none()
33+
34+
def one(self) -> _T:
35+
return super().one()
36+
37+
38+
class Result(_Result, Generic[_T]):
39+
def scalars(self, index: int = 0) -> ScalarResult[_T]:
40+
return super().scalars(index) # type: ignore
41+
42+
def __iter__(self) -> Iterator[_T]: # type: ignore
43+
return super().__iter__() # type: ignore
44+
45+
def __next__(self) -> _T: # type: ignore
46+
return super().__next__() # type: ignore
47+
48+
def partitions(self, size: Optional[int] = None) -> Iterator[List[_T]]: # type: ignore
49+
return super().partitions(size) # type: ignore
50+
51+
def fetchall(self) -> List[_T]: # type: ignore
52+
return super().fetchall() # type: ignore
53+
54+
def fetchone(self) -> Optional[_T]: # type: ignore
55+
return super().fetchone() # type: ignore
56+
57+
def fetchmany(self, size: Optional[int] = None) -> List[_T]: # type: ignore
58+
return super().fetchmany() # type: ignore
59+
60+
def all(self) -> List[_T]: # type: ignore
61+
return super().all() # type: ignore
62+
63+
def first(self) -> Optional[_T]: # type: ignore
64+
return super().first() # type: ignore
65+
66+
def one_or_none(self) -> Optional[_T]: # type: ignore
67+
return super().one_or_none() # type: ignore
68+
69+
def scalar_one(self) -> _T:
70+
return super().scalar_one() # type: ignore
71+
72+
def scalar_one_or_none(self) -> Optional[_T]:
73+
return super().scalar_one_or_none() # type: ignore
74+
75+
def one(self) -> _T: # type: ignore
76+
return super().one() # type: ignore
77+
78+
def scalar(self) -> Optional[_T]:
79+
return super().scalar() # type: ignore

sqlmodel/ext/__init__.py

Whitespace-only changes.

sqlmodel/ext/asyncio/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)