Commit adb8522e262fd313534d8b3c6577b71d95efe9a1
1 parent
ed0097b4
Exists in
master
and in
1 other branch
add some type annotations
Showing
3 changed files
with
21 additions
and
22 deletions
Show diff stats
BUGS.md
| 1 | 1 | ||
| 2 | # BUGS | 2 | # BUGS |
| 3 | 3 | ||
| 4 | -- no login, dar mensagem de erro se aluno nao existir?? | ||
| 5 | -- Verificar o processo de logout. | ||
| 6 | - permitir remover alunos que estão online para poderem comecar de novo. | 4 | - permitir remover alunos que estão online para poderem comecar de novo. |
| 7 | - grade gives internal server error | 5 | - grade gives internal server error |
| 8 | - reload do teste recomeça a contagem no inicio do tempo. | 6 | - reload do teste recomeça a contagem no inicio do tempo. |
perguntations/main.py
| @@ -55,7 +55,7 @@ def parse_cmdline_arguments(): | @@ -55,7 +55,7 @@ def parse_cmdline_arguments(): | ||
| 55 | help='port for the HTTPS server (default: 8443)') | 55 | help='port for the HTTPS server (default: 8443)') |
| 56 | parser.add_argument('--version', | 56 | parser.add_argument('--version', |
| 57 | action='version', | 57 | action='version', |
| 58 | - version=APP_VERSION, | 58 | + version=f'{APP_VERSION} - python {sys.version}', |
| 59 | help='Show version information and exit') | 59 | help='Show version information and exit') |
| 60 | return parser.parse_args() | 60 | return parser.parse_args() |
| 61 | 61 | ||
| @@ -100,7 +100,7 @@ def get_logger_config(debug=False): | @@ -100,7 +100,7 @@ def get_logger_config(debug=False): | ||
| 100 | }, | 100 | }, |
| 101 | } | 101 | } |
| 102 | default_config['loggers'].update({ | 102 | default_config['loggers'].update({ |
| 103 | - APP_NAME+'.'+module: { | 103 | + f'{APP_NAME}.{module}': { |
| 104 | 'handlers': ['default'], | 104 | 'handlers': ['default'], |
| 105 | 'level': level, | 105 | 'level': level, |
| 106 | 'propagate': False, | 106 | 'propagate': False, |
perguntations/test.py
| @@ -10,6 +10,7 @@ import random | @@ -10,6 +10,7 @@ import random | ||
| 10 | from datetime import datetime | 10 | from datetime import datetime |
| 11 | import logging | 11 | import logging |
| 12 | import re | 12 | import re |
| 13 | +from typing import Any, Dict | ||
| 13 | 14 | ||
| 14 | # this project | 15 | # this project |
| 15 | from perguntations.questions import QFactory, QuestionException | 16 | from perguntations.questions import QFactory, QuestionException |
| @@ -33,7 +34,7 @@ class TestFactory(dict): | @@ -33,7 +34,7 @@ class TestFactory(dict): | ||
| 33 | ''' | 34 | ''' |
| 34 | 35 | ||
| 35 | # ------------------------------------------------------------------------ | 36 | # ------------------------------------------------------------------------ |
| 36 | - def __init__(self, conf): | 37 | + def __init__(self, conf: Dict[str, Any]) -> None: |
| 37 | ''' | 38 | ''' |
| 38 | Loads configuration from yaml file, then overrides some configurations | 39 | Loads configuration from yaml file, then overrides some configurations |
| 39 | using the conf argument. | 40 | using the conf argument. |
| @@ -123,7 +124,7 @@ class TestFactory(dict): | @@ -123,7 +124,7 @@ class TestFactory(dict): | ||
| 123 | raise TestFactoryException(f'Could not find questions {qmissing}.') | 124 | raise TestFactoryException(f'Could not find questions {qmissing}.') |
| 124 | 125 | ||
| 125 | # ------------------------------------------------------------------------ | 126 | # ------------------------------------------------------------------------ |
| 126 | - def check_test_ref(self): | 127 | + def check_test_ref(self) -> None: |
| 127 | '''Test must have a `ref`''' | 128 | '''Test must have a `ref`''' |
| 128 | if 'ref' not in self: | 129 | if 'ref' not in self: |
| 129 | raise TestFactoryException('Missing "ref" in configuration!') | 130 | raise TestFactoryException('Missing "ref" in configuration!') |
| @@ -131,7 +132,7 @@ class TestFactory(dict): | @@ -131,7 +132,7 @@ class TestFactory(dict): | ||
| 131 | raise TestFactoryException('Test "ref" can only contain the ' | 132 | raise TestFactoryException('Test "ref" can only contain the ' |
| 132 | 'characters a-zA-Z0-9_-') | 133 | 'characters a-zA-Z0-9_-') |
| 133 | 134 | ||
| 134 | - def check_missing_database(self): | 135 | + def check_missing_database(self) -> None: |
| 135 | '''Test must have a database''' | 136 | '''Test must have a database''' |
| 136 | if 'database' not in self: | 137 | if 'database' not in self: |
| 137 | raise TestFactoryException('Missing "database" in configuration') | 138 | raise TestFactoryException('Missing "database" in configuration') |
| @@ -139,13 +140,13 @@ class TestFactory(dict): | @@ -139,13 +140,13 @@ class TestFactory(dict): | ||
| 139 | msg = f'Database "{self["database"]}" not found!' | 140 | msg = f'Database "{self["database"]}" not found!' |
| 140 | raise TestFactoryException(msg) | 141 | raise TestFactoryException(msg) |
| 141 | 142 | ||
| 142 | - def check_missing_answers_directory(self): | 143 | + def check_missing_answers_directory(self) -> None: |
| 143 | '''Test must have a answers directory''' | 144 | '''Test must have a answers directory''' |
| 144 | if 'answers_dir' not in self: | 145 | if 'answers_dir' not in self: |
| 145 | msg = 'Missing "answers_dir" in configuration' | 146 | msg = 'Missing "answers_dir" in configuration' |
| 146 | raise TestFactoryException(msg) | 147 | raise TestFactoryException(msg) |
| 147 | 148 | ||
| 148 | - def check_answers_directory_writable(self): | 149 | + def check_answers_directory_writable(self) -> None: |
| 149 | '''Answers directory must be writable''' | 150 | '''Answers directory must be writable''' |
| 150 | testfile = path.join(path.expanduser(self['answers_dir']), 'REMOVE-ME') | 151 | testfile = path.join(path.expanduser(self['answers_dir']), 'REMOVE-ME') |
| 151 | try: | 152 | try: |
| @@ -155,7 +156,7 @@ class TestFactory(dict): | @@ -155,7 +156,7 @@ class TestFactory(dict): | ||
| 155 | msg = f'Cannot write answers to directory "{self["answers_dir"]}"' | 156 | msg = f'Cannot write answers to directory "{self["answers_dir"]}"' |
| 156 | raise TestFactoryException(msg) from exc | 157 | raise TestFactoryException(msg) from exc |
| 157 | 158 | ||
| 158 | - def check_questions_directory(self): | 159 | + def check_questions_directory(self) -> None: |
| 159 | '''Check if questions directory is missing or not accessible.''' | 160 | '''Check if questions directory is missing or not accessible.''' |
| 160 | if 'questions_dir' not in self: | 161 | if 'questions_dir' not in self: |
| 161 | logger.warning('Missing "questions_dir". Using "%s"', | 162 | logger.warning('Missing "questions_dir". Using "%s"', |
| @@ -165,7 +166,7 @@ class TestFactory(dict): | @@ -165,7 +166,7 @@ class TestFactory(dict): | ||
| 165 | raise TestFactoryException(f'Can\'t find questions directory ' | 166 | raise TestFactoryException(f'Can\'t find questions directory ' |
| 166 | f'"{self["questions_dir"]}"') | 167 | f'"{self["questions_dir"]}"') |
| 167 | 168 | ||
| 168 | - def check_import_files(self): | 169 | + def check_import_files(self) -> None: |
| 169 | '''Check if there are files to import (with questions)''' | 170 | '''Check if there are files to import (with questions)''' |
| 170 | if 'files' not in self: | 171 | if 'files' not in self: |
| 171 | msg = ('Missing "files" in configuration with the list of ' | 172 | msg = ('Missing "files" in configuration with the list of ' |
| @@ -175,7 +176,7 @@ class TestFactory(dict): | @@ -175,7 +176,7 @@ class TestFactory(dict): | ||
| 175 | if isinstance(self['files'], str): | 176 | if isinstance(self['files'], str): |
| 176 | self['files'] = [self['files']] | 177 | self['files'] = [self['files']] |
| 177 | 178 | ||
| 178 | - def check_question_list(self): | 179 | + def check_question_list(self) -> None: |
| 179 | '''normalize question list''' | 180 | '''normalize question list''' |
| 180 | if 'questions' not in self: | 181 | if 'questions' not in self: |
| 181 | raise TestFactoryException('Missing "questions" in configuration') | 182 | raise TestFactoryException('Missing "questions" in configuration') |
| @@ -191,12 +192,12 @@ class TestFactory(dict): | @@ -191,12 +192,12 @@ class TestFactory(dict): | ||
| 191 | 192 | ||
| 192 | self['questions'][i] = question | 193 | self['questions'][i] = question |
| 193 | 194 | ||
| 194 | - def check_missing_title(self): | 195 | + def check_missing_title(self) -> None: |
| 195 | '''Warns if title is missing''' | 196 | '''Warns if title is missing''' |
| 196 | if not self['title']: | 197 | if not self['title']: |
| 197 | logger.warning('Title is undefined!') | 198 | logger.warning('Title is undefined!') |
| 198 | 199 | ||
| 199 | - def check_grade_scaling(self): | 200 | + def check_grade_scaling(self) -> None: |
| 200 | '''Just informs the scale limits''' | 201 | '''Just informs the scale limits''' |
| 201 | if 'scale_points' in self: | 202 | if 'scale_points' in self: |
| 202 | msg = ('*** DEPRECATION WARNING: *** scale_points, scale_min, ' | 203 | msg = ('*** DEPRECATION WARNING: *** scale_points, scale_min, ' |
| @@ -206,7 +207,7 @@ class TestFactory(dict): | @@ -206,7 +207,7 @@ class TestFactory(dict): | ||
| 206 | 207 | ||
| 207 | 208 | ||
| 208 | # ------------------------------------------------------------------------ | 209 | # ------------------------------------------------------------------------ |
| 209 | - def sanity_checks(self): | 210 | + def sanity_checks(self) -> None: |
| 210 | ''' | 211 | ''' |
| 211 | Checks for valid keys and sets default values. | 212 | Checks for valid keys and sets default values. |
| 212 | Also checks if some files and directories exist | 213 | Also checks if some files and directories exist |
| @@ -304,7 +305,7 @@ class Test(dict): | @@ -304,7 +305,7 @@ class Test(dict): | ||
| 304 | # super().__init__(d) | 305 | # super().__init__(d) |
| 305 | 306 | ||
| 306 | # ------------------------------------------------------------------------ | 307 | # ------------------------------------------------------------------------ |
| 307 | - def register(self, student): | 308 | + def register(self, student: dict) -> None: |
| 308 | ''' | 309 | ''' |
| 309 | Write student id in the test and register start time | 310 | Write student id in the test and register start time |
| 310 | ''' | 311 | ''' |
| @@ -315,18 +316,18 @@ class Test(dict): | @@ -315,18 +316,18 @@ class Test(dict): | ||
| 315 | self['comment'] = '' | 316 | self['comment'] = '' |
| 316 | 317 | ||
| 317 | # ------------------------------------------------------------------------ | 318 | # ------------------------------------------------------------------------ |
| 318 | - def reset_answers(self): | 319 | + def reset_answers(self) -> None: |
| 319 | '''Removes all answers from the test (clean)''' | 320 | '''Removes all answers from the test (clean)''' |
| 320 | for question in self['questions']: | 321 | for question in self['questions']: |
| 321 | question['answer'] = None | 322 | question['answer'] = None |
| 322 | 323 | ||
| 323 | # ------------------------------------------------------------------------ | 324 | # ------------------------------------------------------------------------ |
| 324 | - def update_answer(self, ref, ans): | 325 | + def update_answer(self, ref: str, ans) -> None: |
| 325 | '''updates one answer in the test''' | 326 | '''updates one answer in the test''' |
| 326 | self['questions'][ref].set_answer(ans) | 327 | self['questions'][ref].set_answer(ans) |
| 327 | 328 | ||
| 328 | # ------------------------------------------------------------------------ | 329 | # ------------------------------------------------------------------------ |
| 329 | - def update_answers(self, answers_dict): | 330 | + def update_answers(self, answers_dict) -> None: |
| 330 | ''' | 331 | ''' |
| 331 | Given a dictionary ans={'ref': 'some answer'} updates the answers of | 332 | Given a dictionary ans={'ref': 'some answer'} updates the answers of |
| 332 | multiple questions in the test. | 333 | multiple questions in the test. |
| @@ -337,7 +338,7 @@ class Test(dict): | @@ -337,7 +338,7 @@ class Test(dict): | ||
| 337 | # self['questions'][ref]['answer'] = ans | 338 | # self['questions'][ref]['answer'] = ans |
| 338 | 339 | ||
| 339 | # ------------------------------------------------------------------------ | 340 | # ------------------------------------------------------------------------ |
| 340 | - async def correct(self): | 341 | + async def correct(self) -> float: |
| 341 | '''Corrects all the answers of the test and computes the final grade''' | 342 | '''Corrects all the answers of the test and computes the final grade''' |
| 342 | self['finish_time'] = datetime.now() | 343 | self['finish_time'] = datetime.now() |
| 343 | self['state'] = 'FINISHED' | 344 | self['state'] = 'FINISHED' |
| @@ -354,7 +355,7 @@ class Test(dict): | @@ -354,7 +355,7 @@ class Test(dict): | ||
| 354 | return self['grade'] | 355 | return self['grade'] |
| 355 | 356 | ||
| 356 | # ------------------------------------------------------------------------ | 357 | # ------------------------------------------------------------------------ |
| 357 | - def giveup(self): | 358 | + def giveup(self) -> float: |
| 358 | '''Test is marqued as QUIT and is not corrected''' | 359 | '''Test is marqued as QUIT and is not corrected''' |
| 359 | self['finish_time'] = datetime.now() | 360 | self['finish_time'] = datetime.now() |
| 360 | self['state'] = 'QUIT' | 361 | self['state'] = 'QUIT' |
| @@ -363,7 +364,7 @@ class Test(dict): | @@ -363,7 +364,7 @@ class Test(dict): | ||
| 363 | return self['grade'] | 364 | return self['grade'] |
| 364 | 365 | ||
| 365 | # ------------------------------------------------------------------------ | 366 | # ------------------------------------------------------------------------ |
| 366 | - def __str__(self): | 367 | + def __str__(self) -> str: |
| 367 | return ('Test:\n' | 368 | return ('Test:\n' |
| 368 | f' student: {self.get("student", "--")}\n' | 369 | f' student: {self.get("student", "--")}\n' |
| 369 | f' start_time: {self.get("start_time", "--")}\n' | 370 | f' start_time: {self.get("start_time", "--")}\n' |