Commit 97085de71ed022df486976901f05793c3c601182
1 parent
50d0cebf
Exists in
master
and in
1 other branch
initial convertion of learnapp to sqlalchemy 1.4/2
Showing
3 changed files
with
33 additions
and
35 deletions
Show diff stats
aprendizations/learnapp.py
| @@ -6,7 +6,7 @@ This is the main controller of the application. | @@ -6,7 +6,7 @@ This is the main controller of the application. | ||
| 6 | # python standard library | 6 | # python standard library |
| 7 | import asyncio | 7 | import asyncio |
| 8 | from collections import defaultdict | 8 | from collections import defaultdict |
| 9 | -from contextlib import contextmanager # `with` statement in db sessions | 9 | +# from contextlib import contextmanager # `with` statement in db sessions |
| 10 | from datetime import datetime | 10 | from datetime import datetime |
| 11 | import logging | 11 | import logging |
| 12 | from random import random | 12 | from random import random |
| @@ -16,8 +16,8 @@ from typing import Any, Dict, Iterable, List, Optional, Tuple, Set, DefaultDict | @@ -16,8 +16,8 @@ from typing import Any, Dict, Iterable, List, Optional, Tuple, Set, DefaultDict | ||
| 16 | # third party libraries | 16 | # third party libraries |
| 17 | import bcrypt | 17 | import bcrypt |
| 18 | import networkx as nx | 18 | import networkx as nx |
| 19 | -import sqlalchemy as sa | ||
| 20 | -import sqlalchemy.orm as orm | 19 | +from sqlalchemy import create_engine, select |
| 20 | +from sqlalchemy.orm import Session | ||
| 21 | 21 | ||
| 22 | # this project | 22 | # this project |
| 23 | from aprendizations.models import Student, Answer, Topic, StudentTopic | 23 | from aprendizations.models import Student, Answer, Topic, StudentTopic |
| @@ -57,22 +57,22 @@ class LearnApp(): | @@ -57,22 +57,22 @@ class LearnApp(): | ||
| 57 | 57 | ||
| 58 | 58 | ||
| 59 | # ------------------------------------------------------------------------ | 59 | # ------------------------------------------------------------------------ |
| 60 | - @contextmanager | ||
| 61 | - def _db_session(self, **kw): | ||
| 62 | - ''' | ||
| 63 | - helper to manage db sessions using the `with` statement, for example | ||
| 64 | - with self._db_session() as s: s.query(...) | ||
| 65 | - ''' | ||
| 66 | - session = self.Session(**kw) | ||
| 67 | - try: | ||
| 68 | - yield session | ||
| 69 | - session.commit() | ||
| 70 | - except Exception: | ||
| 71 | - logger.error('!!! Database rollback !!!') | ||
| 72 | - session.rollback() | ||
| 73 | - raise | ||
| 74 | - finally: | ||
| 75 | - session.close() | 60 | + # @contextmanager |
| 61 | + # def _db_session(self, **kw): | ||
| 62 | + # ''' | ||
| 63 | + # helper to manage db sessions using the `with` statement, for example | ||
| 64 | + # with self._db_session() as s: s.query(...) | ||
| 65 | + # ''' | ||
| 66 | + # session = self.Session(**kw) | ||
| 67 | + # try: | ||
| 68 | + # yield session | ||
| 69 | + # session.commit() | ||
| 70 | + # except Exception: | ||
| 71 | + # logger.error('!!! Database rollback !!!') | ||
| 72 | + # session.rollback() | ||
| 73 | + # raise | ||
| 74 | + # finally: | ||
| 75 | + # session.close() | ||
| 76 | 76 | ||
| 77 | # ------------------------------------------------------------------------ | 77 | # ------------------------------------------------------------------------ |
| 78 | def __init__(self, | 78 | def __init__(self, |
| @@ -369,30 +369,31 @@ class LearnApp(): | @@ -369,30 +369,31 @@ class LearnApp(): | ||
| 369 | ''' | 369 | ''' |
| 370 | Fill db table 'Topic' with topics from the graph, if new | 370 | Fill db table 'Topic' with topics from the graph, if new |
| 371 | ''' | 371 | ''' |
| 372 | - with self._db_session() as sess: | ||
| 373 | - new = [Topic(id=t) for t in topics | ||
| 374 | - if (t,) not in sess.query(Topic.id)] | ||
| 375 | - | 372 | + with Session(self._engine) as session: |
| 373 | + db_topics = session.execute(select(Topic.id)).scalars().all() | ||
| 374 | + new = [Topic(id=t) for t in topics if t not in db_topics] | ||
| 376 | if new: | 375 | if new: |
| 377 | - sess.add_all(new) | 376 | + session.add_all(new) |
| 377 | + session.commit() | ||
| 378 | logger.info('Added %d new topic(s) to the database', len(new)) | 378 | logger.info('Added %d new topic(s) to the database', len(new)) |
| 379 | 379 | ||
| 380 | # ------------------------------------------------------------------------ | 380 | # ------------------------------------------------------------------------ |
| 381 | def _db_setup(self, database: str) -> None: | 381 | def _db_setup(self, database: str) -> None: |
| 382 | - '''setup and check database contents''' | 382 | + ''' |
| 383 | + Setup and check database contents | ||
| 384 | + ''' | ||
| 383 | 385 | ||
| 384 | logger.info('Checking database "%s":', database) | 386 | logger.info('Checking database "%s":', database) |
| 385 | if not exists(database): | 387 | if not exists(database): |
| 386 | raise LearnException('Database does not exist. ' | 388 | raise LearnException('Database does not exist. ' |
| 387 | 'Use "initdb-aprendizations" to create') | 389 | 'Use "initdb-aprendizations" to create') |
| 388 | 390 | ||
| 389 | - engine = sa.create_engine(f'sqlite:///{database}', echo=False) | ||
| 390 | - self.Session = orm.sessionmaker(bind=engine) | 391 | + self._engine = create_engine(f'sqlite:///{database}', future=True) |
| 391 | try: | 392 | try: |
| 392 | - with self._db_session() as sess: | ||
| 393 | - count_students: int = sess.query(Student).count() | ||
| 394 | - count_topics: int = sess.query(Topic).count() | ||
| 395 | - count_answers: int = sess.query(Answer).count() | 393 | + with Session(self._engine) as session: |
| 394 | + count_students: int = session.query(Student).count() | ||
| 395 | + count_topics: int = session.query(Topic).count() | ||
| 396 | + count_answers: int = session.query(Answer).count() | ||
| 396 | except Exception as exc: | 397 | except Exception as exc: |
| 397 | logger.error('Database "%s" not usable!', database) | 398 | logger.error('Database "%s" not usable!', database) |
| 398 | raise DatabaseUnusableError() from exc | 399 | raise DatabaseUnusableError() from exc |
aprendizations/models.py
| 1 | 1 | ||
| 2 | -# python standard library | ||
| 3 | -# from typing import Any | ||
| 4 | - | ||
| 5 | # third party libraries | 2 | # third party libraries |
| 6 | from sqlalchemy import Column, ForeignKey, Integer, Float, String | 3 | from sqlalchemy import Column, ForeignKey, Integer, Float, String |
| 7 | from sqlalchemy.orm import declarative_base, relationship | 4 | from sqlalchemy.orm import declarative_base, relationship |
| @@ -10,6 +7,7 @@ from sqlalchemy.orm import declarative_base, relationship | @@ -10,6 +7,7 @@ from sqlalchemy.orm import declarative_base, relationship | ||
| 10 | # =========================================================================== | 7 | # =========================================================================== |
| 11 | # Declare ORM | 8 | # Declare ORM |
| 12 | # FIXME Any is a workaround for mypy static type checking (see https://github.com/python/mypy/issues/6372) | 9 | # FIXME Any is a workaround for mypy static type checking (see https://github.com/python/mypy/issues/6372) |
| 10 | +# from typing import Any | ||
| 13 | # Base: Any = declarative_base() | 11 | # Base: Any = declarative_base() |
| 14 | Base = declarative_base() | 12 | Base = declarative_base() |
| 15 | 13 |
mypy.ini