absfuyu 3.1.1__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 +117 -100
- 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 +182 -107
- 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 +71 -33
- 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 +217 -135
- absfuyu/util/pkl.py +8 -8
- absfuyu/util/zipped.py +17 -19
- absfuyu/version.py +160 -147
- absfuyu-3.3.3.dist-info/METADATA +124 -0
- absfuyu-3.3.3.dist-info/RECORD +59 -0
- {absfuyu-3.1.1.dist-info → absfuyu-3.3.3.dist-info}/WHEEL +1 -2
- {absfuyu-3.1.1.dist-info → absfuyu-3.3.3.dist-info}/entry_points.txt +1 -0
- {absfuyu-3.1.1.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.1.1.dist-info/METADATA +0 -215
- absfuyu-3.1.1.dist-info/RECORD +0 -55
- absfuyu-3.1.1.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,16 +3,15 @@ Absufyu: Utilities
|
|
|
3
3
|
------------------
|
|
4
4
|
Some random utilities
|
|
5
5
|
|
|
6
|
-
Version: 1.
|
|
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
12
|
import pkgutil
|
|
14
|
-
|
|
15
|
-
from typing import Union
|
|
13
|
+
from datetime import datetime
|
|
14
|
+
from typing import Optional, Union
|
|
16
15
|
|
|
17
16
|
from absfuyu.logger import logger
|
|
18
17
|
|
|
@@ -28,17 +27,17 @@ def get_installed_package():
|
|
|
28
27
|
list[str]
|
|
29
28
|
List of installed packages
|
|
30
29
|
"""
|
|
31
|
-
iter_modules = list(
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
iter_modules = list(
|
|
31
|
+
{module.name for module in pkgutil.iter_modules() if module.ispkg}
|
|
32
|
+
)
|
|
34
33
|
return sorted(iter_modules)
|
|
35
34
|
|
|
36
35
|
|
|
37
36
|
def set_min(
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
current_value: Union[int, float],
|
|
38
|
+
*,
|
|
39
|
+
min_value: Union[int, float] = 0,
|
|
40
|
+
) -> Union[int, float]:
|
|
42
41
|
"""
|
|
43
42
|
Return ``min_value`` when ``current_value`` < ``min_value``
|
|
44
43
|
|
|
@@ -46,11 +45,11 @@ def set_min(
|
|
|
46
45
|
----------
|
|
47
46
|
current_value : int | float
|
|
48
47
|
Current value
|
|
49
|
-
|
|
48
|
+
|
|
50
49
|
min_value : int | float
|
|
51
|
-
Minimum value
|
|
50
|
+
Minimum value
|
|
52
51
|
(Default: ``0``)
|
|
53
|
-
|
|
52
|
+
|
|
54
53
|
Returns
|
|
55
54
|
-------
|
|
56
55
|
int | float
|
|
@@ -66,11 +65,12 @@ def set_min(
|
|
|
66
65
|
current_value = min_value
|
|
67
66
|
return current_value
|
|
68
67
|
|
|
68
|
+
|
|
69
69
|
def set_max(
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
70
|
+
current_value: Union[int, float],
|
|
71
|
+
*,
|
|
72
|
+
max_value: Union[int, float] = 100,
|
|
73
|
+
) -> Union[int, float]:
|
|
74
74
|
"""
|
|
75
75
|
Return ``max_value`` when ``current_value`` > ``max_value``
|
|
76
76
|
|
|
@@ -78,11 +78,11 @@ def set_max(
|
|
|
78
78
|
----------
|
|
79
79
|
current_value : int | float
|
|
80
80
|
Current value
|
|
81
|
-
|
|
81
|
+
|
|
82
82
|
max_value : int | float
|
|
83
|
-
Maximum value
|
|
83
|
+
Maximum value
|
|
84
84
|
(Default: ``100``)
|
|
85
|
-
|
|
85
|
+
|
|
86
86
|
Returns
|
|
87
87
|
-------
|
|
88
88
|
int | float
|
|
@@ -98,12 +98,13 @@ def set_max(
|
|
|
98
98
|
current_value = max_value
|
|
99
99
|
return current_value
|
|
100
100
|
|
|
101
|
+
|
|
101
102
|
def set_min_max(
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
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]:
|
|
107
108
|
"""
|
|
108
109
|
Return ``min_value`` | ``max_value`` when ``current_value``
|
|
109
110
|
is outside ``[min_value, max_value]``
|
|
@@ -112,15 +113,15 @@ def set_min_max(
|
|
|
112
113
|
----------
|
|
113
114
|
current_value : int | float
|
|
114
115
|
Current value
|
|
115
|
-
|
|
116
|
+
|
|
116
117
|
min_value : int | float
|
|
117
|
-
Minimum value
|
|
118
|
+
Minimum value
|
|
118
119
|
(Default: ``0``)
|
|
119
|
-
|
|
120
|
+
|
|
120
121
|
max_value : int | float
|
|
121
|
-
Maximum value
|
|
122
|
+
Maximum value
|
|
122
123
|
(Default: ``100``)
|
|
123
|
-
|
|
124
|
+
|
|
124
125
|
Returns
|
|
125
126
|
-------
|
|
126
127
|
int | float
|
|
@@ -137,7 +138,44 @@ def set_min_max(
|
|
|
137
138
|
return current_value
|
|
138
139
|
|
|
139
140
|
|
|
141
|
+
def stop_after_day(
|
|
142
|
+
year: Optional[int] = None, month: Optional[int] = None, day: Optional[int] = None
|
|
143
|
+
) -> None:
|
|
144
|
+
"""
|
|
145
|
+
Stop working after specified day.
|
|
146
|
+
Put the function at the begining of the code is recommended.
|
|
147
|
+
|
|
148
|
+
Parameters
|
|
149
|
+
----------
|
|
150
|
+
year : int
|
|
151
|
+
Desired year
|
|
152
|
+
(Default: ``None``)
|
|
153
|
+
|
|
154
|
+
month : int
|
|
155
|
+
Desired month
|
|
156
|
+
(Default: ``None``)
|
|
157
|
+
|
|
158
|
+
day : int
|
|
159
|
+
Desired day
|
|
160
|
+
(Default: ``None`` - 1 day trial)
|
|
161
|
+
"""
|
|
162
|
+
# None checking - By default: 1 day trial
|
|
163
|
+
now = datetime.now()
|
|
164
|
+
if year is None:
|
|
165
|
+
year = now.year
|
|
166
|
+
if month is None:
|
|
167
|
+
month = now.month
|
|
168
|
+
if day is None:
|
|
169
|
+
day = now.day + 1
|
|
170
|
+
|
|
171
|
+
# Logic
|
|
172
|
+
end_date = datetime(year, month, day)
|
|
173
|
+
result = end_date - now
|
|
174
|
+
if result.days < 0:
|
|
175
|
+
raise SystemExit("End of time")
|
|
176
|
+
|
|
177
|
+
|
|
140
178
|
# Run
|
|
141
179
|
###########################################################################
|
|
142
180
|
if __name__ == "__main__":
|
|
143
|
-
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
|