async def test_finish_commit(raise_exception, tmp_path):
    """
    Tests that the session is automatically committed if and only if the context was not
    exited with an exception.

    """
    db_path = tmp_path / "test.db"
    engine = create_engine(f"sqlite:///{db_path}", poolclass=NullPool)
    with engine.begin() as connection:
        connection.execute(text("CREATE TABLE foo (id INTEGER PRIMARY KEY)"))

        component = SQLAlchemyComponent(url={
            "drivername": "sqlite",
            "database": str(db_path)
        }, )
        with ExitStack() as stack:
            async with Context() as ctx:
                await component.start(ctx)
                session = ctx.require_resource(Session)
                session.execute(text("INSERT INTO foo (id) VALUES(3)"))
                if raise_exception:
                    stack.enter_context(pytest.raises(Exception,
                                                      match="dummy"))
                    raise Exception("dummy")

        rows = connection.execute(text("SELECT * FROM foo")).fetchall()
        assert len(rows) == (0 if raise_exception else 1)
def sqlite_memory_engine():
    engine = create_engine(
        "sqlite:///:memory:", connect_args=dict(check_same_thread=False)
    )
    apply_sqlite_hacks(engine)
    yield engine
    engine.dispose()
def sqlite_file_engine(tmp_path_factory):
    db_path = tmp_path_factory.mktemp("asphalt-sqlalchemy") / "test.db"
    engine = create_engine(
        f"sqlite:///{db_path}", connect_args=dict(check_same_thread=False)
    )
    apply_sqlite_hacks(engine)
    yield engine
    engine.dispose()
    if db_path.exists():
        db_path.unlink()
async def test_bind_sync():
    """Test that a Connection can be passed as "bind" in place of "url"."""
    engine = create_engine("sqlite:///:memory:")
    connection = engine.connect()
    component = SQLAlchemyComponent(bind=connection)
    async with Context() as ctx:
        await component.start(ctx)

        assert ctx.require_resource(Engine) is engine
        assert ctx.require_resource(Session).bind is connection

    connection.close()
async def test_session_event_async(request, asyncpg_url, psycopg2_url):
    """Test that creating a session in a context does not leak memory."""
    listener_session: Session
    listener_thread: Thread

    def listener(session: Session) -> None:
        nonlocal listener_session, listener_thread
        try:
            async_session = get_resource(AsyncSession)
        except NoCurrentContext:
            return

        if async_session and session is async_session.sync_session:
            listener_session = session
            listener_thread = current_thread()

    listen(Session, "before_commit", listener)
    request.addfinalizer(lambda: remove(Session, "before_commit", listener))
    component = SQLAlchemyComponent(url=asyncpg_url)
    async with Context() as ctx:
        await component.start(ctx)
        dbsession = ctx.require_resource(AsyncSession)
        await dbsession.run_sync(
            lambda session: Person.metadata.create_all(session.bind))
        dbsession.add(Person(name="Test person"))

    assert listener_session is dbsession.sync_session
    assert listener_thread is current_thread()

    engine = create_engine(psycopg2_url)
    with Session(engine) as sess:
        sess.add(Person(name="Test person 2"))
        sess.commit()

    engine.dispose()

    assert listener_session is dbsession.sync_session
    assert listener_thread is current_thread()
示例#6
0
def testing_engine(url=None, options=None, future=False):
    """Produce an engine configured by --options with optional overrides."""

    if future or config.db and config.db._is_future:
        from sqlalchemy.future import create_engine
    else:
        from sqlalchemy import create_engine
    from sqlalchemy.engine.url import make_url

    if not options:
        use_reaper = True
    else:
        use_reaper = options.pop("use_reaper", True)

    url = url or config.db.url

    url = make_url(url)
    if options is None:
        if config.db is None or url.drivername == config.db.url.drivername:
            options = config.db_opts
        else:
            options = {}
    elif config.db is not None and url.drivername == config.db.url.drivername:
        default_opt = config.db_opts.copy()
        default_opt.update(options)

    engine = create_engine(url, **options)
    engine._has_events = True  # enable event blocks, helps with profiling

    if isinstance(engine.pool, pool.QueuePool):
        engine.pool._timeout = 0
        engine.pool._max_overflow = 0
    if use_reaper:
        testing_reaper.add_engine(engine)

    return engine
示例#7
0
 def __init__(self):
     super().__init__()
     self.engine = create_engine(self.get_connection_url(), future=True)
     self.sessionmaker = sessionmaker(self.engine)
def psycopg2_engine(patch_psycopg2, psycopg2_url):
    engine = create_engine(psycopg2_url)
    yield engine
    engine.dispose()
def pymysql_engine(mysql_url):
    engine = create_engine(mysql_url)
    yield engine
    engine.dispose()
示例#10
0
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with JulianBC.  If not, see <https://www.gnu.org/licenses/>.
from src.customdatetime import (
    ConvertibleDate,
    ConvertibleDateTime,
    ConvertibleTime,
)
from sqlalchemy.future import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from src.db import ConvertibleCalendar, ConvertibleClock
from src.db.utils import Base

engine = create_engine("sqlite://", future=True)
Session = scoped_session(sessionmaker(bind=engine))
session = Session()
Base.metadata.create_all(engine)
session.commit()
gregorian = ConvertibleCalendar(
    name="Gregorian",
    weekday_names=(
        "Monday",
        "Tuesday",
        "Wednesday",
        "Thursday",
        "Friday",
        "Saturday",
        "Sunday",
    ),