MapleX 3.0.0.dev4__tar.gz → 3.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.
- {maplex-3.0.0.dev4/src/MapleX.egg-info → maplex-3.0.1}/PKG-INFO +3 -8
- {maplex-3.0.0.dev4 → maplex-3.0.1}/README.md +1 -6
- {maplex-3.0.0.dev4 → maplex-3.0.1}/pyproject.toml +2 -2
- maplex-3.0.1/readmes/LoggingBestPractice.md +20 -0
- maplex-3.0.1/readmes/README_Json.md +321 -0
- {maplex-3.0.0.dev4 → maplex-3.0.1}/readmes/README_Logger.md +62 -19
- {maplex-3.0.0.dev4 → maplex-3.0.1/src/MapleX.egg-info}/PKG-INFO +3 -8
- {maplex-3.0.0.dev4 → maplex-3.0.1}/src/MapleX.egg-info/SOURCES.txt +1 -1
- {maplex-3.0.0.dev4 → maplex-3.0.1}/src/maplex/__init__.py +3 -2
- {maplex-3.0.0.dev4 → maplex-3.0.1}/src/maplex/json.py +27 -5
- {maplex-3.0.0.dev4 → maplex-3.0.1}/src/maplex/mapleLogger.py +37 -4
- maplex-3.0.0.dev4/readmes/LoggingTips.md +0 -1
- maplex-3.0.0.dev4/readmes/README_Json.md +0 -93
- {maplex-3.0.0.dev4 → maplex-3.0.1}/LICENSE +0 -0
- {maplex-3.0.0.dev4 → maplex-3.0.1}/MANIFEST.in +0 -0
- {maplex-3.0.0.dev4 → maplex-3.0.1}/logErrorOutputSample.png +0 -0
- {maplex-3.0.0.dev4 → maplex-3.0.1}/logOutputSample.png +0 -0
- {maplex-3.0.0.dev4 → maplex-3.0.1}/readmes/README_ConsoleColors.md +0 -0
- {maplex-3.0.0.dev4 → maplex-3.0.1}/readmes/README_Exceptions.md +0 -0
- {maplex-3.0.0.dev4 → maplex-3.0.1}/readmes/README_MapleTree.md +0 -0
- {maplex-3.0.0.dev4 → maplex-3.0.1}/setup.cfg +0 -0
- {maplex-3.0.0.dev4 → maplex-3.0.1}/src/MapleX.egg-info/dependency_links.txt +0 -0
- {maplex-3.0.0.dev4 → maplex-3.0.1}/src/MapleX.egg-info/requires.txt +0 -0
- {maplex-3.0.0.dev4 → maplex-3.0.1}/src/MapleX.egg-info/top_level.txt +0 -0
- {maplex-3.0.0.dev4 → maplex-3.0.1}/src/maplex/mapleColors.py +0 -0
- {maplex-3.0.0.dev4 → maplex-3.0.1}/src/maplex/mapleExceptions.py +0 -0
- {maplex-3.0.0.dev4 → maplex-3.0.1}/src/maplex/mapleTreeEditor.py +0 -0
- {maplex-3.0.0.dev4 → maplex-3.0.1}/src/maplex/utils.py +0 -0
- {maplex-3.0.0.dev4 → maplex-3.0.1}/tests/test_logger_unittest.py +0 -0
- {maplex-3.0.0.dev4 → maplex-3.0.1}/tests/test_maplejson_unittest.py +0 -0
- {maplex-3.0.0.dev4 → maplex-3.0.1}/tests/test_mapletree_unittest.py +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MapleX
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.1
|
|
4
4
|
Summary: A Python library for simple logging, json file operations, Maple file format operations, and console color utilities.
|
|
5
|
-
Author:
|
|
5
|
+
Author: Ryuji Hazama
|
|
6
6
|
Project-URL: PyPI, https://pypi.org/project/MapleX/
|
|
7
7
|
Project-URL: Homepage, https://github.com/Ryuji-Hazama
|
|
8
8
|
Project-URL: Repository, https://github.com/Ryuji-Hazama/MapleTree
|
|
@@ -78,7 +78,7 @@ Also outputs to the log file:
|
|
|
78
78
|
|
|
79
79
|
[More details](https://github.com/Ryuji-Hazama/MapleTree/blob/main/readmes/README_Logger.md)
|
|
80
80
|
|
|
81
|
-
[Logging
|
|
81
|
+
[Logging Best Practice](https://github.com/Ryuji-Hazama/MapleTree/blob/main/readmes/LoggingBestPractice.md)
|
|
82
82
|
|
|
83
83
|
## MapleJson
|
|
84
84
|
|
|
@@ -185,11 +185,6 @@ All datas after "\nEOF\n" will be ignored
|
|
|
185
185
|
- `--upgrade` option for upgrade from older version.
|
|
186
186
|
- `--break-system-package` option for Python on Linux OS outside the `venv`. ***This might brak the system Python package dependencies.***
|
|
187
187
|
|
|
188
|
-
### Manual Installation
|
|
189
|
-
|
|
190
|
-
1. Download `./dist/maplex-<version>-py3-none-any.whl`
|
|
191
|
-
2. Run `[python[3] -m] pip install /path/to/downloaded/maplex-<version>-py3-none-any.whl [--break-system-packages]`
|
|
192
|
-
|
|
193
188
|
### Build the Package by Yourself
|
|
194
189
|
|
|
195
190
|
Run `python[3] -m build`
|
|
@@ -56,7 +56,7 @@ Also outputs to the log file:
|
|
|
56
56
|
|
|
57
57
|
[More details](https://github.com/Ryuji-Hazama/MapleTree/blob/main/readmes/README_Logger.md)
|
|
58
58
|
|
|
59
|
-
[Logging
|
|
59
|
+
[Logging Best Practice](https://github.com/Ryuji-Hazama/MapleTree/blob/main/readmes/LoggingBestPractice.md)
|
|
60
60
|
|
|
61
61
|
## MapleJson
|
|
62
62
|
|
|
@@ -163,11 +163,6 @@ All datas after "\nEOF\n" will be ignored
|
|
|
163
163
|
- `--upgrade` option for upgrade from older version.
|
|
164
164
|
- `--break-system-package` option for Python on Linux OS outside the `venv`. ***This might brak the system Python package dependencies.***
|
|
165
165
|
|
|
166
|
-
### Manual Installation
|
|
167
|
-
|
|
168
|
-
1. Download `./dist/maplex-<version>-py3-none-any.whl`
|
|
169
|
-
2. Run `[python[3] -m] pip install /path/to/downloaded/maplex-<version>-py3-none-any.whl [--break-system-packages]`
|
|
170
|
-
|
|
171
166
|
### Build the Package by Yourself
|
|
172
167
|
|
|
173
168
|
Run `python[3] -m build`
|
|
@@ -4,13 +4,13 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "MapleX"
|
|
7
|
-
version = "3.0.
|
|
7
|
+
version = "3.0.1"
|
|
8
8
|
description = """A Python library for simple logging, json file operations, Maple file format operations, and console color utilities."""
|
|
9
9
|
keywords = ["logging", "logger", "json", "file operations", "maple file format", "console colors"]
|
|
10
10
|
readme = "README.md"
|
|
11
11
|
license-files = ["LICENSE"]
|
|
12
12
|
authors = [
|
|
13
|
-
{name = "
|
|
13
|
+
{name = "Ryuji Hazama"}
|
|
14
14
|
]
|
|
15
15
|
dependencies = [
|
|
16
16
|
"cryptography>=46.0.3",
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Logging Best Practice
|
|
2
|
+
|
|
3
|
+
## What Is "Logging"
|
|
4
|
+
|
|
5
|
+
### The flight recorder of the application
|
|
6
|
+
|
|
7
|
+
When you are developing an application, you might experience that your application is crashing silently. Then you will insert a bunch of `print()` lines to determine where the application failed, and what was causing the error. That is a log, and those outputs are showing the exact path of your process, and help you understand what is working correctly, why, and where your code failed after the application halts.
|
|
8
|
+
|
|
9
|
+
However, those logs are disappearing when you close the output terminal, or the terminal was automatically closed by the application. That is why you need to output logs to a file like a flight recorder in a black box.
|
|
10
|
+
|
|
11
|
+
### Four W's of Logging
|
|
12
|
+
|
|
13
|
+
Every time the event occurs, the logger should capture the "Four W's" to get the details of the event.
|
|
14
|
+
|
|
15
|
+
- **When** — When the event occured.
|
|
16
|
+
- **Whrere** — Where the event happened.
|
|
17
|
+
- **What** — What was the event.
|
|
18
|
+
- **Weight** — How seriouc is the event?
|
|
19
|
+
|
|
20
|
+
### Logging vs `print()`
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
# MapleJson Class
|
|
2
|
+
|
|
3
|
+
MapleJson class is a class library to manage the JSON formatted files.
|
|
4
|
+
|
|
5
|
+
- You can read a JSON file as a `dict` data.
|
|
6
|
+
- You can write the `dict` data into a file as a JSON formatted string
|
|
7
|
+
- You can save the data as an encrypted data string.
|
|
8
|
+
- You can decrypt the encrypted data.
|
|
9
|
+
|
|
10
|
+
## Class Initialization
|
|
11
|
+
|
|
12
|
+
```python
|
|
13
|
+
|
|
14
|
+
def __init__(
|
|
15
|
+
filePath: str,
|
|
16
|
+
fileEncoding: str = 'utf-8',
|
|
17
|
+
indent: int = 4,
|
|
18
|
+
ensure_ascii: bool = False,
|
|
19
|
+
encrypt: bool = False,
|
|
20
|
+
key: bytes = None
|
|
21
|
+
) -> None:
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
|Property|Required|Value|Version|
|
|
25
|
+
|--------|--------|-----|-------|
|
|
26
|
+
|**`filePath`**|\*|JSON file path|3.0.0|
|
|
27
|
+
|**`fileEncoding`**||File encoding|3.0.0|
|
|
28
|
+
|**`indent`**||Indent size for save as a JSON file|3.0.0|
|
|
29
|
+
|**`ensureAscii`**||Ensure ASCII flag when save to a file|3.0.0|
|
|
30
|
+
|**`encrypt`**||Encryption flag|3.0.0|
|
|
31
|
+
|**`key`**|(\*)|Encryption key (32 bytes)|3.0.0|
|
|
32
|
+
|
|
33
|
+
Initialize the class with a file path.
|
|
34
|
+
|
|
35
|
+
### File encoding
|
|
36
|
+
|
|
37
|
+
You can set a specific file character encoding. Default: `UTF-8`
|
|
38
|
+
|
|
39
|
+
E.g.: If you are using `Shift_JIS` (Japanese system), you should initialize the class like the example below:
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
from maplex import MapleJson
|
|
43
|
+
|
|
44
|
+
jsonInstance = MapleJson("jsonFile.json", fileEncoding="shift_jis")
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Indent size
|
|
48
|
+
|
|
49
|
+
You can set the block indent size with `indent` parameter. Default: `4`
|
|
50
|
+
|
|
51
|
+
If you set `indent=2`, the file will be save like the example below:
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"Data": {
|
|
56
|
+
"Key": "Value",
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Ensure ASCII
|
|
62
|
+
|
|
63
|
+
You can set the flag to ensure ASCII encoding.
|
|
64
|
+
|
|
65
|
+
If you don't set the parameter (Default: `False`), the file contents after saving are look like the example below:
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{
|
|
69
|
+
"data": {
|
|
70
|
+
"japanese": "値",
|
|
71
|
+
"russian": "значение",
|
|
72
|
+
"english": "value"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
But, if you set `ensureAscii=True`, the file contents after saving will be changed like:
|
|
78
|
+
|
|
79
|
+
```json
|
|
80
|
+
{
|
|
81
|
+
"data": {
|
|
82
|
+
"japanese": "\u5024",
|
|
83
|
+
"russian": "\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435",
|
|
84
|
+
"english": "value"
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Encrypt
|
|
90
|
+
|
|
91
|
+
If you set `encrypt=True`, set the [encryption key](#key), and save data to a file using the `MapleJson` class, the file will be encrypted with AES-128 (using Fernet).
|
|
92
|
+
|
|
93
|
+
The encrypted file can be read using the `MapleJson` class, and it is also necessary to set `encrypt=True` and use the same key.
|
|
94
|
+
|
|
95
|
+
**There is no *redo*** in encryption. **DO NOT FORGET** your encryption key, or *you will lose your data FOREVER.*
|
|
96
|
+
|
|
97
|
+
### Key
|
|
98
|
+
|
|
99
|
+
A 32-byte byte-string key for encryption.
|
|
100
|
+
|
|
101
|
+
If you set `encrypt=True` when initializing the class, you must also set the key.
|
|
102
|
+
|
|
103
|
+
Encryption example:
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
from maplex import MapleJson
|
|
107
|
+
|
|
108
|
+
key = b'Yj6wIw5VR3Z-4nXXdWTZAhwU6j2SIgSQNl7QbYgDyCA='
|
|
109
|
+
jsonData = MapleJson("sampleFile.json", encrypt=True, key=key)
|
|
110
|
+
|
|
111
|
+
sampleData = {
|
|
112
|
+
"setting1": True,
|
|
113
|
+
"setting2": "value2",
|
|
114
|
+
"setting3": 12345
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
jsonData.write(sampleData)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Inside the `sampleFile.json` will be:
|
|
121
|
+
|
|
122
|
+
```text
|
|
123
|
+
gAAAAABph_yYxWIyHpS1HImudFoWQQ5WTh2VsPxO4dcXGbYujR62dW1wpZDUf1cZJF-jGzDfTLGHi6e4ihQJRTvNibgIm3sRFLJUyRClRUBSsd1mMmZ0YzFk_ZuinaNSLox3RILZwIMCCE0XbWjw_vs5x_gCKXJQdtEYZ3bSWcSyYBHBAqh3OxA=
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
The you can read the data with:
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
from maplex import MapleJson
|
|
130
|
+
|
|
131
|
+
# Set the same key that was used in encryption
|
|
132
|
+
key = b'Yj6wIw5VR3Z-4nXXdWTZAhwU6j2SIgSQNl7QbYgDyCA='
|
|
133
|
+
jsonData = MapleJson("sampleFile.json", encrypt=True, key=key)
|
|
134
|
+
dictFromJson = jsonData.read()
|
|
135
|
+
|
|
136
|
+
print(dictFromJson)
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
The console output will be:
|
|
140
|
+
|
|
141
|
+
```text
|
|
142
|
+
{'setting1': True, 'setting2': 'value2', 'setting3': 12345}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
**DO NOT FORGET YOUR ENCRYPTION KEY**, or you will lose your data *FOREVER.* There is no redo in encryption.
|
|
146
|
+
|
|
147
|
+
## Functions
|
|
148
|
+
|
|
149
|
+
### `read()`
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
def read(
|
|
153
|
+
*keys: str
|
|
154
|
+
) -> dict | None:
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
|Property|Required|Value|Version|
|
|
158
|
+
|--------|--------|-----|-------|
|
|
159
|
+
|**`*keys`**||Dict keys|3.0.0|
|
|
160
|
+
|
|
161
|
+
This function reads a JSON file, which is specified at the class instance, and returns the data as a `dict` object.
|
|
162
|
+
|
|
163
|
+
While the data in the `sampleFile.json` is:
|
|
164
|
+
|
|
165
|
+
```json
|
|
166
|
+
{
|
|
167
|
+
"settings": {
|
|
168
|
+
"setting1": True,
|
|
169
|
+
"setting2": "value2",
|
|
170
|
+
"setting3": 12345
|
|
171
|
+
},
|
|
172
|
+
"data": {
|
|
173
|
+
"data1": "value1",
|
|
174
|
+
"data2": 67890
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Read with:
|
|
180
|
+
|
|
181
|
+
```python
|
|
182
|
+
from maplex import MapleJson
|
|
183
|
+
|
|
184
|
+
jsonFile = MapleJson("sampleFile.json")
|
|
185
|
+
jsonData = jsonFile.read()
|
|
186
|
+
|
|
187
|
+
print(jsonData)
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
The output will be:
|
|
191
|
+
|
|
192
|
+
```text
|
|
193
|
+
{'settings': {'setting1': True, 'setting2': 'value2', 'setting3': 12345}, 'data': {'data1': 'value1', 'data2': 67890}}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
If you provide the key(s) in the parameter, the function returns the object of the key, and returns `None` if the key does not exist.
|
|
197
|
+
|
|
198
|
+
```python
|
|
199
|
+
from maplex import MapleJson
|
|
200
|
+
|
|
201
|
+
jsonFile = MapleJson("sampleFile.json")
|
|
202
|
+
jsonData = jsonFile.read("data")
|
|
203
|
+
|
|
204
|
+
print(jsonData)
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
This outputs:
|
|
208
|
+
|
|
209
|
+
```text
|
|
210
|
+
{'data1': 'value1', 'data2': 67890}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### `write()`
|
|
214
|
+
|
|
215
|
+
```python
|
|
216
|
+
def write(
|
|
217
|
+
data: dict
|
|
218
|
+
) -> None:
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
|Property|Required|Value|Version|
|
|
222
|
+
|--------|--------|-----|-------|
|
|
223
|
+
|**`data`**|\*|Dict object to save|3.0.0|
|
|
224
|
+
|
|
225
|
+
This function saves the `dict` object to a file in JSON format.
|
|
226
|
+
|
|
227
|
+
This overwrites the existing file and creates a new file if the file does not exist.
|
|
228
|
+
|
|
229
|
+
```python
|
|
230
|
+
from maplex import MapleJson
|
|
231
|
+
|
|
232
|
+
jsonFile = MapleJson("sampleFile")
|
|
233
|
+
jsonData = {"data1": True, "data2": "value2", "data3": 12345}
|
|
234
|
+
jsonFile.write(jsonData)
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
This creates a file that contains the following data:
|
|
238
|
+
|
|
239
|
+
```json
|
|
240
|
+
{
|
|
241
|
+
"data1": True,
|
|
242
|
+
"data2": "value2",
|
|
243
|
+
"data3": 12345
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
The function **overwrites the entire file** with the provided data. So you should be careful, especially when reading with the key(s) and saving their data.
|
|
248
|
+
|
|
249
|
+
While the data in the `sampleFile.json` is:
|
|
250
|
+
|
|
251
|
+
```json
|
|
252
|
+
{
|
|
253
|
+
"settings": {
|
|
254
|
+
"setting1": True,
|
|
255
|
+
"setting2": "value2",
|
|
256
|
+
"setting3": 12345
|
|
257
|
+
},
|
|
258
|
+
"data": {
|
|
259
|
+
"data1": "value1",
|
|
260
|
+
"data2": 67890
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
```python
|
|
266
|
+
from maplex import MapleJson
|
|
267
|
+
|
|
268
|
+
jsonFile = MapleJson("sampleFile.json")
|
|
269
|
+
jsonData = jsonFile.read("settings")
|
|
270
|
+
jsonFile.write(jsonData)
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
This code changes the file contents like the sample below:
|
|
274
|
+
|
|
275
|
+
```json
|
|
276
|
+
{
|
|
277
|
+
"setting1": True,
|
|
278
|
+
"setting2": "value2",
|
|
279
|
+
"setting3": 12345
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### `generateKey()`
|
|
284
|
+
|
|
285
|
+
```python
|
|
286
|
+
def generateKey(
|
|
287
|
+
setAsCurrent: bool = False
|
|
288
|
+
) -> bytes:
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
|Property|Required|Value|Version|
|
|
292
|
+
|--------|--------|-----|-------|
|
|
293
|
+
|**`setAsCurrent`**||Using the generated key as a current encryption key|3.0.0|
|
|
294
|
+
|
|
295
|
+
The function returns the randomly generated encryption byte-string key.
|
|
296
|
+
|
|
297
|
+
- If you set `setAsCurrent=False`, nothing will be changed in the instance state.
|
|
298
|
+
- If you set `setAsCurrent=True` while the encryption state was set as `True`, the instance encryption key is overwritten by the newly generated key.
|
|
299
|
+
- If you set `setAsCurrent=True` while the encryption state was set as `False`, the instance encryption state is changed to `True` and the newly generated key is set as an encryption key.
|
|
300
|
+
|
|
301
|
+
E.g. Encrypt a json file:
|
|
302
|
+
|
|
303
|
+
```python
|
|
304
|
+
from maplex import MapleJson
|
|
305
|
+
|
|
306
|
+
jsonFile = MapleJson("sampleFile.json")
|
|
307
|
+
jsonData = jsonFile.read()
|
|
308
|
+
key = jsonFile.generateKey(True)
|
|
309
|
+
# YOU MUST SAVE THE KEY in the safe storage.
|
|
310
|
+
jsonFile.write(jsonData)
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
The code will encrypt the `sampleFile.json` with AES-128 encryption with the randomly generated key.
|
|
314
|
+
|
|
315
|
+
**There is no *redo*** in encryption. **DO NOT FORGET** your encryption key, or *you will lose your data FOREVER.*
|
|
316
|
+
|
|
317
|
+
## Getters and Setters
|
|
318
|
+
|
|
319
|
+
Every class parameter has its own getter and setter functions, and you can set, change, or get those values after initializing the class.
|
|
320
|
+
|
|
321
|
+
- You need to set the encryption key when you set the encryption to `True`.
|
|
@@ -30,37 +30,50 @@ def __init__(
|
|
|
30
30
|
|
|
31
31
|
The parameter overwrites the settings configured in `config.mpl`.
|
|
32
32
|
|
|
33
|
-
##
|
|
33
|
+
## Functions
|
|
34
|
+
|
|
35
|
+
### `getLogger()`
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
def getLogger(
|
|
39
|
+
name = "",
|
|
40
|
+
**kwargs
|
|
41
|
+
) -> maplex.Logger:
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
|Property|Required|Value|Version|
|
|
45
|
+
|--------|--------|-----|-------|
|
|
46
|
+
|**`name`**||Primary funcion name|`v3.0`|
|
|
47
|
+
|**`**kwargs`**||Other parameters|`v3.0`|
|
|
48
|
+
|
|
49
|
+
This get or creates a Logger instance.
|
|
50
|
+
|
|
51
|
+
If you already have a Logger class instance with the same name, the function returns the existing instance, and you can save your resources on the machine.
|
|
34
52
|
|
|
35
53
|
```python
|
|
36
54
|
from maplex
|
|
37
55
|
|
|
38
|
-
logger = maplex.getLogger(
|
|
39
|
-
logger.info("Hello there!")
|
|
56
|
+
logger = maplex.getLogger(__name__)
|
|
40
57
|
```
|
|
41
58
|
|
|
42
|
-
|
|
59
|
+
## Getters and Setters
|
|
43
60
|
|
|
44
|
-
|
|
45
|
-
[INFO ][FunctionName] <module>(4) Hello there!
|
|
46
|
-
```
|
|
61
|
+
Every class parameter has its own getter and setter functions, and you can set, change, or get those values after initializing the class.
|
|
47
62
|
|
|
48
|
-
|
|
63
|
+
## Logging Methods
|
|
49
64
|
|
|
50
|
-
```
|
|
51
|
-
(
|
|
65
|
+
```python
|
|
66
|
+
def trace(object: any) -> None:
|
|
67
|
+
def debug(object: any) -> None:
|
|
68
|
+
def info(object: any) -> None:
|
|
69
|
+
def warn(object: any) -> None:
|
|
70
|
+
def error(object: any) -> None:
|
|
71
|
+
def fatal(object: any) -> None:
|
|
52
72
|
```
|
|
53
73
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
- `TRACE`
|
|
57
|
-
- `DEBUG`
|
|
58
|
-
- `INFO`
|
|
59
|
-
- `WARN`
|
|
60
|
-
- `ERROR`
|
|
61
|
-
- `FATAL`
|
|
74
|
+
Each function outputs the log in each log level.
|
|
62
75
|
|
|
63
|
-
|
|
76
|
+
## `ShowError` Function
|
|
64
77
|
|
|
65
78
|
This outputs the error logs and stuck trace.
|
|
66
79
|
|
|
@@ -82,6 +95,36 @@ def ShowError(
|
|
|
82
95
|
|
|
83
96
|
- If `fatal=True`, it outputs log as a `FATAL` log level.
|
|
84
97
|
|
|
98
|
+
## Usage
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
from maplex
|
|
102
|
+
|
|
103
|
+
logger = maplex.getLogger("FunctionName")
|
|
104
|
+
logger.info("Hello there!")
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
This outputs:
|
|
108
|
+
|
|
109
|
+
```console
|
|
110
|
+
[INFO ][FunctionName] <module>(4) Hello there!
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
File output will be: `AppLog.log`
|
|
114
|
+
|
|
115
|
+
```log
|
|
116
|
+
(PsNo) yyyy-MM-dd HH:mm:ss.fff [INFO ][FunctionName] <module>(4) Hello there!
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Log Level
|
|
120
|
+
|
|
121
|
+
- `TRACE`
|
|
122
|
+
- `DEBUG`
|
|
123
|
+
- `INFO`
|
|
124
|
+
- `WARN`
|
|
125
|
+
- `ERROR`
|
|
126
|
+
- `FATAL`
|
|
127
|
+
|
|
85
128
|
## Settings
|
|
86
129
|
|
|
87
130
|
- You can configure log settings with a JSON formatted file (default: `config.json`).
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MapleX
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.1
|
|
4
4
|
Summary: A Python library for simple logging, json file operations, Maple file format operations, and console color utilities.
|
|
5
|
-
Author:
|
|
5
|
+
Author: Ryuji Hazama
|
|
6
6
|
Project-URL: PyPI, https://pypi.org/project/MapleX/
|
|
7
7
|
Project-URL: Homepage, https://github.com/Ryuji-Hazama
|
|
8
8
|
Project-URL: Repository, https://github.com/Ryuji-Hazama/MapleTree
|
|
@@ -78,7 +78,7 @@ Also outputs to the log file:
|
|
|
78
78
|
|
|
79
79
|
[More details](https://github.com/Ryuji-Hazama/MapleTree/blob/main/readmes/README_Logger.md)
|
|
80
80
|
|
|
81
|
-
[Logging
|
|
81
|
+
[Logging Best Practice](https://github.com/Ryuji-Hazama/MapleTree/blob/main/readmes/LoggingBestPractice.md)
|
|
82
82
|
|
|
83
83
|
## MapleJson
|
|
84
84
|
|
|
@@ -185,11 +185,6 @@ All datas after "\nEOF\n" will be ignored
|
|
|
185
185
|
- `--upgrade` option for upgrade from older version.
|
|
186
186
|
- `--break-system-package` option for Python on Linux OS outside the `venv`. ***This might brak the system Python package dependencies.***
|
|
187
187
|
|
|
188
|
-
### Manual Installation
|
|
189
|
-
|
|
190
|
-
1. Download `./dist/maplex-<version>-py3-none-any.whl`
|
|
191
|
-
2. Run `[python[3] -m] pip install /path/to/downloaded/maplex-<version>-py3-none-any.whl [--break-system-packages]`
|
|
192
|
-
|
|
193
188
|
### Build the Package by Yourself
|
|
194
189
|
|
|
195
190
|
Run `python[3] -m build`
|
|
@@ -4,7 +4,7 @@ Logger: A simple logging utility for tracking events and debugging.
|
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
from .mapleColors import ConsoleColors
|
|
7
|
-
from .json import MapleJson
|
|
7
|
+
from .json import MapleJson, getMapleJson
|
|
8
8
|
from .mapleLogger import Logger, getLogger, getDailyLogger
|
|
9
9
|
from .mapleExceptions import (
|
|
10
10
|
InvalidMapleFileFormatException,
|
|
@@ -27,6 +27,7 @@ from .utils import winHide, winUnHide
|
|
|
27
27
|
__all__ = [
|
|
28
28
|
'ConsoleColors',
|
|
29
29
|
'getDailyLogger',
|
|
30
|
+
'getMapleJson',
|
|
30
31
|
'getLogger',
|
|
31
32
|
'InvalidMapleFileFormatException',
|
|
32
33
|
'KeyEmptyException',
|
|
@@ -48,6 +49,6 @@ __all__ = [
|
|
|
48
49
|
'winUnHide'
|
|
49
50
|
]
|
|
50
51
|
|
|
51
|
-
__version__ = "3.0.
|
|
52
|
+
__version__ = "3.0.1"
|
|
52
53
|
__author__ = "Ryuji Hazama"
|
|
53
54
|
__license__ = "MIT"
|
|
@@ -63,7 +63,7 @@ class MapleJson:
|
|
|
63
63
|
|
|
64
64
|
return self.encrypt
|
|
65
65
|
|
|
66
|
-
def setEncryption(self, encrypt: bool, key=None) -> None:
|
|
66
|
+
def setEncryption(self, encrypt: bool, key: bytes | None = None) -> None:
|
|
67
67
|
|
|
68
68
|
self.encrypt = encrypt
|
|
69
69
|
|
|
@@ -74,7 +74,7 @@ class MapleJson:
|
|
|
74
74
|
self.key = key
|
|
75
75
|
self.fernet = Fernet(key) if encrypt and key else None
|
|
76
76
|
|
|
77
|
-
def getKey(self) -> bytes:
|
|
77
|
+
def getKey(self) -> bytes | None:
|
|
78
78
|
|
|
79
79
|
return self.key
|
|
80
80
|
|
|
@@ -87,7 +87,7 @@ class MapleJson:
|
|
|
87
87
|
#####################
|
|
88
88
|
# Basic File Operations
|
|
89
89
|
|
|
90
|
-
def read(self, *keys) -> dict | None:
|
|
90
|
+
def read(self, *keys: str) -> dict | None:
|
|
91
91
|
|
|
92
92
|
try:
|
|
93
93
|
|
|
@@ -158,7 +158,6 @@ class MapleJson:
|
|
|
158
158
|
#####################
|
|
159
159
|
# Utility Methods
|
|
160
160
|
|
|
161
|
-
#
|
|
162
161
|
#####################
|
|
163
162
|
# Generate Encryption Key
|
|
164
163
|
|
|
@@ -180,4 +179,27 @@ class MapleJson:
|
|
|
180
179
|
self.fernet = Fernet(key)
|
|
181
180
|
self.encrypt = True
|
|
182
181
|
|
|
183
|
-
return key
|
|
182
|
+
return key
|
|
183
|
+
|
|
184
|
+
_json: dict[str, MapleJson] = {}
|
|
185
|
+
|
|
186
|
+
# Get or create a MapleJson instance
|
|
187
|
+
|
|
188
|
+
def getMapleJson(filePath: str,
|
|
189
|
+
fileEncoding: str = 'utf-8',
|
|
190
|
+
indent: int = 4,
|
|
191
|
+
ensureAscii: bool = False,
|
|
192
|
+
encrypt: bool = False,
|
|
193
|
+
key: bytes = None
|
|
194
|
+
) -> MapleJson:
|
|
195
|
+
|
|
196
|
+
if filePath not in _json:
|
|
197
|
+
|
|
198
|
+
_json[filePath] = MapleJson(filePath,
|
|
199
|
+
fileEncoding,
|
|
200
|
+
indent,
|
|
201
|
+
ensureAscii,
|
|
202
|
+
encrypt,
|
|
203
|
+
key)
|
|
204
|
+
|
|
205
|
+
return _json[filePath]
|
|
@@ -37,6 +37,9 @@ class Logger:
|
|
|
37
37
|
self.consoleColors = ConsoleColors()
|
|
38
38
|
self.fileMode = "append" if fileMode is None else fileMode
|
|
39
39
|
self.encoding = encoding
|
|
40
|
+
self.timestampFormat = "%F %X.%f" # Timestamp format for logs (set this in config in future)
|
|
41
|
+
self.consoleAlignWidth = 16 # Width for function name alignment in logs (set this in config in future)
|
|
42
|
+
self.fileAlignWidth = 4 # Width for function name alignment in logs (set this in config in future)
|
|
40
43
|
|
|
41
44
|
try:
|
|
42
45
|
|
|
@@ -53,6 +56,7 @@ class Logger:
|
|
|
53
56
|
self.__checkOutputDirectory(workingDirectory)
|
|
54
57
|
self.__setLogFileName(self.fileMode)
|
|
55
58
|
self.__setFuncName(kwargs.get("getLogger", False), func)
|
|
59
|
+
self.__setAlignWidth(self.consoleAlignWidth, self.fileAlignWidth)
|
|
56
60
|
self.__setLogFileSize(maxLogSize)
|
|
57
61
|
self.__setOutputLogLevels(cmdLogLevel, fileLogLevel)
|
|
58
62
|
self.__setFileEncoding(encoding)
|
|
@@ -210,6 +214,26 @@ class Logger:
|
|
|
210
214
|
self.func = ""
|
|
211
215
|
self.callerName = f"{caller}."
|
|
212
216
|
|
|
217
|
+
def __setAlignWidth(self, consoleAlignWidth: int | None = None, fileAlignWidth: int | None = None) -> None:
|
|
218
|
+
|
|
219
|
+
'''Set function name alignment width'''
|
|
220
|
+
|
|
221
|
+
if consoleAlignWidth is not None and type(consoleAlignWidth) is int and consoleAlignWidth > 0:
|
|
222
|
+
|
|
223
|
+
self.consoleAlignWidth = consoleAlignWidth
|
|
224
|
+
|
|
225
|
+
else:
|
|
226
|
+
|
|
227
|
+
self.consoleAlignWidth = 16
|
|
228
|
+
|
|
229
|
+
if fileAlignWidth is not None and type(fileAlignWidth) is int and fileAlignWidth > 0:
|
|
230
|
+
|
|
231
|
+
self.fileAlignWidth = fileAlignWidth
|
|
232
|
+
|
|
233
|
+
else:
|
|
234
|
+
|
|
235
|
+
self.fileAlignWidth = 4
|
|
236
|
+
|
|
213
237
|
def __setLogFileSize(self, maxLogSize: any) -> None:
|
|
214
238
|
|
|
215
239
|
self.maxLogSize = 0
|
|
@@ -551,16 +575,26 @@ class Logger:
|
|
|
551
575
|
# Export to console and log file
|
|
552
576
|
|
|
553
577
|
if loglevel >= self.consoleLogLevel:
|
|
554
|
-
|
|
578
|
+
consolePrefix = f"[{col}{loglevel.name:5}{Reset}]{Green}{self.func}{Reset} {bBlack}{callerFunc}({callerLine}){Reset}"
|
|
579
|
+
colorLength = len(col) + len(Reset) + len(Green) + len(Reset) + len(bBlack) + len(Reset)
|
|
580
|
+
consolePrefixLength = len(consolePrefix) - colorLength
|
|
581
|
+
consoleAlignWidth = self.consoleAlignWidth * (consolePrefixLength // self.consoleAlignWidth + (1 if consolePrefixLength % self.consoleAlignWidth != 0 else 0))
|
|
582
|
+
consoleAlignWidth += colorLength
|
|
583
|
+
print(f"{consolePrefix:<{consoleAlignWidth}}: {message}")
|
|
555
584
|
|
|
556
585
|
if loglevel >= self.fileLogLevel:
|
|
557
586
|
|
|
587
|
+
timeStamp = datetime.now().strftime(self.timestampFormat)[:-3]
|
|
588
|
+
prefixString = f"({self.pid}) {timeStamp} [{loglevel.name:5}]{self.func} {self.callerName}{callerFunc}({callerLine})"
|
|
589
|
+
prefixLength = len(prefixString)
|
|
590
|
+
alignWidth = self.fileAlignWidth * (prefixLength // self.fileAlignWidth + (1 if prefixLength % self.fileAlignWidth != 0 else 0))
|
|
591
|
+
|
|
558
592
|
for i in range(3):
|
|
559
593
|
|
|
560
594
|
try:
|
|
561
595
|
|
|
562
596
|
with open(self.logfile, "a", encoding=self.encoding) as f:
|
|
563
|
-
print(f"
|
|
597
|
+
print(f"{prefixString:<{alignWidth}}: {message}", file=f)
|
|
564
598
|
|
|
565
599
|
break
|
|
566
600
|
|
|
@@ -703,8 +737,7 @@ class Logger:
|
|
|
703
737
|
|
|
704
738
|
self.logWriter(logLevel, message, callerDepth=2)
|
|
705
739
|
|
|
706
|
-
self.logWriter(logLevel, ex, callerDepth=2)
|
|
707
|
-
self.logWriter(logLevel, traceback.format_exc(), callerDepth=2)
|
|
740
|
+
self.logWriter(logLevel, f"{ex}\n{traceback.format_exc()}", callerDepth=2)
|
|
708
741
|
|
|
709
742
|
#
|
|
710
743
|
################################
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
# Logging Tips
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
# MapleJson Class
|
|
2
|
-
|
|
3
|
-
MapleJson class is a class library to manage the JSON formatted files.
|
|
4
|
-
|
|
5
|
-
- You can read a JSON file as a `dict` data.
|
|
6
|
-
- You can write the `dict` data into a file as a JSON formatted string
|
|
7
|
-
- You can save the data as an encrypted data string.
|
|
8
|
-
- You can decrypt the encrypted data.
|
|
9
|
-
|
|
10
|
-
## Class Initialization
|
|
11
|
-
|
|
12
|
-
```python
|
|
13
|
-
|
|
14
|
-
def __init__(
|
|
15
|
-
filePath: str,
|
|
16
|
-
fileEncoding: str = 'utf-8',
|
|
17
|
-
indent: int = 4,
|
|
18
|
-
ensure_ascii: bool = False,
|
|
19
|
-
encrypt: bool = False,
|
|
20
|
-
key: bytes = None
|
|
21
|
-
) -> None:
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
|Property|Required|Value|Version|
|
|
25
|
-
|--------|--------|-----|-------|
|
|
26
|
-
|**filePath**|\*|JSON file path|3.0.0|
|
|
27
|
-
|**fileEncoding**||File encoding|3.0.0|
|
|
28
|
-
|**indent**||Indent size for save as a JSON file|3.0.0|
|
|
29
|
-
|**ensureAscii**||Ensure ASCII flag when save to a file|3.0.0|
|
|
30
|
-
|**encrypt**||Encryption flag|3.0.0|
|
|
31
|
-
|**key**|(\*)|Encryption key|3.0.0|
|
|
32
|
-
|
|
33
|
-
Initialize the class with a file path.
|
|
34
|
-
|
|
35
|
-
### File encoding
|
|
36
|
-
|
|
37
|
-
You can set a specific file character encoding. Default: `UTF-8`
|
|
38
|
-
|
|
39
|
-
E.g.: If you are using `Shift_JIS` (Japanese system), you should initialize the class like the example below:
|
|
40
|
-
|
|
41
|
-
```python
|
|
42
|
-
from maplex import MapleJson
|
|
43
|
-
|
|
44
|
-
jsonInstance = MapleJson("jsonFile.json", fileEncoding="shift_jis")
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
### Indent size
|
|
48
|
-
|
|
49
|
-
You can set the block indent size with `indent` parameter. Default: `4`
|
|
50
|
-
|
|
51
|
-
If you set `indent=2`, the file will be save like the example below:
|
|
52
|
-
|
|
53
|
-
```json
|
|
54
|
-
{
|
|
55
|
-
"Data": {
|
|
56
|
-
"Key": "Value",
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
### Ensure ASCII
|
|
62
|
-
|
|
63
|
-
You can set the flag to ensure ASCII encoding.
|
|
64
|
-
|
|
65
|
-
If you don't set the parameter (Default: `False`), the file contents after saving are look like the example below:
|
|
66
|
-
|
|
67
|
-
```json
|
|
68
|
-
{
|
|
69
|
-
"data": {
|
|
70
|
-
"japanese": "値",
|
|
71
|
-
"russian": "значение",
|
|
72
|
-
"english": "value"
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
But, if you set `ensureAscii=True`, the file contents after saving will be changed like:
|
|
78
|
-
|
|
79
|
-
```json
|
|
80
|
-
{
|
|
81
|
-
"data": {
|
|
82
|
-
"japanese": "\u5024",
|
|
83
|
-
"russian": "\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435",
|
|
84
|
-
"english": "value"
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
### Encrypt
|
|
90
|
-
|
|
91
|
-
### Key
|
|
92
|
-
|
|
93
|
-
## Functions
|
|
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
|