absfuyu 3.2.0__py3-none-any.whl → 3.3.3__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.
Potentially problematic release.
This version of absfuyu might be problematic. Click here for more details.
- absfuyu/__init__.py +3 -10
- absfuyu/__main__.py +5 -250
- absfuyu/cli/__init__.py +51 -0
- absfuyu/cli/color.py +24 -0
- absfuyu/cli/config_group.py +56 -0
- absfuyu/cli/do_group.py +76 -0
- absfuyu/cli/game_group.py +109 -0
- absfuyu/config/__init__.py +55 -94
- absfuyu/config/config.json +0 -7
- absfuyu/core.py +5 -66
- absfuyu/everything.py +7 -9
- absfuyu/extensions/beautiful.py +30 -23
- absfuyu/extensions/dev/__init__.py +11 -8
- absfuyu/extensions/dev/password_hash.py +4 -2
- absfuyu/extensions/dev/passwordlib.py +7 -5
- absfuyu/extensions/dev/project_starter.py +4 -2
- absfuyu/extensions/dev/shutdownizer.py +148 -0
- absfuyu/extensions/extra/__init__.py +1 -2
- absfuyu/extensions/extra/data_analysis.py +110 -58
- absfuyu/fun/WGS.py +50 -26
- absfuyu/fun/__init__.py +6 -7
- absfuyu/fun/tarot.py +1 -1
- absfuyu/game/__init__.py +75 -81
- absfuyu/game/game_stat.py +36 -0
- absfuyu/game/sudoku.py +41 -48
- absfuyu/game/tictactoe.py +303 -548
- absfuyu/game/wordle.py +56 -47
- absfuyu/general/__init__.py +17 -7
- absfuyu/general/content.py +16 -15
- absfuyu/general/data_extension.py +282 -90
- absfuyu/general/generator.py +67 -67
- absfuyu/general/human.py +74 -78
- absfuyu/logger.py +94 -68
- absfuyu/pkg_data/__init__.py +29 -25
- absfuyu/py.typed +0 -0
- absfuyu/sort.py +61 -47
- absfuyu/tools/__init__.py +0 -1
- absfuyu/tools/converter.py +80 -62
- absfuyu/tools/keygen.py +62 -67
- absfuyu/tools/obfuscator.py +57 -53
- absfuyu/tools/stats.py +24 -24
- absfuyu/tools/web.py +10 -9
- absfuyu/util/__init__.py +38 -40
- absfuyu/util/api.py +53 -43
- absfuyu/util/json_method.py +25 -27
- absfuyu/util/lunar.py +20 -24
- absfuyu/util/path.py +362 -241
- absfuyu/util/performance.py +36 -98
- absfuyu/util/pkl.py +8 -8
- absfuyu/util/zipped.py +17 -19
- absfuyu/version.py +137 -148
- absfuyu-3.3.3.dist-info/METADATA +124 -0
- absfuyu-3.3.3.dist-info/RECORD +59 -0
- {absfuyu-3.2.0.dist-info → absfuyu-3.3.3.dist-info}/WHEEL +1 -2
- {absfuyu-3.2.0.dist-info → absfuyu-3.3.3.dist-info}/entry_points.txt +1 -0
- {absfuyu-3.2.0.dist-info → absfuyu-3.3.3.dist-info/licenses}/LICENSE +1 -1
- absfuyu/extensions/dev/pkglib.py +0 -98
- absfuyu/game/tictactoe2.py +0 -318
- absfuyu-3.2.0.dist-info/METADATA +0 -216
- absfuyu-3.2.0.dist-info/RECORD +0 -55
- absfuyu-3.2.0.dist-info/top_level.txt +0 -1
absfuyu/tools/web.py
CHANGED
|
@@ -3,15 +3,14 @@ Absfuyu: Web
|
|
|
3
3
|
------------
|
|
4
4
|
Web, ``request``, ``BeautifulSoup`` stuff
|
|
5
5
|
|
|
6
|
-
Version: 1.0.
|
|
7
|
-
Date updated:
|
|
6
|
+
Version: 1.0.2
|
|
7
|
+
Date updated: 05/04/2024 (dd/mm/yyyy)
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
|
-
|
|
11
10
|
# Library
|
|
12
11
|
###########################################################################
|
|
13
|
-
from bs4 import BeautifulSoup
|
|
14
12
|
import requests
|
|
13
|
+
from bs4 import BeautifulSoup
|
|
15
14
|
|
|
16
15
|
from absfuyu.logger import logger
|
|
17
16
|
|
|
@@ -37,21 +36,23 @@ def soup_link(link: str) -> BeautifulSoup:
|
|
|
37
36
|
soup = BeautifulSoup(page.content, "html.parser")
|
|
38
37
|
logger.debug("Soup completed!")
|
|
39
38
|
return soup
|
|
40
|
-
except:
|
|
39
|
+
except Exception:
|
|
41
40
|
logger.error("Can't soup")
|
|
42
|
-
raise SystemExit("Something wrong")
|
|
41
|
+
raise SystemExit("Something wrong") # noqa: B904
|
|
43
42
|
|
|
44
43
|
|
|
45
44
|
def gen_random_commit_msg() -> str:
|
|
46
45
|
"""
|
|
47
46
|
Generate random commit message
|
|
48
47
|
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
Returns
|
|
49
|
+
-------
|
|
50
|
+
str
|
|
51
|
+
Random commit message
|
|
51
52
|
"""
|
|
52
53
|
out = soup_link("https://whatthecommit.com/").get_text()[34:-20]
|
|
53
54
|
logger.debug(out)
|
|
54
|
-
return out
|
|
55
|
+
return out # type: ignore
|
|
55
56
|
|
|
56
57
|
|
|
57
58
|
# Run
|
absfuyu/util/__init__.py
CHANGED
|
@@ -3,17 +3,15 @@ Absufyu: Utilities
|
|
|
3
3
|
------------------
|
|
4
4
|
Some random utilities
|
|
5
5
|
|
|
6
|
-
Version: 1.5.
|
|
7
|
-
Date updated:
|
|
6
|
+
Version: 1.5.1
|
|
7
|
+
Date updated: 05/04/2024 (dd/mm/yyyy)
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
|
-
|
|
11
10
|
# Library
|
|
12
11
|
###########################################################################
|
|
13
|
-
from datetime import datetime
|
|
14
12
|
import pkgutil
|
|
15
|
-
|
|
16
|
-
from typing import Union
|
|
13
|
+
from datetime import datetime
|
|
14
|
+
from typing import Optional, Union
|
|
17
15
|
|
|
18
16
|
from absfuyu.logger import logger
|
|
19
17
|
|
|
@@ -29,17 +27,17 @@ def get_installed_package():
|
|
|
29
27
|
list[str]
|
|
30
28
|
List of installed packages
|
|
31
29
|
"""
|
|
32
|
-
iter_modules = list(
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
iter_modules = list(
|
|
31
|
+
{module.name for module in pkgutil.iter_modules() if module.ispkg}
|
|
32
|
+
)
|
|
35
33
|
return sorted(iter_modules)
|
|
36
34
|
|
|
37
35
|
|
|
38
36
|
def set_min(
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
current_value: Union[int, float],
|
|
38
|
+
*,
|
|
39
|
+
min_value: Union[int, float] = 0,
|
|
40
|
+
) -> Union[int, float]:
|
|
43
41
|
"""
|
|
44
42
|
Return ``min_value`` when ``current_value`` < ``min_value``
|
|
45
43
|
|
|
@@ -47,11 +45,11 @@ def set_min(
|
|
|
47
45
|
----------
|
|
48
46
|
current_value : int | float
|
|
49
47
|
Current value
|
|
50
|
-
|
|
48
|
+
|
|
51
49
|
min_value : int | float
|
|
52
|
-
Minimum value
|
|
50
|
+
Minimum value
|
|
53
51
|
(Default: ``0``)
|
|
54
|
-
|
|
52
|
+
|
|
55
53
|
Returns
|
|
56
54
|
-------
|
|
57
55
|
int | float
|
|
@@ -67,11 +65,12 @@ def set_min(
|
|
|
67
65
|
current_value = min_value
|
|
68
66
|
return current_value
|
|
69
67
|
|
|
68
|
+
|
|
70
69
|
def set_max(
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
70
|
+
current_value: Union[int, float],
|
|
71
|
+
*,
|
|
72
|
+
max_value: Union[int, float] = 100,
|
|
73
|
+
) -> Union[int, float]:
|
|
75
74
|
"""
|
|
76
75
|
Return ``max_value`` when ``current_value`` > ``max_value``
|
|
77
76
|
|
|
@@ -79,11 +78,11 @@ def set_max(
|
|
|
79
78
|
----------
|
|
80
79
|
current_value : int | float
|
|
81
80
|
Current value
|
|
82
|
-
|
|
81
|
+
|
|
83
82
|
max_value : int | float
|
|
84
|
-
Maximum value
|
|
83
|
+
Maximum value
|
|
85
84
|
(Default: ``100``)
|
|
86
|
-
|
|
85
|
+
|
|
87
86
|
Returns
|
|
88
87
|
-------
|
|
89
88
|
int | float
|
|
@@ -99,12 +98,13 @@ def set_max(
|
|
|
99
98
|
current_value = max_value
|
|
100
99
|
return current_value
|
|
101
100
|
|
|
101
|
+
|
|
102
102
|
def set_min_max(
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
103
|
+
current_value: Union[int, float],
|
|
104
|
+
*,
|
|
105
|
+
min_value: Union[int, float] = 0,
|
|
106
|
+
max_value: Union[int, float] = 100,
|
|
107
|
+
) -> Union[int, float]:
|
|
108
108
|
"""
|
|
109
109
|
Return ``min_value`` | ``max_value`` when ``current_value``
|
|
110
110
|
is outside ``[min_value, max_value]``
|
|
@@ -113,15 +113,15 @@ def set_min_max(
|
|
|
113
113
|
----------
|
|
114
114
|
current_value : int | float
|
|
115
115
|
Current value
|
|
116
|
-
|
|
116
|
+
|
|
117
117
|
min_value : int | float
|
|
118
|
-
Minimum value
|
|
118
|
+
Minimum value
|
|
119
119
|
(Default: ``0``)
|
|
120
|
-
|
|
120
|
+
|
|
121
121
|
max_value : int | float
|
|
122
|
-
Maximum value
|
|
122
|
+
Maximum value
|
|
123
123
|
(Default: ``100``)
|
|
124
|
-
|
|
124
|
+
|
|
125
125
|
Returns
|
|
126
126
|
-------
|
|
127
127
|
int | float
|
|
@@ -139,12 +139,10 @@ def set_min_max(
|
|
|
139
139
|
|
|
140
140
|
|
|
141
141
|
def stop_after_day(
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
day: int = None
|
|
145
|
-
) -> None:
|
|
142
|
+
year: Optional[int] = None, month: Optional[int] = None, day: Optional[int] = None
|
|
143
|
+
) -> None:
|
|
146
144
|
"""
|
|
147
|
-
Stop working after specified day.
|
|
145
|
+
Stop working after specified day.
|
|
148
146
|
Put the function at the begining of the code is recommended.
|
|
149
147
|
|
|
150
148
|
Parameters
|
|
@@ -169,7 +167,7 @@ def stop_after_day(
|
|
|
169
167
|
month = now.month
|
|
170
168
|
if day is None:
|
|
171
169
|
day = now.day + 1
|
|
172
|
-
|
|
170
|
+
|
|
173
171
|
# Logic
|
|
174
172
|
end_date = datetime(year, month, day)
|
|
175
173
|
result = end_date - now
|
|
@@ -180,4 +178,4 @@ def stop_after_day(
|
|
|
180
178
|
# Run
|
|
181
179
|
###########################################################################
|
|
182
180
|
if __name__ == "__main__":
|
|
183
|
-
logger.setLevel(10)
|
|
181
|
+
logger.setLevel(10)
|
absfuyu/util/api.py
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
1
|
"""
|
|
3
2
|
Absufyu: API
|
|
4
3
|
------------
|
|
5
4
|
Fetch data stuff
|
|
6
5
|
|
|
7
|
-
Version: 1.
|
|
8
|
-
Date updated:
|
|
6
|
+
Version: 1.2.0
|
|
7
|
+
Date updated: 05/04/2024 (dd/mm/yyyy)
|
|
9
8
|
"""
|
|
10
9
|
|
|
11
|
-
|
|
12
10
|
# Module level
|
|
13
11
|
###########################################################################
|
|
14
12
|
__all__ = [
|
|
@@ -20,58 +18,72 @@ __all__ = [
|
|
|
20
18
|
# Library
|
|
21
19
|
###########################################################################
|
|
22
20
|
import json
|
|
23
|
-
from pathlib import Path
|
|
24
21
|
import re
|
|
25
22
|
import subprocess
|
|
26
|
-
from
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
from typing import List, NamedTuple, Optional, Union
|
|
27
25
|
|
|
28
26
|
import requests
|
|
27
|
+
from deprecated.sphinx import versionchanged
|
|
29
28
|
|
|
30
29
|
from absfuyu.logger import logger
|
|
31
30
|
|
|
32
31
|
|
|
33
32
|
# Function
|
|
34
33
|
###########################################################################
|
|
35
|
-
|
|
34
|
+
class PingResult(NamedTuple):
|
|
35
|
+
"""
|
|
36
|
+
:param host: Host name/IP
|
|
37
|
+
:param result: Ping result in ms
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
host: str
|
|
41
|
+
result: str
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@versionchanged(version="3.4.0", reason="Change function's return")
|
|
45
|
+
def ping_windows(host: List[str], ping_count: int = 3) -> List[PingResult]:
|
|
36
46
|
"""
|
|
37
47
|
Ping web
|
|
38
|
-
|
|
48
|
+
|
|
39
49
|
Parameters
|
|
40
50
|
----------
|
|
41
51
|
host : list[str]
|
|
42
52
|
List of host to ping
|
|
43
|
-
|
|
53
|
+
|
|
44
54
|
ping_count : int
|
|
45
|
-
Number of time to ping to take average
|
|
55
|
+
Number of time to ping to take average
|
|
46
56
|
(Default: ``3``)
|
|
47
|
-
|
|
57
|
+
|
|
48
58
|
Returns
|
|
49
59
|
-------
|
|
50
60
|
list
|
|
51
61
|
List of host with pinged value
|
|
52
|
-
|
|
53
|
-
|
|
62
|
+
|
|
63
|
+
|
|
54
64
|
Example:
|
|
55
65
|
--------
|
|
56
66
|
>>> ping_windows(["1.1.1.1", "google.com"])
|
|
57
67
|
['1.1.1.1 : xxms', 'google.com : xxms']
|
|
58
68
|
"""
|
|
59
|
-
out = []
|
|
60
|
-
|
|
69
|
+
out: List[PingResult] = []
|
|
70
|
+
|
|
61
71
|
for ip in host:
|
|
62
|
-
output = subprocess.
|
|
72
|
+
output = subprocess.run(
|
|
63
73
|
f"ping {ip.strip()} -n {ping_count}",
|
|
64
|
-
|
|
65
|
-
|
|
74
|
+
encoding="utf-8",
|
|
75
|
+
capture_output=True,
|
|
76
|
+
text=True,
|
|
66
77
|
)
|
|
78
|
+
logger.debug(output)
|
|
67
79
|
|
|
68
|
-
data = "".join(output.stdout)
|
|
80
|
+
data: str = "".join(output.stdout)
|
|
69
81
|
res = re.findall(r"Average = (.*)", data)
|
|
70
82
|
if res:
|
|
71
|
-
out.append(
|
|
83
|
+
out.append(PingResult(ip, res[0]))
|
|
72
84
|
else:
|
|
73
|
-
out.append(
|
|
74
|
-
|
|
85
|
+
out.append(PingResult(ip, "FAILED"))
|
|
86
|
+
|
|
75
87
|
return out
|
|
76
88
|
|
|
77
89
|
|
|
@@ -79,51 +91,49 @@ def ping_windows(host: List[str], ping_count: int = 3) -> list:
|
|
|
79
91
|
###########################################################################
|
|
80
92
|
class APIRequest:
|
|
81
93
|
"""API data with cache feature"""
|
|
94
|
+
|
|
82
95
|
def __init__(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
96
|
+
self,
|
|
97
|
+
api_url: str,
|
|
98
|
+
*, # Use "*" to force using keyword in function parameter | Example: APIRequest(url, encoding="utf-8")
|
|
99
|
+
encoding: Optional[str] = "utf-8",
|
|
100
|
+
) -> None:
|
|
88
101
|
"""
|
|
89
102
|
:param api_url: api link
|
|
90
103
|
:param encoding: data encoding (Default: utf-8)
|
|
91
104
|
"""
|
|
92
105
|
self.url = api_url
|
|
93
106
|
self.encoding = encoding
|
|
107
|
+
|
|
94
108
|
def __str__(self) -> str:
|
|
95
109
|
return f"{self.__class__.__name__}({self.url})"
|
|
110
|
+
|
|
96
111
|
def __repr__(self) -> str:
|
|
97
112
|
return self.__str__()
|
|
98
113
|
|
|
99
|
-
def fetch_data(
|
|
100
|
-
self,
|
|
101
|
-
*,
|
|
102
|
-
update: bool = False,
|
|
103
|
-
json_cache: Union[str, Path]
|
|
104
|
-
):
|
|
114
|
+
def fetch_data(self, *, update: bool = False, json_cache: Union[str, Path]):
|
|
105
115
|
"""
|
|
106
116
|
Fetch data from an API then cache it for later use
|
|
107
117
|
|
|
108
118
|
Parameters
|
|
109
119
|
----------
|
|
110
|
-
update :
|
|
111
|
-
Refresh the cache when ``True``
|
|
120
|
+
update :
|
|
121
|
+
Refresh the cache when ``True``
|
|
112
122
|
(Default: ``False``)
|
|
113
|
-
|
|
123
|
+
|
|
114
124
|
json_cache : Path | str
|
|
115
125
|
Name of the cache
|
|
116
|
-
|
|
126
|
+
|
|
117
127
|
Returns
|
|
118
128
|
-------
|
|
119
129
|
Any
|
|
120
130
|
Data
|
|
121
131
|
|
|
122
132
|
None
|
|
123
|
-
No data fetched/unable to fetch data
|
|
133
|
+
No data fetched/unable to fetch data
|
|
124
134
|
"""
|
|
125
135
|
if update:
|
|
126
|
-
json_data=None
|
|
136
|
+
json_data = None
|
|
127
137
|
else:
|
|
128
138
|
try:
|
|
129
139
|
with open(json_cache, "r", encoding=self.encoding) as file:
|
|
@@ -132,7 +142,7 @@ class APIRequest:
|
|
|
132
142
|
except (FileNotFoundError, json.JSONDecodeError) as e:
|
|
133
143
|
logger.debug(f"No local cache found... ({e})")
|
|
134
144
|
json_data = None
|
|
135
|
-
|
|
145
|
+
|
|
136
146
|
if not json_data:
|
|
137
147
|
logger.debug("Fetching new json data... (Creating local cache)")
|
|
138
148
|
try:
|
|
@@ -143,11 +153,11 @@ class APIRequest:
|
|
|
143
153
|
logger.error(f"Can't create cache due to Path error - {e}")
|
|
144
154
|
|
|
145
155
|
return json_data
|
|
146
|
-
|
|
156
|
+
|
|
147
157
|
def fetch_data_only(self) -> requests.Response:
|
|
148
158
|
"""
|
|
149
159
|
Fetch data without cache
|
|
150
|
-
|
|
160
|
+
|
|
151
161
|
Returns
|
|
152
162
|
-------
|
|
153
163
|
Response
|
|
@@ -159,4 +169,4 @@ class APIRequest:
|
|
|
159
169
|
# Run
|
|
160
170
|
###########################################################################
|
|
161
171
|
if __name__ == "__main__":
|
|
162
|
-
logger.setLevel(10)
|
|
172
|
+
logger.setLevel(10)
|
absfuyu/util/json_method.py
CHANGED
|
@@ -3,29 +3,27 @@ Absfuyu: Json Method
|
|
|
3
3
|
--------------------
|
|
4
4
|
``.json`` file handling
|
|
5
5
|
|
|
6
|
-
Version: 1.1.
|
|
7
|
-
Date updated:
|
|
6
|
+
Version: 1.1.3
|
|
7
|
+
Date updated: 05/04/2024 (dd/mm/yyyy)
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
|
-
|
|
11
10
|
# Module level
|
|
12
11
|
###########################################################################
|
|
13
|
-
__all__ = [
|
|
14
|
-
"JsonFile"
|
|
15
|
-
]
|
|
12
|
+
__all__ = ["JsonFile"]
|
|
16
13
|
|
|
17
14
|
|
|
18
15
|
# Library
|
|
19
16
|
###########################################################################
|
|
20
17
|
import json
|
|
21
18
|
from pathlib import Path
|
|
22
|
-
from typing import Optional, Union
|
|
19
|
+
from typing import Any, Dict, Optional, Union
|
|
23
20
|
|
|
24
21
|
|
|
25
22
|
# Function
|
|
26
23
|
###########################################################################
|
|
27
|
-
def load_json(json_file_location: Path):
|
|
24
|
+
def load_json(json_file_location: Path): # Deprecated
|
|
28
25
|
"""Load JSON file"""
|
|
26
|
+
print("This function is deprecated as of version 3.0.0")
|
|
29
27
|
with open(Path(json_file_location), "r") as json_file:
|
|
30
28
|
data = json.load(json_file)
|
|
31
29
|
return data
|
|
@@ -37,14 +35,15 @@ class JsonFile:
|
|
|
37
35
|
"""
|
|
38
36
|
``.json`` file handling
|
|
39
37
|
"""
|
|
38
|
+
|
|
40
39
|
def __init__(
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
40
|
+
self,
|
|
41
|
+
json_file_location: Union[str, Path],
|
|
42
|
+
*,
|
|
43
|
+
encoding: Optional[str] = "utf-8",
|
|
44
|
+
indent: Union[int, str, None] = 4,
|
|
45
|
+
sort_keys: bool = True,
|
|
46
|
+
) -> None:
|
|
48
47
|
"""
|
|
49
48
|
json_file_location: json file location
|
|
50
49
|
encoding: data encoding (Default: utf-8)
|
|
@@ -55,17 +54,18 @@ class JsonFile:
|
|
|
55
54
|
self.encoding = encoding
|
|
56
55
|
self.indent = indent
|
|
57
56
|
self.sort_keys = sort_keys
|
|
58
|
-
self.data = {}
|
|
59
|
-
|
|
57
|
+
self.data: Dict[Any, Any] = {}
|
|
58
|
+
|
|
60
59
|
def __str__(self) -> str:
|
|
61
60
|
return f"{self.__class__.__name__}({self.json_file_location.name})"
|
|
61
|
+
|
|
62
62
|
def __repr__(self) -> str:
|
|
63
63
|
return self.__str__()
|
|
64
|
-
|
|
65
|
-
def load_json(self) ->
|
|
64
|
+
|
|
65
|
+
def load_json(self) -> Dict[Any, Any]:
|
|
66
66
|
"""
|
|
67
67
|
Load ``.json`` file
|
|
68
|
-
|
|
68
|
+
|
|
69
69
|
:returns: ``.json`` data
|
|
70
70
|
:rtype: dict
|
|
71
71
|
"""
|
|
@@ -75,16 +75,14 @@ class JsonFile:
|
|
|
75
75
|
|
|
76
76
|
def save_json(self) -> None:
|
|
77
77
|
"""Save ``.json`` file"""
|
|
78
|
-
json_data = json.dumps(
|
|
79
|
-
self.data, indent=self.indent, sort_keys=self.sort_keys
|
|
80
|
-
)
|
|
78
|
+
json_data = json.dumps(self.data, indent=self.indent, sort_keys=self.sort_keys)
|
|
81
79
|
with open(self.json_file_location, "w", encoding=self.encoding) as file:
|
|
82
80
|
file.writelines(json_data)
|
|
83
|
-
|
|
84
|
-
def update_data(self, data:
|
|
81
|
+
|
|
82
|
+
def update_data(self, data: Dict[Any, Any]) -> None:
|
|
85
83
|
"""
|
|
86
84
|
Update ``.json`` data without save
|
|
87
|
-
|
|
85
|
+
|
|
88
86
|
:param data: ``.json`` data
|
|
89
87
|
:type data: dict
|
|
90
88
|
"""
|
|
@@ -94,4 +92,4 @@ class JsonFile:
|
|
|
94
92
|
# Run
|
|
95
93
|
###########################################################################
|
|
96
94
|
if __name__ == "__main__":
|
|
97
|
-
pass
|
|
95
|
+
pass
|
absfuyu/util/lunar.py
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
# flake8: noqa
|
|
1
2
|
"""
|
|
2
3
|
Absfuyu: Lunar calendar
|
|
3
4
|
-----------------------
|
|
4
5
|
Convert to lunar calendar
|
|
5
6
|
|
|
6
|
-
Version: 1.0.
|
|
7
|
-
Date updated:
|
|
7
|
+
Version: 1.0.2
|
|
8
|
+
Date updated: 05/04/2024 (dd/mm/yyyy)
|
|
8
9
|
|
|
9
10
|
Source:
|
|
10
11
|
-------
|
|
@@ -19,11 +20,9 @@ __all__ = ["LunarCalendar"]
|
|
|
19
20
|
|
|
20
21
|
# Library
|
|
21
22
|
###########################################################################
|
|
22
|
-
from datetime import date, datetime
|
|
23
23
|
import math
|
|
24
|
-
from
|
|
25
|
-
|
|
26
|
-
# from absfuyu.logger import logger
|
|
24
|
+
from datetime import date, datetime
|
|
25
|
+
from typing import Optional, Union
|
|
27
26
|
|
|
28
27
|
|
|
29
28
|
# Class
|
|
@@ -57,9 +56,9 @@ class LunarCalendar:
|
|
|
57
56
|
def _julian_day_from_date(
|
|
58
57
|
self,
|
|
59
58
|
*,
|
|
60
|
-
overwrite_year: int = None,
|
|
61
|
-
overwrite_month: int = None,
|
|
62
|
-
overwrite_day: int = None,
|
|
59
|
+
overwrite_year: Optional[int] = None,
|
|
60
|
+
overwrite_month: Optional[int] = None,
|
|
61
|
+
overwrite_day: Optional[int] = None,
|
|
63
62
|
) -> int:
|
|
64
63
|
"""
|
|
65
64
|
Compute the (integral) Julian day number of `self.date`
|
|
@@ -171,23 +170,23 @@ class LunarCalendar:
|
|
|
171
170
|
julian_day_noon: The number of days since `1/1/4713 BC noon`.
|
|
172
171
|
"""
|
|
173
172
|
T = (julian_day_noon - 2451545.0) / 36525.0
|
|
174
|
-
|
|
175
|
-
|
|
173
|
+
# Time in Julian centuries
|
|
174
|
+
# from 2000-01-01 12:00:00 GMT
|
|
176
175
|
T2 = math.pow(T, 2)
|
|
177
176
|
T3 = math.pow(T, 3)
|
|
178
|
-
dr = math.pi / 180.0
|
|
177
|
+
dr = math.pi / 180.0 # degree to radian
|
|
179
178
|
M = 357.52910 + 35999.05030 * T - 0.0001559 * T2 - 0.00000048 * T3
|
|
180
|
-
|
|
179
|
+
# mean anomaly, degree
|
|
181
180
|
L0 = 280.46645 + 36000.76983 * T + 0.0003032 * T2
|
|
182
|
-
|
|
181
|
+
# mean longitude, degree
|
|
183
182
|
DL = (1.914600 - 0.004817 * T - 0.000014 * T2) * math.sin(dr * M)
|
|
184
183
|
DL += (0.019993 - 0.000101 * T) * math.sin(dr * 2 * M) + 0.000290 * math.sin(
|
|
185
184
|
dr * 3 * M
|
|
186
185
|
)
|
|
187
|
-
L = L0 + DL
|
|
186
|
+
L = L0 + DL # true longitude, degree
|
|
188
187
|
L = L * dr
|
|
189
188
|
L = L - math.pi * 2 * (int(L / (math.pi * 2)))
|
|
190
|
-
|
|
189
|
+
# Normalize to (0, 2*math.pi)
|
|
191
190
|
return L
|
|
192
191
|
|
|
193
192
|
def _get_sun_longitude(self, day_number: int) -> int:
|
|
@@ -201,9 +200,7 @@ class LunarCalendar:
|
|
|
201
200
|
From the day after March equinox and the 1st major term after March equinox, 0 is returned. After that, return 1, 2, 3 ...
|
|
202
201
|
"""
|
|
203
202
|
return int(
|
|
204
|
-
|
|
205
|
-
/ math.pi
|
|
206
|
-
* 6
|
|
203
|
+
self._sun_longitude(day_number - 0.5 - self.time_zone / 24.0) / math.pi * 6
|
|
207
204
|
)
|
|
208
205
|
|
|
209
206
|
def _get_new_moon_day(self, k: int) -> int:
|
|
@@ -212,9 +209,9 @@ class LunarCalendar:
|
|
|
212
209
|
|
|
213
210
|
The time zone if the time difference between local time and UTC: 7.0 for UTC+7:00.
|
|
214
211
|
"""
|
|
215
|
-
return int(
|
|
212
|
+
return int(self._new_moon(k) + 0.5 + self.time_zone / 24.0)
|
|
216
213
|
|
|
217
|
-
def _get_lunar_month_11(self, *, overwrite_year: int = None) -> int:
|
|
214
|
+
def _get_lunar_month_11(self, *, overwrite_year: Optional[int] = None) -> int:
|
|
218
215
|
"""
|
|
219
216
|
Find the day that starts the luner month 11
|
|
220
217
|
of the given year for the given time zone.
|
|
@@ -295,7 +292,7 @@ class LunarCalendar:
|
|
|
295
292
|
lunar_month = lunar_month - 12
|
|
296
293
|
if lunar_month >= 11 and diff < 4:
|
|
297
294
|
lunar_year -= 1
|
|
298
|
-
return __class__(
|
|
295
|
+
return self.__class__(
|
|
299
296
|
lunar_year, lunar_month, lunar_day, lunar_leap=self._lunar_leap
|
|
300
297
|
)
|
|
301
298
|
|
|
@@ -337,7 +334,7 @@ class LunarCalendar:
|
|
|
337
334
|
off += 1
|
|
338
335
|
monthStart = self._get_new_moon_day(k + off)
|
|
339
336
|
out = self._julian_day_to_date(monthStart + lunarD - 1)
|
|
340
|
-
return __class__(out.year, out.month, out.day, lunar_leap=self._lunar_leap)
|
|
337
|
+
return self.__class__(out.year, out.month, out.day, lunar_leap=self._lunar_leap)
|
|
341
338
|
|
|
342
339
|
def convert_all(self) -> dict:
|
|
343
340
|
"""
|
|
@@ -409,5 +406,4 @@ class LunarCalendar:
|
|
|
409
406
|
# Run
|
|
410
407
|
###########################################################################
|
|
411
408
|
if __name__ == "__main__":
|
|
412
|
-
# logger.setLevel(10)
|
|
413
409
|
pass
|