Coverage for aipyapp/exec/prun.py: 51%

1#!/usr/bin/env python

2# -*- coding: utf-8 -*-

3

4""" subprocess-based bash/powershell code execution """

5

6 import traceback

7 import subprocess

8 from typing import Any, Dict, Optional

9

10 from loguru import logger

11

12 class SubprocessExecutor:

13 """使用 subprocess 执行代码块"""

14 name = None

15 command = None

16 timeout = 30 # 默认超时时间为10秒

17

18 def __init__(self, runtime=None):

19 self.runtime = runtime

20 self.log = logger.bind(src=f'{self.name}_executor')

21

22 def get_cmd(self, block) -> Optional[str]:

23 """获取执行命令"""

24 path = block.abs_path

25 if path:

26 cmd = self.command.copy()

27 cmd.append(str(path))

28 else:

29 cmd = None

30 return cmd

31

32 def __call__(self, block) -> Dict[str, Any]:

33 """执行代码块"""

34 cmd = self.get_cmd(block)

35 if not cmd:

36 return {'errstr': 'No file to execute'}

37

38 self.log.info(f"Exec: {cmd}")

39

40 try:

41 cp = subprocess.run(

42 cmd,

43 shell=False,

44 capture_output=True,

45 text=True,

46 encoding="utf-8",

47 errors="ignore",

48 timeout=self.timeout

49 )

50 stdout = cp.stdout.strip() if cp.stdout else None

51 stderr = cp.stderr.strip() if cp.stderr else None

52

53 result = {

54 'stdout': stdout,

55 'stderr': stderr,

56 'returncode': cp.returncode

57 }

58 except subprocess.TimeoutExpired:

59 result = {'errstr': f'Execution timed out after {self.timeout} seconds'}

60 except Exception as e:

61 result = {'errstr': str(e), 'traceback': str(traceback.format_exc())}

62

63 return result

64

65 class BashExecutor(SubprocessExecutor):

66 name = 'bash'

67 command = ['bash']

68

69 class PowerShellExecutor(SubprocessExecutor):

70 name = 'powershell'

71 command = ['powershell', '-Command']

72

73 class AppleScriptExecutor(SubprocessExecutor):

74 name = 'applescript'

75 command = ['osascript']

76

77 class NodeExecutor(SubprocessExecutor):

78 name = 'javascript'

79 command = ['node']