sqlmodel 0.0.8__tar.gz → 0.0.10__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sqlmodel-0.0.8 → sqlmodel-0.0.10}/PKG-INFO +8 -12
- {sqlmodel-0.0.8 → sqlmodel-0.0.10}/README.md +3 -4
- {sqlmodel-0.0.8 → sqlmodel-0.0.10}/pyproject.toml +42 -40
- {sqlmodel-0.0.8 → sqlmodel-0.0.10}/sqlmodel/__init__.py +31 -33
- {sqlmodel-0.0.8 → sqlmodel-0.0.10}/sqlmodel/default.py +2 -2
- {sqlmodel-0.0.8 → sqlmodel-0.0.10}/sqlmodel/ext/asyncio/session.py +39 -7
- {sqlmodel-0.0.8 → sqlmodel-0.0.10}/sqlmodel/main.py +84 -59
- {sqlmodel-0.0.8 → sqlmodel-0.0.10}/sqlmodel/orm/session.py +1 -1
- {sqlmodel-0.0.8 → sqlmodel-0.0.10}/sqlmodel/sql/expression.py +8 -29
- {sqlmodel-0.0.8 → sqlmodel-0.0.10}/sqlmodel/sql/sqltypes.py +0 -1
- sqlmodel-0.0.8/setup.py +0 -36
- {sqlmodel-0.0.8 → sqlmodel-0.0.10}/LICENSE +0 -0
- {sqlmodel-0.0.8 → sqlmodel-0.0.10}/sqlmodel/engine/__init__.py +0 -0
- {sqlmodel-0.0.8 → sqlmodel-0.0.10}/sqlmodel/engine/create.py +0 -0
- {sqlmodel-0.0.8 → sqlmodel-0.0.10}/sqlmodel/engine/result.py +0 -0
- {sqlmodel-0.0.8 → sqlmodel-0.0.10}/sqlmodel/ext/__init__.py +0 -0
- {sqlmodel-0.0.8 → sqlmodel-0.0.10}/sqlmodel/ext/asyncio/__init__.py +0 -0
- {sqlmodel-0.0.8 → sqlmodel-0.0.10}/sqlmodel/orm/__init__.py +0 -0
- {sqlmodel-0.0.8 → sqlmodel-0.0.10}/sqlmodel/pool/__init__.py +0 -0
- {sqlmodel-0.0.8 → sqlmodel-0.0.10}/sqlmodel/py.typed +0 -0
- {sqlmodel-0.0.8 → sqlmodel-0.0.10}/sqlmodel/sql/__init__.py +0 -0
- {sqlmodel-0.0.8 → sqlmodel-0.0.10}/sqlmodel/sql/base.py +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: sqlmodel
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.10
|
|
4
4
|
Summary: SQLModel, SQL databases in Python, designed for simplicity, compatibility, and robustness.
|
|
5
5
|
Home-page: https://github.com/tiangolo/sqlmodel
|
|
6
6
|
License: MIT
|
|
7
7
|
Author: Sebastián Ramírez
|
|
8
8
|
Author-email: tiangolo@gmail.com
|
|
9
|
-
Requires-Python: >=3.
|
|
9
|
+
Requires-Python: >=3.7,<4.0
|
|
10
10
|
Classifier: Development Status :: 4 - Beta
|
|
11
11
|
Classifier: Framework :: AsyncIO
|
|
12
12
|
Classifier: Intended Audience :: Developers
|
|
@@ -18,19 +18,16 @@ Classifier: Programming Language :: Python :: 3.7
|
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.8
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.9
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
22
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
22
|
-
Classifier: Programming Language :: Python :: 3.6
|
|
23
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
24
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
25
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
26
23
|
Classifier: Topic :: Database
|
|
27
24
|
Classifier: Topic :: Database :: Database Engines/Servers
|
|
28
25
|
Classifier: Topic :: Internet
|
|
29
26
|
Classifier: Topic :: Internet :: WWW/HTTP
|
|
30
27
|
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
|
|
31
28
|
Classifier: Typing :: Typed
|
|
32
|
-
Requires-Dist: SQLAlchemy (>=1.4.
|
|
33
|
-
Requires-Dist: pydantic (>=1.
|
|
29
|
+
Requires-Dist: SQLAlchemy (>=1.4.36,<2.0.0)
|
|
30
|
+
Requires-Dist: pydantic (>=1.9.0,<2.0.0)
|
|
34
31
|
Requires-Dist: sqlalchemy2-stubs
|
|
35
32
|
Project-URL: Documentation, https://sqlmodel.tiangolo.com
|
|
36
33
|
Project-URL: Repository, https://github.com/tiangolo/sqlmodel
|
|
@@ -49,9 +46,8 @@ Description-Content-Type: text/markdown
|
|
|
49
46
|
<a href="https://github.com/tiangolo/sqlmodel/actions?query=workflow%3APublish" target="_blank">
|
|
50
47
|
<img src="https://github.com/tiangolo/sqlmodel/workflows/Publish/badge.svg" alt="Publish">
|
|
51
48
|
</a>
|
|
52
|
-
<a href="https://
|
|
53
|
-
<img src="https://
|
|
54
|
-
</a>
|
|
49
|
+
<a href="https://coverage-badge.samuelcolvin.workers.dev/redirect/tiangolo/sqlmodel" target="_blank">
|
|
50
|
+
<img src="https://coverage-badge.samuelcolvin.workers.dev/tiangolo/sqlmodel.svg" alt="Coverage">
|
|
55
51
|
<a href="https://pypi.org/project/sqlmodel" target="_blank">
|
|
56
52
|
<img src="https://img.shields.io/pypi/v/sqlmodel?color=%2334D058&label=pypi%20package" alt="Package version">
|
|
57
53
|
</a>
|
|
@@ -89,7 +85,7 @@ It combines SQLAlchemy and Pydantic and tries to simplify the code you write as
|
|
|
89
85
|
|
|
90
86
|
## Requirements
|
|
91
87
|
|
|
92
|
-
A recent and currently supported
|
|
88
|
+
A recent and currently supported <a href="https://www.python.org/downloads/" class="external-link" target="_blank">version of Python</a>.
|
|
93
89
|
|
|
94
90
|
As **SQLModel** is based on **Pydantic** and **SQLAlchemy**, it requires them. They will be automatically installed when you install SQLModel.
|
|
95
91
|
|
|
@@ -11,9 +11,8 @@
|
|
|
11
11
|
<a href="https://github.com/tiangolo/sqlmodel/actions?query=workflow%3APublish" target="_blank">
|
|
12
12
|
<img src="https://github.com/tiangolo/sqlmodel/workflows/Publish/badge.svg" alt="Publish">
|
|
13
13
|
</a>
|
|
14
|
-
<a href="https://
|
|
15
|
-
<img src="https://
|
|
16
|
-
</a>
|
|
14
|
+
<a href="https://coverage-badge.samuelcolvin.workers.dev/redirect/tiangolo/sqlmodel" target="_blank">
|
|
15
|
+
<img src="https://coverage-badge.samuelcolvin.workers.dev/tiangolo/sqlmodel.svg" alt="Coverage">
|
|
17
16
|
<a href="https://pypi.org/project/sqlmodel" target="_blank">
|
|
18
17
|
<img src="https://img.shields.io/pypi/v/sqlmodel?color=%2334D058&label=pypi%20package" alt="Package version">
|
|
19
18
|
</a>
|
|
@@ -51,7 +50,7 @@ It combines SQLAlchemy and Pydantic and tries to simplify the code you write as
|
|
|
51
50
|
|
|
52
51
|
## Requirements
|
|
53
52
|
|
|
54
|
-
A recent and currently supported
|
|
53
|
+
A recent and currently supported <a href="https://www.python.org/downloads/" class="external-link" target="_blank">version of Python</a>.
|
|
55
54
|
|
|
56
55
|
As **SQLModel** is based on **Pydantic** and **SQLAlchemy**, it requires them. They will be automatically installed when you install SQLModel.
|
|
57
56
|
|
|
@@ -17,10 +17,10 @@ classifiers = [
|
|
|
17
17
|
"Intended Audience :: System Administrators",
|
|
18
18
|
"License :: OSI Approved :: MIT License",
|
|
19
19
|
"Programming Language :: Python :: 3 :: Only",
|
|
20
|
-
"Programming Language :: Python :: 3.6",
|
|
21
20
|
"Programming Language :: Python :: 3.7",
|
|
22
21
|
"Programming Language :: Python :: 3.8",
|
|
23
22
|
"Programming Language :: Python :: 3.9",
|
|
23
|
+
"Programming Language :: Python :: 3.10",
|
|
24
24
|
"Topic :: Database",
|
|
25
25
|
"Topic :: Database :: Database Engines/Servers",
|
|
26
26
|
"Topic :: Internet",
|
|
@@ -30,26 +30,24 @@ classifiers = [
|
|
|
30
30
|
]
|
|
31
31
|
|
|
32
32
|
[tool.poetry.dependencies]
|
|
33
|
-
python = "^3.
|
|
34
|
-
SQLAlchemy = ">=1.4.
|
|
35
|
-
pydantic = "^1.
|
|
33
|
+
python = "^3.7"
|
|
34
|
+
SQLAlchemy = ">=1.4.36,<2.0.0"
|
|
35
|
+
pydantic = "^1.9.0"
|
|
36
36
|
sqlalchemy2-stubs = {version = "*", allow-prereleases = true}
|
|
37
37
|
|
|
38
|
-
[tool.poetry.dev
|
|
39
|
-
pytest = "^
|
|
40
|
-
mypy = "0.
|
|
41
|
-
|
|
42
|
-
black =
|
|
43
|
-
mkdocs = "
|
|
44
|
-
|
|
38
|
+
[tool.poetry.group.dev.dependencies]
|
|
39
|
+
pytest = "^7.0.1"
|
|
40
|
+
mypy = "0.971"
|
|
41
|
+
# Needed by the code generator using templates
|
|
42
|
+
black = "^22.10.0"
|
|
43
|
+
mkdocs-material = "9.1.21"
|
|
44
|
+
pillow = "^9.3.0"
|
|
45
|
+
cairosvg = "^2.5.2"
|
|
45
46
|
mdx-include = "^1.4.1"
|
|
46
|
-
coverage = {extras = ["toml"], version = "^
|
|
47
|
+
coverage = {extras = ["toml"], version = "^6.2"}
|
|
47
48
|
fastapi = "^0.68.1"
|
|
48
49
|
requests = "^2.26.0"
|
|
49
|
-
|
|
50
|
-
isort = "^5.9.3"
|
|
51
|
-
async_generator = {version = "*", python = "~3.6"}
|
|
52
|
-
async-exit-stack = {version = "*", python = "~3.6"}
|
|
50
|
+
ruff = "^0.1.2"
|
|
53
51
|
|
|
54
52
|
[build-system]
|
|
55
53
|
requires = ["poetry-core"]
|
|
@@ -65,6 +63,7 @@ source = [
|
|
|
65
63
|
"tests",
|
|
66
64
|
"sqlmodel"
|
|
67
65
|
]
|
|
66
|
+
context = '${CONTEXT}'
|
|
68
67
|
|
|
69
68
|
[tool.coverage.report]
|
|
70
69
|
exclude_lines = [
|
|
@@ -74,33 +73,36 @@ exclude_lines = [
|
|
|
74
73
|
"if TYPE_CHECKING:",
|
|
75
74
|
]
|
|
76
75
|
|
|
77
|
-
[tool.isort]
|
|
78
|
-
profile = "black"
|
|
79
|
-
known_third_party = ["sqlmodel"]
|
|
80
|
-
skip_glob = [
|
|
81
|
-
"sqlmodel/__init__.py",
|
|
82
|
-
]
|
|
83
|
-
|
|
84
|
-
|
|
85
76
|
[tool.mypy]
|
|
86
|
-
|
|
87
|
-
disallow_any_generics = true
|
|
88
|
-
disallow_subclassing_any = true
|
|
89
|
-
disallow_untyped_calls = true
|
|
90
|
-
disallow_untyped_defs = true
|
|
91
|
-
disallow_incomplete_defs = true
|
|
92
|
-
check_untyped_defs = true
|
|
93
|
-
disallow_untyped_decorators = true
|
|
94
|
-
no_implicit_optional = true
|
|
95
|
-
warn_redundant_casts = true
|
|
96
|
-
warn_unused_ignores = true
|
|
97
|
-
warn_return_any = true
|
|
98
|
-
implicit_reexport = false
|
|
99
|
-
strict_equality = true
|
|
100
|
-
# --strict end
|
|
77
|
+
strict = true
|
|
101
78
|
|
|
102
79
|
[[tool.mypy.overrides]]
|
|
103
80
|
module = "sqlmodel.sql.expression"
|
|
104
81
|
warn_unused_ignores = false
|
|
105
82
|
|
|
106
|
-
|
|
83
|
+
[tool.ruff]
|
|
84
|
+
select = [
|
|
85
|
+
"E", # pycodestyle errors
|
|
86
|
+
"W", # pycodestyle warnings
|
|
87
|
+
"F", # pyflakes
|
|
88
|
+
"I", # isort
|
|
89
|
+
"C", # flake8-comprehensions
|
|
90
|
+
"B", # flake8-bugbear
|
|
91
|
+
"UP", # pyupgrade
|
|
92
|
+
]
|
|
93
|
+
ignore = [
|
|
94
|
+
"E501", # line too long, handled by black
|
|
95
|
+
"B008", # do not perform function calls in argument defaults
|
|
96
|
+
"C901", # too complex
|
|
97
|
+
"W191", # indentation contains tabs
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
[tool.ruff.per-file-ignores]
|
|
101
|
+
# "__init__.py" = ["F401"]
|
|
102
|
+
|
|
103
|
+
[tool.ruff.isort]
|
|
104
|
+
known-third-party = ["sqlmodel", "sqlalchemy", "pydantic", "fastapi"]
|
|
105
|
+
|
|
106
|
+
[tool.ruff.pyupgrade]
|
|
107
|
+
# Preserve types, even if a file imports `from __future__ import annotations`.
|
|
108
|
+
keep-runtime-typing = true
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
__version__ = "0.0.
|
|
1
|
+
__version__ = "0.0.10"
|
|
2
2
|
|
|
3
3
|
# Re-export from SQLAlchemy
|
|
4
4
|
from sqlalchemy.engine import create_mock_engine as create_mock_engine
|
|
5
5
|
from sqlalchemy.engine import engine_from_config as engine_from_config
|
|
6
6
|
from sqlalchemy.inspection import inspect as inspect
|
|
7
7
|
from sqlalchemy.schema import BLANK_SCHEMA as BLANK_SCHEMA
|
|
8
|
+
from sqlalchemy.schema import DDL as DDL
|
|
8
9
|
from sqlalchemy.schema import CheckConstraint as CheckConstraint
|
|
9
10
|
from sqlalchemy.schema import Column as Column
|
|
10
11
|
from sqlalchemy.schema import ColumnDefault as ColumnDefault
|
|
11
12
|
from sqlalchemy.schema import Computed as Computed
|
|
12
13
|
from sqlalchemy.schema import Constraint as Constraint
|
|
13
|
-
from sqlalchemy.schema import DDL as DDL
|
|
14
14
|
from sqlalchemy.schema import DefaultClause as DefaultClause
|
|
15
15
|
from sqlalchemy.schema import FetchedValue as FetchedValue
|
|
16
16
|
from sqlalchemy.schema import ForeignKey as ForeignKey
|
|
@@ -23,6 +23,14 @@ from sqlalchemy.schema import Sequence as Sequence
|
|
|
23
23
|
from sqlalchemy.schema import Table as Table
|
|
24
24
|
from sqlalchemy.schema import ThreadLocalMetaData as ThreadLocalMetaData
|
|
25
25
|
from sqlalchemy.schema import UniqueConstraint as UniqueConstraint
|
|
26
|
+
from sqlalchemy.sql import LABEL_STYLE_DEFAULT as LABEL_STYLE_DEFAULT
|
|
27
|
+
from sqlalchemy.sql import (
|
|
28
|
+
LABEL_STYLE_DISAMBIGUATE_ONLY as LABEL_STYLE_DISAMBIGUATE_ONLY,
|
|
29
|
+
)
|
|
30
|
+
from sqlalchemy.sql import LABEL_STYLE_NONE as LABEL_STYLE_NONE
|
|
31
|
+
from sqlalchemy.sql import (
|
|
32
|
+
LABEL_STYLE_TABLENAME_PLUS_COL as LABEL_STYLE_TABLENAME_PLUS_COL,
|
|
33
|
+
)
|
|
26
34
|
from sqlalchemy.sql import alias as alias
|
|
27
35
|
from sqlalchemy.sql import all_ as all_
|
|
28
36
|
from sqlalchemy.sql import and_ as and_
|
|
@@ -48,14 +56,6 @@ from sqlalchemy.sql import insert as insert
|
|
|
48
56
|
from sqlalchemy.sql import intersect as intersect
|
|
49
57
|
from sqlalchemy.sql import intersect_all as intersect_all
|
|
50
58
|
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
59
|
from sqlalchemy.sql import lambda_stmt as lambda_stmt
|
|
60
60
|
from sqlalchemy.sql import lateral as lateral
|
|
61
61
|
from sqlalchemy.sql import literal as literal
|
|
@@ -85,55 +85,53 @@ from sqlalchemy.sql import values as values
|
|
|
85
85
|
from sqlalchemy.sql import within_group as within_group
|
|
86
86
|
from sqlalchemy.types import ARRAY as ARRAY
|
|
87
87
|
from sqlalchemy.types import BIGINT as BIGINT
|
|
88
|
-
from sqlalchemy.types import BigInteger as BigInteger
|
|
89
88
|
from sqlalchemy.types import BINARY as BINARY
|
|
90
89
|
from sqlalchemy.types import BLOB as BLOB
|
|
91
90
|
from sqlalchemy.types import BOOLEAN as BOOLEAN
|
|
92
|
-
from sqlalchemy.types import Boolean as Boolean
|
|
93
91
|
from sqlalchemy.types import CHAR as CHAR
|
|
94
92
|
from sqlalchemy.types import CLOB as CLOB
|
|
95
93
|
from sqlalchemy.types import DATE as DATE
|
|
96
|
-
from sqlalchemy.types import Date as Date
|
|
97
94
|
from sqlalchemy.types import DATETIME as DATETIME
|
|
98
|
-
from sqlalchemy.types import DateTime as DateTime
|
|
99
95
|
from sqlalchemy.types import DECIMAL as DECIMAL
|
|
100
|
-
from sqlalchemy.types import Enum as Enum
|
|
101
96
|
from sqlalchemy.types import FLOAT as FLOAT
|
|
102
|
-
from sqlalchemy.types import Float as Float
|
|
103
97
|
from sqlalchemy.types import INT as INT
|
|
104
98
|
from sqlalchemy.types import INTEGER as INTEGER
|
|
105
|
-
from sqlalchemy.types import Integer as Integer
|
|
106
|
-
from sqlalchemy.types import Interval as Interval
|
|
107
99
|
from sqlalchemy.types import JSON as JSON
|
|
108
|
-
from sqlalchemy.types import LargeBinary as LargeBinary
|
|
109
100
|
from sqlalchemy.types import NCHAR as NCHAR
|
|
110
101
|
from sqlalchemy.types import NUMERIC as NUMERIC
|
|
111
|
-
from sqlalchemy.types import Numeric as Numeric
|
|
112
102
|
from sqlalchemy.types import NVARCHAR as NVARCHAR
|
|
113
|
-
from sqlalchemy.types import PickleType as PickleType
|
|
114
103
|
from sqlalchemy.types import REAL as REAL
|
|
115
104
|
from sqlalchemy.types import SMALLINT as SMALLINT
|
|
105
|
+
from sqlalchemy.types import TEXT as TEXT
|
|
106
|
+
from sqlalchemy.types import TIME as TIME
|
|
107
|
+
from sqlalchemy.types import TIMESTAMP as TIMESTAMP
|
|
108
|
+
from sqlalchemy.types import VARBINARY as VARBINARY
|
|
109
|
+
from sqlalchemy.types import VARCHAR as VARCHAR
|
|
110
|
+
from sqlalchemy.types import BigInteger as BigInteger
|
|
111
|
+
from sqlalchemy.types import Boolean as Boolean
|
|
112
|
+
from sqlalchemy.types import Date as Date
|
|
113
|
+
from sqlalchemy.types import DateTime as DateTime
|
|
114
|
+
from sqlalchemy.types import Enum as Enum
|
|
115
|
+
from sqlalchemy.types import Float as Float
|
|
116
|
+
from sqlalchemy.types import Integer as Integer
|
|
117
|
+
from sqlalchemy.types import Interval as Interval
|
|
118
|
+
from sqlalchemy.types import LargeBinary as LargeBinary
|
|
119
|
+
from sqlalchemy.types import Numeric as Numeric
|
|
120
|
+
from sqlalchemy.types import PickleType as PickleType
|
|
116
121
|
from sqlalchemy.types import SmallInteger as SmallInteger
|
|
117
122
|
from sqlalchemy.types import String as String
|
|
118
|
-
from sqlalchemy.types import TEXT as TEXT
|
|
119
123
|
from sqlalchemy.types import Text as Text
|
|
120
|
-
from sqlalchemy.types import TIME as TIME
|
|
121
124
|
from sqlalchemy.types import Time as Time
|
|
122
|
-
from sqlalchemy.types import TIMESTAMP as TIMESTAMP
|
|
123
125
|
from sqlalchemy.types import TypeDecorator as TypeDecorator
|
|
124
126
|
from sqlalchemy.types import Unicode as Unicode
|
|
125
127
|
from sqlalchemy.types import UnicodeText as UnicodeText
|
|
126
|
-
from sqlalchemy.types import VARBINARY as VARBINARY
|
|
127
|
-
from sqlalchemy.types import VARCHAR as VARCHAR
|
|
128
128
|
|
|
129
|
-
#
|
|
129
|
+
# From SQLModel, modifications of SQLAlchemy or equivalents of Pydantic
|
|
130
130
|
from .engine.create import create_engine as create_engine
|
|
131
|
+
from .main import Field as Field
|
|
132
|
+
from .main import Relationship as Relationship
|
|
133
|
+
from .main import SQLModel as SQLModel
|
|
131
134
|
from .orm.session import Session as Session
|
|
132
|
-
from .sql.expression import select as select
|
|
133
135
|
from .sql.expression import col as col
|
|
136
|
+
from .sql.expression import select as select
|
|
134
137
|
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
|
|
@@ -6,7 +6,7 @@ class _DefaultPlaceholder:
|
|
|
6
6
|
You shouldn't use this class directly.
|
|
7
7
|
|
|
8
8
|
It's used internally to recognize when a default value has been overwritten, even
|
|
9
|
-
if the
|
|
9
|
+
if the overridden default value was truthy.
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
12
|
def __init__(self, value: Any):
|
|
@@ -27,6 +27,6 @@ def Default(value: _TDefaultType) -> _TDefaultType:
|
|
|
27
27
|
You shouldn't use this function directly.
|
|
28
28
|
|
|
29
29
|
It's used internally to recognize when a default value has been overwritten, even
|
|
30
|
-
if the
|
|
30
|
+
if the overridden default value was truthy.
|
|
31
31
|
"""
|
|
32
32
|
return _DefaultPlaceholder(value) # type: ignore
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
from typing import Any, Mapping, Optional, Sequence, TypeVar, Union
|
|
1
|
+
from typing import Any, Mapping, Optional, Sequence, TypeVar, Union, overload
|
|
2
2
|
|
|
3
3
|
from sqlalchemy import util
|
|
4
4
|
from sqlalchemy.ext.asyncio import AsyncSession as _AsyncSession
|
|
5
5
|
from sqlalchemy.ext.asyncio import engine
|
|
6
6
|
from sqlalchemy.ext.asyncio.engine import AsyncConnection, AsyncEngine
|
|
7
7
|
from sqlalchemy.util.concurrency import greenlet_spawn
|
|
8
|
-
from sqlmodel.sql.base import Executable
|
|
9
8
|
|
|
10
|
-
from ...engine.result import ScalarResult
|
|
9
|
+
from ...engine.result import Result, ScalarResult
|
|
11
10
|
from ...orm.session import Session
|
|
12
|
-
from ...sql.
|
|
11
|
+
from ...sql.base import Executable
|
|
12
|
+
from ...sql.expression import Select, SelectOfScalar
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
_TSelectParam = TypeVar("_TSelectParam")
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class AsyncSession(_AsyncSession):
|
|
@@ -40,14 +40,46 @@ class AsyncSession(_AsyncSession):
|
|
|
40
40
|
Session(bind=bind, binds=binds, **kw) # type: ignore
|
|
41
41
|
)
|
|
42
42
|
|
|
43
|
+
@overload
|
|
43
44
|
async def exec(
|
|
44
45
|
self,
|
|
45
|
-
statement:
|
|
46
|
+
statement: Select[_TSelectParam],
|
|
47
|
+
*,
|
|
48
|
+
params: Optional[Union[Mapping[str, Any], Sequence[Mapping[str, Any]]]] = None,
|
|
49
|
+
execution_options: Mapping[str, Any] = util.EMPTY_DICT,
|
|
50
|
+
bind_arguments: Optional[Mapping[str, Any]] = None,
|
|
51
|
+
_parent_execute_state: Optional[Any] = None,
|
|
52
|
+
_add_event: Optional[Any] = None,
|
|
53
|
+
**kw: Any,
|
|
54
|
+
) -> Result[_TSelectParam]:
|
|
55
|
+
...
|
|
56
|
+
|
|
57
|
+
@overload
|
|
58
|
+
async def exec(
|
|
59
|
+
self,
|
|
60
|
+
statement: SelectOfScalar[_TSelectParam],
|
|
61
|
+
*,
|
|
62
|
+
params: Optional[Union[Mapping[str, Any], Sequence[Mapping[str, Any]]]] = None,
|
|
63
|
+
execution_options: Mapping[str, Any] = util.EMPTY_DICT,
|
|
64
|
+
bind_arguments: Optional[Mapping[str, Any]] = None,
|
|
65
|
+
_parent_execute_state: Optional[Any] = None,
|
|
66
|
+
_add_event: Optional[Any] = None,
|
|
67
|
+
**kw: Any,
|
|
68
|
+
) -> ScalarResult[_TSelectParam]:
|
|
69
|
+
...
|
|
70
|
+
|
|
71
|
+
async def exec(
|
|
72
|
+
self,
|
|
73
|
+
statement: Union[
|
|
74
|
+
Select[_TSelectParam],
|
|
75
|
+
SelectOfScalar[_TSelectParam],
|
|
76
|
+
Executable[_TSelectParam],
|
|
77
|
+
],
|
|
46
78
|
params: Optional[Union[Mapping[str, Any], Sequence[Mapping[str, Any]]]] = None,
|
|
47
79
|
execution_options: Mapping[Any, Any] = util.EMPTY_DICT,
|
|
48
80
|
bind_arguments: Optional[Mapping[str, Any]] = None,
|
|
49
81
|
**kw: Any,
|
|
50
|
-
) -> ScalarResult[
|
|
82
|
+
) -> Union[Result[_TSelectParam], ScalarResult[_TSelectParam]]:
|
|
51
83
|
# TODO: the documentation says execution_options accepts a dict, but only
|
|
52
84
|
# util.immutabledict has the union() method. Is this a bug in SQLAlchemy?
|
|
53
85
|
execution_options = execution_options.union({"prebuffer_rows": True}) # type: ignore
|
|
@@ -11,6 +11,7 @@ from typing import (
|
|
|
11
11
|
Callable,
|
|
12
12
|
ClassVar,
|
|
13
13
|
Dict,
|
|
14
|
+
ForwardRef,
|
|
14
15
|
List,
|
|
15
16
|
Mapping,
|
|
16
17
|
Optional,
|
|
@@ -25,15 +26,24 @@ from typing import (
|
|
|
25
26
|
|
|
26
27
|
from pydantic import BaseConfig, BaseModel
|
|
27
28
|
from pydantic.errors import ConfigError, DictError
|
|
28
|
-
from pydantic.fields import SHAPE_SINGLETON
|
|
29
|
+
from pydantic.fields import SHAPE_SINGLETON, ModelField, Undefined, UndefinedType
|
|
29
30
|
from pydantic.fields import FieldInfo as PydanticFieldInfo
|
|
30
|
-
from pydantic.fields import ModelField, Undefined, UndefinedType
|
|
31
31
|
from pydantic.main import ModelMetaclass, validate_model
|
|
32
|
-
from pydantic.typing import
|
|
32
|
+
from pydantic.typing import NoArgAnyCallable, resolve_annotations
|
|
33
33
|
from pydantic.utils import ROOT_KEY, Representation
|
|
34
|
-
from sqlalchemy import
|
|
34
|
+
from sqlalchemy import (
|
|
35
|
+
Boolean,
|
|
36
|
+
Column,
|
|
37
|
+
Date,
|
|
38
|
+
DateTime,
|
|
39
|
+
Float,
|
|
40
|
+
ForeignKey,
|
|
41
|
+
Integer,
|
|
42
|
+
Interval,
|
|
43
|
+
Numeric,
|
|
44
|
+
inspect,
|
|
45
|
+
)
|
|
35
46
|
from sqlalchemy import Enum as sa_Enum
|
|
36
|
-
from sqlalchemy import Float, ForeignKey, Integer, Interval, Numeric, inspect
|
|
37
47
|
from sqlalchemy.orm import RelationshipProperty, declared_attr, registry, relationship
|
|
38
48
|
from sqlalchemy.orm.attributes import set_attribute
|
|
39
49
|
from sqlalchemy.orm.decl_api import DeclarativeMeta
|
|
@@ -135,12 +145,17 @@ def Field(
|
|
|
135
145
|
lt: Optional[float] = None,
|
|
136
146
|
le: Optional[float] = None,
|
|
137
147
|
multiple_of: Optional[float] = None,
|
|
148
|
+
max_digits: Optional[int] = None,
|
|
149
|
+
decimal_places: Optional[int] = None,
|
|
138
150
|
min_items: Optional[int] = None,
|
|
139
151
|
max_items: Optional[int] = None,
|
|
152
|
+
unique_items: Optional[bool] = None,
|
|
140
153
|
min_length: Optional[int] = None,
|
|
141
154
|
max_length: Optional[int] = None,
|
|
142
155
|
allow_mutation: bool = True,
|
|
143
156
|
regex: Optional[str] = None,
|
|
157
|
+
discriminator: Optional[str] = None,
|
|
158
|
+
repr: bool = True,
|
|
144
159
|
primary_key: bool = False,
|
|
145
160
|
foreign_key: Optional[Any] = None,
|
|
146
161
|
unique: bool = False,
|
|
@@ -166,12 +181,17 @@ def Field(
|
|
|
166
181
|
lt=lt,
|
|
167
182
|
le=le,
|
|
168
183
|
multiple_of=multiple_of,
|
|
184
|
+
max_digits=max_digits,
|
|
185
|
+
decimal_places=decimal_places,
|
|
169
186
|
min_items=min_items,
|
|
170
187
|
max_items=max_items,
|
|
188
|
+
unique_items=unique_items,
|
|
171
189
|
min_length=min_length,
|
|
172
190
|
max_length=max_length,
|
|
173
191
|
allow_mutation=allow_mutation,
|
|
174
192
|
regex=regex,
|
|
193
|
+
discriminator=discriminator,
|
|
194
|
+
repr=repr,
|
|
175
195
|
primary_key=primary_key,
|
|
176
196
|
foreign_key=foreign_key,
|
|
177
197
|
unique=unique,
|
|
@@ -304,9 +324,9 @@ class SQLModelMetaclass(ModelMetaclass, DeclarativeMeta):
|
|
|
304
324
|
config_registry = cast(registry, config_registry)
|
|
305
325
|
# If it was passed by kwargs, ensure it's also set in config
|
|
306
326
|
new_cls.__config__.registry = config_table
|
|
307
|
-
setattr(new_cls, "_sa_registry", config_registry)
|
|
308
|
-
setattr(new_cls, "metadata", config_registry.metadata)
|
|
309
|
-
setattr(new_cls, "__abstract__", True)
|
|
327
|
+
setattr(new_cls, "_sa_registry", config_registry) # noqa: B010
|
|
328
|
+
setattr(new_cls, "metadata", config_registry.metadata) # noqa: B010
|
|
329
|
+
setattr(new_cls, "__abstract__", True) # noqa: B010
|
|
310
330
|
return new_cls
|
|
311
331
|
|
|
312
332
|
# Override SQLAlchemy, allow both SQLAlchemy and plain Pydantic models
|
|
@@ -319,19 +339,16 @@ class SQLModelMetaclass(ModelMetaclass, DeclarativeMeta):
|
|
|
319
339
|
# triggers an error
|
|
320
340
|
base_is_table = False
|
|
321
341
|
for base in bases:
|
|
322
|
-
config = getattr(base, "__config__")
|
|
342
|
+
config = getattr(base, "__config__") # noqa: B009
|
|
323
343
|
if config and getattr(config, "table", False):
|
|
324
344
|
base_is_table = True
|
|
325
345
|
break
|
|
326
346
|
if getattr(cls.__config__, "table", False) and not base_is_table:
|
|
327
|
-
dict_used = dict_.copy()
|
|
328
|
-
for field_name, field_value in cls.__fields__.items():
|
|
329
|
-
dict_used[field_name] = get_column_from_field(field_value)
|
|
330
347
|
for rel_name, rel_info in cls.__sqlmodel_relationships__.items():
|
|
331
348
|
if rel_info.sa_relationship:
|
|
332
349
|
# There's a SQLAlchemy relationship declared, that takes precedence
|
|
333
350
|
# over anything else, use that and continue with the next attribute
|
|
334
|
-
|
|
351
|
+
setattr(cls, rel_name, rel_info.sa_relationship) # Fix #315
|
|
335
352
|
continue
|
|
336
353
|
ann = cls.__annotations__[rel_name]
|
|
337
354
|
temp_field = ModelField.infer(
|
|
@@ -349,7 +366,7 @@ class SQLModelMetaclass(ModelMetaclass, DeclarativeMeta):
|
|
|
349
366
|
rel_kwargs["back_populates"] = rel_info.back_populates
|
|
350
367
|
if rel_info.link_model:
|
|
351
368
|
ins = inspect(rel_info.link_model)
|
|
352
|
-
local_table = getattr(ins, "local_table")
|
|
369
|
+
local_table = getattr(ins, "local_table") # noqa: B009
|
|
353
370
|
if local_table is None:
|
|
354
371
|
raise RuntimeError(
|
|
355
372
|
"Couldn't find the secondary table for "
|
|
@@ -364,53 +381,57 @@ class SQLModelMetaclass(ModelMetaclass, DeclarativeMeta):
|
|
|
364
381
|
rel_value: RelationshipProperty = relationship( # type: ignore
|
|
365
382
|
relationship_to, *rel_args, **rel_kwargs
|
|
366
383
|
)
|
|
367
|
-
dict_used[rel_name] = rel_value
|
|
368
384
|
setattr(cls, rel_name, rel_value) # Fix #315
|
|
369
|
-
|
|
385
|
+
# SQLAlchemy no longer uses dict_
|
|
386
|
+
# Ref: https://github.com/sqlalchemy/sqlalchemy/commit/428ea01f00a9cc7f85e435018565eb6da7af1b77
|
|
387
|
+
# Tag: 1.4.36
|
|
388
|
+
DeclarativeMeta.__init__(cls, classname, bases, dict_, **kw)
|
|
370
389
|
else:
|
|
371
390
|
ModelMetaclass.__init__(cls, classname, bases, dict_, **kw)
|
|
372
391
|
|
|
373
392
|
|
|
374
|
-
def
|
|
375
|
-
if
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
393
|
+
def get_sqlalchemy_type(field: ModelField) -> Any:
|
|
394
|
+
if isinstance(field.type_, type) and field.shape == SHAPE_SINGLETON:
|
|
395
|
+
# Check enums first as an enum can also be a str, needed by Pydantic/FastAPI
|
|
396
|
+
if issubclass(field.type_, Enum):
|
|
397
|
+
return sa_Enum(field.type_)
|
|
398
|
+
if issubclass(field.type_, str):
|
|
399
|
+
if field.field_info.max_length:
|
|
400
|
+
return AutoString(length=field.field_info.max_length)
|
|
401
|
+
return AutoString
|
|
402
|
+
if issubclass(field.type_, float):
|
|
403
|
+
return Float
|
|
404
|
+
if issubclass(field.type_, bool):
|
|
405
|
+
return Boolean
|
|
406
|
+
if issubclass(field.type_, int):
|
|
407
|
+
return Integer
|
|
408
|
+
if issubclass(field.type_, datetime):
|
|
409
|
+
return DateTime
|
|
410
|
+
if issubclass(field.type_, date):
|
|
411
|
+
return Date
|
|
412
|
+
if issubclass(field.type_, timedelta):
|
|
413
|
+
return Interval
|
|
414
|
+
if issubclass(field.type_, time):
|
|
415
|
+
return Time
|
|
416
|
+
if issubclass(field.type_, bytes):
|
|
417
|
+
return LargeBinary
|
|
418
|
+
if issubclass(field.type_, Decimal):
|
|
419
|
+
return Numeric(
|
|
420
|
+
precision=getattr(field.type_, "max_digits", None),
|
|
421
|
+
scale=getattr(field.type_, "decimal_places", None),
|
|
422
|
+
)
|
|
423
|
+
if issubclass(field.type_, ipaddress.IPv4Address):
|
|
424
|
+
return AutoString
|
|
425
|
+
if issubclass(field.type_, ipaddress.IPv4Network):
|
|
426
|
+
return AutoString
|
|
427
|
+
if issubclass(field.type_, ipaddress.IPv6Address):
|
|
428
|
+
return AutoString
|
|
429
|
+
if issubclass(field.type_, ipaddress.IPv6Network):
|
|
430
|
+
return AutoString
|
|
431
|
+
if issubclass(field.type_, Path):
|
|
432
|
+
return AutoString
|
|
433
|
+
if issubclass(field.type_, uuid.UUID):
|
|
434
|
+
return GUID
|
|
414
435
|
raise ValueError(f"The field {field.name} has no matching SQLAlchemy type")
|
|
415
436
|
|
|
416
437
|
|
|
@@ -418,7 +439,7 @@ def get_column_from_field(field: ModelField) -> Column: # type: ignore
|
|
|
418
439
|
sa_column = getattr(field.field_info, "sa_column", Undefined)
|
|
419
440
|
if isinstance(sa_column, Column):
|
|
420
441
|
return sa_column
|
|
421
|
-
sa_type =
|
|
442
|
+
sa_type = get_sqlalchemy_type(field)
|
|
422
443
|
primary_key = getattr(field.field_info, "primary_key", False)
|
|
423
444
|
index = getattr(field.field_info, "index", Undefined)
|
|
424
445
|
if index is Undefined:
|
|
@@ -427,7 +448,7 @@ def get_column_from_field(field: ModelField) -> Column: # type: ignore
|
|
|
427
448
|
# Override derived nullability if the nullable property is set explicitly
|
|
428
449
|
# on the field
|
|
429
450
|
if hasattr(field.field_info, "nullable"):
|
|
430
|
-
field_nullable = getattr(field.field_info, "nullable")
|
|
451
|
+
field_nullable = getattr(field.field_info, "nullable") # noqa: B009
|
|
431
452
|
if field_nullable != Undefined:
|
|
432
453
|
nullable = field_nullable
|
|
433
454
|
args = []
|
|
@@ -576,7 +597,11 @@ class SQLModel(BaseModel, metaclass=SQLModelMetaclass, registry=default_registry
|
|
|
576
597
|
|
|
577
598
|
def __repr_args__(self) -> Sequence[Tuple[Optional[str], Any]]:
|
|
578
599
|
# Don't show SQLAlchemy private attributes
|
|
579
|
-
return [
|
|
600
|
+
return [
|
|
601
|
+
(k, v)
|
|
602
|
+
for k, v in super().__repr_args__()
|
|
603
|
+
if not (isinstance(k, str) and k.startswith("_sa_"))
|
|
604
|
+
]
|
|
580
605
|
|
|
581
606
|
# From Pydantic, override to enforce validation with dict
|
|
582
607
|
@classmethod
|
|
@@ -4,11 +4,11 @@ from sqlalchemy import util
|
|
|
4
4
|
from sqlalchemy.orm import Query as _Query
|
|
5
5
|
from sqlalchemy.orm import Session as _Session
|
|
6
6
|
from sqlalchemy.sql.base import Executable as _Executable
|
|
7
|
-
from sqlmodel.sql.expression import Select, SelectOfScalar
|
|
8
7
|
from typing_extensions import Literal
|
|
9
8
|
|
|
10
9
|
from ..engine.result import Result, ScalarResult
|
|
11
10
|
from ..sql.base import Executable
|
|
11
|
+
from ..sql.expression import Select, SelectOfScalar
|
|
12
12
|
|
|
13
13
|
_TSelectParam = TypeVar("_TSelectParam")
|
|
14
14
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# WARNING: do not modify this code, it is generated by expression.py.jinja2
|
|
2
2
|
|
|
3
|
-
import sys
|
|
4
3
|
from datetime import datetime
|
|
5
4
|
from typing import (
|
|
6
5
|
TYPE_CHECKING,
|
|
@@ -12,7 +11,6 @@ from typing import (
|
|
|
12
11
|
Type,
|
|
13
12
|
TypeVar,
|
|
14
13
|
Union,
|
|
15
|
-
cast,
|
|
16
14
|
overload,
|
|
17
15
|
)
|
|
18
16
|
from uuid import UUID
|
|
@@ -24,36 +22,17 @@ from sqlalchemy.sql.expression import Select as _Select
|
|
|
24
22
|
|
|
25
23
|
_TSelect = TypeVar("_TSelect")
|
|
26
24
|
|
|
27
|
-
# Workaround Generics incompatibility in Python 3.6
|
|
28
|
-
# Ref: https://github.com/python/typing/issues/449#issuecomment-316061322
|
|
29
|
-
if sys.version_info.minor >= 7:
|
|
30
25
|
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
class Select(_Select, Generic[_TSelect]):
|
|
27
|
+
inherit_cache = True
|
|
33
28
|
|
|
34
|
-
# This is not comparable to sqlalchemy.sql.selectable.ScalarSelect, that has a different
|
|
35
|
-
# purpose. This is the same as a normal SQLAlchemy Select class where there's only one
|
|
36
|
-
# entity, so the result will be converted to a scalar by default. This way writing
|
|
37
|
-
# for loops on the results will feel natural.
|
|
38
|
-
class SelectOfScalar(_Select, Generic[_TSelect]):
|
|
39
|
-
inherit_cache = True
|
|
40
29
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
class _Py36Select(_Select, Generic[_TSelect], metaclass=GenericSelectMeta):
|
|
48
|
-
inherit_cache = True
|
|
49
|
-
|
|
50
|
-
class _Py36SelectOfScalar(_Select, Generic[_TSelect], metaclass=GenericSelectMeta):
|
|
51
|
-
inherit_cache = True
|
|
52
|
-
|
|
53
|
-
# Cast them for editors to work correctly, from several tricks tried, this works
|
|
54
|
-
# for both VS Code and PyCharm
|
|
55
|
-
Select = cast("Select", _Py36Select) # type: ignore
|
|
56
|
-
SelectOfScalar = cast("SelectOfScalar", _Py36SelectOfScalar) # type: ignore
|
|
30
|
+
# This is not comparable to sqlalchemy.sql.selectable.ScalarSelect, that has a different
|
|
31
|
+
# purpose. This is the same as a normal SQLAlchemy Select class where there's only one
|
|
32
|
+
# entity, so the result will be converted to a scalar by default. This way writing
|
|
33
|
+
# for loops on the results will feel natural.
|
|
34
|
+
class SelectOfScalar(_Select, Generic[_TSelect]):
|
|
35
|
+
inherit_cache = True
|
|
57
36
|
|
|
58
37
|
|
|
59
38
|
if TYPE_CHECKING: # pragma: no cover
|
sqlmodel-0.0.8/setup.py
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
from setuptools import setup
|
|
3
|
-
|
|
4
|
-
packages = \
|
|
5
|
-
['sqlmodel',
|
|
6
|
-
'sqlmodel.engine',
|
|
7
|
-
'sqlmodel.ext',
|
|
8
|
-
'sqlmodel.ext.asyncio',
|
|
9
|
-
'sqlmodel.orm',
|
|
10
|
-
'sqlmodel.pool',
|
|
11
|
-
'sqlmodel.sql']
|
|
12
|
-
|
|
13
|
-
package_data = \
|
|
14
|
-
{'': ['*']}
|
|
15
|
-
|
|
16
|
-
install_requires = \
|
|
17
|
-
['SQLAlchemy>=1.4.17,<=1.4.41', 'pydantic>=1.8.2,<2.0.0', 'sqlalchemy2-stubs']
|
|
18
|
-
|
|
19
|
-
setup_kwargs = {
|
|
20
|
-
'name': 'sqlmodel',
|
|
21
|
-
'version': '0.0.8',
|
|
22
|
-
'description': 'SQLModel, SQL databases in Python, designed for simplicity, compatibility, and robustness.',
|
|
23
|
-
'long_description': '<p align="center">\n <a href="https://sqlmodel.tiangolo.com"><img src="https://sqlmodel.tiangolo.com/img/logo-margin/logo-margin-vector.svg" alt="SQLModel"></a>\n</p>\n<p align="center">\n <em>SQLModel, SQL databases in Python, designed for simplicity, compatibility, and robustness.</em>\n</p>\n<p align="center">\n<a href="https://github.com/tiangolo/sqlmodel/actions?query=workflow%3ATest" target="_blank">\n <img src="https://github.com/tiangolo/sqlmodel/workflows/Test/badge.svg" alt="Test">\n</a>\n<a href="https://github.com/tiangolo/sqlmodel/actions?query=workflow%3APublish" target="_blank">\n <img src="https://github.com/tiangolo/sqlmodel/workflows/Publish/badge.svg" alt="Publish">\n</a>\n<a href="https://codecov.io/gh/tiangolo/sqlmodel" target="_blank">\n <img src="https://img.shields.io/codecov/c/github/tiangolo/sqlmodel?color=%2334D058" alt="Coverage">\n</a>\n<a href="https://pypi.org/project/sqlmodel" target="_blank">\n <img src="https://img.shields.io/pypi/v/sqlmodel?color=%2334D058&label=pypi%20package" alt="Package version">\n</a>\n</p>\n\n---\n\n**Documentation**: <a href="https://sqlmodel.tiangolo.com" target="_blank">https://sqlmodel.tiangolo.com</a>\n\n**Source Code**: <a href="https://github.com/tiangolo/sqlmodel" target="_blank">https://github.com/tiangolo/sqlmodel</a>\n\n---\n\nSQLModel is a library for interacting with <abbr title=\'Also called "Relational databases"\'>SQL databases</abbr> from Python code, with Python objects. It is designed to be intuitive, easy to use, highly compatible, and robust.\n\n**SQLModel** is based on Python type annotations, and powered by <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> and <a href="https://sqlalchemy.org/" class="external-link" target="_blank">SQLAlchemy</a>.\n\nThe key features are:\n\n* **Intuitive to write**: Great editor support. <abbr title="also known as auto-complete, autocompletion, IntelliSense">Completion</abbr> everywhere. Less time debugging. Designed to be easy to use and learn. Less time reading docs.\n* **Easy to use**: It has sensible defaults and does a lot of work underneath to simplify the code you write.\n* **Compatible**: It is designed to be compatible with **FastAPI**, Pydantic, and SQLAlchemy.\n* **Extensible**: You have all the power of SQLAlchemy and Pydantic underneath.\n* **Short**: Minimize code duplication. A single type annotation does a lot of work. No need to duplicate models in SQLAlchemy and Pydantic.\n\n## SQL Databases in FastAPI\n\n<a href="https://fastapi.tiangolo.com" target="_blank"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" style="width: 20%;"></a>\n\n**SQLModel** is designed to simplify interacting with SQL databases in <a href="https://fastapi.tiangolo.com" class="external-link" target="_blank">FastAPI</a> applications, it was created by the same <a href="https://tiangolo.com/" class="external-link" target="_blank">author</a>. 😁\n\nIt combines SQLAlchemy and Pydantic and tries to simplify the code you write as much as possible, allowing you to reduce the **code duplication to a minimum**, but while getting the **best developer experience** possible.\n\n**SQLModel** is, in fact, a thin layer on top of **Pydantic** and **SQLAlchemy**, carefully designed to be compatible with both.\n\n## Requirements\n\nA recent and currently supported version of Python (right now, <a href="https://www.python.org/downloads/" class="external-link" target="_blank">Python supports versions 3.6 and above</a>).\n\nAs **SQLModel** is based on **Pydantic** and **SQLAlchemy**, it requires them. They will be automatically installed when you install SQLModel.\n\n## Installation\n\n<div class="termy">\n\n```console\n$ pip install sqlmodel\n---> 100%\nSuccessfully installed sqlmodel\n```\n\n</div>\n\n## Example\n\nFor an introduction to databases, SQL, and everything else, see the <a href="https://sqlmodel.tiangolo.com" target="_blank">SQLModel documentation</a>.\n\nHere\'s a quick example. ✨\n\n### A SQL Table\n\nImagine you have a SQL table called `hero` with:\n\n* `id`\n* `name`\n* `secret_name`\n* `age`\n\nAnd you want it to have this data:\n\n| id | name | secret_name | age |\n-----|------|-------------|------|\n| 1 | Deadpond | Dive Wilson | null |\n| 2 | Spider-Boy | Pedro Parqueador | null |\n| 3 | Rusty-Man | Tommy Sharp | 48 |\n\n### Create a SQLModel Model\n\nThen you could create a **SQLModel** model like this:\n\n```Python\nfrom typing import Optional\n\nfrom sqlmodel import Field, SQLModel\n\n\nclass Hero(SQLModel, table=True):\n id: Optional[int] = Field(default=None, primary_key=True)\n name: str\n secret_name: str\n age: Optional[int] = None\n```\n\nThat class `Hero` is a **SQLModel** model, the equivalent of a SQL table in Python code.\n\nAnd each of those class attributes is equivalent to each **table column**.\n\n### Create Rows\n\nThen you could **create each row** of the table as an **instance** of the model:\n\n```Python\nhero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")\nhero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")\nhero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)\n```\n\nThis way, you can use conventional Python code with **classes** and **instances** that represent **tables** and **rows**, and that way communicate with the **SQL database**.\n\n### Editor Support\n\nEverything is designed for you to get the best developer experience possible, with the best editor support.\n\nIncluding **autocompletion**:\n\n<img class="shadow" src="https://sqlmodel.tiangolo.com/img/index/autocompletion01.png">\n\nAnd **inline errors**:\n\n<img class="shadow" src="https://sqlmodel.tiangolo.com/img/index/inline-errors01.png">\n\n### Write to the Database\n\nYou can learn a lot more about **SQLModel** by quickly following the **tutorial**, but if you need a taste right now of how to put all that together and save to the database, you can do this:\n\n```Python hl_lines="18 21 23-27"\nfrom typing import Optional\n\nfrom sqlmodel import Field, Session, SQLModel, create_engine\n\n\nclass Hero(SQLModel, table=True):\n id: Optional[int] = Field(default=None, primary_key=True)\n name: str\n secret_name: str\n age: Optional[int] = None\n\n\nhero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")\nhero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")\nhero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)\n\n\nengine = create_engine("sqlite:///database.db")\n\n\nSQLModel.metadata.create_all(engine)\n\nwith Session(engine) as session:\n session.add(hero_1)\n session.add(hero_2)\n session.add(hero_3)\n session.commit()\n```\n\nThat will save a **SQLite** database with the 3 heroes.\n\n### Select from the Database\n\nThen you could write queries to select from that same database, for example with:\n\n```Python hl_lines="15-18"\nfrom typing import Optional\n\nfrom sqlmodel import Field, Session, SQLModel, create_engine, select\n\n\nclass Hero(SQLModel, table=True):\n id: Optional[int] = Field(default=None, primary_key=True)\n name: str\n secret_name: str\n age: Optional[int] = None\n\n\nengine = create_engine("sqlite:///database.db")\n\nwith Session(engine) as session:\n statement = select(Hero).where(Hero.name == "Spider-Boy")\n hero = session.exec(statement).first()\n print(hero)\n```\n\n### Editor Support Everywhere\n\n**SQLModel** was carefully designed to give you the best developer experience and editor support, **even after selecting data** from the database:\n\n<img class="shadow" src="https://sqlmodel.tiangolo.com/img/index/autocompletion02.png">\n\n## SQLAlchemy and Pydantic\n\nThat class `Hero` is a **SQLModel** model.\n\nBut at the same time, ✨ it is a **SQLAlchemy** model ✨. So, you can combine it and use it with other SQLAlchemy models, or you could easily migrate applications with SQLAlchemy to **SQLModel**.\n\nAnd at the same time, ✨ it is also a **Pydantic** model ✨. You can use inheritance with it to define all your **data models** while avoiding code duplication. That makes it very easy to use with **FastAPI**.\n\n## License\n\nThis project is licensed under the terms of the [MIT license](https://github.com/tiangolo/sqlmodel/blob/main/LICENSE).\n',
|
|
24
|
-
'author': 'Sebastián Ramírez',
|
|
25
|
-
'author_email': 'tiangolo@gmail.com',
|
|
26
|
-
'maintainer': 'None',
|
|
27
|
-
'maintainer_email': 'None',
|
|
28
|
-
'url': 'https://github.com/tiangolo/sqlmodel',
|
|
29
|
-
'packages': packages,
|
|
30
|
-
'package_data': package_data,
|
|
31
|
-
'install_requires': install_requires,
|
|
32
|
-
'python_requires': '>=3.6.1,<4.0.0',
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
setup(**setup_kwargs)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|