Compare View

switch
from
...
to
 
Commits (2)
aprendizations/learnapp.py
@@ -159,8 +159,8 @@ class Application(): @@ -159,8 +159,8 @@ class Application():
159 await asyncio.sleep(random()) 159 await asyncio.sleep(random())
160 160
161 with Session(self._engine) as session: 161 with Session(self._engine) as session:
162 - query = select(Student).where(Student.id == uid)  
163 - student = session.execute(query).scalar_one_or_none() 162 + query_student = select(Student).where(Student.id == uid)
  163 + student = session.execute(query_student).scalar_one_or_none()
164 if student is None: 164 if student is None:
165 logger.info('User "%s" does not exist', uid) 165 logger.info('User "%s" does not exist', uid)
166 return False 166 return False
@@ -179,8 +179,10 @@ class Application(): @@ -179,8 +179,10 @@ class Application():
179 179
180 # get topics for this student and set its current state 180 # get topics for this student and set its current state
181 with Session(self._engine) as session: 181 with Session(self._engine) as session:
182 - query = select(StudentTopic).where(StudentTopic.student_id == uid)  
183 - student_topics = session.execute(query).scalars().all() 182 + query_student_topics = select(StudentTopic) \
  183 + .where(StudentTopic.student_id == uid)
  184 + student_topics = session.execute(query_student_topics) \
  185 + .scalars().all()
184 186
185 state = {t.topic_id: { 187 state = {t.topic_id: {
186 'level': t.level, 188 'level': t.level,
aprendizations/questions.py
@@ -11,11 +11,11 @@ import logging @@ -11,11 +11,11 @@ import logging
11 from os import path 11 from os import path
12 import random 12 import random
13 import re 13 import re
14 -from typing import Any, Dict, NewType 14 +from typing import Any, Dict, List, NewType
15 import uuid 15 import uuid
16 16
17 -# this project  
18 -from aprendizations.tools import run_script 17 +# third party libraries
  18 +import yaml
19 19
20 # setup logger for this module 20 # setup logger for this module
21 logger = logging.getLogger(__name__) 21 logger = logging.getLogger(__name__)
@@ -33,8 +33,9 @@ class QuestionException(Exception): @@ -33,8 +33,9 @@ class QuestionException(Exception):
33 # ============================================================================ 33 # ============================================================================
34 class Question(dict): 34 class Question(dict):
35 ''' 35 '''
36 - Classes derived from this base class are meant to instantiate questions  
37 - for each student. 36 + Base class for all question types
  37 +
  38 + Classes derived from this base class can instantiate questions.
38 Instances can shuffle options or automatically generate questions. 39 Instances can shuffle options or automatically generate questions.
39 ''' 40 '''
40 41
@@ -695,3 +696,44 @@ class QFactory(): @@ -695,3 +696,44 @@ class QFactory():
695 question = question_from(qdict) # returns a Question instance 696 question = question_from(qdict) # returns a Question instance
696 question.gen() 697 question.gen()
697 return question 698 return question
  699 +
  700 +# -----------------------------------------------------------------------------
  701 +async def run_script(script: str,
  702 + args: List[str],
  703 + stdin: str = '',
  704 + timeout: int = 5) -> Any:
  705 +
  706 + # normalize args
  707 + script = path.expanduser(script)
  708 + input_bytes = stdin.encode('utf-8')
  709 + args = [str(a) for a in args]
  710 +
  711 + try:
  712 + p = await asyncio.create_subprocess_exec(
  713 + script, *args,
  714 + stdin=asyncio.subprocess.PIPE,
  715 + stdout=asyncio.subprocess.PIPE,
  716 + stderr=asyncio.subprocess.DEVNULL,
  717 + )
  718 + except FileNotFoundError:
  719 + logger.error(f'Can not execute script "{script}": not found.')
  720 + except PermissionError:
  721 + logger.error(f'Can not execute script "{script}": wrong permissions.')
  722 + except OSError:
  723 + logger.error(f'Can not execute script "{script}": unknown reason.')
  724 + else:
  725 + try:
  726 + stdout, _ = await asyncio.wait_for(p.communicate(input_bytes), timeout)
  727 + except asyncio.TimeoutError:
  728 + logger.warning(f'Timeout {timeout}s exceeded running "{script}".')
  729 + return
  730 +
  731 + if p.returncode != 0:
  732 + logger.error(f'Return code {p.returncode} running "{script}".')
  733 + else:
  734 + try:
  735 + output = yaml.safe_load(stdout.decode('utf-8', 'ignore'))
  736 + except yaml.YAMLError:
  737 + logger.error(f'Error parsing yaml output of "{script}"')
  738 + else:
  739 + return output
aprendizations/tools.py
@@ -212,42 +212,42 @@ def load_yaml(filename: str, default: Any = None) -> Any: @@ -212,42 +212,42 @@ def load_yaml(filename: str, default: Any = None) -> Any:
212 # ---------------------------------------------------------------------------- 212 # ----------------------------------------------------------------------------
213 # Same as above, but asynchronous 213 # Same as above, but asynchronous
214 # ---------------------------------------------------------------------------- 214 # ----------------------------------------------------------------------------
215 -async def run_script(script: str,  
216 - args: List[str] = [],  
217 - stdin: str = '',  
218 - timeout: int = 2) -> Any:  
219 -  
220 - # normalize args  
221 - script = path.expanduser(script)  
222 - input_bytes = stdin.encode('utf-8')  
223 - args = [str(a) for a in args]  
224 -  
225 - try:  
226 - p = await asyncio.create_subprocess_exec(  
227 - script, *args,  
228 - stdin=asyncio.subprocess.PIPE,  
229 - stdout=asyncio.subprocess.PIPE,  
230 - stderr=asyncio.subprocess.DEVNULL,  
231 - )  
232 - except FileNotFoundError:  
233 - logger.error(f'Can not execute script "{script}": not found.')  
234 - except PermissionError:  
235 - logger.error(f'Can not execute script "{script}": wrong permissions.')  
236 - except OSError:  
237 - logger.error(f'Can not execute script "{script}": unknown reason.')  
238 - else:  
239 - try:  
240 - stdout, _ = await asyncio.wait_for(p.communicate(input_bytes), timeout)  
241 - except asyncio.TimeoutError:  
242 - logger.warning(f'Timeout {timeout}s exceeded running "{script}".')  
243 - return  
244 -  
245 - if p.returncode != 0:  
246 - logger.error(f'Return code {p.returncode} running "{script}".')  
247 - else:  
248 - try:  
249 - output = yaml.safe_load(stdout.decode('utf-8', 'ignore'))  
250 - except Exception:  
251 - logger.error(f'Error parsing yaml output of "{script}"')  
252 - else:  
253 - return output 215 +# async def run_script(script: str,
  216 +# args: List[str] = [],
  217 +# stdin: str = '',
  218 +# timeout: int = 5) -> Any:
  219 +#
  220 +# # normalize args
  221 +# script = path.expanduser(script)
  222 +# input_bytes = stdin.encode('utf-8')
  223 +# args = [str(a) for a in args]
  224 +#
  225 +# try:
  226 +# p = await asyncio.create_subprocess_exec(
  227 +# script, *args,
  228 +# stdin=asyncio.subprocess.PIPE,
  229 +# stdout=asyncio.subprocess.PIPE,
  230 +# stderr=asyncio.subprocess.DEVNULL,
  231 +# )
  232 +# except FileNotFoundError:
  233 +# logger.error(f'Can not execute script "{script}": not found.')
  234 +# except PermissionError:
  235 +# logger.error(f'Can not execute script "{script}": wrong permissions.')
  236 +# except OSError:
  237 +# logger.error(f'Can not execute script "{script}": unknown reason.')
  238 +# else:
  239 +# try:
  240 +# stdout, _ = await asyncio.wait_for(p.communicate(input_bytes), timeout)
  241 +# except asyncio.TimeoutError:
  242 +# logger.warning(f'Timeout {timeout}s exceeded running "{script}".')
  243 +# return
  244 +#
  245 +# if p.returncode != 0:
  246 +# logger.error(f'Return code {p.returncode} running "{script}".')
  247 +# else:
  248 +# try:
  249 +# output = yaml.safe_load(stdout.decode('utf-8', 'ignore'))
  250 +# except Exception:
  251 +# logger.error(f'Error parsing yaml output of "{script}"')
  252 +# else:
  253 +# return output