Commit 7c49db426cbe94a3c319e396c96873b736b243aa
1 parent
f1ad38ab
Exists in
master
and in
1 other branch
more changes towards sqlalchemy-1.4 compatibility
Showing
2 changed files
with
37 additions
and
26 deletions
Show diff stats
perguntations/__init__.py
1 | -# Copyright (C) 2020 Miguel Barão | 1 | +# Copyright (C) 2021 Miguel Barão |
2 | # | 2 | # |
3 | # THE MIT License | 3 | # THE MIT License |
4 | # | 4 | # |
@@ -32,10 +32,10 @@ proof of submission and for review. | @@ -32,10 +32,10 @@ proof of submission and for review. | ||
32 | ''' | 32 | ''' |
33 | 33 | ||
34 | APP_NAME = 'perguntations' | 34 | APP_NAME = 'perguntations' |
35 | -APP_VERSION = '2021.01.dev1' | 35 | +APP_VERSION = '2021.09.dev1' |
36 | APP_DESCRIPTION = __doc__ | 36 | APP_DESCRIPTION = __doc__ |
37 | 37 | ||
38 | __author__ = 'Miguel Barão' | 38 | __author__ = 'Miguel Barão' |
39 | -__copyright__ = 'Copyright 2020, Miguel Barão' | 39 | +__copyright__ = 'Copyright 2021, Miguel Barão' |
40 | __license__ = 'MIT license' | 40 | __license__ = 'MIT license' |
41 | __version__ = APP_VERSION | 41 | __version__ = APP_VERSION |
perguntations/app.py
1 | ''' | 1 | ''' |
2 | -Main application module | 2 | +File: perguntations/app.py |
3 | +Description: Main application logic. | ||
3 | ''' | 4 | ''' |
4 | 5 | ||
5 | 6 | ||
@@ -21,10 +22,10 @@ from sqlalchemy.exc import NoResultFound | @@ -21,10 +22,10 @@ from sqlalchemy.exc import NoResultFound | ||
21 | 22 | ||
22 | # this project | 23 | # this project |
23 | from perguntations.models import Student, Test, Question | 24 | from perguntations.models import Student, Test, Question |
25 | +from perguntations.questions import question_from | ||
24 | from perguntations.tools import load_yaml | 26 | from perguntations.tools import load_yaml |
25 | from perguntations.testfactory import TestFactory, TestFactoryException | 27 | from perguntations.testfactory import TestFactory, TestFactoryException |
26 | import perguntations.test | 28 | import perguntations.test |
27 | -from perguntations.questions import question_from | ||
28 | 29 | ||
29 | # setup logger for this module | 30 | # setup logger for this module |
30 | logger = logging.getLogger(__name__) | 31 | logger = logging.getLogger(__name__) |
@@ -113,44 +114,44 @@ class App(): | @@ -113,44 +114,44 @@ class App(): | ||
113 | len(self.allowed)) | 114 | len(self.allowed)) |
114 | self._pregenerate_tests(len(self.allowed)) | 115 | self._pregenerate_tests(len(self.allowed)) |
115 | else: | 116 | else: |
116 | - logger.info('No tests were generated.') | 117 | + logger.info('No tests generated yet.') |
117 | 118 | ||
118 | if conf['correct']: | 119 | if conf['correct']: |
119 | self._correct_tests() | 120 | self._correct_tests() |
120 | 121 | ||
122 | + # ------------------------------------------------------------------------ | ||
121 | def _db_setup(self) -> None: | 123 | def _db_setup(self) -> None: |
122 | logger.info('Setup database') | 124 | logger.info('Setup database') |
123 | 125 | ||
124 | # connect to database and check registered students | 126 | # connect to database and check registered students |
125 | dbfile = path.expanduser(self.testfactory['database']) | 127 | dbfile = path.expanduser(self.testfactory['database']) |
126 | if not path.exists(dbfile): | 128 | if not path.exists(dbfile): |
127 | - raise AppException('Database does not exist.') | 129 | + raise AppException('Database does not exist. Use "initdb" to create.') |
128 | self._engine = create_engine(f'sqlite:///{dbfile}', future=True) | 130 | self._engine = create_engine(f'sqlite:///{dbfile}', future=True) |
129 | 131 | ||
130 | try: | 132 | try: |
131 | - query = select(func.count(Student.id)).where(Student.id != '0') | ||
132 | with Session(self._engine, future=True) as session: | 133 | with Session(self._engine, future=True) as session: |
133 | - num = session.execute(query).scalar() | 134 | + num = session.execute( |
135 | + select(func.count(Student.id)).where(Student.id != '0') | ||
136 | + ).scalar() | ||
134 | except Exception as exc: | 137 | except Exception as exc: |
135 | raise AppException(f'Database unusable {dbfile}.') from exc | 138 | raise AppException(f'Database unusable {dbfile}.') from exc |
136 | 139 | ||
137 | - # try: | ||
138 | - # with self._db_session() as sess: | ||
139 | - # num = sess.query(Student).filter(Student.id != '0').count() | ||
140 | - # except Exception as exc: | ||
141 | - # raise AppException(f'Database unusable {dbfile}.') from exc | ||
142 | logger.info('Database "%s" has %s students.', dbfile, num) | 140 | logger.info('Database "%s" has %s students.', dbfile, num) |
143 | 141 | ||
144 | - | ||
145 | - | ||
146 | # ------------------------------------------------------------------------ | 142 | # ------------------------------------------------------------------------ |
147 | def _correct_tests(self): | 143 | def _correct_tests(self): |
148 | - with self._db_session() as sess: | 144 | + with Session(self._engine, future=True) as session: |
149 | # Find which tests have to be corrected | 145 | # Find which tests have to be corrected |
150 | - dbtests = sess.query(Test)\ | ||
151 | - .filter(Test.ref == self.testfactory['ref'])\ | ||
152 | - .filter(Test.state == "SUBMITTED")\ | ||
153 | - .all() | 146 | + dbtests = session.execute( |
147 | + select(Test). | ||
148 | + where(Test.ref == self.testfactory['ref']). | ||
149 | + where(Test.state == "SUBMITTED") | ||
150 | + ).all() | ||
151 | + # dbtests = session.query(Test)\ | ||
152 | + # .filter(Test.ref == self.testfactory['ref'])\ | ||
153 | + # .filter(Test.state == "SUBMITTED")\ | ||
154 | + # .all() | ||
154 | 155 | ||
155 | logger.info('Correcting %d tests...', len(dbtests)) | 156 | logger.info('Correcting %d tests...', len(dbtests)) |
156 | for dbtest in dbtests: | 157 | for dbtest in dbtests: |
@@ -204,16 +205,26 @@ class App(): | @@ -204,16 +205,26 @@ class App(): | ||
204 | logger.warning('"%s" unauthorized.', uid) | 205 | logger.warning('"%s" unauthorized.', uid) |
205 | return 'unauthorized' | 206 | return 'unauthorized' |
206 | 207 | ||
207 | - with self._db_session() as sess: | ||
208 | - name, hashed_pw = sess.query(Student.name, Student.password)\ | ||
209 | - .filter_by(id=uid)\ | ||
210 | - .one() | 208 | + with Session(self._engine, future=True) as session: |
209 | + # with self._db_session() as sess: | ||
210 | + name, hashed_pw = session.execute( | ||
211 | + select(Student.name, Student.password). | ||
212 | + where(id == uid) | ||
213 | + ).one() | ||
214 | + # name, hashed_pw = sess.query(Student.name, Student.password)\ | ||
215 | + # .filter_by(id=uid)\ | ||
216 | + # .one() | ||
211 | 217 | ||
212 | if hashed_pw == '': # update password on first login | 218 | if hashed_pw == '': # update password on first login |
213 | await self.update_student_password(uid, try_pw) | 219 | await self.update_student_password(uid, try_pw) |
214 | pw_ok = True | 220 | pw_ok = True |
215 | else: # check password | 221 | else: # check password |
216 | - pw_ok = await check_password(try_pw, hashed_pw) # async bcrypt | 222 | + loop = asyncio.get_running_loop() |
223 | + pw_ok = await loop.run_in_executor(None, | ||
224 | + bcrypt.checkpw, | ||
225 | + try_pw.encode('utf-8'), | ||
226 | + hashed_pw.password) | ||
227 | + # pw_ok = await check_password(try_pw, hashed_pw) # async bcrypt | ||
217 | 228 | ||
218 | if not pw_ok: # wrong password | 229 | if not pw_ok: # wrong password |
219 | logger.info('"%s" wrong password.', uid) | 230 | logger.info('"%s" wrong password.', uid) |