Skip to content

Commit

Permalink
Fixed breakage on SQLAlchemy 1.3 (#2)
Browse files Browse the repository at this point in the history
  • Loading branch information
nickswebsite authored Aug 14, 2022
1 parent cf4bb0d commit 8db2067
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 40 deletions.
12 changes: 12 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,18 @@ Use ``instance`` as desired.
>>> print(instance.value)
RNvnAvOpyEVAoNGnVZQU

Supported Versions
------------------

Currently SQLAlchemy versions 1.3 and 1.4 are supported. Support for SQLAlchemy 2.0 will be added when it is released.

Faker versions ``>=8`` are currently supported, though it should be noted that the testing matrix isn't exhaustive. If
bugs come up with a particular version of faker beyond version 8.0, submit a ticket to add support.

Python versions ``>=3.7`` are currently supported. If python 3.6 support is desired, submit a ticket to add support. Support
for Python 3.11 will be added when it is officially supported by SQLAlchemy. Currently, this is waiting on greenlet
releasing support for python 3.11.


.. |PyPI| image:: https://img.shields.io/pypi/v/faker_sqlalchemy
:target: https://pypi.org/project/faker_sqlalchemy/
Expand Down
20 changes: 18 additions & 2 deletions faker_sqlalchemy.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,18 @@
>>> print(instance.value)
RNvnAvOpyEVAoNGnVZQU
Supported Versions
------------------
Currently SQLAlchemy versions 1.3 and 1.4 are supported. Support for SQLAlchemy 2.0 will be added when it is released.
Faker versions ``>=8`` are currently supported, though it should be noted that the testing matrix isn't exhaustive. If
bugs come up with a particular version of faker beyond version 8.0, submit a ticket to add support.
Python versions ``>=3.7`` are currently supported. If python 3.6 support is desired, submit a ticket to add support. Support
for Python 3.11 will be added when it is officially supported by SQLAlchemy. Currently, this is waiting on greenlet
releasing support for python 3.11.
"""

import datetime
Expand All @@ -46,7 +58,11 @@
from faker.providers.date_time import Provider as DateTimeProvider
from faker.providers.misc import Provider as MiscProvider
from faker.providers.python import Provider as PythonProvider
from sqlalchemy.orm import DeclarativeMeta, Mapper, RelationshipProperty
from sqlalchemy.orm import Mapper, RelationshipProperty
try:
from sqlalchemy.orm import DeclarativeMeta
except ImportError:
from sqlalchemy.ext.declarative import DeclarativeMeta
from sqlalchemy.sql.type_api import TypeEngine
from sqlalchemy import (
inspect,
Expand All @@ -72,7 +88,7 @@
UnicodeText,
)

__version__ = "0.10.220813"
__version__ = "0.10.2208140"
__all__ = (
"SqlAlchemyProvider",
)
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ classifiers = [
"Topic :: Utilities",
]
dependencies = [
"faker >=10.0",
"faker >=8.0",
"sqlalchemy >=1.3,<2.0",
]
requires-python = ">=3.7"
Expand Down
80 changes: 57 additions & 23 deletions tests/test_acceptance.py
Original file line number Diff line number Diff line change
@@ -1,50 +1,87 @@
import datetime
import os.path
import unittest
from typing import Union
import tempfile
from typing import Union, ClassVar
import warnings

from faker import Faker
from sqlalchemy.exc import SAWarning
from sqlalchemy.orm import Session
from sqlalchemy.orm import sessionmaker
from sqlalchemy.dialects.sqlite import DATE as SQLITE_DATE
from sqlalchemy import (
create_engine,
select,
)
from sqlalchemy import create_engine

from faker_sqlalchemy import SqlAlchemyProvider
from tests.test_models import Base, Model, RelationshipModel, TypeOverrideModel

engine = create_engine("sqlite:///.test-db.sqlite3", echo=False, future=True)

class _TestSessionFixture:
def __init__(self, path=None):
self._session = None
self._temp_file = None

if path is None:
self._temp_file = tempfile.TemporaryDirectory()
self._temp_file.__enter__()
fs_path = os.path.join(self._temp_file.name, "db.sqlite3")
path = f"sqlite:///{fs_path}"

try:
self.engine = create_engine(path, echo=False, future=True)
self.Session = sessionmaker(bind=self.engine, future=True)
except TypeError:
# SA 1.3
self.engine = create_engine(path, echo=False)
self.Session = sessionmaker(bind=self.engine)
Base.metadata.create_all(self.engine)

def __enter__(self):
self._session = self.Session()
return self._session

def __exit__(self, exc_type, exc_val, exc_tb):
if self._session:
self._session.commit()
self._session.close()

def clear(self):
with self as session:
for m in Base.__subclasses__():
session.query(m).delete()

def teardown(self):
Base.metadata.drop_all(self.engine)
if self._temp_file:
self._temp_file.__exit__(None, None, None)


class AcceptanceTests(unittest.TestCase):
session_fixture: ClassVar[_TestSessionFixture]

@classmethod
def setUpClass(cls) -> None:
cls._ctx = warnings.catch_warnings()
cls._ctx.__enter__()
warnings.simplefilter("ignore", category=SAWarning)

Base.metadata.create_all(engine)
cls.session_fixture = _TestSessionFixture(None)

super().setUpClass()

@classmethod
def tearDownClass(cls):
super().tearDownClass()

Base.metadata.drop_all(engine)
cls.session_fixture.teardown()

cls._ctx.__exit__()

def setUp(self) -> None:
SqlAlchemyProvider.reset_type_mappings()

super().setUp()

with Session(engine) as session:
for m in Base.__subclasses__():
session.query(m).delete()
session.commit()
self.session_fixture.clear()

self.faker: Union[SqlAlchemyProvider, Faker] = Faker()
self.faker.add_provider(SqlAlchemyProvider)
Expand All @@ -70,25 +107,22 @@ def test_generates_models_for_model(self):
def test_models_can_be_saved(self):
model = self.faker.sqlalchemy_model(Model)

with Session(engine) as session:
with self.session_fixture as session:
session.add_all([model])
session.commit()

results = session.scalars(
select(Model)
).one()
results = session.query(Model).first()

self.assertEqual(results.unicode, model.unicode)

def test_related_models_can_be_saved(self):
model = self.faker.sqlalchemy_model(RelationshipModel, generate_related=True)

with Session(engine) as session:
session.add_all([model])
with self.session_fixture as session:
session.add_all([model, model.model])
session.commit()

results = session.scalars(
select(RelationshipModel),
).one()
results = session.query(RelationshipModel).first()

self.assertIsNotNone(results.model.id)
self.assertEqual(results.model.id, model.model_id)

Expand Down
1 change: 0 additions & 1 deletion tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
TIME,
Time,
TIMESTAMP,
TupleType,
TypeDecorator,
Unicode,
UnicodeText,
Expand Down
20 changes: 7 additions & 13 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[tox]
envlist =
py{37,38,39,310}-sqlalchemy{13,14}
py{37,310}-faker{10,9999}
py{37,310}-faker{8,10,9999}

basepython =
py37: python3.7
Expand All @@ -20,15 +20,9 @@ python =

[testenv]
commands = python -m unittest discover

[testenv:sqlalchemy13]
deps = sqlalchemy ~=1.3

[testenv:sqlalchemy14]
deps = sqlalchemy ~=1.4

[testenv:faker10]
deps = faker >=10,<13

[testenv:faker9999]
deps = faker >=13
deps =
py3{7,8,9,10}-sqlalchemy13: sqlalchemy ~=1.3,<1.4
py3{7,8,9,10}-sqlalchemy14: sqlalchemy >=1.4,<2
py{37,310}-faker8: faker >=8,<9
py{37,310}-faker10: faker >=10,<11
py{37,310}-faker9999: faker >=13

0 comments on commit 8db2067

Please sign in to comment.