Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix GH Actions by removing broken poetry-version-plugin and dropping python 3.6 support #602

Closed
wants to merge 11 commits into from
7 changes: 1 addition & 6 deletions .github/workflows/build-docs.yml
Expand Up @@ -37,14 +37,9 @@ jobs:
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-root-docs
- name: Install poetry
if: steps.cache.outputs.cache-hit != 'true'
# TODO: remove python -m pip install --force git+https://github.com/python-poetry/poetry-core.git@ad33bc2
# once there's a release of Poetry 1.2.x including poetry-core > 1.1.0a6
# Ref: https://github.com/python-poetry/poetry-core/pull/188
run: |
python -m pip install --upgrade pip
python -m pip install --force git+https://github.com/python-poetry/poetry-core.git@ad33bc2
python -m pip install "poetry==1.2.0a2"
python -m poetry plugin add poetry-version-plugin
python -m pip install "poetry==1.5.1"
- name: Configure poetry
run: python -m poetry config virtualenvs.create false
- name: Install Dependencies
Expand Down
4 changes: 1 addition & 3 deletions .github/workflows/publish.yml
Expand Up @@ -38,9 +38,7 @@ jobs:
# Ref: https://github.com/python-poetry/poetry-core/pull/188
run: |
python -m pip install --upgrade pip
python -m pip install --force git+https://github.com/python-poetry/poetry-core.git@ad33bc2
python -m pip install "poetry==1.2.0a2"
python -m poetry plugin add poetry-version-plugin
python -m pip install "poetry==1.5.1"
- name: Configure poetry
run: python -m poetry config virtualenvs.create false
- name: Install Dependencies
Expand Down
7 changes: 2 additions & 5 deletions .github/workflows/test.yml
Expand Up @@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-20.04
strategy:
matrix:
python-version: ["3.6.15", "3.7", "3.8", "3.9", "3.10"]
python-version: ["3.7", "3.8", "3.9", "3.10"]
fail-fast: false

steps:
Expand All @@ -45,16 +45,13 @@ jobs:
# Ref: https://github.com/python-poetry/poetry-core/pull/188
run: |
python -m pip install --upgrade pip
python -m pip install --force git+https://github.com/python-poetry/poetry-core.git@ad33bc2
python -m pip install "poetry==1.2.0a2"
python -m poetry plugin add poetry-version-plugin
python -m pip install "poetry==1.5.1"
- name: Configure poetry
run: python -m poetry config virtualenvs.create false
- name: Install Dependencies
if: steps.cache.outputs.cache-hit != 'true'
run: python -m poetry install
- name: Lint
if: ${{ matrix.python-version != '3.6.15' }}
run: python -m poetry run bash scripts/lint.sh
- run: mkdir coverage
- name: Test
Expand Down
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -50,7 +50,7 @@ It combines SQLAlchemy and Pydantic and tries to simplify the code you write as

## Requirements

A 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>).
A 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.7 and above</a>).

As **SQLModel** is based on **Pydantic** and **SQLAlchemy**, it requires them. They will be automatically installed when you install SQLModel.

Expand Down
2 changes: 1 addition & 1 deletion docs/contributing.md
Expand Up @@ -8,7 +8,7 @@ If you already cloned the repository and you know that you need to deep dive in

### Python

SQLModel supports Python 3.6 and above, but for development you should have at least **Python 3.7**.
SQLModel supports Python 3.7 and above, but for development you should have at least **Python 3.7**.

### Poetry

Expand Down
2 changes: 1 addition & 1 deletion docs/features.md
Expand Up @@ -12,7 +12,7 @@ Nevertheless, SQLModel is completely **independent** of FastAPI and can be used

## Just Modern Python

It's all based on standard <abbr title="Python currently supported versions, 3.6 and above.">modern **Python**</abbr> type annotations. No new syntax to learn. Just standard modern Python.
It's all based on standard <abbr title="Python currently supported versions, 3.7 and above.">modern **Python**</abbr> type annotations. No new syntax to learn. Just standard modern Python.

If you need a 2 minute refresher of how to use Python types (even if you don't use SQLModel or FastAPI), check the FastAPI tutorial section: <a href="https://fastapi.tiangolo.com/python-types/" class="external-link" target="_blank">Python types intro</a>.

Expand Down
2 changes: 1 addition & 1 deletion docs/index.md
Expand Up @@ -50,7 +50,7 @@ It combines SQLAlchemy and Pydantic and tries to simplify the code you write as

## Requirements

A 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>).
A 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.7 and above</a>).

As **SQLModel** is based on **Pydantic** and **SQLAlchemy**, it requires them. They will be automatically installed when you install SQLModel.

Expand Down
3 changes: 1 addition & 2 deletions docs/tutorial/index.md
Expand Up @@ -64,7 +64,7 @@ $ cd sqlmodel-tutorial

Make sure you have an officially supported version of Python.

Currently it is **Python 3.6** and above (Python 3.5 was already deprecated).
Currently it is **Python 3.7** and above.

You can check which version you have with:

Expand All @@ -85,7 +85,6 @@ You might want to try with the specific versions, for example with:
* `python3.9`
* `python3.8`
* `python3.7`
* `python3.6`

The code would look like this:

Expand Down
20 changes: 4 additions & 16 deletions pyproject.toml
@@ -1,6 +1,6 @@
[tool.poetry]
name = "sqlmodel"
version = "0"
version = "0.0.8"
description = "SQLModel, SQL databases in Python, designed for simplicity, compatibility, and robustness."
authors = ["Sebastián Ramírez <tiangolo@gmail.com>"]
readme = "README.md"
Expand All @@ -17,7 +17,6 @@ classifiers = [
"Intended Audience :: System Administrators",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
Expand All @@ -30,7 +29,7 @@ classifiers = [
]

[tool.poetry.dependencies]
python = "^3.6.1"
python = "^3.7.0"
SQLAlchemy = ">=1.4.17,<=1.4.41"
pydantic = "^1.8.2"
sqlalchemy2-stubs = {version = "*", allow-prereleases = true}
Expand All @@ -50,23 +49,14 @@ fastapi = "^0.68.1"
requests = "^2.26.0"
autoflake = "^1.4"
isort = "^5.9.3"
async_generator = {version = "*", python = "~3.6"}
async-exit-stack = {version = "*", python = "~3.6"}

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

[tool.poetry-version-plugin]
source = "init"

[tool.coverage.run]
parallel = true
source = [
"docs_src",
"tests",
"sqlmodel"
]
source = ["docs_src", "tests", "sqlmodel"]
context = '${CONTEXT}'

[tool.coverage.report]
Expand All @@ -80,9 +70,7 @@ exclude_lines = [
[tool.isort]
profile = "black"
known_third_party = ["sqlmodel"]
skip_glob = [
"sqlmodel/__init__.py",
]
skip_glob = ["sqlmodel/__init__.py"]


[tool.mypy]
Expand Down
2 changes: 0 additions & 2 deletions scripts/lint.sh
Expand Up @@ -7,5 +7,3 @@ mypy sqlmodel
flake8 sqlmodel tests docs_src
black sqlmodel tests docs_src --check
isort sqlmodel tests docs_src scripts --check-only
# TODO: move this to test.sh after deprecating Python 3.6
CHECK_JINJA=1 python scripts/generate_select.py
2 changes: 2 additions & 0 deletions scripts/test.sh
Expand Up @@ -7,3 +7,5 @@ coverage run -m pytest tests
coverage combine
coverage report --show-missing
coverage html

CHECK_JINJA=1 python scripts/generate_select.py
3 changes: 2 additions & 1 deletion sqlmodel/main.py
Expand Up @@ -11,6 +11,7 @@
Callable,
ClassVar,
Dict,
ForwardRef,
List,
Mapping,
Optional,
Expand All @@ -29,7 +30,7 @@
from pydantic.fields import FieldInfo as PydanticFieldInfo
from pydantic.fields import ModelField, Undefined, UndefinedType
from pydantic.main import ModelMetaclass, validate_model
from pydantic.typing import ForwardRef, NoArgAnyCallable, resolve_annotations
from pydantic.typing import NoArgAnyCallable, resolve_annotations
from pydantic.utils import ROOT_KEY, Representation
from sqlalchemy import Boolean, Column, Date, DateTime
from sqlalchemy import Enum as sa_Enum
Expand Down
37 changes: 8 additions & 29 deletions sqlmodel/sql/expression.py
@@ -1,6 +1,5 @@
# WARNING: do not modify this code, it is generated by expression.py.jinja2

import sys
from datetime import datetime
from typing import (
TYPE_CHECKING,
Expand All @@ -12,7 +11,6 @@
Type,
TypeVar,
Union,
cast,
overload,
)
from uuid import UUID
Expand All @@ -24,36 +22,17 @@

_TSelect = TypeVar("_TSelect")

# Workaround Generics incompatibility in Python 3.6
# Ref: https://github.com/python/typing/issues/449#issuecomment-316061322
if sys.version_info.minor >= 7:

class Select(_Select, Generic[_TSelect]):
inherit_cache = True
class Select(_Select, Generic[_TSelect]):
inherit_cache = True

# This is not comparable to sqlalchemy.sql.selectable.ScalarSelect, that has a different
# purpose. This is the same as a normal SQLAlchemy Select class where there's only one
# entity, so the result will be converted to a scalar by default. This way writing
# for loops on the results will feel natural.
class SelectOfScalar(_Select, Generic[_TSelect]):
inherit_cache = True

else:
from typing import GenericMeta # type: ignore

class GenericSelectMeta(GenericMeta, _Select.__class__): # type: ignore
pass

class _Py36Select(_Select, Generic[_TSelect], metaclass=GenericSelectMeta):
inherit_cache = True

class _Py36SelectOfScalar(_Select, Generic[_TSelect], metaclass=GenericSelectMeta):
inherit_cache = True

# Cast them for editors to work correctly, from several tricks tried, this works
# for both VS Code and PyCharm
Select = cast("Select", _Py36Select) # type: ignore
SelectOfScalar = cast("SelectOfScalar", _Py36SelectOfScalar) # type: ignore
# This is not comparable to sqlalchemy.sql.selectable.ScalarSelect, that has a different
# purpose. This is the same as a normal SQLAlchemy Select class where there's only one
# entity, so the result will be converted to a scalar by default. This way writing
# for loops on the results will feel natural.
class SelectOfScalar(_Select, Generic[_TSelect]):
inherit_cache = True


if TYPE_CHECKING: # pragma: no cover
Expand Down
40 changes: 8 additions & 32 deletions sqlmodel/sql/expression.py.jinja2
@@ -1,4 +1,3 @@
import sys
from datetime import datetime
from typing import (
TYPE_CHECKING,
Expand All @@ -10,7 +9,6 @@ from typing import (
Type,
TypeVar,
Union,
cast,
overload,
)
from uuid import UUID
Expand All @@ -22,37 +20,15 @@ from sqlalchemy.sql.expression import Select as _Select

_TSelect = TypeVar("_TSelect")

# Workaround Generics incompatibility in Python 3.6
# Ref: https://github.com/python/typing/issues/449#issuecomment-316061322
if sys.version_info.minor >= 7:

class Select(_Select, Generic[_TSelect]):
inherit_cache = True

# This is not comparable to sqlalchemy.sql.selectable.ScalarSelect, that has a different
# purpose. This is the same as a normal SQLAlchemy Select class where there's only one
# entity, so the result will be converted to a scalar by default. This way writing
# for loops on the results will feel natural.
class SelectOfScalar(_Select, Generic[_TSelect]):
inherit_cache = True

else:
from typing import GenericMeta # type: ignore

class GenericSelectMeta(GenericMeta, _Select.__class__): # type: ignore
pass

class _Py36Select(_Select, Generic[_TSelect], metaclass=GenericSelectMeta):
inherit_cache = True

class _Py36SelectOfScalar(_Select, Generic[_TSelect], metaclass=GenericSelectMeta):
inherit_cache = True

# Cast them for editors to work correctly, from several tricks tried, this works
# for both VS Code and PyCharm
Select = cast("Select", _Py36Select) # type: ignore
SelectOfScalar = cast("SelectOfScalar", _Py36SelectOfScalar) # type: ignore
class Select(_Select, Generic[_TSelect]):
inherit_cache = True

# This is not comparable to sqlalchemy.sql.selectable.ScalarSelect, that has a different
# purpose. This is the same as a normal SQLAlchemy Select class where there's only one
# entity, so the result will be converted to a scalar by default. This way writing
# for loops on the results will feel natural.
class SelectOfScalar(_Select, Generic[_TSelect]):
inherit_cache = True

if TYPE_CHECKING: # pragma: no cover
from ..main import SQLModel
Expand Down