pymud 0.19.3__py3-none-any.whl → 0.19.3.post2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
pymud/session.py CHANGED
@@ -11,6 +11,18 @@ from .settings import Settings
11
11
  class Session:
12
12
  """
13
13
  会话管理主对象,每一个角色的所有处理实现均在该类中实现。
14
+
15
+ **Session对象由PyMudApp对象进行创建和管理,不需要手动创建。**
16
+
17
+ :param app: 对应的PyMudApp对象
18
+ :param name: 本会话的名称
19
+ :param host: 本会话连接的远程服务器地址
20
+ :param port: 本会话连接的远程服务器端口
21
+ :param encoding: 远程服务器的编码
22
+ :param after_connect: 当连接到远程服务器后执行的操作
23
+ :param loop: asyncio的消息循环队列
24
+ :param kwargs: 关键字参数清单,当前支持的关键字 **scripts** : 需加载的脚本清单
25
+
14
26
  """
15
27
  #_esc_regx = re.compile("\x1b\\[[^mz]+[mz]")
16
28
  _esc_regx = re.compile("\x1b\\[[\d;]+[abcdmz]", flags = re.IGNORECASE)
@@ -156,6 +168,7 @@ class Session:
156
168
  self.open()
157
169
 
158
170
  def initialize(self):
171
+ "初始化Session有关对象。 **无需脚本调用。**"
159
172
  self._line_buffer = bytearray()
160
173
 
161
174
  self._triggers = DotDict()
@@ -172,10 +185,11 @@ class Session:
172
185
  self._command_history = []
173
186
 
174
187
  def open(self):
188
+ "创建到远程服务器的连接,同步方式。通过调用异步connect方法实现。"
175
189
  asyncio.ensure_future(self.connect(), loop = self.loop)
176
190
 
177
191
  async def connect(self):
178
- "异步非阻塞方式创建远程连接"
192
+ "创建到远程服务器的连接,异步非阻塞方式。"
179
193
  def _protocol_factory():
180
194
  return MudClientProtocol(self, onDisconnected = self.onDisconnected)
181
195
 
@@ -200,11 +214,17 @@ class Session:
200
214
  asyncio.ensure_future(self.reconnect(wait), loop = self.loop)
201
215
 
202
216
  async def reconnect(self, timeout = 15):
217
+ """
218
+ 重新连接到远程服务器,异步非阻塞方式。该方法在 `Settings.client['auto_reconnect']` 设置为真时,断开后自动调用
219
+
220
+ :param timeout: 重连之前的等待时间,默认15s,可由 `Settings.client['reconnect_wait']` 设置所覆盖
221
+ """
203
222
  self.info(f"{timeout}秒之后将自动重新连接...")
204
223
  await asyncio.sleep(timeout)
205
224
  await self.create_task(self.connect())
206
225
 
207
226
  def onConnected(self):
227
+ "当连接到服务器之后执行的操作。包括打印连接时间,执行自定义事件(若设置)等。"
208
228
  now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
209
229
  self.info(f"{now}: 已成功连接到服务器")
210
230
  if isinstance(self.after_connect, str):
@@ -215,6 +235,7 @@ class Session:
215
235
  event_connected(self)
216
236
 
217
237
  def disconnect(self):
238
+ "断开到服务器的连接。"
218
239
  if self.connected:
219
240
  self.write_eof()
220
241
 
@@ -224,6 +245,7 @@ class Session:
224
245
  # self.handle_save()
225
246
 
226
247
  def onDisconnected(self, protocol):
248
+ "当从服务器连接断开时执行的操作。包括保存变量(若设置)、打印断开时间、执行自定义事件(若设置)等。"
227
249
  # 断开时自动保存变量数据
228
250
  if Settings.client["var_autosave"]:
229
251
  self.handle_save()
@@ -241,8 +263,8 @@ class Session:
241
263
  asyncio.ensure_future(self.reconnect(wait), loop = self.loop)
242
264
 
243
265
  @property
244
- def connected(self):
245
- "返回服务器端连接状态"
266
+ def connected(self) -> bool:
267
+ "只读属性,返回服务器端的连接状态"
246
268
  if self._protocol:
247
269
  con = self._protocol.connected
248
270
  else:
@@ -251,8 +273,8 @@ class Session:
251
273
  return con
252
274
 
253
275
  @property
254
- def duration(self):
255
- "返回服务器端连接的时间,以秒为单位"
276
+ def duration(self) -> float:
277
+ "只读属性,返回服务器端连接的时间,以秒为单位"
256
278
  dura = 0
257
279
  if self._protocol and self._protocol.connected:
258
280
  dura = self._protocol.duration
@@ -261,6 +283,21 @@ class Session:
261
283
 
262
284
  @property
263
285
  def status_maker(self):
286
+ """
287
+ 可读写属性,会话状态窗口的内容生成器,应为一个可返回 `AnyFormattedText` 对象的不带额外参数的方法
288
+
289
+ 示例:
290
+ .. code:: python
291
+
292
+ class Configuration:
293
+ def __init__(self, session):
294
+ self.session = session
295
+ self.session.status_maker = self.mystatus
296
+
297
+ def mystatus(self):
298
+ '可返回AnyFormattedText类型的对象。具体参见 prompt_toolkit 。'
299
+ return "this is a test status"
300
+ """
264
301
  return self._status_maker
265
302
 
266
303
  @status_maker.setter
@@ -270,6 +307,20 @@ class Session:
270
307
 
271
308
  @property
272
309
  def event_connected(self):
310
+ """
311
+ 可读写属性,自定义的会话连接事件,应为一个带一个额外参数 Session 的方法
312
+
313
+ 示例:
314
+ .. code:: Python
315
+
316
+ class Configuration:
317
+ def __init__(self, session):
318
+ self.session = session
319
+ self.session.event_connected = self.onSessionConnected
320
+
321
+ def onSessionConnected(self, session):
322
+ session.info("Connected!")
323
+ """
273
324
  return self._events["connected"]
274
325
 
275
326
  @event_connected.setter
@@ -278,6 +329,11 @@ class Session:
278
329
 
279
330
  @property
280
331
  def event_disconnected(self):
332
+ """
333
+ 可读写属性,自定义的会话断开事件,应为一个带一个参数 Session 的方法
334
+
335
+ 使用方法同 event_connected
336
+ """
281
337
  return self._events["disconnected"]
282
338
 
283
339
  @event_disconnected.setter
@@ -285,51 +341,119 @@ class Session:
285
341
  self._events["disconnected"] = event
286
342
 
287
343
  @property
288
- def modules(self):
289
- "返回本会话加载的所有模块,类型为顺序字典"
344
+ def modules(self) -> OrderedDict:
345
+ """
346
+ 只读属性,返回本会话加载的所有模块,类型为顺序字典 OrderedDict
347
+
348
+ 在字典中,关键字为模块名,值为模块本身与配置对象的二级字典,包含两个关键字, module 与 config
349
+
350
+ 如,存在一个名为 my.py的模块文件,则加载后,session.modules['my'] 可以访问该模块有关信息。其中:
351
+
352
+ - `session.modules['my']['module']` 访问模块对象
353
+ - `session.modules['my']['config']` 访问该该模块文件中的Configuration类的实例(若有定义)
354
+ """
290
355
  return self._modules
291
356
 
292
357
  @property
293
- def plugins(self):
294
- "返回PYMUD的插件清单辅助访问器"
358
+ def plugins(self) -> DotDict:
359
+ """
360
+ 只读属性,为PYMUD插件的辅助点访问器
361
+
362
+ 如,存在一个名为myplugin.py的插件文件并已正常加载,该文件中定义了 PLUGIN_NAME 为 "myplugin",则可以通过本属性及插件名访问该插件
363
+
364
+ .. code:: Python
365
+
366
+ plugin = session.plugins.myplugin # plugin为 Plugin类型的对象实例
367
+ """
295
368
  return self.application.plugins
296
369
 
297
370
  @property
298
371
  def vars(self):
299
- "本会话变量的辅助访问器"
372
+ """
373
+ 本会话内变量的辅助点访问器,可以通过vars+变量名快速访问该变量值
374
+
375
+ .. code:: Python
376
+
377
+ # 以下两个获取变量值的方法等价
378
+ exp = session.vars.exp
379
+ exp = session.getVariable('exp')
380
+
381
+ # 以下两个为变量赋值的方法等价
382
+ session.vars.exp = 10000
383
+ session.setVariable('exp', 10000)
384
+ """
300
385
  return self._variables
301
386
 
302
387
  @property
303
388
  def globals(self):
304
- "全局变量的辅助访问器"
389
+ """
390
+ 全局变量的辅助点访问器,可以通过globals+变量名快速访问该变量值
391
+
392
+ 全局变量与会话变量的区别在于,全局变量在所有会话之间是共享和统一的
393
+
394
+ .. code:: Python
395
+
396
+ # 以下两个获取全局变量值的方法等价
397
+ hooked = session.globals.hooked
398
+ hooked = session.getGlobal('hooked')
399
+
400
+ # 以下两个为全局变量赋值的方法等价
401
+ session.globals.hooked = True
402
+ session.setGlobal('hooked', True)
403
+ """
305
404
  return self.application.globals
306
405
 
307
406
  @property
308
407
  def tris(self):
309
- "本回话的触发器辅助访问器"
408
+ """
409
+ 本会话的触发器的辅助点访问器,可以通过tris+触发器id快速访问触发器
410
+
411
+ .. code:: Python
412
+
413
+ session.tris.mytri.enabled = False
414
+ """
310
415
  return self._triggers
311
416
 
312
417
  @property
313
418
  def alis(self):
314
- "本回话的别名辅助访问器"
419
+ """
420
+ 本会话的别名辅助点访问器,可以通过alis+别名id快速访问别名
421
+
422
+ .. code:: Python
423
+
424
+ session.alis.myali.enabled = False
425
+ """
315
426
  return self._aliases
316
427
 
317
428
  @property
318
429
  def cmds(self):
319
- "本回话的命令辅助访问器"
430
+ """
431
+ 本会话的命令辅助点访问器,可以通过cmds+命令id快速访问命令
432
+
433
+ .. code:: Python
434
+
435
+ session.cmds.mycmd.enabled = False
436
+ """
320
437
  return self._commands
321
438
 
322
439
  @property
323
440
  def timers(self):
324
- "本回话的定时器辅助访问器"
441
+ """
442
+ 本会话的定时器辅助点访问器,可以通过timers+定时器id快速访问定时器
443
+
444
+ .. code:: Python
445
+
446
+ session.timers.mytimer.enabled = False
447
+ """
325
448
  return self._timers
326
449
 
327
450
  @property
328
451
  def gmcp(self):
329
- "本回话的GMCP辅助访问器"
452
+ "本会话的GMCP辅助访问器"
330
453
  return self._gmcp
331
454
 
332
455
  def get_status(self):
456
+ "返回状态窗口内容的真实函数。 **脚本中无需调用。**"
333
457
  text = f"这是一个默认的状态窗口信息\n会话: {self.name} 连接状态: {self.connected}"
334
458
  if callable(self._status_maker):
335
459
  text = self._status_maker()
@@ -337,7 +461,15 @@ class Session:
337
461
  return text
338
462
 
339
463
  def getPlainText(self, rawText: str, trim_newline = False) -> str:
340
- "将带有VT100或者MXP转义字符的字符串转换为正常字符串(删除所有转义)"
464
+ """
465
+ 将带有VT100或者MXP转义字符的字符串转换为正常字符串(删除所有转义)。 **脚本中无需调用。**
466
+
467
+ :param rawText: 原始文本对象
468
+ :param trim_newline: 返回值是否删除末尾的回车符和换行符
469
+
470
+ :return: 经处理后的纯文本字符串
471
+
472
+ """
341
473
  plainText = self._esc_regx.sub("", rawText)
342
474
  if trim_newline:
343
475
  plainText = plainText.rstrip("\n").rstrip("\r")
@@ -345,7 +477,12 @@ class Session:
345
477
  return plainText
346
478
 
347
479
  def writetobuffer(self, data, newline = False):
348
- "将数据写入到用于本地显示的缓冲中"
480
+ """
481
+ 将数据写入到用于本地显示的缓冲中。 **脚本中无需调用。**
482
+
483
+ :param data: 写入的数据, 应为 str 类型
484
+ :param newline: 是否额外增加换行符
485
+ """
349
486
  self.buffer.insert_text(data)
350
487
 
351
488
  if len(data) > 0 and (data[-1] == "\n"):
@@ -356,18 +493,29 @@ class Session:
356
493
  self._line_count += 1
357
494
 
358
495
  def clear_half(self):
359
- "清除过多缓冲"
496
+ """
497
+ 清除半数缓冲。 **脚本中无需调用。**
498
+
499
+ 半数的数量由 Settings.client['buffer_lines'] 确定,默认为5000行。
500
+ """
360
501
  if (self._line_count >= 2 * Settings.client["buffer_lines"]) and self.buffer.document.is_cursor_at_the_end:
361
502
  self._line_count = self.buffer.clear_half()
362
503
 
363
504
  def feed_data(self, data) -> None:
364
- "永远只会传递1个字节的数据,以bytes形式"
505
+ """
506
+ 由协议对象调用,将收到的远程数据加入会话缓冲。永远只会传递1个字节的数据,以bytes形式。 **脚本中无需调用。**
507
+
508
+ :param data: 传入的数据, bytes 格式
509
+ """
365
510
  self._line_buffer.extend(data)
366
511
 
367
512
  if (len(data) == 1) and (data[0] == ord("\n")):
368
513
  self.go_ahead()
369
514
 
370
515
  def feed_eof(self) -> None:
516
+ """
517
+ 由协议对象调用,处理收到远程 eof 数据,即远程断开连接。 **脚本中无需调用。**
518
+ """
371
519
  self._eof = True
372
520
  if self.connected:
373
521
  self._transport.write_eof()
@@ -375,6 +523,16 @@ class Session:
375
523
  self.log.info(f"服务器断开连接! {self._protocol.__repr__}")
376
524
 
377
525
  def feed_gmcp(self, name, value) -> None:
526
+ """
527
+ 由协议对象调用,处理收到远程 GMCP 数据。 **脚本中无需调用。**
528
+
529
+ :param name: 收到的GMCP数据的 name
530
+ :param value: 收到的GMCP数据的 value。 该数据值类型为 字符串形式执行过eval后的结果
531
+
532
+ **注** 当未通过GMCPTrigger对某个name的GMCP数据进行处理时,会通过session.info将该GMCP数据打印出来以供调试。
533
+ 当已有GMCPTrigger处理该name的GMCP数据时,则不会再打印此信息。
534
+ """
535
+
378
536
  nothandle = True
379
537
  if name in self._gmcp.keys():
380
538
  gmcp = self._gmcp[name]
@@ -386,13 +544,32 @@ class Session:
386
544
  self.info(f"{name}: {value}", "GMCP")
387
545
 
388
546
  def feed_msdp(self, name, value) -> None:
547
+ """
548
+ 由协议对象调用,处理收到远程 MSDP 数据。 **脚本中无需调用。**
549
+
550
+ :param name: 收到的MSDP数据的 name
551
+ :param value: 收到的MSDP数据的 value
552
+
553
+ **注** 由于北大侠客行不支持MSDP,因此该函数体并未实现
554
+ """
389
555
  pass
390
556
 
391
557
  def feed_mssp(self, name, value) -> None:
392
- pass
558
+ """
559
+ 由协议对象调用,处理收到远程 MSSP 数据。 **脚本中无需调用。**
560
+
561
+ :param name: 收到的MSSP数据的 name
562
+ :param value: 收到的MSSP数据的 value
563
+
564
+ **注** 由于北大侠客行不支持MSSP,因此该函数体并未实现
565
+ """
393
566
 
394
567
  def go_ahead(self) -> None:
395
- "把当前接收缓冲内容放到显示缓冲中"
568
+ """
569
+ 对当前接收缓冲内容进行处理并放到显示缓冲中。 **脚本中无需调用。**
570
+
571
+ 触发器的响应在该函数中进行处理。
572
+ """
396
573
  raw_line = self._line_buffer.decode(self.encoding, Settings.server["encoding_errors"])
397
574
  tri_line = self.getPlainText(raw_line, trim_newline = True)
398
575
  self._line_buffer.clear()
@@ -441,43 +618,88 @@ class Session:
441
618
  self.writetobuffer(self.display_line)
442
619
 
443
620
  def set_exception(self, exc: Exception):
621
+ """
622
+ 由协议对象调用,处理异常。 **脚本中无需调用。**
623
+
624
+ :param exc: 异常对象
625
+ """
444
626
  self.error(f"连接过程中发生异常,异常信息为: {exc}")
445
- pass
627
+
446
628
 
447
629
  def create_task(self, coro, *args, name: str = None) -> asyncio.Task:
630
+ """
631
+ 创建一个任务,并将其加入到会话的任务管理队列中。
632
+
633
+ 加入会话管理的任务,在任务完成(结束或中止)后,会自动从管理队列中移除。
634
+
635
+ :param coro: 一个async定义的协程对象或者其他可等待对象
636
+ :param name: 任务的名称定义,可选项。该属性仅在3.10及以后的Python版本中支持
637
+
638
+ 示例:
639
+ .. code:: Python
640
+
641
+ class Configuration:
642
+ def __init__(self, session):
643
+ self.session = session
644
+ self.session.create_task(self.async_example())
645
+
646
+ async def async_example(self):
647
+ await asyncio.sleep(1)
648
+ self.session.info("show a message after 1 second")
649
+ """
448
650
  if self.pyversion in ["3.7", "3.8", "3.9"]:
449
651
  task = self.loop.create_task(coro)
450
- #task = asyncio.create_task(coro)
451
652
  else:
452
653
  task = self.loop.create_task(coro, name = name)
453
- #task = asyncio.create_task(coro, name = name)
654
+
454
655
  task.add_done_callback(self._tasks.discard)
455
656
  self._tasks.add(task)
456
- #self._tasks.append(task)
657
+
457
658
  return task
458
659
 
459
660
  def remove_task(self, task: asyncio.Task, msg = None):
661
+ """
662
+ 清除一个受本会话管理的任务。若任务未完成,则取消该任务。
663
+
664
+ 由于加入会话管理的任务,在任务完成后会自动从管理队列中移除,因此该方法主要用来取消未完成的任务。
665
+
666
+ :param task: 由本会话管理的一个 asyncio.Task 对象
667
+ :param msg: 本意是用来反馈 task.cancel() 时的消息,但为了保持兼容低版本Python环境,该参数并未使用。
668
+ """
460
669
  result = task.cancel()
461
670
  self._tasks.discard(task)
462
- # if task in self._tasks:
463
- # self._tasks.remove(task)
671
+
464
672
  return result
465
673
 
466
674
  def clean_finished_tasks(self):
467
- "清理已经完成的任务"
468
- self._tasks = set([t for t in self._tasks if not t.done()])
675
+ # 清理已经完成的任务。
676
+ # 自PyMUD 0.19.2post2版之后,清理完成任务在该任务完成时刻自动调用,因此本函数不再使用,保留的目的是为了向前兼容。
469
677
 
470
- # for task in self._tasks:
471
- # if isinstance(task, asyncio.Task) and task.done():
472
- # self._tasks.remove(task)
678
+ self._tasks = set([t for t in self._tasks if not t.done()])
473
679
 
474
680
  def write(self, data) -> None:
475
- "向服务器写入数据(RAW格式字节数组/字节串)"
681
+ """
682
+ 向服务器写入数据(RAW格式字节数组/字节串)。 **一般不应在脚本中直接调用。**
683
+
684
+ :param data: 向传输中写入的数据, 应为 bytes, bytearray, memoryview 类型
685
+ """
476
686
  if self._transport and not self._transport.is_closing():
477
687
  self._transport.write(data)
478
688
 
479
689
  def writeline(self, line: str) -> None:
480
- "向服务器中写入一行。如果使用;分隔(使用Settings.client.seperator指定)的多个命令,将逐行写入"
690
+ """
691
+ 向服务器中写入一行,用于向服务器写入不经别名或命令解析时的数据。将自动在行尾添加换行符。
692
+
693
+ - 如果line中包含分隔符(由Settings.client.seperator指定,默认为半角分号;)的多个命令,将逐行依次写入。
694
+ - 当 Settings.cleint["echo_input"] 为真时,向服务器写入的内容同时在本地缓冲中回显。
695
+
696
+ :param line: 字符串行内容
697
+
698
+ 示例:
699
+ .. code:: Python
700
+
701
+ session.writeline("open door")
702
+ """
481
703
  if self.seperator in line:
482
704
  lines = line.split(self.seperator)
483
705
  for ln in lines:
@@ -497,8 +719,22 @@ class Session:
497
719
 
498
720
  def exec(self, cmd: str, name = None, *args, **kwargs):
499
721
  """
500
- 在名称为name的会话中使用exec_command执行MUD命令
501
- 当不指定name时,在当前会话中执行。
722
+ 在名称为name的会话中使用exec_command执行MUD命令。当不指定name时,在当前会话中执行。
723
+
724
+ - exec 与 writeline 都会向服务器写入数据。其差异在于,exec执行的内容,会先经过Alias处理和Command处理,实际向远程发送内容与cmd可以不一致。
725
+ - exec 在内部通过调用 exec_command 实现, exec 可以实现与 exec_command 完全相同的功能
726
+ - exec 是后来增加的函数,因此保留 exec_command 的目的是为了脚本的向前兼容
727
+
728
+ :param cmd: 要执行的命令
729
+ :param name: 要执行命令的会话的名称,当不指定时,在当前会话执行。
730
+ :param args: 保留兼容与扩展性所需,脚本中调用时无需指定
731
+ :param kwargs: 保留兼容与扩展性所需,脚本中调用时无需指定
732
+
733
+ 示例:
734
+ .. code:: Python
735
+
736
+ session.addAlias(SimpleAlias(self.session, "^cb\s(\S+)\s(\S+)", "#3 get %1 from jinnang;#wa 250;combine gem;#wa 250;pack gem", id = "ali_combine"))
737
+ session.exec("cb j1a")
502
738
  """
503
739
  name = name or self.name
504
740
  if name in self.application.sessions.keys():
@@ -507,10 +743,32 @@ class Session:
507
743
  else:
508
744
  self.error(f"不存在名称为{name}的会话")
509
745
 
746
+ async def exec_async(self, cmd: str, name = None, *args, **kwargs):
747
+ """
748
+ exec的异步形式。在名称为name的会话中使用exec_command_async执行MUD命令。当不指定name时,在当前会话中执行。
749
+
750
+ - exec_async 在内部通过调用 exec_command_async 实现, exec_async 可以实现与 exec_command_async 完全相同的功能
751
+ - exec_async 是后来增加的函数,因此保留 exec_command_async 的目的是为了脚本的向前兼容
752
+ - 异步调用时,该函数要等待对应的代码执行完毕后才会返回。可以用于确保命令执行完毕。
753
+ """
754
+ name = name or self.name
755
+ if name in self.application.sessions.keys():
756
+ session = self.application.sessions[name]
757
+ await session.exec_command_async(cmd, *args, **kwargs)
758
+ else:
759
+ self.error(f"不存在名称为{name}的会话")
760
+
761
+
762
+
510
763
  def exec_code(self, cl: CodeLine, *args, **kwargs):
511
764
  """
512
- 执行解析为CodeLine形式的MUD命令(必定为单个命令)
513
- 这是新修改命令执行后的最核心执行函数,所有真实调用的起源
765
+ 执行解析为CodeLine形式的MUD命令(必定为单个命令)。一般情况下,脚本中不应调用该方法,而应使用exec/exec_command。
766
+
767
+ 这是命令执行的最核心执行函数,所有真实调用的起源(同步调用情况下)
768
+
769
+ :param cl: CodeLine形式的执行代码
770
+ :param args: 保留兼容与扩展性所需
771
+ :param kwargs: 保留兼容与扩展性所需
514
772
  """
515
773
  if cl.length == 0:
516
774
  self.writeline("")
@@ -565,8 +823,15 @@ class Session:
565
823
 
566
824
  async def exec_code_async(self, cl: CodeLine, *args, **kwargs):
567
825
  """
568
- 执行解析为CodeLine形式的MUD命令(必定为单个命令)
569
- 这是新修改命令执行后的最核心执行函数,所有真实调用的起源
826
+ 该方法为exec_code的异步形式实现。一般情况下,脚本中不应调用该方法,而应使用 exec_command_async。
827
+
828
+ 这是命令执行的最核心执行函数,所有真实调用的起源(异步调用情况下)。
829
+
830
+ 异步调用时,该函数要等待对应的代码执行完毕后才会返回。可以用于确保命令执行完毕。
831
+
832
+ :param cl: CodeLine形式的执行代码
833
+ :param args: 保留兼容与扩展性所需
834
+ :param kwargs: 保留兼容与扩展性所需
570
835
  """
571
836
  if cl.length == 0:
572
837
  self.writeline("")
@@ -606,7 +871,7 @@ class Session:
606
871
  handler = self._cmds_handler.get(cmd, None)
607
872
  if handler and callable(handler):
608
873
  if asyncio.iscoroutinefunction(handler):
609
- await handler(code = cl, *args, **kwargs)
874
+ await self.create_task(handler(code = cl, *args, **kwargs))
610
875
  else:
611
876
  handler(code = cl, *args, **kwargs)
612
877
  else:
@@ -618,7 +883,11 @@ class Session:
618
883
 
619
884
  def exec_text(self, cmdtext: str):
620
885
  """
621
- 执行文本形式的MUD命令(必定为单个命令,且确定不是#开头的)
886
+ 执行文本形式的MUD命令。必定为单个命令,且确定不是#开头的,同时不进行参数替代
887
+
888
+ 一般情况下,脚本中不应调用该方法,而应使用 exec/exec_command。
889
+
890
+ :param cmdtext: 纯文本命令
622
891
  """
623
892
  isNotCmd = True
624
893
  for command in self._commands.values():
@@ -644,9 +913,13 @@ class Session:
644
913
  if notAlias:
645
914
  self.writeline(cmdtext)
646
915
 
647
- # self.clean_finished_tasks()
648
-
649
916
  async def exec_text_async(self, cmdtext: str):
917
+ """
918
+ 该方法为 exec_text 的异步形式实现。一般情况下,脚本中不应调用该方法,而应使用 exec_async/exec_command_async。
919
+
920
+ 异步调用时,该函数要等待对应的代码执行完毕后才会返回。可以用于确保命令执行完毕。
921
+ """
922
+
650
923
  isNotCmd = True
651
924
  for command in self._commands.values():
652
925
  if isinstance(command, Command) and command.enabled:
@@ -673,10 +946,18 @@ class Session:
673
946
 
674
947
  def exec_command(self, line: str, *args, **kwargs) -> None:
675
948
  """
676
- 执行MUD命令。多个命令可以用分隔符隔开。
677
- 此函数中,多个命令是一次性发送到服务器的,并未进行等待确认上一条命令执行完毕
678
- 本函数和writeline的区别在于,本函数会先进行Command和Alias解析,若不是再使用writeline发送
679
- 当line不包含Command和Alias时,等同于writeline
949
+ 在当前会话中执行MUD命令。多个命令可以用分隔符隔开。
950
+
951
+ - 此函数中,多个命令是一次性发送到服务器的,并未进行等待确认上一条命令执行完毕。
952
+ - 若要等待每一个命令执行完毕后再进行下一个命令,则应使用本函数的异步形式 exec_command_async
953
+ - 本函数和writeline的区别在于,本函数会先进行Command和Alias解析,若不是再使用writeline发送
954
+ - 当line不包含Command和Alias时,等同于writeline
955
+ - 本函数使用方法与 exec 相同,差异在于不能指定会话名
956
+ - exec 是后来增加的函数,因此保留 exec_command 的目的是为了脚本的向前兼容
957
+
958
+ :param line: 需指定的内容
959
+ :param args: 保留兼容性与扩展性需要
960
+ :param kwargs: 保留兼容性与扩展性需要
680
961
  """
681
962
 
682
963
  ## 以下为函数执行本体
@@ -690,7 +971,12 @@ class Session:
690
971
  cb.execute(self)
691
972
 
692
973
  def exec_command_after(self, wait: float, line: str):
693
- "延时一段时间之后,执行命令(exec_command)"
974
+ """
975
+ 延时一段时间之后,执行命令exec_command
976
+
977
+ :param wait: float, 延时等待时间,单位为秒。
978
+ :param line: str, 延时等待结束后执行的内容
979
+ """
694
980
  async def delay_task():
695
981
  await asyncio.sleep(wait)
696
982
  self.exec_command(line)
@@ -699,8 +985,12 @@ class Session:
699
985
 
700
986
  async def exec_command_async(self, line: str, *args, **kwargs):
701
987
  """
702
- 异步执行MUD命令,是exec_command的异步实现
703
- 异步时,多个命令是逐个发送到服务器的,每一命令都等待确认上一条命令执行完毕,且多命令之间会插入interval时间等待
988
+ exec_command 的异步形式。在当前会话中执行MUD命令。多个命令可以用分隔符隔开。
989
+
990
+ - 异步时,多个命令是逐个发送到服务器的,每一命令都等待确认上一条命令执行完毕,且多命令之间会插入一定时间等待
991
+ - 多个命令之间的间隔等待时间由 Settings.client["interval"] 指定,单位为 ms
992
+ - 本函数使用方法与 exec_async 相同,差异在于不能指定会话名
993
+ - exec_async 是后来增加的函数,因此保留 exec_command_async 的目的是为了脚本的向前兼容
704
994
  """
705
995
 
706
996
  ## 以下为函数执行本体
@@ -715,19 +1005,39 @@ class Session:
715
1005
  await cb.async_execute(self)
716
1006
 
717
1007
  def write_eof(self) -> None:
1008
+ """
1009
+ 向服务器发送 eof 信息,即与服务器断开连接。 **脚本中无需调用。**
1010
+
1011
+ 若要在脚本中控制断开与服务器的连接,请使用 session.disconnect()
1012
+ """
718
1013
  self._transport.write_eof()
719
1014
 
720
1015
  def getUniqueNumber(self):
721
- "获取本session中的唯一编号"
1016
+ """
1017
+ 获取本session中的唯一数值。该方法用来为各类对象生成随机不重复ID
1018
+
1019
+ :return: 返回为整数,返回结果在本会话中唯一。
1020
+ """
722
1021
  self._uid += 1
723
1022
  return self._uid
724
1023
 
725
1024
  def getUniqueID(self, prefix):
726
- "根据唯一编号获取本session中的唯一名称, 格式为: prefix_uid"
1025
+ """
1026
+ 根据唯一编号获取本session中的唯一名称, 格式为: prefix_uid
1027
+
1028
+ :param prefix: 为唯一数值增加的前缀
1029
+ :return: 形式为 prefix_uid 的唯一标识
1030
+ """
727
1031
  return "{0}_{1}".format(prefix, self.getUniqueNumber())
728
1032
 
729
1033
  def enableGroup(self, group: str, enabled = True):
730
- "使能或禁用Group中所有对象, 返回组内对象个数。顺序为:别名,触发器,命令,定时器,GMCP"
1034
+ """
1035
+ 使能或禁用Group中所有对象, 返回组内各对象个数。
1036
+
1037
+ :param group: 组名,即各对象的 group 属性的值
1038
+ :param enabled: 使能/禁用开关。为True时表示使能, False为禁用
1039
+ :return: 5个整数的列表,依次表示改组内操作的 别名,触发器,命令,定时器,GMCP 的个数
1040
+ """
731
1041
  counts = [0, 0, 0, 0, 0]
732
1042
  for ali in self._aliases.values():
733
1043
  if isinstance(ali, Alias) and (ali.group == group):
@@ -800,59 +1110,158 @@ class Session:
800
1110
  self._delObject(id, cls)
801
1111
 
802
1112
  def addAliases(self, alis: dict):
803
- "向会话中增加多个别名"
1113
+ """
1114
+ 向会话中增加多个别名
1115
+
1116
+ :param alis: 多个别名的字典。字典 key 应为每个别名的 id。
1117
+
1118
+ 示例:
1119
+ .. code:: Python
1120
+
1121
+ class Configuration:
1122
+ def __init__(self, session):
1123
+ self.session = session
1124
+ self._aliases = dict()
1125
+
1126
+ self._initAliases()
1127
+
1128
+ def _initAliases(self):
1129
+ self._aliases['my_ali1'] = SimpleAlias(self.session, "n", "north", id = "my_ali1")
1130
+ self._aliases['my_ali2'] = SimpleAlias(self.session, "s", "south", id = "my_ali2")
1131
+ self.session.addAliases(self._aliases)
1132
+ """
804
1133
  self._addObjects(alis, Alias)
805
1134
 
806
1135
  def addCommands(self, cmds: dict):
807
- "向会话中增加多个命令"
1136
+ """
1137
+ 向会话中增加多个命令。使用方法与 addAliases 类似。
1138
+
1139
+ :param cmds: 多个命令的字典。字典 key 应为每个命令的 id。
1140
+ """
808
1141
  self._addObjects(cmds, Command)
809
1142
 
810
1143
  def addTriggers(self, tris: dict):
811
- "向会话中增加多个触发器"
1144
+ """
1145
+ 向会话中增加多个触发器。使用方法与 addAliases 类似。
1146
+
1147
+ :param tris: 多个触发器的字典。字典 key 应为每个触发器的 id。
1148
+ """
812
1149
  self._addObjects(tris, Trigger)
813
1150
 
814
1151
  def addGMCPs(self, gmcps: dict):
815
- "增加多个GMCP处理函数"
1152
+ """
1153
+ 向会话中增加多个GMCPTrigger。使用方法与 addAliases 类似。
1154
+
1155
+ :param gmcps: 多个GMCPTrigger的字典。字典 key 应为每个GMCPTrigger的 id。
1156
+ """
816
1157
  self._addObjects(gmcps, GMCPTrigger)
817
1158
 
818
1159
  def addTimers(self, tis: dict):
819
- "向会话中增加多个定时器"
1160
+ """
1161
+ 向会话中增加多个定时器。使用方法与 addAliases 类似。
1162
+
1163
+ :param tis: 多个定时器的字典。字典 key 应为每个定时器的 id。
1164
+ """
820
1165
  self._addObjects(tis, Timer)
821
1166
 
822
1167
  def addAlias(self, ali: Alias):
823
- "向会话中增加别名"
1168
+ """
1169
+ 向会话中增加一个别名。
1170
+
1171
+ :param ali: 要增加的别名对象,应为 Alias 类型或其子类
1172
+ """
824
1173
  self._addObject(ali, Alias)
825
1174
 
826
1175
  def addCommand(self, cmd: Command):
827
- "向会话中增加命令"
1176
+ """
1177
+ 向会话中增加一个命令。
1178
+
1179
+ :param cmd: 要增加的命令对象,应为 Command 类型或其子类
1180
+ """
828
1181
  self._addObject(cmd, Command)
829
1182
 
830
1183
  def addTrigger(self, tri: Trigger):
831
- "向会话中增加触发器"
1184
+ """
1185
+ 向会话中增加一个触发器。
1186
+
1187
+ :param tri: 要增加的触发器对象,应为 Trigger 类型或其子类
1188
+ """
832
1189
  self._addObject(tri, Trigger)
833
1190
 
834
1191
  def addTimer(self, ti: Timer):
835
- "向会话中增加定时器"
1192
+ """
1193
+ 向会话中增加一个定时器。
1194
+
1195
+ :param ti: 要增加的定时器对象,应为 Timer 类型或其子类
1196
+ """
836
1197
  self._addObject(ti, Timer)
837
1198
 
838
1199
  def addGMCP(self, gmcp: GMCPTrigger):
839
- "增加GMCP处理函数"
1200
+ """
1201
+ 向会话中增加一个GMCP触发器。
1202
+
1203
+ :param gmcp: 要增加的GMCP触发器对象,应为 GMCPTrigger 类型或其子类
1204
+ """
1205
+
840
1206
  self._addObject(gmcp, GMCPTrigger)
841
1207
 
842
1208
  def delAlias(self, ali):
843
- "从会话中移除别名,可接受Alias对象或alias的id"
1209
+ """
1210
+ 从会话中移除一个别名,可接受 Alias 对象或其 id
1211
+
1212
+ :param ali: 要删除的别名指代,可以为别名 id 或者别名自身
1213
+
1214
+ 示例:
1215
+ .. code:: Python
1216
+
1217
+ class Configuration:
1218
+ def __init__(self, session):
1219
+ self.session = session
1220
+
1221
+ ali = Alias(session, "s", "south", id = "my_ali1")
1222
+ session.addAlias(ali)
1223
+
1224
+ # 以下两行语句均可以删除该别名
1225
+ session.delAlias("my_ali1")
1226
+ session.delAlias(ali)
1227
+ """
844
1228
  if isinstance(ali, Alias):
845
1229
  self._delObject(ali.id, Alias)
846
1230
  elif isinstance(ali, str) and (ali in self._aliases.keys()):
847
1231
  self._delObject(ali, Alias)
848
1232
 
849
1233
  def delAliases(self, ali_es: Iterable):
850
- "删除一组别名"
1234
+ """
1235
+ 从会话中移除一组别名,可接受 Alias 对象或其 id 的迭代器
1236
+
1237
+ :param ali_es: 要删除的一组别名指代,可以为别名 id 或者别名自身的列表
1238
+
1239
+ 示例:
1240
+ .. code:: Python
1241
+
1242
+ class Configuration:
1243
+ def __init__(self, session):
1244
+ self.session = session
1245
+ self._aliases = dict()
1246
+
1247
+ self._aliases["my_ali1"] = Alias(session, "s", "south", id = "my_ali1")
1248
+ self._aliases["my_ali2"] = Alias(session, "n", "north", id = "my_ali2")
1249
+
1250
+ session.addAliases(self._aliase)
1251
+
1252
+ # 以下两行语句均可以删除两个别名
1253
+ session.delAliases(self._aliases)
1254
+ session.delAliases(self._aliases.keys())
1255
+ """
851
1256
  for ali in ali_es:
852
1257
  self.delAlias(ali)
853
1258
 
854
1259
  def delCommand(self, cmd):
855
- "从会话中移除命令,可接受Command对象或command的id"
1260
+ """
1261
+ 从会话中移除一个命令,可接受 Command 对象或其 id。使用方法与 delAlias 类似
1262
+
1263
+ :param cmd: 要删除的命令指代,可以为命令id或者命令自身
1264
+ """
856
1265
  if isinstance(cmd, Command):
857
1266
  cmd.reset()
858
1267
  self._delObject(cmd.id, Command)
@@ -861,24 +1270,42 @@ class Session:
861
1270
  self._delObject(cmd, Command)
862
1271
 
863
1272
  def delCommands(self, cmd_s: Iterable):
864
- "删除一组命令"
1273
+ """
1274
+ 从会话中移除一组命令,可接受可接受 Command 对象或其 id 的迭代器。使用方法与 delAliases 类似
1275
+
1276
+ :param cmd_s: 要删除的命令指代,可以为命令 id 或者命令自身的列表
1277
+ """
865
1278
  for cmd in cmd_s:
866
1279
  self.delCommand(cmd)
867
1280
 
868
1281
  def delTrigger(self, tri):
869
- "从会话中移除触发器,可接受Trigger对象或trigger的id"
1282
+ """
1283
+ 从会话中移除一个触发器,可接受 Trigger 对象或其的id。使用方法与 delAlias 类似
1284
+
1285
+ :param tri: 要删除的触发器指代,可以为触发器 id 或者触发器自身
1286
+ """
1287
+
870
1288
  if isinstance(tri, Trigger):
871
1289
  self._delObject(tri.id, Trigger)
872
1290
  elif isinstance(tri, str) and (tri in self._triggers.keys()):
873
1291
  self._delObject(tri, Trigger)
874
1292
 
875
1293
  def delTriggers(self, tri_s: Iterable):
876
- "删除一组触发器"
1294
+ """
1295
+ 从会话中移除一组触发器,可接受可接受 Trigger 对象或其 id 的迭代器。使用方法与 delAliases 类似
1296
+
1297
+ :param tri_s: 要删除的触发器指代,可以为触发器 id 或者触发器自身的列表
1298
+ """
877
1299
  for tri in tri_s:
878
1300
  self.delTrigger(tri)
879
1301
 
880
1302
  def delTimer(self, ti):
881
- "从会话中移除定时器,可接受Timer对象或者timer的id"
1303
+ """
1304
+ 从会话中移除一个定时器,可接受 Timer 对象或其的id。使用方法与 delAlias 类似
1305
+
1306
+ :param ti: 要删除的定时器指代,可以为定时器 id 或者定时器自身
1307
+ """
1308
+
882
1309
  if isinstance(ti, Timer):
883
1310
  ti.enabled = False
884
1311
  self._delObject(ti.id, Timer)
@@ -887,24 +1314,40 @@ class Session:
887
1314
  self._delObject(ti, Timer)
888
1315
 
889
1316
  def delTimers(self, ti_s: Iterable):
890
- "删除一组定时器"
1317
+ """
1318
+ 从会话中移除一组定时器,可接受可接受 Timer 对象或其 id 的迭代器。使用方法与 delAliases 类似
1319
+
1320
+ :param ti_s: 要删除的定时器指代,可以为定时器 id 或者定时器自身的列表
1321
+ """
891
1322
  for ti in ti_s:
892
1323
  self.delTimer(ti)
893
1324
 
894
1325
  def delGMCP(self, gmcp: GMCPTrigger):
895
- "从会话中移除GMCP触发器,可接受GMCPTrigger对象或其id"
1326
+ """
1327
+ 从会话中移除一个GMCP触发器,可接受 GMCPTrigger 对象或其的id。使用方法与 delAlias 类似
1328
+
1329
+ :param gmcp: 要删除的GMCP触发器指代,可以为GMCP触发器 id 或者GMCP触发器自身
1330
+ """
896
1331
  if isinstance(gmcp, GMCPTrigger):
897
1332
  self._delObject(gmcp.id, GMCPTrigger)
898
1333
  elif isinstance(gmcp, str) and (gmcp in self._gmcp.keys()):
899
1334
  self._delObject(gmcp, GMCPTrigger)
900
1335
 
901
1336
  def delGMCPs(self, gmcp_s: Iterable):
902
- "删除一组GMCP"
1337
+ """
1338
+ 从会话中移除一组GMCP触发器,可接受可接受 GMCPTrigger 对象或其 id 的迭代器。使用方法与 delAliases 类似
1339
+
1340
+ :param gmcp_s: 要删除的GMCP触发器指代,可以为 id 或者GMCP触发器自身的列表
1341
+ """
903
1342
  for gmcp in gmcp_s:
904
1343
  self.delGMCP(gmcp)
905
1344
 
906
1345
  def replace(self, newstr):
907
- "替换当前行内容显示为newstr"
1346
+ """
1347
+ 将当前行内容显示替换为newstr。该方法仅在用于触发器的同步处置中才能正确相应
1348
+
1349
+ :param newstr: 替换后的内容
1350
+ """
908
1351
  if len(newstr) > 0:
909
1352
  newstr += Settings.client["newline"]
910
1353
  self.display_line = newstr
@@ -914,23 +1357,66 @@ class Session:
914
1357
  ## 变量 Variables 处理
915
1358
  ## ###################
916
1359
  def delVariable(self, name):
917
- """删除一个变量"""
1360
+ """
1361
+ 删除一个变量。删除变量是从session管理的变量列表中移除关键字,而不是设置为 None
1362
+
1363
+ :param name: 变量名
1364
+ """
918
1365
  assert isinstance(name, str), "name必须是一个字符串"
919
1366
  if name in self._variables.keys():
920
1367
  self._variables.pop(name)
921
1368
 
922
1369
  def setVariable(self, name, value):
923
- """设置一个变量的值"""
1370
+ """
1371
+ 设置一个变量的值。可以使用vars快捷点访问器实现同样效果。
1372
+
1373
+ :param name: 变量名。变量名必须为一个字符串
1374
+ :param value: 变量的值。变量值可以为任意 Python 类型。但为了要保存变量数据到硬盘,建议使用可序列化类型。
1375
+
1376
+ 示例:
1377
+ .. code:: Python
1378
+
1379
+ # 以下两种方式等价
1380
+ session.setVariable("myvar1", "the value")
1381
+ session.vars.myvar1 = "the value"
1382
+ """
924
1383
  assert isinstance(name, str), "name必须是一个字符串"
925
1384
  self._variables[name] = value
926
1385
 
927
1386
  def getVariable(self, name, default = None):
1387
+ """
1388
+ 获取一个变量的值。可以使用vars快捷点访问器实现类似效果,但vars访问时,默认值总为None。
1389
+
1390
+ :param name: 变量名。变量名必须为一个字符串
1391
+ :param default: 当会话中不存在该变量时,返回的值。默认为 None。
1392
+ :return: 变量的值,或者 default
1393
+
1394
+ 示例:
1395
+ .. code:: Python
1396
+
1397
+ # 以下两种方式等价
1398
+ myvar = session.getVariable("myvar1", None)
1399
+ myvar = session.vars.myvar1
1400
+ """
928
1401
  """获取一个变量的值. 当name指定的变量不存在时,返回default"""
929
1402
  assert isinstance(name, str), "name必须是一个字符串"
930
1403
  return self._variables.get(name, default)
931
1404
 
932
1405
  def setVariables(self, names, values):
933
- """设置一组变量的值,names为名称元组,values为值元组"""
1406
+ """
1407
+ 同时设置一组变量的值。要注意,变量名称和值的数量要相同。当不相同时,抛出异常。
1408
+
1409
+ :param names: 所有变量名的元组或列表
1410
+ :param values: 所有变量对应值的元祖或列表
1411
+
1412
+ 示例:
1413
+ .. code:: Python
1414
+
1415
+ hp_key = ("qi", "jing", "neili", "jingli")
1416
+ hp_value = [1000, 800, 1100, 1050]
1417
+
1418
+ session.setVariables(hp_key, hp_value)
1419
+ """
934
1420
  assert isinstance(names, tuple) or isinstance(names, list), "names命名应为元组或列表,不接受其他类型"
935
1421
  assert isinstance(values, tuple) or isinstance(values, list), "values值应为元组或列表,不接受其他类型"
936
1422
  assert (len(names) > 0) and (len(values) > 0) and (len(names) == len(values)), "names与values应不为空,且长度相等"
@@ -940,7 +1426,17 @@ class Session:
940
1426
  self.setVariable(name, value)
941
1427
 
942
1428
  def getVariables(self, names):
943
- """获取一组变量的值,names为获取值的元组,返回values元组"""
1429
+ """
1430
+ 同时获取一组变量的值。
1431
+
1432
+ :param names: 所有变量名的元组或列表
1433
+ :return: 返回所有变量值的元组。可在获取值时直接解包。
1434
+
1435
+ 示例:
1436
+ .. code:: Python
1437
+
1438
+ qi, jing, neili, jingli = session.getVariables(["qi", "jing", "neili", "jingli"])
1439
+ """
944
1440
  assert isinstance(names, tuple) or isinstance(names, list), "names命名应为元组或列表,不接受其他类型"
945
1441
  assert len(names) > 0, "names应不为空"
946
1442
  values = list()
@@ -951,24 +1447,51 @@ class Session:
951
1447
  return tuple(values)
952
1448
 
953
1449
  def updateVariables(self, kvdict: dict):
954
- """使用dict字典更新变量值"""
1450
+ """
1451
+ 使用字典更新一组变量的值。若变量不存在将自动添加。
1452
+
1453
+ :param kvdict: 变量/值的字典
1454
+
1455
+ 示例:
1456
+ .. code:: Python
1457
+
1458
+ newvars = {"qi": 1000, "jing": 800, "neili": 1100, "jingli": 1050}
1459
+ session.updateVariables(newvars)
1460
+ """
1461
+
955
1462
  self._variables.update(kvdict)
956
1463
 
957
1464
  ## ###################
958
1465
  ## 全局变量 Globals 处理
959
1466
  ## ###################
960
1467
  def delGlobal(self, name):
961
- "删除一个全局变量"
1468
+ """
1469
+ 删除一个全局变量,使用方式与会话变量variable相同
1470
+
1471
+ :param name: 全局变量的名称
1472
+ """
962
1473
  assert isinstance(name, str), "name必须是一个字符串"
963
1474
  self.application.del_globals(name)
964
1475
 
965
1476
  def setGlobal(self, name, value):
966
- """设置一个全局变量的值"""
1477
+ """
1478
+ 设置一个全局变量的值,使用方式与会话变量variable相同
1479
+
1480
+ :param name: 全局变量的名称
1481
+ :param value: 全局变量的值
1482
+ """
967
1483
  assert isinstance(name, str), "name必须是一个字符串"
968
1484
  self.application.set_globals(name, value)
969
1485
 
970
1486
  def getGlobal(self, name, default = None):
971
- """获取一个全局变量的值。当name指定的变量不存在时,返回default"""
1487
+ """
1488
+ 获取一个全局变量的值,使用方式与会话变量variable相同
1489
+
1490
+ :param name: 全局变量的名称
1491
+ :param default: 当全局变量不存在时的返回值
1492
+ :return: 全局变量的值,或者 default
1493
+ """
1494
+
972
1495
  assert isinstance(name, str), "name必须是一个字符串"
973
1496
  return self.application.get_globals(name, default)
974
1497
 
@@ -1688,7 +2211,13 @@ class Session:
1688
2211
  ss.exec_command(new_cmd)
1689
2212
 
1690
2213
  def clean(self):
1691
- "清除会话有关任务项和事件标识"
2214
+ """
2215
+ 清除会话有关任务项和事件标识,具体包括:
2216
+
2217
+ - 复位所有可能包含异步操作的对象,包括定时器、触发器、别名、GMCP触发器、命令
2218
+ - 取消所有由本会话管理但仍未完成的任务
2219
+ - 清空会话管理的所有任务
2220
+ """
1692
2221
  try:
1693
2222
  # 加载时,取消所有任务,复位所有含async的对象, 保留变量
1694
2223
  for tm in self._timers.values():
@@ -1720,7 +2249,9 @@ class Session:
1720
2249
  pass
1721
2250
 
1722
2251
  def reset(self):
1723
- "复位:清除所有异步项和等待对象,卸载所有模块,清除所有会话有关对象"
2252
+ """
2253
+ 复位:清除所有异步项和等待对象,卸载所有模块,清除所有会话有关对象。
2254
+ """
1724
2255
  self.clean()
1725
2256
 
1726
2257
  modules = self._modules.values()
@@ -1735,7 +2266,15 @@ class Session:
1735
2266
  self._tasks.clear()
1736
2267
 
1737
2268
  def load_module(self, module_names):
1738
- "当名称为元组/列表时,加载指定名称的系列模块,当名称为字符串时,加载单个模块"
2269
+ """
2270
+ 模块加载函数。
2271
+
2272
+ :param module_names: 要加载的模块清单。为元组/列表时,加载指定名称的系列模块,当名称为字符串时,加载单个模块。
2273
+
2274
+ 示例:
2275
+ - session.load_module('mymodule'): 加载名为mymodule.py文件对应的模块
2276
+ - session.load_modules(['mymod1', 'mymod2']): 依次加载mymod1.py与mymod2.py文件对应的模块
2277
+ """
1739
2278
  if isinstance(module_names, (list, tuple)):
1740
2279
  for mod in module_names:
1741
2280
  mod = mod.strip()
@@ -1777,7 +2316,14 @@ class Session:
1777
2316
  self.error(f"异常追踪为: {traceback.format_exc()}")
1778
2317
 
1779
2318
  def unload_module(self, module_names):
1780
- "当名称为元组/列表时,卸载指定名称的系列模块,当名称为字符串时,卸载单个模块"
2319
+ """
2320
+ 模块卸载函数。卸载模块时,将自动调用模块中名称为Configuration类对象的unload方法。
2321
+
2322
+ 一般使用 #unload 命令来卸载模块,而不是在脚本中使用 unload_module 函数来卸载模块
2323
+
2324
+ :param module_names: 要卸载的模块清单。为元组/列表时,卸载指定名称的系列模块,当名称为字符串时,卸载单个模块。
2325
+ """
2326
+
1781
2327
  if isinstance(module_names, (list, tuple)):
1782
2328
  for mod in module_names:
1783
2329
  mod = mod.strip()
@@ -1807,7 +2353,13 @@ class Session:
1807
2353
  self.warning(f"指定模块名称 {module_name} 并未加载.")
1808
2354
 
1809
2355
  def reload_module(self, module_names = None):
1810
- "重新加载指定名称模块,可以字符串指定单个或以列表形式指定多个模块。若未指定名称,则重新加载所有已加载模块"
2356
+ """
2357
+ 模块重新加载函数。
2358
+
2359
+ 一般使用 #reload 命令来重新加载模块,而不是在脚本中使用 reload_module 函数来重新加载模块
2360
+
2361
+ :param module_names: 要重新加载的模块清单。为元组/列表时,卸载指定名称的系列模块,当名称为字符串时,卸载单个模块。当不指定时,重新加载所有已加载模块。
2362
+ """
1811
2363
  if module_names is None:
1812
2364
  self.clean()
1813
2365
  mods = list(self._modules.keys())
@@ -2234,13 +2786,31 @@ class Session:
2234
2786
  self.writetobuffer("{}[{}] {}{}".format(style, title, msg, Settings.CLR_STYLE), newline = True)
2235
2787
 
2236
2788
  def info(self, msg, title = "PYMUD INFO", style = Settings.INFO_STYLE):
2237
- "输出信息(蓝色),自动换行"
2789
+ """
2790
+ 使用默认的INFO_STYLE(绿色)输出信息,并自动换行。信息格式类似 [title] msg
2791
+
2792
+ :param msg: 要输出的信息
2793
+ :param title: 要显示在前面的标题,不指定时默认为 PYMUD INFO
2794
+ :param style: 要输出信息的格式(ANSI), 默认为 INFO_STYLE, \x1b[32m
2795
+ """
2238
2796
  self.info2(msg, title, style)
2239
2797
 
2240
2798
  def warning(self, msg, title = "PYMUD WARNING", style = Settings.WARN_STYLE):
2241
- "输出警告(黄色),自动换行"
2799
+ """
2800
+ 使用默认的WARN_STYLE(黄色)输出信息,并自动换行。信息格式类似 [title] msg
2801
+
2802
+ :param msg: 要输出的信息
2803
+ :param title: 要显示在前面的标题,不指定时默认为 PYMUD WARNING
2804
+ :param style: 要输出信息的格式(ANSI), 默认为 WARN_STYLE, \x1b[33m
2805
+ """
2242
2806
  self.info2(msg, title, style)
2243
2807
 
2244
2808
  def error(self, msg, title = "PYMUD ERROR", style = Settings.ERR_STYLE):
2245
- "输出错误(红色),自动换行"
2809
+ """
2810
+ 使用默认的ERR_STYLE(红色)输出信息,并自动换行。信息格式类似 [title] msg
2811
+
2812
+ :param msg: 要输出的信息
2813
+ :param title: 要显示在前面的标题,不指定时默认为 PYMUD ERROR
2814
+ :param style: 要输出信息的格式(ANSI), 默认为 ERR_STYLE, \x1b[31m
2815
+ """
2246
2816
  self.info2(msg, title, style)