codosdk 1.0.26__tar.gz → 1.0.28__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.
Files changed (53) hide show
  1. {codosdk-1.0.26 → codosdk-1.0.28}/PKG-INFO +1 -1
  2. {codosdk-1.0.26 → codosdk-1.0.28}/codosdk.egg-info/PKG-INFO +1 -1
  3. {codosdk-1.0.26 → codosdk-1.0.28}/setup.py +1 -1
  4. codosdk-1.0.28/websdk2/api_set.py +57 -0
  5. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/utils/__init__.py +133 -53
  6. codosdk-1.0.26/websdk2/api_set.py +0 -43
  7. {codosdk-1.0.26 → codosdk-1.0.28}/LICENSE +0 -0
  8. {codosdk-1.0.26 → codosdk-1.0.28}/README.md +0 -0
  9. {codosdk-1.0.26 → codosdk-1.0.28}/codosdk.egg-info/SOURCES.txt +0 -0
  10. {codosdk-1.0.26 → codosdk-1.0.28}/codosdk.egg-info/dependency_links.txt +0 -0
  11. {codosdk-1.0.26 → codosdk-1.0.28}/codosdk.egg-info/requires.txt +0 -0
  12. {codosdk-1.0.26 → codosdk-1.0.28}/codosdk.egg-info/top_level.txt +0 -0
  13. {codosdk-1.0.26 → codosdk-1.0.28}/opssdk/__init__.py +0 -0
  14. {codosdk-1.0.26 → codosdk-1.0.28}/opssdk/utils/__init__.py +0 -0
  15. {codosdk-1.0.26 → codosdk-1.0.28}/pyproject.toml +0 -0
  16. {codosdk-1.0.26 → codosdk-1.0.28}/setup.cfg +0 -0
  17. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/__init__.py +0 -0
  18. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/apis/__init__.py +0 -0
  19. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/apis/admin_apis.py +0 -0
  20. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/apis/agent_apis.py +0 -0
  21. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/apis/cmdb_apis.py +0 -0
  22. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/apis/kerrigan_apis.py +0 -0
  23. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/apis/mgv4_apis.py +0 -0
  24. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/apis/notice_apis.py +0 -0
  25. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/apis/task_apis.py +0 -0
  26. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/application.py +0 -0
  27. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/base_handler.py +0 -0
  28. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/cache.py +0 -0
  29. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/cache_context.py +0 -0
  30. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/client.py +0 -0
  31. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/cloud/__init__.py +0 -0
  32. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/cloud/qcloud_api.py +0 -0
  33. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/cloud/ucloud_api.py +0 -0
  34. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/cloud_utils.py +0 -0
  35. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/configs.py +0 -0
  36. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/consts.py +0 -0
  37. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/crud_utils.py +0 -0
  38. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/db_context.py +0 -0
  39. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/error.py +0 -0
  40. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/fetch_coroutine.py +0 -0
  41. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/jwt_token.py +0 -0
  42. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/ldap.py +0 -0
  43. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/logger.py +0 -0
  44. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/model_utils.py +0 -0
  45. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/mqhelper.py +0 -0
  46. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/program.py +0 -0
  47. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/salt_api.py +0 -0
  48. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/sqlalchemy_pagination.py +0 -0
  49. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/tools.py +0 -0
  50. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/utils/cc_crypto.py +0 -0
  51. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/utils/date_format.py +0 -0
  52. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/utils/pydantic_utils.py +0 -0
  53. {codosdk-1.0.26 → codosdk-1.0.28}/websdk2/web_logs.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: codosdk
3
- Version: 1.0.26
3
+ Version: 1.0.28
4
4
  Summary: CODO项目的Python SDK
5
5
  Home-page: https://github.com/ss1917/codo_sdk/
6
6
  Author: shenshuo
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: codosdk
3
- Version: 1.0.26
3
+ Version: 1.0.28
4
4
  Summary: CODO项目的Python SDK
5
5
  Home-page: https://github.com/ss1917/codo_sdk/
6
6
  Author: shenshuo
@@ -9,7 +9,7 @@ desc : CODO SDK
9
9
  import sys
10
10
  from setuptools import setup, find_packages
11
11
 
12
- VERSION = '1.0.26'
12
+ VERSION = '1.0.28'
13
13
 
14
14
  if sys.version_info < (2, 7) or (3, 0) <= sys.version_info < (3, 6):
15
15
  print('This program requires at least Python 2.7 or 3.6 to run.')
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Version : 0.0.1
5
+ Contact : 191715030@qq.com
6
+ Author : shenshuo
7
+ Date : 2025/02/12 17:56
8
+ Desc : API集合
9
+ """
10
+
11
+ from .tools import singleton
12
+ from .apis import AdminAPIS, TaskAPIS, KerriganAPIS, AdminV4APIS, CMDBAPIS, AgentAPIS, NoticeAPIS
13
+
14
+
15
+ @singleton
16
+ class ConstAPIS(AdminAPIS, TaskAPIS, KerriganAPIS, AdminV4APIS, CMDBAPIS, AgentAPIS, NoticeAPIS):
17
+ """
18
+ 集合所有常用 API 配置的常量类,继承了各个 API 模块的接口配置。
19
+
20
+ 提供了对 API 配置项的只读管理,并且对每个新增属性值进行校验。
21
+ """
22
+
23
+ def __init__(self):
24
+ pass
25
+
26
+ def __setattr__(self, name: str, value: dict) -> None:
27
+
28
+ """
29
+ 自定义属性设置方法,确保 API 配置项的合法性。
30
+
31
+ 校验条件:
32
+ 1. 不允许重新绑定常量。
33
+ 2. 属性值必须是字典格式。
34
+ 3. 必须包含 'url' 和 'description' 字段。
35
+
36
+ Args:
37
+ name (str): 属性名称
38
+ value (dict): 属性值,必须为字典格式并包含必要字段
39
+ """
40
+
41
+ if name in self.__dict__:
42
+ raise TypeError(f"Cannot rebind constant '{name}'.")
43
+
44
+ if not isinstance(value, dict):
45
+ raise TypeError(f"Value for '{name}' must be a dictionary.")
46
+
47
+ # 确保包含 'url' 和 'description' 字段
48
+ if 'url' not in value:
49
+ raise TypeError(f"Value for '{name}' must contain 'url'.")
50
+
51
+ if 'description' not in value:
52
+ raise TypeError(f"Value for '{name}' must contain 'description'.")
53
+
54
+ self.__dict__[name] = value
55
+
56
+
57
+ api_set = ConstAPIS()
@@ -8,101 +8,181 @@ Desc :
8
8
  """
9
9
 
10
10
  import json
11
+ import logging
11
12
  import os
12
13
  import smtplib
13
14
  import socket
14
15
  import time
15
16
  import uuid
16
17
  from datetime import datetime
17
- from email.mime.multipart import MIMEMultipart
18
+ from typing import List, Union
18
19
  from email.mime.text import MIMEText
20
+ from email.mime.multipart import MIMEMultipart
19
21
 
20
22
  from ..consts import const
21
23
 
22
24
 
23
- class SendMail(object):
24
- def __init__(self, mail_host, mail_port, mail_user, mail_password, mail_ssl=False, mail_tls=False):
25
+ class SendMail:
26
+ def __init__(self, mail_host: str, mail_port: int, mail_user: str, mail_password: str, mail_ssl: bool = False,
27
+ mail_tls: bool = False):
25
28
  """
29
+ 初始化邮件发送客户端
30
+
26
31
  :param mail_host: SMTP主机
27
32
  :param mail_port: SMTP端口
28
33
  :param mail_user: SMTP账号
29
34
  :param mail_password: SMTP密码
30
- :param mail_ssl: SSL=True, 如果SMTP端口是465,通常需要启用SSL, 如果SMTP端口是587,通常需要启用TLS
35
+ :param mail_ssl: 是否启用SSL加密,如果SMTP端口是465,通常需要启用SSL
36
+ :param mail_tls: 是否启用TLS加密,如果SMTP端口是587,通常需要启用TLS
31
37
  """
32
38
  self.mail_host = mail_host
33
39
  self.mail_port = mail_port
34
- self.__mail_user = mail_user
35
- self.__mail_password = mail_password
40
+ self.mail_user = mail_user
41
+ self.__mail_password = mail_password # 使用单下划线,表示这是一个受保护的属性
36
42
  self.mail_ssl = mail_ssl
37
43
  self.mail_tls = mail_tls
38
44
 
39
- def send_mail(self, to_list, subject, content, subtype='plain', att=None):
45
+ def send_mail(self, to_list: Union[str, List[str]], subject: str, content: str, subtype: str = 'plain',
46
+ att: Union[str, None] = None):
40
47
  """
41
- :param to_list: 收件人,多收件人半角逗号分割, 必填
42
- :param subject: 标题, 必填
43
- :param content: 内容, 必填
44
- :param subtype: 格式,默认:plain, 可选html
45
- :param att: 附件,支持单附件,选填
48
+ 发送邮件
49
+
50
+ :param to_list: 收件人列表,可以是单个邮箱地址字符串,也可以是多个邮箱地址的列表,必填
51
+ :param subject: 邮件标题,必填
52
+ :param content: 邮件内容,必填
53
+ :param subtype: 邮件内容格式,默认为plain,可选html
54
+ :param att: 附件路径,支持单个附件,选填
46
55
  """
56
+
57
+ if isinstance(to_list, list):
58
+ to_list = ','.join(to_list) # 将列表转换为逗号分隔的字符串
59
+
47
60
  msg = MIMEMultipart()
48
- msg['Subject'] = subject ## 标题
49
- msg['From'] = self.__mail_user ## 发件人
50
- msg['To'] = to_list # 收件人,必须是一个字符串
51
- # 邮件正文内容
61
+ msg['Subject'] = subject
62
+ msg['From'] = self.mail_user
63
+ msg['To'] = to_list
64
+
52
65
  msg.attach(MIMEText(content, subtype, 'utf-8'))
66
+
53
67
  if att:
54
68
  if not os.path.isfile(att):
55
- raise FileNotFoundError('{0} file does not exist'.format(att))
69
+ raise FileNotFoundError(f'{att} 文件不存在')
70
+ try:
71
+ with open(att, 'rb') as f:
72
+ file_data = f.read()
56
73
 
57
- dirname, filename = os.path.split(att)
58
- # 构造附件1,传送当前目录下的 test.txt 文件
59
- att1 = MIMEText(open(att, 'rb').read(), 'base64', 'utf-8')
60
- att1["Content-Type"] = 'application/octet-stream'
61
- # 这里的filename可以任意写,写什么名字,邮件中显示什么名字
62
- att1["Content-Disposition"] = 'attachment; filename="{0}"'.format(filename)
63
- msg.attach(att1)
74
+ filename = os.path.basename(att)
75
+ attachment = MIMEText(file_data.decode('utf-8'), 'base64', 'utf-8')
76
+ attachment['Content-Type'] = 'application/octet-stream'
77
+ attachment['Content-Disposition'] = f'attachment; filename="{filename}"'
78
+ msg.attach(attachment)
79
+ except Exception as err:
80
+ logging.error(f"发送附件出错 {err}")
64
81
 
65
82
  try:
66
- if self.mail_ssl:
67
- '''SSL加密方式,通信过程加密,邮件数据安全, 使用端口465'''
68
- # print('Use SSL SendMail')
69
- server = smtplib.SMTP_SSL(host=self.mail_host)
70
- server.connect(self.mail_host, self.mail_port) # 连接服务器
71
- server.login(self.__mail_user, self.__mail_password) # 登录操作
72
- server.sendmail(self.__mail_user, to_list.split(','), msg.as_string())
73
- server.close()
74
- elif self.mail_tls:
75
- # print('Use TLS SendMail')
76
- '''使用TLS模式'''
77
- server = smtplib.SMTP()
78
- server.connect(self.mail_host, self.mail_port) # 连接服务器
79
- server.starttls()
80
- server.login(self.__mail_user, self.__mail_password) # 登录操作
81
- server.sendmail(self.__mail_user, to_list.split(','), msg.as_string())
82
- server.close()
83
- return True
84
- else:
85
- '''使用普通模式'''
86
- server = smtplib.SMTP()
87
- server.connect(self.mail_host, self.mail_port) # 连接服务器
88
- server.login(self.__mail_user, self.__mail_password) # 登录操作
89
- server.sendmail(self.__mail_user, to_list.split(','), msg.as_string())
90
- server.close()
91
- return True
83
+ with self._get_server() as server:
84
+ server.sendmail(self.mail_user, to_list.split(','), msg.as_string())
85
+ return True
92
86
  except Exception as e:
93
- print(str(e))
87
+ logging.error(f'邮件发送失败: {e}')
94
88
  return False
95
89
 
90
+ def _get_server(self):
91
+ if self.mail_ssl:
92
+ server = smtplib.SMTP_SSL(self.mail_host, self.mail_port)
93
+ elif self.mail_tls:
94
+ server = smtplib.SMTP(self.mail_host, self.mail_port)
95
+ server.starttls()
96
+ else:
97
+ server = smtplib.SMTP(self.mail_host, self.mail_port)
98
+
99
+ server.login(self.mail_user, self.__mail_password)
100
+ return server
101
+
102
+
103
+ # class SendMail(object):
104
+ # def __init__(self, mail_host, mail_port, mail_user, mail_password, mail_ssl=False, mail_tls=False):
105
+ # """
106
+ # :param mail_host: SMTP主机
107
+ # :param mail_port: SMTP端口
108
+ # :param mail_user: SMTP账号
109
+ # :param mail_password: SMTP密码
110
+ # :param mail_ssl: SSL=True, 如果SMTP端口是465,通常需要启用SSL, 如果SMTP端口是587,通常需要启用TLS
111
+ # """
112
+ # self.mail_host = mail_host
113
+ # self.mail_port = mail_port
114
+ # self.__mail_user = mail_user
115
+ # self.__mail_password = mail_password
116
+ # self.mail_ssl = mail_ssl
117
+ # self.mail_tls = mail_tls
118
+ #
119
+ # def send_mail(self, to_list, subject, content, subtype='plain', att=None):
120
+ # """
121
+ # :param to_list: 收件人,多收件人半角逗号分割, 必填
122
+ # :param subject: 标题, 必填
123
+ # :param content: 内容, 必填
124
+ # :param subtype: 格式,默认:plain, 可选html
125
+ # :param att: 附件,支持单附件,选填
126
+ # """
127
+ # msg = MIMEMultipart()
128
+ # msg['Subject'] = subject ## 标题
129
+ # msg['From'] = self.__mail_user ## 发件人
130
+ # msg['To'] = to_list # 收件人,必须是一个字符串
131
+ # # 邮件正文内容
132
+ # msg.attach(MIMEText(content, subtype, 'utf-8'))
133
+ # if att:
134
+ # if not os.path.isfile(att):
135
+ # raise FileNotFoundError('{0} file does not exist'.format(att))
136
+ #
137
+ # dirname, filename = os.path.split(att)
138
+ # # 构造附件1,传送当前目录下的 test.txt 文件
139
+ # att1 = MIMEText(open(att, 'rb').read(), 'base64', 'utf-8')
140
+ # att1["Content-Type"] = 'application/octet-stream'
141
+ # # 这里的filename可以任意写,写什么名字,邮件中显示什么名字
142
+ # att1["Content-Disposition"] = 'attachment; filename="{0}"'.format(filename)
143
+ # msg.attach(att1)
144
+ #
145
+ # try:
146
+ # if self.mail_ssl:
147
+ # '''SSL加密方式,通信过程加密,邮件数据安全, 使用端口465'''
148
+ # # print('Use SSL SendMail')
149
+ # server = smtplib.SMTP_SSL(host=self.mail_host)
150
+ # server.connect(self.mail_host, self.mail_port) # 连接服务器
151
+ # server.login(self.__mail_user, self.__mail_password) # 登录操作
152
+ # server.sendmail(self.__mail_user, to_list.split(','), msg.as_string())
153
+ # server.close()
154
+ # elif self.mail_tls:
155
+ # # print('Use TLS SendMail')
156
+ # '''使用TLS模式'''
157
+ # server = smtplib.SMTP(host=self.mail_host)
158
+ # server.connect(self.mail_host, self.mail_port) # 连接服务器
159
+ # server.starttls()
160
+ # server.login(self.__mail_user, self.__mail_password) # 登录操作
161
+ # server.sendmail(self.__mail_user, to_list.split(','), msg.as_string())
162
+ # server.close()
163
+ # return True
164
+ # else:
165
+ # '''使用普通模式'''
166
+ # server = smtplib.SMTP()
167
+ # server.connect(self.mail_host, self.mail_port) # 连接服务器
168
+ # server.login(self.__mail_user, self.__mail_password) # 登录操作
169
+ # server.sendmail(self.__mail_user, to_list.split(','), msg.as_string())
170
+ # server.close()
171
+ # return True
172
+ # except Exception as e:
173
+ # print(str(e))
174
+ # return False
175
+ #
96
176
 
97
177
  def mail_login(user, password, mail_server='smtp.exmail.qq.com'):
98
- ### 模拟登录来验证邮箱
178
+ # 模拟登录来验证邮箱
99
179
  try:
100
180
  server = smtplib.SMTP()
101
181
  server.connect(mail_server)
102
182
  server.login(user, password)
103
183
  return True
104
184
  except Exception as e:
105
- print(user, e)
185
+ logging.error(f"{user}邮箱认证出错:{e}")
106
186
  return False
107
187
 
108
188
 
@@ -1,43 +0,0 @@
1
- #!/usr/bin/env python
2
- # -*- coding: utf-8 -*-
3
- """
4
- Version : 0.0.1
5
- Contact : 191715030@qq.com
6
- Author : shenshuo
7
- Date : 2019/12/12 17:56
8
- Desc : API集合
9
- """
10
-
11
- from .tools import singleton
12
- from .apis import AdminAPIS, TaskAPIS, KerriganAPIS, AdminV4APIS, CMDBAPIS, AgentAPIS, NoticeAPIS
13
-
14
-
15
- @singleton
16
- class ConstAPIS(AdminAPIS, TaskAPIS, KerriganAPIS, AdminV4APIS, CMDBAPIS, AgentAPIS, NoticeAPIS):
17
- def __init__(self):
18
- pass
19
-
20
- def __setattr__(self, name, value):
21
- if name in self.__dict__:
22
- raise TypeError("Can't rebind const (%s)" % name)
23
-
24
- if not isinstance(value, dict):
25
- raise TypeError("Value must be in dict format")
26
-
27
- if not value.get('url'):
28
- raise TypeError("Value must have url")
29
-
30
- if not value.get('description'):
31
- raise TypeError("Value must have description")
32
-
33
- # body_data = value.get('body')
34
- # if body_data is not None and not isinstance(body_data, (dict, list)):
35
- # try:
36
- # json.loads(body_data)
37
- # except (TypeError, ValueError):
38
- # raise TypeError("Body data cannot be loaded as JSON")
39
-
40
- self.__dict__[name] = value
41
-
42
-
43
- api_set = ConstAPIS()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes