diff --git a/BUGS.md b/BUGS.md index c1afd25..2ea1eeb 100644 --- a/BUGS.md +++ b/BUGS.md @@ -11,7 +11,6 @@ # TODO -- servir imagens/ficheiros. - session management. close after inactive time. - each topic only loads a sample of K questions (max) in random order. - radio e checkboxes, aceitar numeros como seleccao das opcoes. @@ -30,6 +29,7 @@ # FIXED +- servir imagens/ficheiros. - radio: suporte para multiplas opcoes correctas e erradas, escolhendo-se uma selecção aleatoria destas (so com 1 certa). - checkbox: cada opção pode ser uma dupla (certo, errado) sendo escolhida uma aleatória. - async/threadpool no bcrypt do initdb. diff --git a/demo/solar_system/questions.yaml b/demo/solar_system/questions.yaml index 6e891b7..63bd8bd 100644 --- a/demo/solar_system/questions.yaml +++ b/demo/solar_system/questions.yaml @@ -1,20 +1,23 @@ --- -# # --------------------------------------------------------------------------- -# - -# ref: solar-system -# type: radio -# title: Sistema solar -# text: Qual é o maior planeta do Sistema Solar? -# options: -# - Mercúrio -# - Marte -# - Júpiter -# - Têm todos o mesmo tamanho -# # opcional -# correct: 2 -# shuffle: False -# discount: True +# --------------------------------------------------------------------------- +- + ref: solar-system + type: radio + title: Sistema solar + text: | + ![planetas](planetsa.png " Planetas do Sistema Solar") + + Qual é o maior planeta do Sistema Solar? + options: + - Mercúrio + - Marte + - Júpiter + - Têm todos o mesmo tamanho + # opcional + correct: 2 + shuffle: False + discount: True # # --------------------------------------------------------------------------- # - diff --git a/serve.py b/serve.py index 92e721d..a735fb0 100755 --- a/serve.py +++ b/serve.py @@ -30,8 +30,8 @@ class WebApplication(tornado.web.Application): (r'/change_password', ChangePasswordHandler), (r'/question', QuestionHandler), # each question (r'/topic/(.+)', TopicHandler), # page for doing a topic - # (r'/file/(.+)', FileHandler), # FIXME - (r'/.*', RootHandler), # show list of topics + (r'/file/(.+)', FileHandler), # FIXME + (r'/', RootHandler), # show list of topics ] settings = { 'template_path': path.join(path.dirname(__file__), 'templates'), @@ -143,20 +143,36 @@ class TopicHandler(BaseHandler): self.redirect('/') # ---------------------------------------------------------------------------- -# FIXME +# Based on https://bhch.github.io/posts/2017/12/serving-large-files-with-tornado-safely-without-blocking/ class FileHandler(BaseHandler): @tornado.web.authenticated - def get(self, filename): + async def get(self, filename): uid = self.current_user public_dir = self.learn.get_current_public_dir(uid) filepath = path.expanduser(path.join(public_dir, filename)) + chunk_size = 1024 * 1024 # serve 1MiB multiple times try: f = open(filepath, 'rb') except FileNotFoundError: - raise tornado.web.HTTPError(404) + logging.error(f'File not found: {filepath}') + except PermissionError: + logging.error(f'No permission: {filepath}') else: - self.write(f.read()) - f.close() + with f: + while True: + chunk = f.read(chunk_size) + if not chunk: break + try: + self.write(chunk) # write the cunk to response + await self.flush() # flush the current chunk to socket + except iostream.StreamClosedError: + # client closed the connection + break + finally: + del chunk + await gen.sleep(0.000000001) # 1 nanosecond (hack) + # in tornnado 5.0 use `await asyncio.sleep(0)` instead + # ---------------------------------------------------------------------------- # respond to AJAX to get a JSON question diff --git a/tools.py b/tools.py index f45a110..4fbb5d5 100644 --- a/tools.py +++ b/tools.py @@ -99,19 +99,10 @@ class HighlightRenderer(mistune.Renderer): def table(self, header, body): return '' + header + '' + body + "
" - # def image(self, src, title, text): - # if src.startswith('javascript:'): - # src = '' - # text = mistune.escape(text, quote=True) - # if title: - # title = mistune.escape(title, quote=True) - # html = '%s' % html - # return '%s>' % html - + def image(self, src, title, alt): + alt = mistune.escape(alt, quote=True) + title = mistune.escape(title or '', quote=True) + return f'{alt}' # Pass math through unaltered - mathjax does the rendering in the browser def block_math(self, text): -- libgit2 0.21.2