| 266 | |
| 267 | |
| 268 | class Task: |
| 269 | |
| 270 | @contextmanager |
| 271 | def session_context(self): |
| 272 | """ |
| 273 | >>> with session_context(): |
| 274 | ... res = self.coros[-1].send(data) |
| 275 | """ |
| 276 | |
| 277 | # todo issue: with 语句可能发生嵌套,导致内层with退出时,将属性置空 |
| 278 | _context.current_session = self.session |
| 279 | _context.current_task_id = self.coro_id |
| 280 | try: |
| 281 | yield |
| 282 | finally: |
| 283 | _context.current_session = None |
| 284 | _context.current_task_id = None |
| 285 | |
| 286 | @staticmethod |
| 287 | def gen_coro_id(coro=None): |
| 288 | """生成协程id""" |
| 289 | name = 'coro' |
| 290 | if hasattr(coro, '__name__'): |
| 291 | name = coro.__name__ |
| 292 | |
| 293 | return '%s-%s' % (name, random_str(10)) |
| 294 | |
| 295 | def __init__(self, coro, session: CoroutineBasedSession, on_coro_stop=None): |
| 296 | """ |
| 297 | :param coro: 协程对象 |
| 298 | :param session: 创建该Task的会话实例 |
| 299 | :param on_coro_stop: 任务结束(正常结束或外部调用Task.close)时运行的回调 |
| 300 | """ |
| 301 | self.session = session |
| 302 | self.coro = coro |
| 303 | self.result = None |
| 304 | self.task_closed = False # 任务完毕/取消 |
| 305 | self.on_coro_stop = on_coro_stop or (lambda _: None) |
| 306 | |
| 307 | self.coro_id = self.gen_coro_id(self.coro) |
| 308 | |
| 309 | self.pending_futures = {} # id(future) -> future |
| 310 | |
| 311 | logger.debug('Task[%s] created ', self.coro_id) |
| 312 | |
| 313 | def step(self, result=None, throw_exp=False): |
| 314 | """激活协程 |
| 315 | |
| 316 | :param any result: 向协程传入的数据 |
| 317 | :param bool throw_exp: 是否向协程引发异常,为 True 时, result 参数为相应的异常对象 |
| 318 | """ |
| 319 | coro_yield = None |
| 320 | with self.session_context(): |
| 321 | try: |
| 322 | if throw_exp: |
| 323 | coro_yield = self.coro.throw(result) |
| 324 | else: |
| 325 | coro_yield = self.coro.send(result) |
no outgoing calls
no test coverage detected
searching dependent graphs…