datacomshell 0.1.0__tar.gz → 0.1.2__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: datacomshell
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Summary: Add your description here
5
5
  Author: Saven
6
6
  Author-email: Saven <2416844857@qq.com>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "datacomshell"
3
- version = "0.1.0"
3
+ version = "0.1.2"
4
4
  description = "Add your description here"
5
5
  authors = [
6
6
  { name = "Saven", email = "2416844857@qq.com" },
@@ -17,11 +17,15 @@ class LoginError(RuntimeError):
17
17
  pass
18
18
 
19
19
 
20
- __const_command_runned_pattern = re.compile(
20
+ _CONST_COMMAND_RUNNED_PATTERN = re.compile(
21
21
  r'<.*>|\[.*\]|<~.*>|\[~.*\]|<\*.*>|\[\*.*\]')
22
+ _CONST_COMMAND_RUNNED_PATTERN_LIST = [_CONST_COMMAND_RUNNED_PATTERN]
22
23
 
24
+ _CONST_COMMAND_ERROR_PATTERN = re.compile(r'%.*')
25
+ _CONST_COMMAND_ERROR_PATTERN_LIST = [_CONST_COMMAND_ERROR_PATTERN]
23
26
 
24
- class DatacomShell(object):
27
+
28
+ class AsyncTelnetUtil(object):
25
29
  def __init__(self,
26
30
  host: str,
27
31
  username: str,
@@ -29,6 +33,7 @@ class DatacomShell(object):
29
33
  port: int = 23,
30
34
  connect_timeout: Optional[float] = None
31
35
  ) -> None:
36
+ # 连接基本信息
32
37
  self.__host = host
33
38
  self.__port = port
34
39
  self.__connect_timeout = connect_timeout
@@ -40,11 +45,41 @@ class DatacomShell(object):
40
45
  self.__reader: TelnetReader | TelnetReaderUnicode | None = None
41
46
  self.__writer: TelnetWriter | TelnetWriterUnicode | None = None
42
47
 
43
- self.__const_command_runned_pattern = __const_command_runned_pattern
48
+ # 默认命令执行匹配
49
+ self.__DEFAULT_CONST_COMMAND_RUNNED_PATTERN_LIST = [
50
+ _CONST_COMMAND_RUNNED_PATTERN]
51
+
52
+ self.__DEFAULT_CONST_COMMAND_ERROR_PATTERN_LIST = [
53
+ _CONST_COMMAND_ERROR_PATTERN]
54
+
55
+ def __successfulMatch(self, pattern_list: Optional[list[re.Pattern]] = None, buffer: str = '') -> bool:
56
+ if pattern_list is not None:
57
+ for pattern in pattern_list:
58
+ if re.search(pattern=pattern, string=buffer) is not None:
59
+ return True
60
+ else:
61
+ for pattern in self.__DEFAULT_CONST_COMMAND_RUNNED_PATTERN_LIST:
62
+ if re.search(pattern=pattern, string=buffer) is not None:
63
+ return True
64
+
65
+ return False
66
+
67
+ def __errorMatch(self, error_pattern_list: Optional[list[re.Pattern]] = None, buffer: str = '') -> bool:
68
+ if error_pattern_list is not None:
69
+ for pattern in error_pattern_list:
70
+ if re.search(pattern=pattern, string=buffer) is not None:
71
+ return True
72
+ else:
73
+ for pattern in self.__DEFAULT_CONST_COMMAND_ERROR_PATTERN_LIST:
74
+ if re.search(pattern=pattern, string=buffer) is not None:
75
+ return True
44
76
 
77
+ return False
78
+
79
+ # 读取命令返回数据
45
80
  async def __read(self,
46
- pattern: Optional[re.Pattern] = __const_command_runned_pattern,
47
- error_pattern: Optional[re.Pattern] = None,
81
+ pattern_list: Optional[list[re.Pattern]] = None,
82
+ error_pattern_list: Optional[list[re.Pattern]] = None,
48
83
  timeout: Optional[float] = 10.0,
49
84
  size: int = 1024
50
85
  ) -> str | None:
@@ -54,7 +89,7 @@ class DatacomShell(object):
54
89
  if self.__reader is None or self.__writer is None:
55
90
  raise ConnectError("Not connected to device")
56
91
 
57
- while True:
92
+ while runStatus:
58
93
  try:
59
94
  res = await asyncio.wait_for(self.__reader.read(size), timeout)
60
95
  except asyncio.TimeoutError:
@@ -68,15 +103,21 @@ class DatacomShell(object):
68
103
  elif res is str:
69
104
  buffer += res
70
105
 
71
- if pattern is not None and re.search(pattern=pattern, string=buffer, flags=0) is not None:
72
- break
106
+ __temp_match_status = False
107
+ if not __temp_match_status:
108
+ __temp_match_status = self.__successfulMatch(
109
+ pattern_list=pattern_list, buffer=buffer)
110
+
111
+ if not __temp_match_status:
112
+ __temp_match_status = self.__errorMatch(
113
+ error_pattern_list=error_pattern_list, buffer=buffer)
73
114
 
74
- if error_pattern is not None and re.search(pattern=error_pattern, string=buffer, flags=0) is not None:
115
+ if __temp_match_status:
75
116
  runStatus = False
76
- break
77
117
 
78
118
  return buffer if runStatus else None
79
119
 
120
+ # 写入命令
80
121
  def __write(self, command: str) -> None:
81
122
  if self.__writer is None:
82
123
  raise ConnectError("Not connected to device")
@@ -89,6 +130,7 @@ class DatacomShell(object):
89
130
  else:
90
131
  self.__writer.write(in_command.encode('utf-8'))
91
132
 
133
+ # 建立连接
92
134
  async def connect(self) -> None:
93
135
  try:
94
136
  self.__reader, self.__writer = await telnetlib3.open_connection(
@@ -102,21 +144,22 @@ class DatacomShell(object):
102
144
 
103
145
  return
104
146
 
147
+ # 建立登录
105
148
  async def login(self) -> None:
106
149
  if self.__login_status:
107
150
  return
108
151
 
109
- if self.__read(pattern=re.compile(r"Username:")) is not None:
152
+ if await self.__read(pattern_list=[re.compile(r"Username:")]) is not None:
110
153
  self.__write(self.__username)
111
154
  else:
112
155
  raise LoginError("Failed to connect to device")
113
156
 
114
- if self.__read(pattern=re.compile(r"Password:")) is not None:
157
+ if await self.__read(pattern_list=[re.compile(r"Password:")]) is not None:
115
158
  self.__write(self.__password)
116
159
  else:
117
160
  raise LoginError("Failed to connect to device")
118
161
 
119
- if self.__read(pattern=self.__const_command_runned_pattern) is not None:
162
+ if await self.__read(pattern_list=self.__DEFAULT_CONST_COMMAND_RUNNED_PATTERN_LIST) is not None:
120
163
  self.__login_status = True
121
164
  return
122
165
 
@@ -124,6 +167,9 @@ class DatacomShell(object):
124
167
  self.__write(command)
125
168
  return await self.__read()
126
169
 
170
+ def only_send_command(self, command: str) -> None:
171
+ self.__write(command)
172
+
127
173
  async def build(self) -> None:
128
174
  await self.connect()
129
175
  await self.login()
@@ -0,0 +1,3 @@
1
+
2
+ class TelnetShellClient(object):
3
+ pass
@@ -0,0 +1,39 @@
1
+ import uuid
2
+
3
+ __EMPTY_SYNC_PIPELINE_INDEX = -1
4
+
5
+
6
+ class Command(object):
7
+ def __init__(self, command_str: str) -> None:
8
+ self.__command_id = None
9
+ self.__command_str = command_str
10
+ self.__command_has_result = True
11
+ self.__command_result = None
12
+
13
+
14
+ class TelnetShellServer(object):
15
+ """
16
+ Telnet shell server.
17
+ """
18
+
19
+ def __init__(self) -> None:
20
+
21
+ self.__sync_command_pipeline = []
22
+ self.__async_command_pipeline = []
23
+ self.__command_runned_result_dict = {}
24
+
25
+ self.__sync_current_command_index = __EMPTY_SYNC_PIPELINE_INDEX
26
+
27
+ self.__connect_pool = []
28
+
29
+ def __check_reset_result_dict_count(self) -> bool:
30
+ if self.__command_runned_result_dict.__len__() > 1000:
31
+ self.__command_runned_result_dict.clear()
32
+ return True
33
+ return False
34
+
35
+ def gen_command_process_id(self) -> uuid.UUID:
36
+ return uuid.uuid4()
37
+
38
+ def sync_push(self, command: Command) -> None:
39
+ self.__sync_command_pipeline.insert(0, command)
File without changes