Coverage for aipyapp/exec/python/runtime.py: 35%
66 statements
« prev ^ index » next coverage.py v7.10.3, created at 2025-08-11 12:02 +0200
« prev ^ index » next coverage.py v7.10.3, created at 2025-08-11 12:02 +0200
1#! /usr/bin/env python3
2# -*- coding: utf-8 -*-
3import sys
4import subprocess
5from abc import ABC, abstractmethod
6from typing import Any
8from loguru import logger
10class PythonRuntime(ABC):
11 def __init__(self, envs=None):
12 self.envs = envs or {}
13 self.packages = set()
14 self.session = {}
15 self.block_states = {}
16 self.current_state = {}
17 self.block = None
18 self.log = logger.bind(src='runtime')
20 def start_block(self, block):
21 """开始一个新的代码块执行"""
22 self.current_state = {}
23 self.block_states[block.name] = self.current_state
24 self.block = block
26 def set_state(self, success: bool, **kwargs) -> None:
27 """
28 Set the state of the current code block
30 Args:
31 success: Whether the code block is successful
32 **kwargs: Other state values
34 Example:
35 set_state(success=True, result="Hello, world!")
36 set_state(success=False, error="Error message")
37 """
38 self.current_state['success'] = success
39 self.current_state.update(kwargs)
41 def get_block_state(self, block_name: str) -> Any:
42 """
43 Get the state of code block by name
45 Args:
46 block_name: The name of the code block
48 Returns:
49 Any: The state of the code block
51 Example:
52 state = get_block_state("code_block_name")
53 if state.get("success"):
54 print(state.get("result"))
55 else:
56 print(state.get("error"))
57 """
58 return self.block_states.get(block_name)
60 def set_persistent_state(self, **kwargs) -> None:
61 """
62 Set the state of the current code block in the session
64 Args:
65 **kwargs: The state values
66 """
67 self.session.update(kwargs)
68 self.block.add_dep('set_state', list(kwargs.keys()))
70 def get_persistent_state(self, key: str) -> Any:
71 """
72 Get the state of the current code block in the session
74 Args:
75 key: The key of the state
77 Returns:
78 Any: The state of the code block
79 """
80 self.block.add_dep('get_state', key)
81 return self.session.get(key)
83 def set_env(self, name, value, desc):
84 self.envs[name] = (value, desc)
86 def ensure_packages(self, *packages, upgrade=False, quiet=False):
87 if not packages:
88 return True
90 packages = list(set(packages) - self.packages)
91 if not packages:
92 return True
94 cmd = [sys.executable, "-m", "pip", "install"]
95 if upgrade:
96 cmd.append("--upgrade")
97 if quiet:
98 cmd.append("-q")
99 cmd.extend(packages)
101 try:
102 subprocess.check_call(cmd)
103 self.packages.update(packages)
104 return True
105 except subprocess.CalledProcessError:
106 self.log.error("依赖安装失败: {}", " ".join(packages))
108 return False
110 def ensure_requirements(self, path="requirements.txt", **kwargs):
111 with open(path) as f:
112 reqs = [line.strip() for line in f if line.strip() and not line.startswith("#")]
113 return self.ensure_packages(*reqs, **kwargs)
115 @abstractmethod
116 def install_packages(self, *packages: str):
117 pass
119 @abstractmethod
120 def get_env(self, name: str, default: Any = None, *, desc: str = None) -> Any:
121 pass
123 @abstractmethod
124 def show_image(self, path: str = None, url: str = None) -> None:
125 pass
127 @abstractmethod
128 def input(self, prompt: str = '') -> str:
129 pass