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 | 3 | # THE MIT License |
4 | 4 | # |
... | ... | @@ -32,10 +32,10 @@ proof of submission and for review. |
32 | 32 | ''' |
33 | 33 | |
34 | 34 | APP_NAME = 'perguntations' |
35 | -APP_VERSION = '2021.01.dev1' | |
35 | +APP_VERSION = '2021.09.dev1' | |
36 | 36 | APP_DESCRIPTION = __doc__ |
37 | 37 | |
38 | 38 | __author__ = 'Miguel Barão' |
39 | -__copyright__ = 'Copyright 2020, Miguel Barão' | |
39 | +__copyright__ = 'Copyright 2021, Miguel Barão' | |
40 | 40 | __license__ = 'MIT license' |
41 | 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 | 22 | |
22 | 23 | # this project |
23 | 24 | from perguntations.models import Student, Test, Question |
25 | +from perguntations.questions import question_from | |
24 | 26 | from perguntations.tools import load_yaml |
25 | 27 | from perguntations.testfactory import TestFactory, TestFactoryException |
26 | 28 | import perguntations.test |
27 | -from perguntations.questions import question_from | |
28 | 29 | |
29 | 30 | # setup logger for this module |
30 | 31 | logger = logging.getLogger(__name__) |
... | ... | @@ -113,44 +114,44 @@ class App(): |
113 | 114 | len(self.allowed)) |
114 | 115 | self._pregenerate_tests(len(self.allowed)) |
115 | 116 | else: |
116 | - logger.info('No tests were generated.') | |
117 | + logger.info('No tests generated yet.') | |
117 | 118 | |
118 | 119 | if conf['correct']: |
119 | 120 | self._correct_tests() |
120 | 121 | |
122 | + # ------------------------------------------------------------------------ | |
121 | 123 | def _db_setup(self) -> None: |
122 | 124 | logger.info('Setup database') |
123 | 125 | |
124 | 126 | # connect to database and check registered students |
125 | 127 | dbfile = path.expanduser(self.testfactory['database']) |
126 | 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 | 130 | self._engine = create_engine(f'sqlite:///{dbfile}', future=True) |
129 | 131 | |
130 | 132 | try: |
131 | - query = select(func.count(Student.id)).where(Student.id != '0') | |
132 | 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 | 137 | except Exception as exc: |
135 | 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 | 140 | logger.info('Database "%s" has %s students.', dbfile, num) |
143 | 141 | |
144 | - | |
145 | - | |
146 | 142 | # ------------------------------------------------------------------------ |
147 | 143 | def _correct_tests(self): |
148 | - with self._db_session() as sess: | |
144 | + with Session(self._engine, future=True) as session: | |
149 | 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 | 156 | logger.info('Correcting %d tests...', len(dbtests)) |
156 | 157 | for dbtest in dbtests: |
... | ... | @@ -204,16 +205,26 @@ class App(): |
204 | 205 | logger.warning('"%s" unauthorized.', uid) |
205 | 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 | 218 | if hashed_pw == '': # update password on first login |
213 | 219 | await self.update_student_password(uid, try_pw) |
214 | 220 | pw_ok = True |
215 | 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 | 229 | if not pw_ok: # wrong password |
219 | 230 | logger.info('"%s" wrong password.', uid) | ... | ... |