eric-tools 1.3.3__py3-none-any.whl → 1.3.3.1__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.
eric_tools/__init__.py CHANGED
@@ -4,16 +4,14 @@
4
4
  @Time : 2020-11-30 17:31
5
5
  @IDE : PyCharm
6
6
  '''
7
- from . import decorator, Abstract, convert_json, jwt_encrypt, send_email, readconfig, sftp
8
- from . import ip, logger, resize_image, exception_class, pgsql, encryption_classmethod
9
- from . import async_queue, downloader, logMixin, nginx_log, excel_generator
7
+
10
8
  from .dynamic_settings import DynamicConfig
11
9
 
12
10
 
13
11
  name = 'Eric-Tools'
14
12
  __title__ = 'tools'
15
13
  __description__ = 'Python HTTP for Humans.'
16
- __version__ = "1.3.3"
14
+ __version__ = "1.3.3.1"
17
15
  __author__ = 'Eric'
18
16
  __doc__ = ["Python Daily Development Tools"]
19
17
  __url__ = "https://github.com/Eric-jxl/Tools"
@@ -0,0 +1,61 @@
1
+ import os
2
+ import hashlib
3
+ import imagehash
4
+ from PIL import Image
5
+
6
+
7
+ def get_file_hash(file_path, is_image=False):
8
+ """计算文件的哈希值(图片使用感知哈希,其他文件使用 SHA-256)"""
9
+ try:
10
+ if is_image:
11
+ with Image.open(file_path) as img:
12
+ return str(imagehash.phash(img)) # 感知哈希(pHash)
13
+ else:
14
+ hasher = hashlib.sha256()
15
+ with open(file_path, "rb") as f:
16
+ while chunk := f.read(8192): # 逐块读取,适用于大文件
17
+ hasher.update(chunk)
18
+ return hasher.hexdigest()
19
+ except Exception as e:
20
+ print(f"无法处理 {file_path},错误: {e}")
21
+ return None
22
+
23
+
24
+ def find_duplicates(folder_path):
25
+ """查找并收集重复文件"""
26
+ hashes = {} # 存储 {哈希值: 文件路径}
27
+ duplicates = []
28
+
29
+ for root, _, files in os.walk(folder_path):
30
+ for file in files:
31
+ file_path = os.path.join(root, file)
32
+ ext = file.lower().split('.')[-1]
33
+
34
+ # 判断是否为图片
35
+ is_image = ext in ('png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp')
36
+
37
+ file_hash = get_file_hash(file_path, is_image)
38
+ if file_hash:
39
+ if file_hash in hashes:
40
+ duplicates.append(file_path) # 记录重复项
41
+ else:
42
+ hashes[file_hash] = file_path
43
+
44
+ return duplicates
45
+
46
+
47
+ def remove_duplicates(duplicates):
48
+ """删除重复文件"""
49
+ for dup in duplicates:
50
+ print(f"删除重复文件: {dup}")
51
+ os.remove(dup)
52
+
53
+
54
+ if __name__ == "__main__":
55
+ FOLDER_PATH = "/Users/eric/Downloads/Downloads/哔哩哔哩壁纸"
56
+ duplicates = find_duplicates(FOLDER_PATH)
57
+ if duplicates:
58
+ remove_duplicates(duplicates)
59
+ print(f"已删除 {len(duplicates)} 个重复文件!")
60
+ else:
61
+ print("未发现重复文件!")
@@ -42,9 +42,8 @@ class DynamicConfig(MutableMapping):
42
42
 
43
43
  def _start_watching(self):
44
44
  """Starts a background thread to monitor file changes."""
45
- event_handler = ConfigFileHandler(self, self.watch_file)
46
45
  observer = Observer()
47
- observer.schedule(event_handler, path=os.path.dirname(
46
+ observer.schedule(ConfigFileHandler(self, self.watch_file), path=os.path.dirname(
48
47
  self.watch_file) or ".", recursive=False)
49
48
  observer.start()
50
49
  self._observer = observer
@@ -146,9 +145,6 @@ class DynamicConfig(MutableMapping):
146
145
  self._observer.join()
147
146
 
148
147
 
149
- config = DynamicConfig("config.yml", debug=True, mode="production")
150
-
151
-
152
148
  @app.route("/", methods=["GET"])
153
149
  def index():
154
150
  return redirect("/config/")
@@ -156,6 +152,7 @@ def index():
156
152
 
157
153
  @app.route("/config/", methods=["GET"])
158
154
  def get_config():
155
+ config = DynamicConfig("config.yml", debug=True, mode="production")
159
156
  config.force_reload()
160
157
  return jsonify(config.config)
161
158
 
@@ -163,8 +160,9 @@ def get_config():
163
160
  @app.route("/config/<path:key>", methods=["GET"]) # ✅ 允许 `/` 作为 key 的一部分
164
161
  def get_config_key(key):
165
162
  """获取指定配置项的值,并支持自动重新加载"""
163
+ config = DynamicConfig("config.yml", debug=True, mode="production")
166
164
  config.force_reload() # ✅ 先重新加载配置
167
- value = config.get(key) # ✅ 取值
165
+ value = Config.get(key) # ✅ 取值
168
166
  if value is None:
169
167
  return jsonify({"error": "Key not found"}), 404 # ✅ 404 + 友好错误信息
170
168
  return jsonify(value)
eric_tools/jwt_encrypt.py CHANGED
@@ -8,18 +8,21 @@
8
8
  from jose.exceptions import ExpiredSignatureError, JWTError
9
9
  from jose import jwt
10
10
  import uuid
11
- from datetime import datetime,timedelta
11
+ from datetime import datetime, timedelta
12
+
12
13
 
13
14
  class GenerateAuthenticate(object):
14
- def __init__(self,secretKey,cipher_text):
15
+ def __init__(self, secretKey, cipher_text):
15
16
  self.secretKey = secretKey
16
17
  self.cipher_text = cipher_text
17
- super(GenerateAuthenticate,self).__init__(secret_key=secretKey,cipher_text=cipher_text)
18
+ super(GenerateAuthenticate, self).__init__(
19
+ secret_key=secretKey, cipher_text=cipher_text)
18
20
 
19
21
  @staticmethod
20
22
  def generate_access_token(SECRET_KEY, Plaintext):
21
23
  expire = datetime.utcnow() + timedelta(minutes=1)
22
- to_encode = {"exp": expire, "sub": str(Plaintext), "uid": str(uuid.uuid4())}
24
+ to_encode = {"exp": expire, "sub": str(
25
+ Plaintext), "uid": str(uuid.uuid4())}
23
26
  token = jwt.encode(to_encode, SECRET_KEY, algorithm="HS256")
24
27
  return token
25
28
 
@@ -29,7 +32,7 @@ class GenerateAuthenticate(object):
29
32
  payload = jwt.decode(Ciphertext, secretKey, algorithms="HS256")
30
33
  import sys
31
34
  if isinstance(payload, unicode) or sys.version_info[0] < 3:
32
- print str(payload).encode('utf-8').replace('u\'', '')
35
+ print(str(payload).encode('utf-8').replace('u\'', ''))
33
36
  else:
34
37
  print(payload)
35
38
  return payload
@@ -37,4 +40,4 @@ class GenerateAuthenticate(object):
37
40
  except ExpiredSignatureError:
38
41
  print(u"token过期")
39
42
  except JWTError:
40
- print(u"token验证失败")
43
+ print(u"token验证失败")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: eric-tools
3
- Version: 1.3.3
3
+ Version: 1.3.3.1
4
4
  Summary: Python Daily Development Tools
5
5
  Home-page: https://github.com/Eric-jxl/Tools
6
6
  Author: Eric
@@ -21,7 +21,7 @@ Requires-Dist: xlsxwriter
21
21
 
22
22
  # Tools
23
23
  [![License](https://img.shields.io/:license-apache-blue.svg)](https://opensource.org/licenses/Apache-2.0)
24
- ![latest 1.3.3](https://img.shields.io/badge/latest-1.3.3-green.svg?style=flat)
24
+ ![latest 1.3.3.1](https://img.shields.io/badge/latest-1.3.3.1-green.svg?style=flat)
25
25
  ![GitHub commits since latest release](https://img.shields.io/github/commits-since/eric-jxl/Tools/latest)
26
26
  [![Publish Python Package](https://github.com/eric-jxl/Tools/actions/workflows/publish-pypi.yml/badge.svg)](https://github.com/eric-jxl/Tools/actions/workflows/publish-pypi.yml)
27
27
 
@@ -72,6 +72,7 @@ pip install eric_tools
72
72
  > * nginx_log.py nginx日志解析(默认access.log)
73
73
  >
74
74
  > * dynamic_settings 一个动态加载配置类(支持toml、yml、conf、csv、ini等)
75
- >
75
+ >
76
+ > * delete_duplicate 删除工作区重复文件(包括图片等)
76
77
 
77
78
 
@@ -1,15 +1,16 @@
1
1
  eric_tools/Abstract.py,sha256=8HpTno0VnviyYaRvc2whTUfUJefg2tZhgR94RU9f-FQ,1619
2
- eric_tools/__init__.py,sha256=8mWCYt9rkqEdtJAaFlvVNnmAoPwfWIxc2Ow4jVjwzyg,639
2
+ eric_tools/__init__.py,sha256=AzdqdRGGJQONw9Wm-92xghu7pbW5dDJCs_w4JM2fhig,388
3
3
  eric_tools/async_queue.py,sha256=-wiImRYCWcNBbCAMLXFTjKkPrK94mFL836-f_wvUewA,1122
4
4
  eric_tools/convert_json.py,sha256=Qcs8VQGB7cBkwAiqH1Xd9vbagw19sA2bE9s4EJFA33E,638
5
5
  eric_tools/decorator.py,sha256=DEN_-TSvtAo0TWvs_7-HbeMQCqdgVAkxz2K5fekYFbM,1887
6
+ eric_tools/delete_duplicate.py,sha256=X3mXW2rjD4TnhmJPYFl6H06lu4rsUkoltL2C3btpkL4,1919
6
7
  eric_tools/downloader.py,sha256=iSs6fpcxzlZX5VRjeahPOtf5G_HclY7aPNGXL5XyOwg,1758
7
- eric_tools/dynamic_settings.py,sha256=fLvBnAw9NUWD70m3zr83ORdJVyg-S8VYxO4zKbSMTyg,5681
8
+ eric_tools/dynamic_settings.py,sha256=WGsjU1YYdXkoXB3J_8Tm6TUvNqc7qjQ2NmVzt0CnH1U,5717
8
9
  eric_tools/encryption_classmethod.py,sha256=JaR0rBnaxOEWxOtoOZ6qN1x31Zm1boh5kw264juHLWg,1662
9
10
  eric_tools/excel_generator.py,sha256=8pfd4yfDfd63f6XzFUuMKdpgLiSAnrEfyRcYXKAh8XM,1430
10
11
  eric_tools/exception_class.py,sha256=4ntO2ynm3D9tGoeJ538OGKKsudqhoDRw-fpFd4X6Hy0,741
11
12
  eric_tools/ip.py,sha256=TqeWnJe2M5HhoI8WGNFwyYrsI7kYDQ4PBDBDIDjLSkc,915
12
- eric_tools/jwt_encrypt.py,sha256=qiKlitswvC44xpDft8_Iekk8Ewc1HeUA7_Ayc7jFwEY,1324
13
+ eric_tools/jwt_encrypt.py,sha256=_FxRezFnfEwCviFzx3K0s1yN872VqxqaAwMsU-GI3EI,1358
13
14
  eric_tools/logMixin.py,sha256=D7S8FmjO_5ON6vIQXrOQFblDNmeoTHb3TV2eisJOFAQ,2298
14
15
  eric_tools/logger.py,sha256=zvpDv0YpeXZld2w2yPIuosfLWdbdvOqSQsJS2PtstXQ,3058
15
16
  eric_tools/nginx_log.py,sha256=zEhfYBtXNJam9tfRbOY5TjezvZspFQzcV5fgrcXv_PM,1260
@@ -19,8 +20,8 @@ eric_tools/remove.py,sha256=RtnNFZzvRc-YNKdDb0h9zVZAPXyDSM1nVcUHTFEjQGk,1163
19
20
  eric_tools/resize_image.py,sha256=A2OBCF7XfnQesWIYTs2W1jmZDslftagPxcc-Fijmyoo,2855
20
21
  eric_tools/send_email.py,sha256=z1SMVpRaJZQIpA-zUHxxd3WKnUGMaAl9ZG-GirO9fTQ,1177
21
22
  eric_tools/sftp.py,sha256=UUBmy4R-7Pezo9haA8JufDyJRcxZg2pKquX0KJIDZIw,423
22
- eric_tools-1.3.3.dist-info/LICENSE,sha256=wURoCIWynkcZ4qUfCqtUOaHgLZgGkrWq8IbK4Scn8os,10849
23
- eric_tools-1.3.3.dist-info/METADATA,sha256=mTnFMtTllt-gW7BjF25MXplNn94nQTIEj_YVzIPVQlk,5074
24
- eric_tools-1.3.3.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
25
- eric_tools-1.3.3.dist-info/top_level.txt,sha256=mtO1Tce6qLPcuy4F8bXHByXuIb2LSAEkQEqeQ3UZpzU,11
26
- eric_tools-1.3.3.dist-info/RECORD,,
23
+ eric_tools-1.3.3.1.dist-info/LICENSE,sha256=wURoCIWynkcZ4qUfCqtUOaHgLZgGkrWq8IbK4Scn8os,10849
24
+ eric_tools-1.3.3.1.dist-info/METADATA,sha256=iiQhVWg7FoqVUmWUXePM7GX8zy_tZkZKv_yvG6iOvxo,5152
25
+ eric_tools-1.3.3.1.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
26
+ eric_tools-1.3.3.1.dist-info/top_level.txt,sha256=mtO1Tce6qLPcuy4F8bXHByXuIb2LSAEkQEqeQ3UZpzU,11
27
+ eric_tools-1.3.3.1.dist-info/RECORD,,