Commit a08b82c950e6fccd4cf46d01f87c9001afde6b54
1 parent
0b1ced64
Exists in
master
and in
1 other branch
- changed how paths are handled so that the ~ is expanded to $HOME only when man…
…ipulating files, and not saving expanded paths (to avoid /User vs /home conflicts between OSX and Linux).
Showing
7 changed files
with
32 additions
and
20 deletions
Show diff stats
BUGS.md
| ... | ... | @@ -27,6 +27,7 @@ |
| 27 | 27 | |
| 28 | 28 | # FIXED |
| 29 | 29 | |
| 30 | +- Quando grava JSON do teste deve usar 'path' tal como definido na configuração e não expandido. Isto porque em OSX /home é /Users e quando se muda de um sistema para outro não encontra os testes. Assim, usando ~ na configuração deveria funcionar sempre. | |
| 30 | 31 | - configuração do teste não joga bem com o do aprendizations. Em particular os scripts não ficam com o mesmo path!!! |
| 31 | 32 | - configurar pf em freebsd, port forward 80 -> 8080. documentacao |
| 32 | 33 | - barras com notas em grade estão desalinhadas. | ... | ... |
app.py
| ... | ... | @@ -34,7 +34,8 @@ class App(object): |
| 34 | 34 | self.testfactory = test.TestFactory(filename, conf=conf) |
| 35 | 35 | |
| 36 | 36 | # connect to database and check registered students |
| 37 | - engine = create_engine('sqlite:///{}'.format(self.testfactory['database']), echo=False) | |
| 37 | + dbfile = path.expanduser(self.testfactory['database']) | |
| 38 | + engine = create_engine('sqlite:///{}'.format(dbfile), echo=False) | |
| 38 | 39 | self.Session = scoped_session(sessionmaker(bind=engine)) |
| 39 | 40 | |
| 40 | 41 | try: |
| ... | ... | @@ -133,7 +134,7 @@ class App(object): |
| 133 | 134 | |
| 134 | 135 | # save test in JSON format |
| 135 | 136 | fname = ' -- '.join((t['student']['number'], t['ref'], str(t['finish_time']))) + '.json' |
| 136 | - fpath = path.abspath(path.join(t['answers_dir'], fname)) | |
| 137 | + fpath = path.join(t['answers_dir'], fname) | |
| 137 | 138 | t.save_json(fpath) |
| 138 | 139 | |
| 139 | 140 | # insert test and questions into database | ... | ... |
questions.py
| ... | ... | @@ -447,7 +447,7 @@ class QuestionTextArea(Question): |
| 447 | 447 | 'correct': '' # trying to execute this will fail => grade 0.0 |
| 448 | 448 | }) |
| 449 | 449 | |
| 450 | - self['correct'] = path.abspath(path.normpath(path.join(self['path'], self['correct']))) | |
| 450 | + self['correct'] = path.join(self['path'], self['correct']) | |
| 451 | 451 | |
| 452 | 452 | #------------------------------------------------------------------------ |
| 453 | 453 | # can return negative values for wrong answers | ... | ... |
serve.py
| ... | ... | @@ -281,12 +281,19 @@ class Root(object): |
| 281 | 281 | @require(name_is('0')) |
| 282 | 282 | def review(self, test_id): |
| 283 | 283 | fname = self.app.get_json_filename_of_test(test_id) |
| 284 | - with open(fname) as f: | |
| 285 | - t = json.load(f) | |
| 286 | - r = self.template['review'].render(t=t) | |
| 287 | - # import pdfkit | |
| 288 | - # pdfkit.from_string(r, 'out.pdf') # FIXME fails getting css, images, etc | |
| 289 | - return r | |
| 284 | + try: | |
| 285 | + f = open(path.expanduser(fname)) | |
| 286 | + except FileNotFoundError: | |
| 287 | + logging.error('Cannot find "{}" for review.'.format(fname)) | |
| 288 | + except Exception as e: | |
| 289 | + raise e | |
| 290 | + else: | |
| 291 | + with f: | |
| 292 | + t = json.load(f) | |
| 293 | + return self.template['review'].render(t=t) | |
| 294 | + # FIXME | |
| 295 | + # import pdfkit | |
| 296 | + # pdfkit.from_string(r, 'out.pdf') # FIXME fails getting css, images, etc | |
| 290 | 297 | |
| 291 | 298 | @cherrypy.expose |
| 292 | 299 | @require(name_is('0')) | ... | ... |
templates/review.html
| ... | ... | @@ -226,7 +226,7 @@ |
| 226 | 226 | |
| 227 | 227 | % if t['show_points']: |
| 228 | 228 | <p class="text-right"> |
| 229 | - <small>(Cotação: ${round(q['points'] / total_points * 20.0, 1)} pontos)</small> | |
| 229 | + <small>(Cotação: ${round(q['points'] / total_points * 20.0, 2)} pontos)</small> | |
| 230 | 230 | <p> |
| 231 | 231 | % endif |
| 232 | 232 | ... | ... |
test.py
| ... | ... | @@ -74,7 +74,7 @@ class TestFactory(dict): |
| 74 | 74 | if 'ref' not in self: |
| 75 | 75 | logger.warning('Missing "ref". Will use current date/time.') |
| 76 | 76 | if 'answers_dir' not in self: |
| 77 | - logger.warning('Missing "answers_dir". Will use current directory!') | |
| 77 | + logger.warning('Missing "answers_dir". Will save to current directory {}'.format(path.abspath(path.curdir))) | |
| 78 | 78 | if 'questions_dir' not in self: |
| 79 | 79 | logger.warning('Missing "questions_dir". Using {}'.format(path.abspath(path.curdir))) |
| 80 | 80 | if 'files' not in self: |
| ... | ... | @@ -89,15 +89,15 @@ class TestFactory(dict): |
| 89 | 89 | self.setdefault('show_ref', False) |
| 90 | 90 | self.setdefault('questions_dir', path.curdir) |
| 91 | 91 | self.setdefault('answers_dir', path.curdir) |
| 92 | - self['database'] = path.abspath(path.expanduser(self['database'])) | |
| 93 | - self['questions_dir'] = path.abspath(path.expanduser(self['questions_dir'])) | |
| 94 | - self['answers_dir'] = path.abspath(path.expanduser(self['answers_dir'])) | |
| 92 | + # self['database'] = path.abspath(path.expanduser(self['database'])) | |
| 93 | + # self['questions_dir'] = path.abspath(path.expanduser(self['questions_dir'])) | |
| 94 | + # self['answers_dir'] = path.abspath(path.expanduser(self['answers_dir'])) | |
| 95 | 95 | |
| 96 | - if not path.isfile(self['database']): | |
| 96 | + if not path.isfile(path.expanduser(self['database'])): | |
| 97 | 97 | logger.critical('Can\'t find database "{}"'.format(self['database'])) |
| 98 | 98 | raise TestFactoryException() |
| 99 | 99 | |
| 100 | - if not path.isdir(self['questions_dir']): | |
| 100 | + if not path.isdir(path.expanduser(self['questions_dir'])): | |
| 101 | 101 | logger.critical('Can\'t find questions directory "{}"'.format(self['questions_dir'])) |
| 102 | 102 | raise TestFactoryException() |
| 103 | 103 | |
| ... | ... | @@ -117,7 +117,7 @@ class TestFactory(dict): |
| 117 | 117 | |
| 118 | 118 | |
| 119 | 119 | try: |
| 120 | - f = open(path.join(self['answers_dir'],'REMOVE-ME'), 'w') | |
| 120 | + f = open(path.join(path.expanduser(self['answers_dir']),'REMOVE-ME'), 'w') | |
| 121 | 121 | except EnvironmentError: |
| 122 | 122 | logger.critical('Cannot write answers to "{0}".'.format(self['answers_dir'])) |
| 123 | 123 | raise TestFactoryException() |
| ... | ... | @@ -175,7 +175,7 @@ class TestFactory(dict): |
| 175 | 175 | 'show_hints': self['show_hints'], |
| 176 | 176 | 'show_points': self['show_points'], |
| 177 | 177 | 'show_ref': self['show_ref'], |
| 178 | - 'debug': self['debug'], | |
| 178 | + 'debug': self['debug'], # required by template test.html | |
| 179 | 179 | 'database': self['database'], |
| 180 | 180 | 'questions_dir': self['questions_dir'], |
| 181 | 181 | 'files': self['files'], |
| ... | ... | @@ -249,7 +249,7 @@ class Test(dict): |
| 249 | 249 | |
| 250 | 250 | # ----------------------------------------------------------------------- |
| 251 | 251 | def save_json(self, filepath): |
| 252 | - with open(filepath, 'w') as f: | |
| 252 | + with open(path.expanduser(filepath), 'w') as f: | |
| 253 | 253 | json.dump(self, f, indent=2, default=str) |
| 254 | 254 | # HACK default=str is required for datetime objects |
| 255 | 255 | logger.info('Student {}: saved JSON file.'.format(self['student']['number'])) | ... | ... |
tools.py
| 1 | 1 | |
| 2 | +from os import path | |
| 2 | 3 | import subprocess |
| 3 | 4 | import logging |
| 5 | + | |
| 4 | 6 | import yaml |
| 5 | 7 | import markdown |
| 6 | 8 | |
| ... | ... | @@ -12,7 +14,7 @@ logger = logging.getLogger(__name__) |
| 12 | 14 | # --------------------------------------------------------------------------- |
| 13 | 15 | def load_yaml(filename, default=None): |
| 14 | 16 | try: |
| 15 | - f = open(filename, 'r', encoding='utf-8') | |
| 17 | + f = open(path.expanduser(filename), 'r', encoding='utf-8') | |
| 16 | 18 | except IOError: |
| 17 | 19 | logger.error('Can\'t open file "{}"'.format(filename)) |
| 18 | 20 | return default |
| ... | ... | @@ -30,6 +32,7 @@ def load_yaml(filename, default=None): |
| 30 | 32 | # Note: requires python 3.5+ |
| 31 | 33 | # --------------------------------------------------------------------------- |
| 32 | 34 | def run_script(script, stdin='', timeout=5): |
| 35 | + script = path.expanduser(script) | |
| 33 | 36 | try: |
| 34 | 37 | p = subprocess.run([script], |
| 35 | 38 | input=stdin, | ... | ... |