Commit 9b8820e43d7c164f7cef3372224d6b9d6975ecef
1 parent
a7d6b9e1
Exists in
dev
move run_script to questions.py
it was only used there.
Showing
2 changed files
with
86 additions
and
44 deletions
Show diff stats
aprendizations/questions.py
... | ... | @@ -11,11 +11,11 @@ import logging |
11 | 11 | from os import path |
12 | 12 | import random |
13 | 13 | import re |
14 | -from typing import Any, Dict, NewType | |
14 | +from typing import Any, Dict, List, NewType | |
15 | 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 | 20 | # setup logger for this module |
21 | 21 | logger = logging.getLogger(__name__) |
... | ... | @@ -33,8 +33,9 @@ class QuestionException(Exception): |
33 | 33 | # ============================================================================ |
34 | 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 | 39 | Instances can shuffle options or automatically generate questions. |
39 | 40 | ''' |
40 | 41 | |
... | ... | @@ -695,3 +696,44 @@ class QFactory(): |
695 | 696 | question = question_from(qdict) # returns a Question instance |
696 | 697 | question.gen() |
697 | 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 | 212 | # ---------------------------------------------------------------------------- |
213 | 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 | ... | ... |