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.

Files changed (61) hide show
  1. absfuyu/__init__.py +3 -10
  2. absfuyu/__main__.py +5 -250
  3. absfuyu/cli/__init__.py +51 -0
  4. absfuyu/cli/color.py +24 -0
  5. absfuyu/cli/config_group.py +56 -0
  6. absfuyu/cli/do_group.py +76 -0
  7. absfuyu/cli/game_group.py +109 -0
  8. absfuyu/config/__init__.py +117 -100
  9. absfuyu/config/config.json +0 -7
  10. absfuyu/core.py +5 -66
  11. absfuyu/everything.py +7 -9
  12. absfuyu/extensions/beautiful.py +30 -23
  13. absfuyu/extensions/dev/__init__.py +11 -8
  14. absfuyu/extensions/dev/password_hash.py +4 -2
  15. absfuyu/extensions/dev/passwordlib.py +7 -5
  16. absfuyu/extensions/dev/project_starter.py +4 -2
  17. absfuyu/extensions/dev/shutdownizer.py +148 -0
  18. absfuyu/extensions/extra/__init__.py +1 -2
  19. absfuyu/extensions/extra/data_analysis.py +182 -107
  20. absfuyu/fun/WGS.py +50 -26
  21. absfuyu/fun/__init__.py +6 -7
  22. absfuyu/fun/tarot.py +1 -1
  23. absfuyu/game/__init__.py +75 -81
  24. absfuyu/game/game_stat.py +36 -0
  25. absfuyu/game/sudoku.py +41 -48
  26. absfuyu/game/tictactoe.py +303 -548
  27. absfuyu/game/wordle.py +56 -47
  28. absfuyu/general/__init__.py +17 -7
  29. absfuyu/general/content.py +16 -15
  30. absfuyu/general/data_extension.py +282 -90
  31. absfuyu/general/generator.py +67 -67
  32. absfuyu/general/human.py +74 -78
  33. absfuyu/logger.py +94 -68
  34. absfuyu/pkg_data/__init__.py +29 -25
  35. absfuyu/py.typed +0 -0
  36. absfuyu/sort.py +61 -47
  37. absfuyu/tools/__init__.py +0 -1
  38. absfuyu/tools/converter.py +80 -62
  39. absfuyu/tools/keygen.py +62 -67
  40. absfuyu/tools/obfuscator.py +57 -53
  41. absfuyu/tools/stats.py +24 -24
  42. absfuyu/tools/web.py +10 -9
  43. absfuyu/util/__init__.py +71 -33
  44. absfuyu/util/api.py +53 -43
  45. absfuyu/util/json_method.py +25 -27
  46. absfuyu/util/lunar.py +20 -24
  47. absfuyu/util/path.py +362 -241
  48. absfuyu/util/performance.py +217 -135
  49. absfuyu/util/pkl.py +8 -8
  50. absfuyu/util/zipped.py +17 -19
  51. absfuyu/version.py +160 -147
  52. absfuyu-3.3.3.dist-info/METADATA +124 -0
  53. absfuyu-3.3.3.dist-info/RECORD +59 -0
  54. {absfuyu-3.1.1.dist-info → absfuyu-3.3.3.dist-info}/WHEEL +1 -2
  55. {absfuyu-3.1.1.dist-info → absfuyu-3.3.3.dist-info}/entry_points.txt +1 -0
  56. {absfuyu-3.1.1.dist-info → absfuyu-3.3.3.dist-info/licenses}/LICENSE +1 -1
  57. absfuyu/extensions/dev/pkglib.py +0 -98
  58. absfuyu/game/tictactoe2.py +0 -318
  59. absfuyu-3.1.1.dist-info/METADATA +0 -215
  60. absfuyu-3.1.1.dist-info/RECORD +0 -55
  61. 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.1
7
- Date updated: 24/11/2023 (dd/mm/yyyy)
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
- :returns: Random commit message
50
- :rtype: str
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.4.4
7
- Date updated: 24/11/2023 (dd/mm/yyyy)
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
- # import sys
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({module.name for module in pkgutil.iter_modules() if module.ispkg})
32
- # builtin = sys.builtin_module_names
33
- # return set.union(iter_modules, builtin)
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
- current_value: Union[int, float],
39
- *,
40
- min_value: Union[int, float] = 0,
41
- ) -> Union[int, float]:
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
- current_value: Union[int, float],
71
- *,
72
- max_value: Union[int, float] = 100,
73
- ) -> Union[int, float]:
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
- current_value: Union[int, float],
103
- *,
104
- min_value: Union[int, float] = 0,
105
- max_value: Union[int, float] = 100
106
- ) -> Union[int, float]:
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.1.2
8
- Date updated: 24/11/2023 (dd/mm/yyyy)
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 typing import List, Optional, Union
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
- def ping_windows(host: List[str], ping_count: int = 3) -> list:
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.Popen(
72
+ output = subprocess.run(
63
73
  f"ping {ip.strip()} -n {ping_count}",
64
- stdout=subprocess.PIPE,
65
- encoding="utf-8"
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(f"{ip} : {res[0]}")
83
+ out.append(PingResult(ip, res[0]))
72
84
  else:
73
- out.append(f"{ip} : FAILED")
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
- self,
84
- api_url: str,
85
- *, # Use "*" to force using keyword in function parameter | Example: APIRequest(url, encoding="utf-8")
86
- encoding: Optional[str] = "utf-8"
87
- ) -> None:
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)
@@ -3,29 +3,27 @@ Absfuyu: Json Method
3
3
  --------------------
4
4
  ``.json`` file handling
5
5
 
6
- Version: 1.1.1
7
- Date updated: 24/11/2023 (dd/mm/yyyy)
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): # Depreciated
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
- self,
42
- json_file_location: Union[str, Path],
43
- *,
44
- encoding: Optional[str] = "utf-8",
45
- indent: Union[int, str, None] = 4,
46
- sort_keys: bool = True
47
- ) -> None:
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) -> dict:
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: dict) -> None:
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.1
7
- Date updated: 24/11/2023 (dd/mm/yyyy)
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 typing import Union
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
- ## Time in Julian centuries
175
- ## from 2000-01-01 12:00:00 GMT
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 ## degree to radian
177
+ dr = math.pi / 180.0 # degree to radian
179
178
  M = 357.52910 + 35999.05030 * T - 0.0001559 * T2 - 0.00000048 * T3
180
- ## mean anomaly, degree
179
+ # mean anomaly, degree
181
180
  L0 = 280.46645 + 36000.76983 * T + 0.0003032 * T2
182
- ## mean longitude, degree
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 ## true longitude, degree
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
- #### Normalize to (0, 2*math.pi)
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
- __class__._sun_longitude(day_number - 0.5 - self.time_zone / 24.0)
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(__class__._new_moon(k) + 0.5 + self.time_zone / 24.0)
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