ezKit 1.8.2__py3-none-any.whl → 1.8.4__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.
ezKit/cipher.py CHANGED
@@ -1,9 +1,8 @@
1
- """
2
- https://docs.python.org/3.10/library/hashlib.html
3
- https://www.pycrypto.org/
4
- https://stackoverflow.com/a/21928790
5
- pip install pycryptodome
6
- """
1
+ """Cipher"""
2
+ # https://docs.python.org/3.10/library/hashlib.html
3
+ # https://www.pycrypto.org/
4
+ # https://stackoverflow.com/a/21928790
5
+ # pip install pycryptodome
7
6
  import base64
8
7
  import hashlib
9
8
 
ezKit/cls.py CHANGED
@@ -88,3 +88,169 @@ def up_down_analysis(
88
88
  logger.error(f"{info} [失败]")
89
89
  logger.exception(e)
90
90
  return None
91
+
92
+
93
+ # --------------------------------------------------------------------------------------------------
94
+
95
+
96
+ def latest_data(
97
+ payload: str | dict,
98
+ data_type: str = "stock",
99
+ df: bool = False
100
+ ) -> list | pd.DataFrame | None:
101
+ """股票或板块的最新数据"""
102
+
103
+ # ----------------------------------------------------------------------------------------------
104
+
105
+ # 判断参数类型
106
+ match True:
107
+ case True if True not in [isinstance(payload, str), isinstance(payload, dict)]:
108
+ logger.error("Incorrect function argument type: payload")
109
+ return None
110
+ case True if False in [isinstance(data_type, str), utils.v_true(data_type, str)]:
111
+ logger.error("Incorrect function argument type: data_type")
112
+ return None
113
+ case _:
114
+ pass
115
+
116
+ # ----------------------------------------------------------------------------------------------
117
+
118
+ # 判断数据类型. 数据类型: 个股, 板块 (产业链: industry)
119
+ if data_type not in ["stock", "plate"]:
120
+ logger.error("data_type error")
121
+ return None
122
+
123
+ # ----------------------------------------------------------------------------------------------
124
+
125
+ # 日志信息
126
+
127
+ # 个股 (默认)
128
+ info: str = "获取股票最新数据"
129
+
130
+ # 板块
131
+ if data_type == "plate":
132
+ info = "获取板块最新数据"
133
+
134
+ # match True:
135
+ # case True if data_type == "plate":
136
+ # info = "获取板块最新数据"
137
+ # case True if data_type == "industry":
138
+ # info = "获取产业链最新数据"
139
+ # case _:
140
+ # pass
141
+
142
+ # ----------------------------------------------------------------------------------------------
143
+
144
+ try:
145
+
146
+ logger.info(f"{info} ......")
147
+
148
+ # ------------------------------------------------------------------------------------------
149
+
150
+ # HTTP User Agent
151
+ user_agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
152
+
153
+ # HTTP Headers
154
+ headers = {"User-Agent": user_agent}
155
+
156
+ # ------------------------------------------------------------------------------------------
157
+
158
+ # 请求参数
159
+ params: dict = {}
160
+
161
+ # 默认请求参数
162
+ if isinstance(payload, str) and utils.v_true(payload, str):
163
+ params = {"secu_code": payload}
164
+
165
+ # 请求参数
166
+ if isinstance(payload, dict) and utils.v_true(payload, dict):
167
+ params = payload
168
+
169
+ # ------------------------------------------------------------------------------------------
170
+
171
+ # 不直接在API后面跟参数, 使用 params 传递参数
172
+
173
+ # API: 股票
174
+ # api: str = f"https://x-quote.cls.cn/quote/stock/basic?secu_code={code}"
175
+ api: str = "https://x-quote.cls.cn/quote/stock/basic"
176
+
177
+ # API: 板块
178
+ if data_type == "plate":
179
+ # api = f"https://x-quote.cls.cn/web_quote/plate/stocks?secu_code={code}"
180
+ api = "https://x-quote.cls.cn/web_quote/plate/stocks"
181
+
182
+ # match True:
183
+ # case True if data_type == "plate":
184
+ # # 板块
185
+ # # api = f"https://x-quote.cls.cn/web_quote/plate/stocks?secu_code={code}"
186
+ # api = "https://x-quote.cls.cn/web_quote/plate/stocks"
187
+ # case True if data_type == "industry":
188
+ # # 产业链
189
+ # # api = f"https://x-quote.cls.cn/web_quote/plate/industry?secu_code={code}"
190
+ # api = "https://x-quote.cls.cn/web_quote/plate/industry"
191
+ # case _:
192
+ # pass
193
+
194
+ # ------------------------------------------------------------------------------------------
195
+
196
+ # 获取数据
197
+ # response = requests.get(api, headers=headers, timeout=10)
198
+ response = requests.get(api, headers=headers, params=params, timeout=10)
199
+
200
+ # 转换数据类型
201
+ response_dict: dict = response.json()
202
+
203
+ # ------------------------------------------------------------------------------------------
204
+
205
+ # 个股
206
+
207
+ if data_type == "stock":
208
+
209
+ # 停牌, 返回 None
210
+ if response_dict["data"]["trade_status"] == "STOPT":
211
+ logger.error(f"{info} [停牌]")
212
+ return None
213
+
214
+ # pd.DataFrame 数据
215
+ if utils.v_true(df, bool) is True:
216
+ df_data = {
217
+ # "date": [pd.to_datetime(date_today)],
218
+ "open": [float(response_dict["data"]["open_px"])],
219
+ "close": [float(response_dict["data"]["last_px"])],
220
+ "high": [float(response_dict["data"]["high_px"])],
221
+ "low": [float(response_dict["data"]["low_px"])],
222
+ "volume": [int(response_dict["data"]["business_amount"])],
223
+ "turnover": [float(response_dict["data"]["tr"])]
224
+ }
225
+ logger.success(f"{info} [成功]")
226
+ return pd.DataFrame(data=df_data)
227
+
228
+ # 默认返回的数据
229
+ logger.success(f"{info} [成功]")
230
+ return response_dict["data"]
231
+
232
+ # ------------------------------------------------------------------------------------------
233
+
234
+ # 板块
235
+
236
+ # 板块数据不能转换为 pd.DataFrame
237
+ if (data_type == "plate") and (utils.v_true(df, bool) is True):
238
+ logger.error(f"{info} [错误]")
239
+ return None
240
+
241
+ # 数据结果
242
+ result: list = []
243
+
244
+ # 筛选 主板, 非ST, 非银行, 非证券 的股票
245
+ for i in response_dict["data"]["stocks"]:
246
+ if (re.match(r"^(sz00|sh60)", i["secu_code"])) and (not re.search(r"ST|银行|证券", i["secu_name"])):
247
+ result.append(i)
248
+
249
+ # 返回数据
250
+ logger.success(f"{info} [成功]")
251
+ return result
252
+
253
+ except Exception as e:
254
+ logger.error(f"{info} [失败]")
255
+ logger.exception(e)
256
+ return None
ezKit/database.py CHANGED
@@ -1,11 +1,10 @@
1
- """
2
- Column, Table, MetaData API
3
- https://docs.sqlalchemy.org/en/14/core/metadata.html#column-table-metadata-api
4
- CursorResult
5
- https://docs.sqlalchemy.org/en/20/core/connections.html#sqlalchemy.engine.CursorResult
6
- PostgreSQL 14 Data Types
7
- https://www.postgresql.org/docs/14/datatype.html
8
- """
1
+ """Database"""
2
+ # Column, Table, MetaData API
3
+ # https://docs.sqlalchemy.org/en/14/core/metadata.html#column-table-metadata-api
4
+ # CursorResult
5
+ # https://docs.sqlalchemy.org/en/20/core/connections.html#sqlalchemy.engine.CursorResult
6
+ # PostgreSQL 14 Data Types
7
+ # https://www.postgresql.org/docs/14/datatype.html
9
8
  import csv
10
9
  from typing import Any
11
10
 
ezKit/http.py CHANGED
@@ -1,3 +1,4 @@
1
+ """HTTP"""
1
2
  import json
2
3
  from typing import Any
3
4
 
ezKit/qywx.py CHANGED
@@ -1,14 +1,10 @@
1
- """
2
- 企业微信开发者中心
3
-
4
- https://developer.work.weixin.qq.com/
5
- https://developer.work.weixin.qq.com/document/path/90313 (全局错误码)
6
-
7
- 参考文档:
8
-
9
- https://www.gaoyuanqi.cn/python-yingyong-qiyewx/
10
- https://www.jianshu.com/p/020709b130d3
11
- """
1
+ """企业微信"""
2
+ # 企业微信开发者中心
3
+ # https://developer.work.weixin.qq.com/
4
+ # https://developer.work.weixin.qq.com/document/path/90313 (全局错误码)
5
+ # 参考文档:
6
+ # https://www.gaoyuanqi.cn/python-yingyong-qiyewx/
7
+ # https://www.jianshu.com/p/020709b130d3
12
8
  import json
13
9
  import time
14
10
 
@@ -39,12 +35,15 @@ class QYWX:
39
35
  def getaccess_token(self) -> str | None:
40
36
  try:
41
37
  response = requests.get(f"{self.url_prefix}/cgi-bin/gettoken?corpid={self.work_id}&corpsecret={self.agent_secret}", timeout=10)
42
- if response.status_code == 200:
43
- result: dict = response.json()
44
- self.access_token = result.get('access_token')
45
- else:
38
+
39
+ if response.status_code != 200:
46
40
  self.access_token = None
41
+ return None
42
+
43
+ result: dict = response.json()
44
+ self.access_token = result.get('access_token')
47
45
  return result.get('access_token')
46
+
48
47
  except Exception as e:
49
48
  logger.exception(e)
50
49
  return None
@@ -151,15 +150,19 @@ class QYWX:
151
150
  users: list = []
152
151
 
153
152
  match True:
154
- case True if utils.v_true(mobile, list):
153
+ case True if isinstance(mobile, list) and utils.v_true(mobile, list):
155
154
  users = mobile
156
- case True if utils.v_true(mobile, str):
155
+ case True if isinstance(mobile, str) and utils.v_true(mobile, str):
157
156
  users.append(mobile)
158
157
  case _:
159
- return None
158
+ return False
160
159
 
161
160
  for user in users:
162
161
  user_object = self.get_user_id_by_mobile(user)
162
+
163
+ if not isinstance(user_object, dict):
164
+ continue
165
+
163
166
  json_dict = {
164
167
  'touser': user_object.get('userid'),
165
168
  'msgtype': 'text',
ezKit/stock.py CHANGED
@@ -1,5 +1,4 @@
1
1
  """股票"""
2
- # pylint: disable=R0911
3
2
  from copy import deepcopy
4
3
  from typing import Any
5
4
 
ezKit/xftp.py CHANGED
@@ -1,6 +1,5 @@
1
- """
2
- ftplib: https://docs.python.org/3.11/library/ftplib.html
3
- """
1
+ """FTP"""
2
+ # ftplib: https://docs.python.org/3.11/library/ftplib.html
4
3
  import os
5
4
  from ftplib import FTP
6
5
  from pathlib import Path
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ezKit
3
- Version: 1.8.2
3
+ Version: 1.8.4
4
4
  Summary: Easy Kit
5
5
  Author: septvean
6
6
  Author-email: septvean@gmail.com
@@ -0,0 +1,20 @@
1
+ ezKit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ ezKit/bottle.py,sha256=usKK1wVaZw4_D-4VwMYmOIc8jtz4TrpM30nck59HMFw,180178
3
+ ezKit/bottle_extensions.py,sha256=LQikCbbYZBAa4AcihvrTvixWHHMY7OjCBsT02PqWMMM,1129
4
+ ezKit/cipher.py,sha256=0T_StbjiNI4zgrjVgcfU-ffKgu1waBA9UDudAnqFcNM,2896
5
+ ezKit/cls.py,sha256=_M6ymGiJVb0V5sK93rhkJnI3v9xwS0qN4VH0gwCWdSY,9260
6
+ ezKit/database.py,sha256=kYb0ybACxrdFZnwJ40bTbG8Obh2oEF3GQWmCbPVgH-c,6878
7
+ ezKit/http.py,sha256=N2x86HCmJ5ejwA3-gHowEgSpaFTFT9nCWFjPuQ1T_do,1801
8
+ ezKit/mongo.py,sha256=P6WTwFRxaaHixJK_PyKlOfPHkeJRxxrNLV77xy5LVBQ,2048
9
+ ezKit/qywx.py,sha256=rdhusXl6YZUbsYm4HJUzWqGPFFlGqwKA4ygzwxiiBl4,7171
10
+ ezKit/redis.py,sha256=HVofsLdSBbBHAR-veumsrjTwZQspRDy2FXNR6MDCCXs,1972
11
+ ezKit/sendemail.py,sha256=Qxu4XQkHRPeX6FSJdzj-MXND9NyKcgHljbafNmy34H0,8243
12
+ ezKit/stock.py,sha256=p-l6Tv0oZdJ3juxkddScphm7BW4vH-mBozBgSH1Qu0w,1730
13
+ ezKit/token.py,sha256=9CAZhPdXiRiWoOIeWmP0q6L3j1zQAv4YcVWH95Tjefs,1755
14
+ ezKit/utils.py,sha256=an7joZy_EEpYfN8zBtEWAnhP0YXYfPieabsK_HAxXl4,48921
15
+ ezKit/xftp.py,sha256=XyIdr_2rxRVLqPofG6fIYWhAMVsFwTyp46dg5P9FLW4,7774
16
+ ezKit-1.8.4.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
17
+ ezKit-1.8.4.dist-info/METADATA,sha256=XpWOxkE-UKyjOd9YDJ03BiumX3K2aLhvUolVanZQPjM,190
18
+ ezKit-1.8.4.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
19
+ ezKit-1.8.4.dist-info/top_level.txt,sha256=aYLB_1WODsqNTsTFWcKP-BN0KCTKcV-HZJ4zlHkCFw8,6
20
+ ezKit-1.8.4.dist-info/RECORD,,
@@ -1,20 +0,0 @@
1
- ezKit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- ezKit/bottle.py,sha256=usKK1wVaZw4_D-4VwMYmOIc8jtz4TrpM30nck59HMFw,180178
3
- ezKit/bottle_extensions.py,sha256=LQikCbbYZBAa4AcihvrTvixWHHMY7OjCBsT02PqWMMM,1129
4
- ezKit/cipher.py,sha256=uVUzeoYg5ZPJLpqg2wLst-7vfdDGmqWKka9Oyi0WrCA,2883
5
- ezKit/cls.py,sha256=mkNSguUNocP8aKh1GEpkUMgL9xRXfMKdGs6tEeeV5X8,3266
6
- ezKit/database.py,sha256=awTEdD4aqevyJg5LPBHmUPrOKweqzJ2Ezqqx0_xgUDA,6859
7
- ezKit/http.py,sha256=cyS18-TW9f7p1OaiJ4nnVsKZT8Ghy-8OewkfYm8yesw,1790
8
- ezKit/mongo.py,sha256=P6WTwFRxaaHixJK_PyKlOfPHkeJRxxrNLV77xy5LVBQ,2048
9
- ezKit/qywx.py,sha256=ra2e3u8IJmNZXr569u1mik3KArAiMdC9x0SgXGXEJes,7003
10
- ezKit/redis.py,sha256=HVofsLdSBbBHAR-veumsrjTwZQspRDy2FXNR6MDCCXs,1972
11
- ezKit/sendemail.py,sha256=Qxu4XQkHRPeX6FSJdzj-MXND9NyKcgHljbafNmy34H0,8243
12
- ezKit/stock.py,sha256=gEy4N7S0GsZCdfEdYHfaUHMEHMFmNGfHm198hG5n5eI,1754
13
- ezKit/token.py,sha256=9CAZhPdXiRiWoOIeWmP0q6L3j1zQAv4YcVWH95Tjefs,1755
14
- ezKit/utils.py,sha256=an7joZy_EEpYfN8zBtEWAnhP0YXYfPieabsK_HAxXl4,48921
15
- ezKit/xftp.py,sha256=7BABr-gjxZxK2UXoW9XxN76i1HdubeaomYlYMqRurHE,7770
16
- ezKit-1.8.2.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
17
- ezKit-1.8.2.dist-info/METADATA,sha256=Vnx7icBFnyUYYAHZz3jh5hhDS11d3hHngGlBz-DkWwU,190
18
- ezKit-1.8.2.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
19
- ezKit-1.8.2.dist-info/top_level.txt,sha256=aYLB_1WODsqNTsTFWcKP-BN0KCTKcV-HZJ4zlHkCFw8,6
20
- ezKit-1.8.2.dist-info/RECORD,,
File without changes
File without changes