pymud 0.20.4__py3-none-any.whl → 0.21.0__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/objects.py CHANGED
@@ -4,10 +4,12 @@ MUD会话(session)中, 支持的对象列表
4
4
 
5
5
  import asyncio, logging, re, importlib
6
6
  from abc import ABC, ABCMeta, abstractmethod
7
+ from typing import Optional, Union, List, Dict, Tuple
7
8
  from collections.abc import Iterable
8
9
  from collections import namedtuple
9
10
  from typing import Any
10
11
  from .settings import Settings
12
+ from .decorators import exception, async_exception, print_exception
11
13
 
12
14
  class CodeLine:
13
15
  """
@@ -37,7 +39,7 @@ class CodeLine:
37
39
  elif ch == "}":
38
40
  brace_count -= 1
39
41
  if brace_count < 0:
40
- raise Exception("错误的代码块,大括号数量不匹配")
42
+ raise Exception(Settings.gettext("excpetion_brace_not_matched"))
41
43
  arg += ch
42
44
  elif ch == "'":
43
45
  if single_quote == 0:
@@ -60,7 +62,7 @@ class CodeLine:
60
62
  arg += ch
61
63
 
62
64
  if (single_quote > 0) or (double_quote > 0):
63
- raise Exception("引号的数量不匹配")
65
+ raise Exception(Settings.gettext("exception_quote_not_matched"))
64
66
 
65
67
  if arg:
66
68
  code_params.append(arg)
@@ -77,7 +79,7 @@ class CodeLine:
77
79
 
78
80
  return syncmode, hasvar, tuple(code_params),
79
81
  else:
80
- return syncmode, hasvar, tuple()
82
+ return "dontcare", hasvar, tuple()
81
83
 
82
84
  def __init__(self, _code: str) -> None:
83
85
  self.__code = _code
@@ -108,7 +110,7 @@ class CodeLine:
108
110
 
109
111
  line = kwargs.get("line", None) or session.getVariable("%line", "None")
110
112
  raw = kwargs.get("raw", None) or session.getVariable("%raw", "None")
111
- wildcards = kwargs.get("wildcards", None)
113
+ wildcards = kwargs.get("wildcards", ())
112
114
 
113
115
  for item in self.code:
114
116
  if len(item) == 0: continue
@@ -178,7 +180,7 @@ class CodeBlock:
178
180
  elif ch == "}":
179
181
  brace_count -= 1
180
182
  if brace_count < 0:
181
- raise Exception("错误的代码块,大括号数量不匹配")
183
+ raise Exception(Settings.gettext("excpetion_brace_not_matched"))
182
184
  line += ch
183
185
  elif ch == ";":
184
186
  if brace_count == 0:
@@ -264,7 +266,7 @@ class CodeBlock:
264
266
  elif self.syncmode == "sync":
265
267
  sync = True
266
268
  elif self.syncmode == "conflict":
267
- session.warning("该命令中同时存在强制同步命令和强制异步命令,将使用异步执行,同步命令将失效。")
269
+ session.warning(Settings.gettext("exception_forced_async"))
268
270
  sync = False
269
271
 
270
272
  if sync:
@@ -326,11 +328,11 @@ class BaseObject:
326
328
  if isinstance(session, Session):
327
329
  self.session = session
328
330
  else:
329
- assert("session must be an instance of class Session!")
331
+ assert(Settings.gettext("exception_session_type_fail"))
330
332
 
331
333
  self._enabled = True # give a default value
332
334
  self.log = logging.getLogger(f"pymud.{self.__class__.__name__}")
333
- self.id = kwargs.get("id", session.getUniqueID(self.__class__.__abbr__))
335
+ self.id = kwargs.get("id", self.session.getUniqueID(self.__class__.__abbr__))
334
336
  self.group = kwargs.get("group", "") # 组
335
337
  self.enabled = kwargs.get("enabled", True) # 使能与否
336
338
  self.priority = kwargs.get("priority", 100) # 优先级
@@ -417,6 +419,8 @@ class GMCPTrigger(BaseObject):
417
419
  def __init__(self, session, name, *args, **kwargs):
418
420
  self.event = asyncio.Event()
419
421
  self.value = None
422
+ # 确保不要有重复的id
423
+ kwargs.pop("id", None)
420
424
  super().__init__(session, id = name, *args, **kwargs)
421
425
 
422
426
  def __del__(self):
@@ -445,10 +449,13 @@ class GMCPTrigger(BaseObject):
445
449
 
446
450
  self.line = value
447
451
  self.value = value_exp
448
-
452
+
449
453
  if callable(self._onSuccess):
450
454
  self.event.set()
451
- self._onSuccess(self.id, value, value_exp)
455
+ try:
456
+ self._onSuccess(self.id, value, value_exp)
457
+ except Exception as e:
458
+ print_exception(self.session, e)
452
459
 
453
460
  def __detailed__(self) -> str:
454
461
  group = f'group = "{self.group}" ' if self.group else ''
@@ -502,7 +509,7 @@ class MatchObject(BaseObject):
502
509
  return self._patterns
503
510
 
504
511
  @patterns.setter
505
- def patterns(self, patterns):
512
+ def patterns(self, patterns: Union[str, Union[Tuple[str], List[str]]]):
506
513
  self._patterns = patterns
507
514
 
508
515
  if isinstance(patterns, str):
@@ -515,14 +522,17 @@ class MatchObject(BaseObject):
515
522
  if self.isRegExp:
516
523
  flag = 0
517
524
  if self.ignoreCase: flag = re.I
518
- if not self.multiline:
519
- self._regExp = re.compile(self.patterns, flag) # 此处可考虑增加flags
525
+ if isinstance(patterns, str):
526
+ self.multiline = False
527
+ self.linesToMatch = 1
528
+ self._regExp = re.compile(patterns, flag) # 此处可考虑增加flags
520
529
  else:
521
530
  self._regExps = []
522
- for line in self.patterns:
531
+ for line in patterns:
523
532
  self._regExps.append(re.compile(line, flag))
524
533
 
525
534
  self.linesToMatch = len(self._regExps)
535
+ self.multiline = True
526
536
  self._mline = 0
527
537
 
528
538
  def reset(self):
@@ -542,76 +552,79 @@ class MatchObject(BaseObject):
542
552
 
543
553
  :return: BaseObject.State 类型,一个包含 result, id, name, line, wildcards 的命名元组对象
544
554
  """
545
- result = self.NOTSET
546
-
547
- if not self.multiline: # 非多行
548
- if self.isRegExp:
549
- m = self._regExp.match(line)
550
- if m:
551
- result = self.SUCCESS
552
- self.wildcards.clear()
553
- if len(m.groups()) > 0:
554
- self.wildcards.extend(m.groups())
555
+ try:
556
+ result = self.NOTSET
555
557
 
556
- self.lines.clear()
557
- self.lines.append(line)
558
- else:
559
- #if line.find(self.patterns) >= 0:
560
- #if line == self.patterns:
561
- if self.patterns in line:
562
- result = self.SUCCESS
563
- self.lines.clear()
564
- self.lines.append(line)
565
- self.wildcards.clear()
566
-
567
- else: # 多行匹配情况
568
- # multilines match. 多行匹配时,受限于行的捕获方式,必须一行一行来,设置状态标志进行处理。
569
- if self._mline == 0: # 当尚未开始匹配时,匹配第1行
570
- m = self._regExps[0].match(line)
571
- if m:
572
- self.lines.clear()
573
- self.lines.append(line)
574
- self.wildcards.clear()
575
- if len(m.groups()) > 0:
576
- self.wildcards.extend(m.groups())
577
- self._mline = 1 # 下一状态 (中间行)
578
- elif (self._mline > 0) and (self._mline < self.linesToMatch - 1):
579
- m = self._regExps[self._mline].match(line)
580
- if m:
581
- self.lines.append(line)
582
- if len(m.groups()) > 0:
583
- self.wildcards.extend(m.groups())
584
- self._mline += 1
558
+ if not self.multiline: # 非多行
559
+ if self.isRegExp:
560
+ m = self._regExp.match(line)
561
+ if m:
562
+ result = self.SUCCESS
563
+ self.wildcards.clear()
564
+ if len(m.groups()) > 0:
565
+ self.wildcards.extend(m.groups())
566
+
567
+ self.lines.clear()
568
+ self.lines.append(line)
585
569
  else:
586
- self._mline = 0
587
- elif self._mline == self.linesToMatch - 1: # 最终行
588
- m = self._regExps[self._mline].match(line)
589
- if m:
590
- self.lines.append(line)
591
- if len(m.groups()) > 0:
592
- self.wildcards.extend(m.groups())
593
- result = self.SUCCESS
594
-
595
- self._mline = 0
570
+ #if line.find(self.patterns) >= 0:
571
+ #if line == self.patterns:
572
+ if isinstance(self.patterns, str) and (self.patterns in line):
573
+ result = self.SUCCESS
574
+ self.lines.clear()
575
+ self.lines.append(line)
576
+ self.wildcards.clear()
577
+
578
+ else: # 多行匹配情况
579
+ # multilines match. 多行匹配时,受限于行的捕获方式,必须一行一行来,设置状态标志进行处理。
580
+ if self._mline == 0: # 当尚未开始匹配时,匹配第1行
581
+ m = self._regExps[0].match(line)
582
+ if m:
583
+ self.lines.clear()
584
+ self.lines.append(line)
585
+ self.wildcards.clear()
586
+ if len(m.groups()) > 0:
587
+ self.wildcards.extend(m.groups())
588
+ self._mline = 1 # 下一状态 (中间行)
589
+ elif (self._mline > 0) and (self._mline < self.linesToMatch - 1):
590
+ m = self._regExps[self._mline].match(line)
591
+ if m:
592
+ self.lines.append(line)
593
+ if len(m.groups()) > 0:
594
+ self.wildcards.extend(m.groups())
595
+ self._mline += 1
596
+ else:
597
+ self._mline = 0
598
+ elif self._mline == self.linesToMatch - 1: # 最终行
599
+ m = self._regExps[self._mline].match(line)
600
+ if m:
601
+ self.lines.append(line)
602
+ if len(m.groups()) > 0:
603
+ self.wildcards.extend(m.groups())
604
+ result = self.SUCCESS
596
605
 
597
- state = BaseObject.State(result, self.id, "\n".join(self.lines), tuple(self.wildcards))
606
+ self._mline = 0
598
607
 
599
- # 采用回调方式执行的时候,执行函数回调(仅当self.sync和docallback均为真时才执行同步
600
- # 当docallback为真时,是真正的进行匹配和触发,为false时,仅返回匹配结果,不实际触发
601
- if docallback:
602
- if self.sync:
603
- if state.result == self.SUCCESS:
604
- self._onSuccess(state.id, state.line, state.wildcards)
605
- elif state.result == self.FAILURE:
606
- self._onFailure(state.id, state.line, state.wildcards)
607
- elif state.result == self.TIMEOUT:
608
- self._onTimeout(state.id, state.line, state.wildcards)
609
-
610
- if state.result == self.SUCCESS:
611
- self.event.set()
608
+ state = BaseObject.State(result, self.id, "\n".join(self.lines), tuple(self.wildcards))
609
+
610
+ # 采用回调方式执行的时候,执行函数回调(仅当self.sync和docallback均为真时才执行同步
611
+ # 当docallback为真时,是真正的进行匹配和触发,为false时,仅返回匹配结果,不实际触发
612
+ if docallback:
613
+ if self.sync:
614
+ if state.result == self.SUCCESS:
615
+ self._onSuccess(state.id, state.line, state.wildcards)
616
+ elif state.result == self.FAILURE:
617
+ self._onFailure(state.id, state.line, state.wildcards)
618
+ elif state.result == self.TIMEOUT:
619
+ self._onTimeout(state.id, state.line, state.wildcards)
612
620
 
613
- self.state = state
614
- return state
621
+ if state.result == self.SUCCESS:
622
+ self.event.set()
623
+
624
+ self.state = state
625
+ return state
626
+ except Exception as e:
627
+ print_exception(self.session, e)
615
628
 
616
629
  async def matched(self) -> BaseObject.State:
617
630
  """
@@ -624,10 +637,10 @@ class MatchObject(BaseObject):
624
637
  self.reset()
625
638
  await self.event.wait()
626
639
  self.reset()
627
- except Exception as e:
628
- self.error(f"异步执行中遇到异常, {e}")
629
640
 
630
- return self.state
641
+ return self.state
642
+ except Exception as e:
643
+ print_exception(self.session, e)
631
644
 
632
645
  def __detailed__(self) -> str:
633
646
  group = f'group = "{self.group}" ' if self.group else ''
@@ -676,7 +689,7 @@ class Trigger(MatchObject):
676
689
 
677
690
  __abbr__ = "tri"
678
691
 
679
- def __init__(self, session, patterns, *args, **kwargs):
692
+ def __init__(self, session, patterns: Union[str, Union[Tuple[str], List[str]]], *args, **kwargs):
680
693
  super().__init__(session, patterns, *args, **kwargs)
681
694
  self._task = None
682
695
 
@@ -787,7 +800,7 @@ class Command(MatchObject):
787
800
  if isinstance(task, asyncio.Task) and (not task.done()):
788
801
  self.remove_task(task)
789
802
 
790
- async def execute(self, cmd, *args, **kwargs):
803
+ async def execute(self, cmd, *args, **kwargs) -> Any:
791
804
  """
792
805
  命令调用的入口函数。该函数由 Session 进行自动调用。
793
806
  通过 ``Session.exec`` 系列方法调用的命令,最终是执行该命令的 execute 方法。
@@ -815,7 +828,7 @@ class SimpleCommand(Command):
815
828
 
816
829
  MAX_RETRY = 20
817
830
 
818
- def __init__(self, session, patterns, succ_tri, *args, **kwargs):
831
+ def __init__(self, session, patterns: str, succ_tri, *args, **kwargs):
819
832
  super().__init__(session, patterns, succ_tri, *args, **kwargs)
820
833
  self._succ_tris = list()
821
834
  self._fail_tris = list()
@@ -857,7 +870,7 @@ class SimpleCommand(Command):
857
870
  """
858
871
  self.reset()
859
872
  # 0. check command
860
- cmd = cmd or self.patterns
873
+ cmd = cmd or self.patterns.__str__()
861
874
  # 1. save the command, to use later.
862
875
  self._executed_cmd = cmd
863
876
  # 2. writer command
@@ -912,23 +925,14 @@ class SimpleCommand(Command):
912
925
  break
913
926
 
914
927
  if result == self.SUCCESS:
915
- self._onSuccess(name = self.id, cmd = cmd, line = line, wildcards = wildcards)
916
- _outer_onSuccess = kwargs.get("onSuccess", None)
917
- if callable(_outer_onSuccess):
918
- _outer_onSuccess(name = self.id, cmd = cmd, line = line, wildcards = wildcards)
928
+ self._onSuccess(name = self.id, cmd = cmd, line = "", wildcards = [])
919
929
 
920
930
  elif result == self.FAILURE:
921
- self._onFailure(name = self.id, cmd = cmd, line = line, wildcards = wildcards)
922
- _outer_onFailure = kwargs.get("onFailure", None)
923
- if callable(_outer_onFailure):
924
- _outer_onFailure(name = self.id, cmd = cmd, line = line, wildcards = wildcards)
931
+ self._onFailure(name = self.id, cmd = cmd, line = "", wildcards = [])
925
932
 
926
933
  elif result == self.TIMEOUT:
927
934
  self._onTimeout(name = self.id, cmd = cmd, timeout = self.timeout)
928
- _outer_onTimeout = kwargs.get("onTimeout", None)
929
- if callable(_outer_onTimeout):
930
- _outer_onTimeout(name = self.id, cmd = cmd, timeout = self.timeout)
931
-
935
+
932
936
  return result
933
937
 
934
938
  class Timer(BaseObject):