Commit a08b82c950e6fccd4cf46d01f87c9001afde6b54

Authored by Miguel Barão
1 parent 0b1ced64
Exists in master and in 1 other branch dev

- 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).
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,
... ...