eric-tools 1.3.3__py3-none-any.whl → 1.3.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.
- eric_tools/__init__.py +2 -4
- eric_tools/delete_duplicate.py +61 -0
- eric_tools/dynamic_settings.py +3 -5
- eric_tools/jwt_encrypt.py +9 -6
- eric_tools/logMixin.py +0 -2
- eric_tools/pgsql.py +5 -12
- eric_tools/remove.py +3 -6
- {eric_tools-1.3.3.dist-info → eric_tools-1.3.4.dist-info}/METADATA +5 -3
- {eric_tools-1.3.3.dist-info → eric_tools-1.3.4.dist-info}/RECORD +12 -12
- eric_tools/readconfig.py +0 -30
- {eric_tools-1.3.3.dist-info → eric_tools-1.3.4.dist-info}/LICENSE +0 -0
- {eric_tools-1.3.3.dist-info → eric_tools-1.3.4.dist-info}/WHEEL +0 -0
- {eric_tools-1.3.3.dist-info → eric_tools-1.3.4.dist-info}/top_level.txt +0 -0
eric_tools/__init__.py
CHANGED
@@ -4,16 +4,14 @@
|
|
4
4
|
@Time : 2020-11-30 17:31
|
5
5
|
@IDE : PyCharm
|
6
6
|
'''
|
7
|
-
|
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.
|
14
|
+
__version__ = "1.3.4"
|
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("未发现重复文件!")
|
eric_tools/dynamic_settings.py
CHANGED
@@ -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(
|
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,6 +160,7 @@ 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
165
|
value = config.get(key) # ✅ 取值
|
168
166
|
if value is None:
|
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__(
|
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(
|
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
|
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验证失败")
|
eric_tools/logMixin.py
CHANGED
eric_tools/pgsql.py
CHANGED
@@ -25,17 +25,14 @@ class PostgreSQL(object):
|
|
25
25
|
self.__dict__[key] = value
|
26
26
|
|
27
27
|
def __getattr__(self, item):
|
28
|
-
print self.__dict__[item]
|
29
28
|
return self.__dict__[item]
|
30
29
|
|
31
30
|
def __call__(self, *args, **kwargs):
|
32
|
-
print
|
31
|
+
print('%s' % PostgreSQL.__dict__)
|
33
32
|
|
34
33
|
@property
|
35
34
|
def info(self):
|
36
|
-
return psycopg2.__version__,psycopg2.__doc__
|
37
|
-
|
38
|
-
|
35
|
+
return psycopg2.__version__, psycopg2.__doc__
|
39
36
|
|
40
37
|
def operate(self, sql, params):
|
41
38
|
count = 0
|
@@ -45,7 +42,7 @@ class PostgreSQL(object):
|
|
45
42
|
self.conn.commit()
|
46
43
|
self.close()
|
47
44
|
except Exception, e:
|
48
|
-
print
|
45
|
+
print(e.message)
|
49
46
|
return count
|
50
47
|
|
51
48
|
def connect(self):
|
@@ -66,7 +63,7 @@ class PostgreSQL(object):
|
|
66
63
|
result = self.cursor.fetchone()
|
67
64
|
self.close()
|
68
65
|
except Exception, e:
|
69
|
-
print
|
66
|
+
print(e.message)
|
70
67
|
return result
|
71
68
|
|
72
69
|
def get_all(self, sql, params=()):
|
@@ -77,7 +74,7 @@ class PostgreSQL(object):
|
|
77
74
|
tup = self.cursor.fetchall()
|
78
75
|
self.close()
|
79
76
|
except Exception, e:
|
80
|
-
print
|
77
|
+
print(e.message)
|
81
78
|
return tup
|
82
79
|
|
83
80
|
def insert(self, sql, params=()):
|
@@ -88,7 +85,3 @@ class PostgreSQL(object):
|
|
88
85
|
|
89
86
|
def delete(self, sql, params=()):
|
90
87
|
return self.operate(sql, params)
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
eric_tools/remove.py
CHANGED
@@ -17,7 +17,6 @@ class RemoveFile(object):
|
|
17
17
|
|
18
18
|
@staticmethod
|
19
19
|
def fileremove(filename, timedifference):
|
20
|
-
'''remove file'''
|
21
20
|
|
22
21
|
date = datetime.datetime.fromtimestamp(os.path.getmtime(filename))
|
23
22
|
now = datetime.datetime.now()
|
@@ -25,17 +24,15 @@ class RemoveFile(object):
|
|
25
24
|
if (now - date).seconds > timedifference:
|
26
25
|
if os.path.exists(filename):
|
27
26
|
os.remove(filename)
|
28
|
-
print
|
27
|
+
print('remove file: %s' % filename)
|
29
28
|
else:
|
30
|
-
print
|
29
|
+
print('no such file: %s' % filename)
|
31
30
|
|
32
31
|
|
33
32
|
FILE_DIR = '/home'
|
34
33
|
|
35
34
|
if __name__ == '__main__':
|
36
35
|
|
37
|
-
print 'Script is running...'
|
38
|
-
|
39
36
|
while True:
|
40
37
|
ITEMS = os.listdir(FILE_DIR)
|
41
38
|
NEWLIST = []
|
@@ -44,7 +41,7 @@ if __name__ == '__main__':
|
|
44
41
|
NEWLIST.append(FILE_DIR + names)
|
45
42
|
|
46
43
|
for names in NEWLIST:
|
47
|
-
print
|
44
|
+
print('current file: %s' % (names))
|
48
45
|
RemoveFile.fileremove(names, 10)
|
49
46
|
|
50
47
|
time.sleep(2)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: eric-tools
|
3
|
-
Version: 1.3.
|
3
|
+
Version: 1.3.4
|
4
4
|
Summary: Python Daily Development Tools
|
5
5
|
Home-page: https://github.com/Eric-jxl/Tools
|
6
6
|
Author: Eric
|
@@ -18,10 +18,11 @@ Requires-Dist: requests
|
|
18
18
|
Requires-Dist: paramiko
|
19
19
|
Requires-Dist: Pillow
|
20
20
|
Requires-Dist: xlsxwriter
|
21
|
+
Requires-Dist: ImageHash
|
21
22
|
|
22
23
|
# Tools
|
23
24
|
[](https://opensource.org/licenses/Apache-2.0)
|
24
|
-

|
25
26
|

|
26
27
|
[](https://github.com/eric-jxl/Tools/actions/workflows/publish-pypi.yml)
|
27
28
|
|
@@ -72,6 +73,7 @@ pip install eric_tools
|
|
72
73
|
> * nginx_log.py nginx日志解析(默认access.log)
|
73
74
|
>
|
74
75
|
> * dynamic_settings 一个动态加载配置类(支持toml、yml、conf、csv、ini等)
|
75
|
-
>
|
76
|
+
>
|
77
|
+
> * delete_duplicate 删除工作区重复文件(包括图片等)
|
76
78
|
|
77
79
|
|
@@ -1,26 +1,26 @@
|
|
1
1
|
eric_tools/Abstract.py,sha256=8HpTno0VnviyYaRvc2whTUfUJefg2tZhgR94RU9f-FQ,1619
|
2
|
-
eric_tools/__init__.py,sha256=
|
2
|
+
eric_tools/__init__.py,sha256=G4_vDPbMbHzI9mJzrTSxvoFguhxsTpseOUyE7MwIM0s,386
|
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=
|
8
|
+
eric_tools/dynamic_settings.py,sha256=a5t4m1QXRrrnljRWEyH99WZnE8KHo2W1svGFmiTxRCc,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=
|
13
|
-
eric_tools/logMixin.py,sha256=
|
13
|
+
eric_tools/jwt_encrypt.py,sha256=_FxRezFnfEwCviFzx3K0s1yN872VqxqaAwMsU-GI3EI,1358
|
14
|
+
eric_tools/logMixin.py,sha256=1-atM_plpGaZ2KxxDZ9-c38buhPfahrQJ2sRrRo-meI,2235
|
14
15
|
eric_tools/logger.py,sha256=zvpDv0YpeXZld2w2yPIuosfLWdbdvOqSQsJS2PtstXQ,3058
|
15
16
|
eric_tools/nginx_log.py,sha256=zEhfYBtXNJam9tfRbOY5TjezvZspFQzcV5fgrcXv_PM,1260
|
16
|
-
eric_tools/pgsql.py,sha256=
|
17
|
-
eric_tools/
|
18
|
-
eric_tools/remove.py,sha256=RtnNFZzvRc-YNKdDb0h9zVZAPXyDSM1nVcUHTFEjQGk,1163
|
17
|
+
eric_tools/pgsql.py,sha256=6rBZillrJF2zOptpnPUiczhKf8-HYosFcoshKrrFGpI,2286
|
18
|
+
eric_tools/remove.py,sha256=M1BOj1Np-YMduDfOqfSqnday-Yy68kJdMT352gtF0PA,1106
|
19
19
|
eric_tools/resize_image.py,sha256=A2OBCF7XfnQesWIYTs2W1jmZDslftagPxcc-Fijmyoo,2855
|
20
20
|
eric_tools/send_email.py,sha256=z1SMVpRaJZQIpA-zUHxxd3WKnUGMaAl9ZG-GirO9fTQ,1177
|
21
21
|
eric_tools/sftp.py,sha256=UUBmy4R-7Pezo9haA8JufDyJRcxZg2pKquX0KJIDZIw,423
|
22
|
-
eric_tools-1.3.
|
23
|
-
eric_tools-1.3.
|
24
|
-
eric_tools-1.3.
|
25
|
-
eric_tools-1.3.
|
26
|
-
eric_tools-1.3.
|
22
|
+
eric_tools-1.3.4.dist-info/LICENSE,sha256=wURoCIWynkcZ4qUfCqtUOaHgLZgGkrWq8IbK4Scn8os,10849
|
23
|
+
eric_tools-1.3.4.dist-info/METADATA,sha256=OtGmfKqJB2wtikjYuaI5YX6d09rGnv3cQp6uD8PmAWo,5171
|
24
|
+
eric_tools-1.3.4.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
25
|
+
eric_tools-1.3.4.dist-info/top_level.txt,sha256=mtO1Tce6qLPcuy4F8bXHByXuIb2LSAEkQEqeQ3UZpzU,11
|
26
|
+
eric_tools-1.3.4.dist-info/RECORD,,
|
eric_tools/readconfig.py
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
# -*- coding:utf-8 -*-
|
2
|
-
'''
|
3
|
-
@Author : Eric
|
4
|
-
@Time : 2021-02-07 14:01
|
5
|
-
@IDE : PyCharm
|
6
|
-
'''
|
7
|
-
import sys
|
8
|
-
|
9
|
-
import configparser
|
10
|
-
|
11
|
-
# proDir = os.path.split(os.path.realpath(__file__))[0]
|
12
|
-
# configPath = os.path.join(proDir, "config.ini")
|
13
|
-
|
14
|
-
|
15
|
-
class ReadConfig(object):
|
16
|
-
def __init__(self, configPath,title, name):
|
17
|
-
self.conf = configparser.ConfigParser()
|
18
|
-
self.title = title
|
19
|
-
self.name = name
|
20
|
-
self.conf.read(configPath, encoding='utf-8')
|
21
|
-
self.conf.get(title, name)
|
22
|
-
print self.conf.get(title, name)
|
23
|
-
|
24
|
-
|
25
|
-
def __repr__(self):
|
26
|
-
if sys.version_info < 3:
|
27
|
-
print '%s' % self.conf.get(self.title, self.name)
|
28
|
-
else:
|
29
|
-
print('%s' % self.conf.get(self.title, self.name))
|
30
|
-
|
File without changes
|
File without changes
|
File without changes
|