inspy-logger 3.0.dev5__tar.gz → 3.0.2.dev1__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.
- {inspy_logger-3.0.dev5 → inspy_logger-3.0.2.dev1}/PKG-INFO +1 -1
- inspy_logger-3.0.2.dev1/inspy_logger/Scripts/main.py +105 -0
- {inspy_logger-3.0.dev5 → inspy_logger-3.0.2.dev1}/inspy_logger/__about__.py +0 -13
- {inspy_logger-3.0.dev5 → inspy_logger-3.0.2.dev1}/inspy_logger/__init__.py +4 -0
- {inspy_logger-3.0.dev5 → inspy_logger-3.0.2.dev1}/inspy_logger/helpers/base_classes.py +10 -0
- inspy_logger-3.0.2.dev1/inspy_logger/helpers/debug/__init__.py +0 -0
- inspy_logger-3.0.2.dev1/inspy_logger/helpers/debug/environment.py +179 -0
- inspy_logger-3.0.2.dev1/inspy_logger/helpers/debug/system/__init__.py +0 -0
- inspy_logger-3.0.2.dev1/inspy_logger/helpers/debug/system/processor/__init__.py +64 -0
- inspy_logger-3.0.2.dev1/inspy_logger/helpers/debug/system/winx/__init__.py +25 -0
- {inspy_logger-3.0.dev5 → inspy_logger-3.0.2.dev1}/inspy_logger/helpers/network.py +5 -5
- inspy_logger-3.0.2.dev1/inspy_logger/helpers/units.py +57 -0
- inspy_logger-3.0.2.dev1/inspy_logger/version.py +240 -0
- {inspy_logger-3.0.dev5 → inspy_logger-3.0.2.dev1}/pyproject.toml +5 -1
- inspy_logger-3.0.dev5/inspy_logger/Scripts/main.py +0 -91
- inspy_logger-3.0.dev5/inspy_logger/helpers/cache.py +0 -140
- inspy_logger-3.0.dev5/inspy_logger/version.py +0 -287
- {inspy_logger-3.0.dev5 → inspy_logger-3.0.2.dev1}/LICENSE.md +0 -0
- {inspy_logger-3.0.dev5 → inspy_logger-3.0.2.dev1}/README.md +0 -0
- {inspy_logger-3.0.dev5 → inspy_logger-3.0.2.dev1}/inspy_logger/errors/__init__.py +0 -0
- {inspy_logger-3.0.dev5 → inspy_logger-3.0.2.dev1}/inspy_logger/helpers/__init__.py +0 -0
- {inspy_logger-3.0.dev5 → inspy_logger-3.0.2.dev1}/inspy_logger/manifest.py +0 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"""
|
|
2
|
+
|
|
3
|
+
File:
|
|
4
|
+
inspy_logger/Scripts/main.py
|
|
5
|
+
|
|
6
|
+
Author:
|
|
7
|
+
Inspyre Softworks
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
INSPY_LOG_LEVEL = 'info'
|
|
11
|
+
|
|
12
|
+
from argparse import ArgumentParser
|
|
13
|
+
from inspy_logger.helpers.debug.environment import fetch_system_info
|
|
14
|
+
from inspy_logger.version import parse_version, get_full_version_name, PyPiVersionInfo
|
|
15
|
+
from rich import print
|
|
16
|
+
from rich.table import Table
|
|
17
|
+
import sys
|
|
18
|
+
|
|
19
|
+
# ---- SET UP PARSER --------------------------------
|
|
20
|
+
|
|
21
|
+
parser = ArgumentParser('inspy-logger-version', description='Displays version information for inspy-logger.')
|
|
22
|
+
|
|
23
|
+
parser.add_argument('-v', '--version', action='version', version=parse_version())
|
|
24
|
+
|
|
25
|
+
# ---- SET UP SUBPARSERS --------------------------------
|
|
26
|
+
|
|
27
|
+
subparsers = parser.add_subparsers(title='subcommands', dest='subcommand')
|
|
28
|
+
|
|
29
|
+
# ---- UPDATE COMMAND --------------------------------
|
|
30
|
+
|
|
31
|
+
update_parser =subparsers.add_parser('update', help='Checks for updates to inspy-logger.')
|
|
32
|
+
|
|
33
|
+
update_parser.add_argument('-p', '--pre-release', action='store_true', help='When checking for updates, include pre-release versions.')
|
|
34
|
+
|
|
35
|
+
# ---- DEBUG COMMAND --------------------------------
|
|
36
|
+
|
|
37
|
+
debug_parser = subparsers.add_parser('debug', help='Fetches a collection of environment information to help debug inspy-logger.')
|
|
38
|
+
|
|
39
|
+
debug_parser.add_argument('-C', '--copy-to-clipboard', action='store_true', help='Copies the debug information to the clipboard.')
|
|
40
|
+
debug_parser.add_argument('-P', '--print', action='store_true', help='Prints the debug information to the console.', default=True)
|
|
41
|
+
|
|
42
|
+
# ---- FORMAT FLAGS --------------------------------
|
|
43
|
+
|
|
44
|
+
fmt_grp = debug_parser.add_mutually_exclusive_group()
|
|
45
|
+
|
|
46
|
+
fmt_grp.add_argument('-M', '--markdown', action='store_true', help='Formats the debug information in Markdown.')
|
|
47
|
+
|
|
48
|
+
fmt_grp.add_argument('-J', '--json', action='store_true', help='Formats the debug information in JSON.')
|
|
49
|
+
|
|
50
|
+
fmt_grp.add_argument('-T', '--text', action='store_true', help='Formats the debug information in plain text.')
|
|
51
|
+
|
|
52
|
+
# Parse the arguments
|
|
53
|
+
parsed_args = parser.parse_args()
|
|
54
|
+
|
|
55
|
+
# END PARSER SETUP
|
|
56
|
+
|
|
57
|
+
if parsed_args.subcommand == 'update':
|
|
58
|
+
INCLUDE_PRE_RELEASE_FOR_UPDATE_CHECK = parsed_args.pre_release
|
|
59
|
+
else:
|
|
60
|
+
INCLUDE_PRE_RELEASE_FOR_UPDATE_CHECK = False
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def main():
|
|
67
|
+
|
|
68
|
+
version = PyPiVersionInfo()
|
|
69
|
+
|
|
70
|
+
ACTIONS = {
|
|
71
|
+
'default': version.print_version_info,
|
|
72
|
+
'update': version.update,
|
|
73
|
+
'debug': fetch_system_info,
|
|
74
|
+
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if parsed_args.subcommand is None:
|
|
78
|
+
parsed_args.subcommand = 'default'
|
|
79
|
+
|
|
80
|
+
if parsed_args.subcommand == 'debug':
|
|
81
|
+
|
|
82
|
+
if (
|
|
83
|
+
parsed_args.markdown
|
|
84
|
+
or not parsed_args.json
|
|
85
|
+
and not parsed_args.text
|
|
86
|
+
):
|
|
87
|
+
fmt = 'markdown'
|
|
88
|
+
elif parsed_args.json:
|
|
89
|
+
fmt = 'json'
|
|
90
|
+
else:
|
|
91
|
+
fmt = 'text'
|
|
92
|
+
|
|
93
|
+
fetch_system_info(copy_to_clipboard=parsed_args.copy_to_clipboard, format_type=fmt, print_to_console=parsed_args.print)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
if parsed_args.subcommand in ACTIONS:
|
|
98
|
+
ACTIONS[parsed_args.subcommand]()
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
return parsed_args
|
|
103
|
+
|
|
104
|
+
if __name__ == '__main__':
|
|
105
|
+
main()
|
|
@@ -19,16 +19,3 @@ __authors__ = [
|
|
|
19
19
|
('Inspyre-Softworks', 'https://inspyre.tech'),
|
|
20
20
|
('Taylor-Jayde Blackstone', '<t.blackstone@inspyre.tech')
|
|
21
21
|
]
|
|
22
|
-
|
|
23
|
-
'''
|
|
24
|
-
File Change History:
|
|
25
|
-
11/5/22 - 4:21 AM (v2.1.2):
|
|
26
|
-
- Added description to docstring. (target: 2.1.2)
|
|
27
|
-
|
|
28
|
-
11/5/22 - 4:41 AM:
|
|
29
|
-
- Version bump (target: 2.1.3)
|
|
30
|
-
|
|
31
|
-
08/16/2023 - 13:49 (v3.0):
|
|
32
|
-
- Version bump (v2.1.3 -> v3.0-dev.1)
|
|
33
|
-
|
|
34
|
-
'''
|
|
@@ -251,10 +251,12 @@ class Logger:
|
|
|
251
251
|
"""
|
|
252
252
|
self._log(logging.INFO, message, args=(), stacklevel=2)
|
|
253
253
|
|
|
254
|
+
|
|
254
255
|
def warning(self, message):
|
|
255
256
|
"""
|
|
256
257
|
Logs a warning message.
|
|
257
258
|
|
|
259
|
+
|
|
258
260
|
Args:
|
|
259
261
|
message (str): The message to log.
|
|
260
262
|
"""
|
|
@@ -264,6 +266,7 @@ class Logger:
|
|
|
264
266
|
"""
|
|
265
267
|
Logs an error message.
|
|
266
268
|
|
|
269
|
+
|
|
267
270
|
Args:
|
|
268
271
|
message (str): The message to log.
|
|
269
272
|
"""
|
|
@@ -284,6 +287,7 @@ class Logger:
|
|
|
284
287
|
|
|
285
288
|
return f'<Logger: {name} w/ level {self.logger.level} at {hex_id}{parent_part}>'
|
|
286
289
|
|
|
290
|
+
|
|
287
291
|
@classmethod
|
|
288
292
|
def create_logger_for_caller(cls):
|
|
289
293
|
"""
|
|
@@ -61,6 +61,16 @@ class Loggable:
|
|
|
61
61
|
class_logger = None
|
|
62
62
|
|
|
63
63
|
def __init__(self, parent_log_device=None, **kwargs):
|
|
64
|
+
"""
|
|
65
|
+
Initializes an instance of the class.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
parent_log_device (optional): The parent log device. Defaults to None.
|
|
69
|
+
**kwargs: Additional keyword arguments.
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
None
|
|
73
|
+
"""
|
|
64
74
|
self.parent_log_device = parent_log_device
|
|
65
75
|
self.__log_name = self.__class__.__name__
|
|
66
76
|
if self.parent_log_device is not None:
|
|
File without changes
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import json
|
|
3
|
+
import platform
|
|
4
|
+
import sys
|
|
5
|
+
import pyperclip
|
|
6
|
+
from pyperclip import copy
|
|
7
|
+
|
|
8
|
+
from inspy_logger.version import parse_version
|
|
9
|
+
|
|
10
|
+
VALID_DATA_FORMATS = [
|
|
11
|
+
'markdown',
|
|
12
|
+
'json',
|
|
13
|
+
'text'
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def determine_execution_mode():
|
|
18
|
+
"""
|
|
19
|
+
Determines the execution mode of the program.
|
|
20
|
+
|
|
21
|
+
Returns:
|
|
22
|
+
str:
|
|
23
|
+
Either 'Script' or 'REPL' depending on the execution mode.
|
|
24
|
+
"""
|
|
25
|
+
return "REPL" if len(sys.argv) == 1 else "Script"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def get_operating_system_info():
|
|
29
|
+
"""
|
|
30
|
+
Gets the operating system information.
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
dict:
|
|
34
|
+
A dictionary containing the operating system information.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
os_name = platform.system()
|
|
38
|
+
|
|
39
|
+
if os_name.lower() == 'windows':
|
|
40
|
+
from inspy_logger.helpers.debug.system.winx import get_win_version_info
|
|
41
|
+
|
|
42
|
+
return get_win_version_info()
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
'name': platform.system(),
|
|
46
|
+
'version': platform.release()
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def is_valid_data_format(data_format):
|
|
52
|
+
"""
|
|
53
|
+
Checks if the specified data format is valid.
|
|
54
|
+
|
|
55
|
+
This function is case-insensitive and compares the specified data format against the `VALID_DATA_FORMATS` list.
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
Note:
|
|
59
|
+
Valid formats are as follows:
|
|
60
|
+
- markdown
|
|
61
|
+
- json
|
|
62
|
+
- text
|
|
63
|
+
|
|
64
|
+
Parameters:
|
|
65
|
+
data_format (str):
|
|
66
|
+
The format you'd like the data to be returned in.
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
bool:
|
|
70
|
+
Whether the specified data format is valid.
|
|
71
|
+
|
|
72
|
+
"""
|
|
73
|
+
return data_format.lower() in VALID_DATA_FORMATS
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def get_system_info(format_type='markdown'):
|
|
77
|
+
"""
|
|
78
|
+
Gathers system information and formats it based on the specified format type.
|
|
79
|
+
|
|
80
|
+
Parameters:
|
|
81
|
+
format_type (str):
|
|
82
|
+
The format type for the output. Options are 'markdown', 'json', 'text'.
|
|
83
|
+
Default is 'markdown'.
|
|
84
|
+
|
|
85
|
+
Note:
|
|
86
|
+
Valid formats are 'markdown', 'json', and 'text'.
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
str:
|
|
90
|
+
A string containing the system information in the specified format.
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
if not is_valid_data_format(format_type):
|
|
94
|
+
raise ValueError(f"Invalid format type: {format_type}. Must be one of {VALID_DATA_FORMATS}")
|
|
95
|
+
|
|
96
|
+
# Gather system information
|
|
97
|
+
os_name = platform.system()
|
|
98
|
+
os_version = platform.release()
|
|
99
|
+
|
|
100
|
+
os_version_full = platform.version()
|
|
101
|
+
|
|
102
|
+
if os_name.lower() == 'windows' and os_version == '10':
|
|
103
|
+
from inspy_logger.helpers.debug.system.winx import is_win_11
|
|
104
|
+
|
|
105
|
+
if is_win_11(os_version_full):
|
|
106
|
+
os_version = '11'
|
|
107
|
+
|
|
108
|
+
os_version = f'{os_version} ({os_version_full})'
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
python_version = platform.python_version()
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
sys_info = {
|
|
117
|
+
'os_name': platform.system(),
|
|
118
|
+
'os_version': platform.release(),
|
|
119
|
+
'python_version': platform.python_version(),
|
|
120
|
+
'isl_version': parse_version(),
|
|
121
|
+
'execution_mode': "REPL" if len(sys.argv) == 1 else "Script"
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
# Format the information
|
|
125
|
+
if format_type == 'markdown':
|
|
126
|
+
return f"""
|
|
127
|
+
💻 **System Info:**
|
|
128
|
+
- 💾 **Operating System**:
|
|
129
|
+
- [x] {os_name} {os_version}
|
|
130
|
+
- 🐍 **Python Version**: {python_version}
|
|
131
|
+
- 🌈 **InSPy-Logger Version**: {sys_info['isl_version']}
|
|
132
|
+
- - [{sys_info['execution_mode'] == 'Script'}] Script
|
|
133
|
+
- [{sys_info['execution_mode'] == 'REPL'}] REPL
|
|
134
|
+
""".strip()
|
|
135
|
+
elif format_type == 'json':
|
|
136
|
+
return json.dumps({
|
|
137
|
+
"System Info": {
|
|
138
|
+
"Operating System": f"{os_name} {os_version}",
|
|
139
|
+
"Python Version": python_version,
|
|
140
|
+
"InSPy-Logger Version": sys_info['isl_version'],
|
|
141
|
+
"Execution Mode": sys_info['execution_mode']
|
|
142
|
+
}
|
|
143
|
+
}, indent=4)
|
|
144
|
+
else: # plain text
|
|
145
|
+
return f"""
|
|
146
|
+
System Info:
|
|
147
|
+
Operating System: {os_name} {os_version}
|
|
148
|
+
Python Version: {python_version}
|
|
149
|
+
InSPy-Logger Version: {sys_info['isl_version']}
|
|
150
|
+
Execution Mode: {sys_info['execution_mode']}
|
|
151
|
+
""".strip()
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def fetch_system_info(copy_to_clipboard=False, format_type='markdown', print_to_console=None):
|
|
155
|
+
"""
|
|
156
|
+
Fetches system information and formats it based on the specified format type.
|
|
157
|
+
|
|
158
|
+
Parameters:
|
|
159
|
+
copy_to_clipboard (bool):
|
|
160
|
+
Whether to copy the output to the clipboard. Default is False.
|
|
161
|
+
|
|
162
|
+
format_type (str):
|
|
163
|
+
The format type for the output. Options are 'markdown',
|
|
164
|
+
'json', 'text'. Default is 'markdown'.
|
|
165
|
+
|
|
166
|
+
print_to_console (bool):
|
|
167
|
+
Whether to print the output to the console. Default is None.
|
|
168
|
+
|
|
169
|
+
Note:
|
|
170
|
+
If this is None, it will default to True.
|
|
171
|
+
|
|
172
|
+
Returns:
|
|
173
|
+
str:
|
|
174
|
+
A string containing the system information in the specified format.
|
|
175
|
+
"""
|
|
176
|
+
info = get_system_info(format_type)
|
|
177
|
+
if copy_to_clipboard:
|
|
178
|
+
copy(info)
|
|
179
|
+
return info
|
|
File without changes
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import platform
|
|
2
|
+
import multiprocessing
|
|
3
|
+
import psutil
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
# Function to check if the system architecture is 64-bit
|
|
7
|
+
def is_64bit():
|
|
8
|
+
"""
|
|
9
|
+
Checks if the system architecture is 64-bit.
|
|
10
|
+
|
|
11
|
+
Returns:
|
|
12
|
+
bool: True if the system architecture is 64-bit, False otherwise.
|
|
13
|
+
"""
|
|
14
|
+
return platform.architecture()[0] == '64bit'
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# Function to get the number of cores
|
|
18
|
+
def number_of_cores():
|
|
19
|
+
"""
|
|
20
|
+
Gets the number of cores in the system.
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
int: The number of cores in the system.
|
|
24
|
+
"""
|
|
25
|
+
return multiprocessing.cpu_count()
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# Function to get the processor core information
|
|
29
|
+
def get_processor_core_info():
|
|
30
|
+
"""
|
|
31
|
+
Gets the processor core information.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
dict: A dictionary containing the total number of cores, the number of physical cores, and the number of logical cores.
|
|
35
|
+
"""
|
|
36
|
+
phys = psutil.cpu_count(logical=False)
|
|
37
|
+
total = number_of_cores()
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
'total': total,
|
|
41
|
+
'physical': phys,
|
|
42
|
+
'logical': total - phys
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
# Function to get the processor information
|
|
47
|
+
def _get_processor_info():
|
|
48
|
+
"""
|
|
49
|
+
Gets the processor information.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
dict: A dictionary containing the name of the processor, the architecture of the processor, and the core information of the processor.
|
|
53
|
+
"""
|
|
54
|
+
cores = get_processor_core_info()
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
'name': platform.processor(),
|
|
58
|
+
'architecture': '64-bit' if is_64bit() else '32-bit',
|
|
59
|
+
'cores': get_processor_core_info()
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
# A dictionary containing the processor information
|
|
64
|
+
PROCESSOR_INFO = _get_processor_info()
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from packaging import version
|
|
2
|
+
import platform
|
|
3
|
+
|
|
4
|
+
WIN_11_VERSION = version.parse('10.0.2200')
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def is_win_11(os_version):
|
|
8
|
+
return version.parse(os_version) >= WIN_11_VERSION
|
|
9
|
+
|
|
10
|
+
def is_64bit():
|
|
11
|
+
return platform.architecture()[0] == '64bit'
|
|
12
|
+
|
|
13
|
+
def get_win_version():
|
|
14
|
+
release, build_num, service_pack, _ = platform.win32_ver()
|
|
15
|
+
|
|
16
|
+
if release == '10' and is_win_11(build_num):
|
|
17
|
+
release = '11'
|
|
18
|
+
|
|
19
|
+
ver = {
|
|
20
|
+
'release': f'Windows {release}',
|
|
21
|
+
'build': build_num,
|
|
22
|
+
'service_pack': service_pack.replace('SP', ''),
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
}
|
|
@@ -27,8 +27,7 @@ from __future__ import annotations
|
|
|
27
27
|
from urllib.parse import quote as url_safe
|
|
28
28
|
|
|
29
29
|
import requests
|
|
30
|
-
|
|
31
|
-
from inspy_logger.helpers.cache import TLDCache
|
|
30
|
+
from public_suffix_list import PublicSuffixList
|
|
32
31
|
|
|
33
32
|
DEFAULT_TEST_HOSTS = [
|
|
34
33
|
['https', 'inspyre', 'tech'],
|
|
@@ -44,10 +43,11 @@ hosts = []
|
|
|
44
43
|
:obj:`list`[:obj:`Host`]:
|
|
45
44
|
A list of host objects that will be used to connect to.
|
|
46
45
|
"""
|
|
46
|
+
psl = PublicSuffixList()
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
URL_SUFFIXES = psl._suffixes
|
|
49
49
|
|
|
50
|
-
VALID_TLDS =
|
|
50
|
+
VALID_TLDS = URL_SUFFIXES
|
|
51
51
|
|
|
52
52
|
|
|
53
53
|
class Host():
|
|
@@ -169,7 +169,7 @@ class Host():
|
|
|
169
169
|
def tld(self, new):
|
|
170
170
|
if not isinstance(new, str):
|
|
171
171
|
raise TypeError(f"New value must be a string not {type(new)}")
|
|
172
|
-
if new not in
|
|
172
|
+
if new not in URL_SUFFIXES:
|
|
173
173
|
raise ValueError("TLD must be valid!")
|
|
174
174
|
|
|
175
175
|
self.__tld = new
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
class ByteConverter:
|
|
2
|
+
"""
|
|
3
|
+
A class to convert between various units of digital storage.
|
|
4
|
+
|
|
5
|
+
Supported units: Bytes, Kilobytes, Megabytes, Gigabytes, Terabytes, Petabytes, Exabytes, Zettabytes, Yottabytes,
|
|
6
|
+
Kibibytes, Mebibytes, Gibibytes, Tebibytes, Pebibytes, Exbibytes, Zebibytes, Yobibytes.
|
|
7
|
+
|
|
8
|
+
Methods:
|
|
9
|
+
convert(value, from_unit, to_unit): Converts the given value from one unit to another.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
# Dictionary to store conversion rates relative to bytes
|
|
13
|
+
_conversion_rates = {
|
|
14
|
+
'bytes': 1,
|
|
15
|
+
'kilobytes': 1000,
|
|
16
|
+
'megabytes': 1000 ** 2,
|
|
17
|
+
'gigabytes': 1000 ** 3,
|
|
18
|
+
'terabytes': 1000 ** 4,
|
|
19
|
+
'petabytes': 1000 ** 5,
|
|
20
|
+
'exabytes': 1000 ** 6,
|
|
21
|
+
'zettabytes': 1000 ** 7,
|
|
22
|
+
'yottabytes': 1000 ** 8,
|
|
23
|
+
'kibibytes': 1024,
|
|
24
|
+
'mebibytes': 1024 ** 2,
|
|
25
|
+
'gibibytes': 1024 ** 3,
|
|
26
|
+
'tebibytes': 1024 ** 4,
|
|
27
|
+
'pebibytes': 1024 ** 5,
|
|
28
|
+
'exbibytes': 1024 ** 6,
|
|
29
|
+
'zebibytes': 1024 ** 7,
|
|
30
|
+
'yobibytes': 1024 ** 8
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@classmethod
|
|
34
|
+
def convert(cls, value: float, from_unit: str, to_unit: str) -> float:
|
|
35
|
+
"""
|
|
36
|
+
Converts the given value from one unit to another.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
value (float): The value to convert.
|
|
40
|
+
from_unit (str): The unit to convert from. Must be one of the supported units.
|
|
41
|
+
to_unit (str): The unit to convert to. Must be one of the supported units.
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
float: The converted value in the target unit.
|
|
45
|
+
|
|
46
|
+
Raises:
|
|
47
|
+
ValueError: If an unsupported unit is specified.
|
|
48
|
+
"""
|
|
49
|
+
from_unit = from_unit.lower()
|
|
50
|
+
to_unit = to_unit.lower()
|
|
51
|
+
|
|
52
|
+
if from_unit not in cls._conversion_rates or to_unit not in cls._conversion_rates:
|
|
53
|
+
raise ValueError("Unsupported unit. Supported units are: " + ', '.join(cls._conversion_rates.keys()))
|
|
54
|
+
|
|
55
|
+
# Convert the value to bytes first, then to the target unit
|
|
56
|
+
value_in_bytes = value * cls._conversion_rates[from_unit]
|
|
57
|
+
return value_in_bytes / cls._conversion_rates[to_unit]
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
from packaging import version as pkg_version
|
|
3
|
+
import sys
|
|
4
|
+
from rich.table import Table
|
|
5
|
+
from rich import print
|
|
6
|
+
|
|
7
|
+
# Constants
|
|
8
|
+
RELEASE_MAP = {
|
|
9
|
+
'dev': 'Development Build',
|
|
10
|
+
'alpha': 'Alpha Build',
|
|
11
|
+
'beta': 'Beta Build',
|
|
12
|
+
'rc': 'Release Candidate Build',
|
|
13
|
+
'final': 'Final Release Build'
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
__VERSION__ = {
|
|
17
|
+
'major': 3,
|
|
18
|
+
'minor': 0,
|
|
19
|
+
'patch': 2,
|
|
20
|
+
'release': 'dev',
|
|
21
|
+
'release_num': 1
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def parse_version():
|
|
26
|
+
"""
|
|
27
|
+
Parses the version information into a string.
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
str: The version information.
|
|
31
|
+
|
|
32
|
+
Since:
|
|
33
|
+
v1.0
|
|
34
|
+
"""
|
|
35
|
+
version = f'{__VERSION__["major"]}.{__VERSION__["minor"]}.{__VERSION__["patch"]}'
|
|
36
|
+
|
|
37
|
+
if __VERSION__['release'] != 'final':
|
|
38
|
+
version += f'-{__VERSION__["release"]}.{__VERSION__["release_num"]}'
|
|
39
|
+
|
|
40
|
+
return version
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def get_full_version_name():
|
|
44
|
+
"""
|
|
45
|
+
Gets the full version name.
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
str: The full version name.
|
|
49
|
+
|
|
50
|
+
Since:
|
|
51
|
+
v1.0
|
|
52
|
+
"""
|
|
53
|
+
ver = parse_version()
|
|
54
|
+
ver = ver.split('-')[0]
|
|
55
|
+
|
|
56
|
+
release_type = RELEASE_MAP[__VERSION__["release"]]
|
|
57
|
+
release_num = __VERSION__["release_num"]
|
|
58
|
+
release_str = f" {release_type} {'' if __VERSION__['release'].lower() == 'final' else f'({release_num})'}"
|
|
59
|
+
return f'v{ver}{release_str}'
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class PyPiVersionInfo:
|
|
63
|
+
"""
|
|
64
|
+
A class to represent the version information for this package from PyPi.
|
|
65
|
+
|
|
66
|
+
Attributes:
|
|
67
|
+
latest_stable (packaging.version.Version):
|
|
68
|
+
The latest stable version of the package on PyPi.
|
|
69
|
+
|
|
70
|
+
latest_pre_release (packaging.version.Version):
|
|
71
|
+
The latest pre-release version of the package.
|
|
72
|
+
Since:
|
|
73
|
+
v3.0
|
|
74
|
+
"""
|
|
75
|
+
__url = 'https://pypi.org/pypi/inspy-logger/json'
|
|
76
|
+
__installed = parse_version()
|
|
77
|
+
__checked_for_update = False
|
|
78
|
+
__newer_available_version = None
|
|
79
|
+
|
|
80
|
+
def __init__(self, include_pre_release_for_update_check=False):
|
|
81
|
+
self.__latest_stable = None
|
|
82
|
+
self.__latest_pre_release = None
|
|
83
|
+
self.__all_versions = None
|
|
84
|
+
self.include_pre_release_for_update_check = include_pre_release_for_update_check
|
|
85
|
+
self.__query_versions()
|
|
86
|
+
|
|
87
|
+
@property
|
|
88
|
+
def all_versions(self):
|
|
89
|
+
if self.__all_versions is None:
|
|
90
|
+
self.__query_versions()
|
|
91
|
+
return sorted([pkg_version.parse(v) for v in self.__all_versions])
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
def checked_for_update(self):
|
|
95
|
+
return self.__checked_for_update
|
|
96
|
+
|
|
97
|
+
@property
|
|
98
|
+
def installed(self):
|
|
99
|
+
"""
|
|
100
|
+
Gets the installed version of the package.
|
|
101
|
+
"""
|
|
102
|
+
return pkg_version.parse(self.__installed)
|
|
103
|
+
|
|
104
|
+
@property
|
|
105
|
+
def installed_newer_than_latest(self):
|
|
106
|
+
return self.installed > self.latest
|
|
107
|
+
|
|
108
|
+
@property
|
|
109
|
+
def latest(self):
|
|
110
|
+
return (
|
|
111
|
+
self.all_versions[-1]
|
|
112
|
+
if self.include_pre_release_for_update_check
|
|
113
|
+
else self.latest_stable
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
@property
|
|
117
|
+
def latest_stable(self):
|
|
118
|
+
"""
|
|
119
|
+
Gets the latest stable version of the package on PyPi.
|
|
120
|
+
"""
|
|
121
|
+
if self.__latest_stable is None:
|
|
122
|
+
self.__query_versions()
|
|
123
|
+
return pkg_version.parse(self.__latest_stable)
|
|
124
|
+
|
|
125
|
+
@property
|
|
126
|
+
def latest_pre_release(self):
|
|
127
|
+
"""
|
|
128
|
+
Gets the latest pre-release version of the package.
|
|
129
|
+
"""
|
|
130
|
+
if self.__all_versions is None:
|
|
131
|
+
self.__query_versions()
|
|
132
|
+
pre_release_versions = [v for v in self.all_versions if v.is_prerelease]
|
|
133
|
+
return pre_release_versions[-1] if pre_release_versions else None
|
|
134
|
+
|
|
135
|
+
@property
|
|
136
|
+
def newer_available_version(self):
|
|
137
|
+
|
|
138
|
+
if self.__newer_available_version is None:
|
|
139
|
+
self.check_for_update()
|
|
140
|
+
|
|
141
|
+
return self.__newer_available_version
|
|
142
|
+
|
|
143
|
+
def __query_versions(self):
|
|
144
|
+
"""
|
|
145
|
+
Queries the versions from PyPi.
|
|
146
|
+
"""
|
|
147
|
+
try:
|
|
148
|
+
response = requests.get(self.__url)
|
|
149
|
+
response.raise_for_status()
|
|
150
|
+
data = response.json()
|
|
151
|
+
|
|
152
|
+
self.__all_versions = list(data['releases'].keys())
|
|
153
|
+
self.__latest_stable = data['info']['version']
|
|
154
|
+
except requests.RequestException as e:
|
|
155
|
+
# Handle connection errors, HTTP errors, etc.
|
|
156
|
+
print(f"Error querying PyPi: {e}")
|
|
157
|
+
|
|
158
|
+
@property
|
|
159
|
+
def update_available(self):
|
|
160
|
+
"""
|
|
161
|
+
Checks if an update is available.
|
|
162
|
+
"""
|
|
163
|
+
if self.__newer_available_version is None:
|
|
164
|
+
self.check_for_update()
|
|
165
|
+
return self.__newer_available_version is not None
|
|
166
|
+
|
|
167
|
+
def check_for_update(self, include_pre_releases=False):
|
|
168
|
+
latest_version = self.latest_stable
|
|
169
|
+
|
|
170
|
+
if include_pre_releases or self.include_pre_release_for_update_check:
|
|
171
|
+
latest_version = max(latest_version, self.latest_pre_release)
|
|
172
|
+
|
|
173
|
+
if latest_version > self.installed:
|
|
174
|
+
self.__newer_available_version = latest_version
|
|
175
|
+
|
|
176
|
+
self.__checked_for_update = True
|
|
177
|
+
|
|
178
|
+
return latest_version > self.installed
|
|
179
|
+
|
|
180
|
+
def update(self):
|
|
181
|
+
"""
|
|
182
|
+
Checks for updates to inspy-logger.
|
|
183
|
+
|
|
184
|
+
Returns:
|
|
185
|
+
None`
|
|
186
|
+
|
|
187
|
+
Since:
|
|
188
|
+
v3.0
|
|
189
|
+
"""
|
|
190
|
+
|
|
191
|
+
local_newer_statement = 'Local version is newer than latest version. This is likely a development build.'
|
|
192
|
+
|
|
193
|
+
if not self.installed_newer_than_latest:
|
|
194
|
+
local_newer_statement = ''
|
|
195
|
+
|
|
196
|
+
try:
|
|
197
|
+
if self.update_available:
|
|
198
|
+
print(f'\n\n[bold green]Update Available![/bold green] New version: '
|
|
199
|
+
f'[bold cyan]{self.update_available}[/bold cyan]')
|
|
200
|
+
else:
|
|
201
|
+
print(f'\n\n[bold green]No update available.[/bold green] Current version: '
|
|
202
|
+
f'[bold cyan]{parse_version()}[/bold cyan] {local_newer_statement}')
|
|
203
|
+
|
|
204
|
+
except Exception as e:
|
|
205
|
+
print(f'An error occurred during the update check: {str(e)}')
|
|
206
|
+
|
|
207
|
+
def print_version_info(self):
|
|
208
|
+
"""
|
|
209
|
+
Print version information in a formatted table.
|
|
210
|
+
|
|
211
|
+
This function creates a table using the `Table` class and populates it with version information about the current Python environment. It then prints the table to the console.
|
|
212
|
+
|
|
213
|
+
Parameters:
|
|
214
|
+
self: The current instance of the class.
|
|
215
|
+
|
|
216
|
+
Returns:
|
|
217
|
+
None
|
|
218
|
+
"""
|
|
219
|
+
|
|
220
|
+
# Create a table
|
|
221
|
+
|
|
222
|
+
table = Table(show_header=False, show_lines=True, expand=True, border_style='bright_blue',
|
|
223
|
+
row_styles=['none', 'dim'])
|
|
224
|
+
|
|
225
|
+
# Add columns
|
|
226
|
+
table.add_column('Property', style='cyan', width=20)
|
|
227
|
+
table.add_column('Value', justify='center')
|
|
228
|
+
|
|
229
|
+
# Add rows
|
|
230
|
+
table.add_row('Version', parse_version(), )
|
|
231
|
+
table.add_row('Full Version Name', get_full_version_name())
|
|
232
|
+
|
|
233
|
+
if self.update_available:
|
|
234
|
+
table.add_row('Update Available', '[bold green]Yes[/bold green]')
|
|
235
|
+
table.add_row('Latest Version', f'{self.new_version_available_num}')
|
|
236
|
+
|
|
237
|
+
table.add_row('Python Executable Path', sys.executable)
|
|
238
|
+
table.add_row('Python Version', sys.version)
|
|
239
|
+
|
|
240
|
+
print(table)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "inspy-logger"
|
|
3
|
-
version = "3.0-dev.
|
|
3
|
+
version = "3.0.2-dev.1"
|
|
4
4
|
description = "Colorable, scalable logger for CLI"
|
|
5
5
|
authors = ["Taylor-Jayde Blackstone <tayjaybabee@gmail.com>"]
|
|
6
6
|
homepage = 'https://github.com/Inspyre-Softworks/inSPy-Logger'
|
|
@@ -62,6 +62,10 @@ sphinxcontrib-autoprogram = "^0.1.8"
|
|
|
62
62
|
[tool.poetry.group.dev.dependencies]
|
|
63
63
|
poetry-plugin-export = "^1.6.0"
|
|
64
64
|
|
|
65
|
+
|
|
66
|
+
[tool.poetry.group.debug.dependencies]
|
|
67
|
+
pyperclip = "^1.8.2"
|
|
68
|
+
|
|
65
69
|
[build-system]
|
|
66
70
|
requires = ["poetry-core>=1.0.0"]
|
|
67
71
|
build-backend = "poetry.core.masonry.api"
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
|
|
3
|
-
File:
|
|
4
|
-
inspy_logger/Scripts/main.py
|
|
5
|
-
|
|
6
|
-
Author:
|
|
7
|
-
Inspyre Softworks
|
|
8
|
-
|
|
9
|
-
"""
|
|
10
|
-
INSPY_LOG_LEVEL = 'info'
|
|
11
|
-
|
|
12
|
-
from inspy_logger.version import parse_version, get_full_version_name, PyPiVersionInfo
|
|
13
|
-
import sys
|
|
14
|
-
from rich import print
|
|
15
|
-
from rich.table import Table
|
|
16
|
-
from argparse import ArgumentParser
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
parser = ArgumentParser('inspy-logger-version', description='Displays version information for inspy-logger.')
|
|
20
|
-
|
|
21
|
-
parser.add_argument('-v', '--version', action='version', version=parse_version())
|
|
22
|
-
|
|
23
|
-
subparsers = parser.add_subparsers(title='subcommands', dest='subcommand')
|
|
24
|
-
|
|
25
|
-
update_parser =subparsers.add_parser('update', help='Checks for updates to inspy-logger.')
|
|
26
|
-
|
|
27
|
-
update_parser.add_argument('-p', '--pre-release', action='store_true', help='When checking for updates, include pre-release versions.')
|
|
28
|
-
|
|
29
|
-
parsed_args = parser.parse_args()
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if parsed_args.subcommand == 'update':
|
|
33
|
-
INCLUDE_PRE_RELEASE_FOR_UPDATE_CHECK = parsed_args.pre_release
|
|
34
|
-
else:
|
|
35
|
-
INCLUDE_PRE_RELEASE_FOR_UPDATE_CHECK = False
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
pypi_info = PyPiVersionInfo(include_pre_release_for_update_check=INCLUDE_PRE_RELEASE_FOR_UPDATE_CHECK)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
def update():
|
|
42
|
-
"""
|
|
43
|
-
Checks for updates to inspy-logger.
|
|
44
|
-
|
|
45
|
-
Returns:
|
|
46
|
-
None
|
|
47
|
-
|
|
48
|
-
Since:
|
|
49
|
-
v3.0
|
|
50
|
-
"""
|
|
51
|
-
try:
|
|
52
|
-
if pypi_info.update_available:
|
|
53
|
-
print(f'\n\n[bold green]Update Available![/bold green] New version: [bold cyan]{pypi_info.new_version_available}[/bold cyan]')
|
|
54
|
-
else:
|
|
55
|
-
print(f'\n\n[bold green]No update available.[/bold green] Current version: [bold cyan]{parse_version()}[/bold cyan] {"which is newer than the available version on PyPi.org" if pypi_info.installed_newer_than_latest else ""}')
|
|
56
|
-
except Exception as e:
|
|
57
|
-
print(f'An error occurred during the update check: {str(e)}')
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
def get_version_info():
|
|
61
|
-
# Create a table
|
|
62
|
-
table = Table(show_header=False, show_lines=True, expand=True, border_style='bright_blue',
|
|
63
|
-
row_styles=['none', 'dim'])
|
|
64
|
-
|
|
65
|
-
# Add columns
|
|
66
|
-
table.add_column('Property', style='cyan', width=20)
|
|
67
|
-
table.add_column('Value', justify='center')
|
|
68
|
-
|
|
69
|
-
# Add rows
|
|
70
|
-
table.add_row('Version', parse_version(), )
|
|
71
|
-
table.add_row('Full Version Name', get_full_version_name())
|
|
72
|
-
|
|
73
|
-
if pypi_info.update_available:
|
|
74
|
-
table.add_row('Update Available', '[bold green]Yes[/bold green]')
|
|
75
|
-
table.add_row('Latest Version', f'{pypi_info.new_version_available_num}')
|
|
76
|
-
|
|
77
|
-
table.add_row('Python Executable Path', sys.executable)
|
|
78
|
-
table.add_row('Python Version', sys.version)
|
|
79
|
-
|
|
80
|
-
print(table)
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
def main():
|
|
85
|
-
|
|
86
|
-
return update() if parsed_args.subcommand == 'update' else get_version_info()
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
if __name__ == '__main__':
|
|
91
|
-
main()
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from os import makedirs
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
from pickle import dump as pkl_dump
|
|
6
|
-
from pickle import load as pkl_load
|
|
7
|
-
from time import time
|
|
8
|
-
from appdirs import user_cache_dir
|
|
9
|
-
from domain_suffixes.suffixes import Suffixes
|
|
10
|
-
from humanize.time import precisedelta
|
|
11
|
-
|
|
12
|
-
PICKLE_FILEPATH = Path(
|
|
13
|
-
user_cache_dir(
|
|
14
|
-
appname='InspyLogger',
|
|
15
|
-
appauthor='Inspyre-Softworks'
|
|
16
|
-
)
|
|
17
|
-
).joinpath('tld.pkl')
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class TLDCache(object):
|
|
21
|
-
|
|
22
|
-
parent_dir = PICKLE_FILEPATH.parent
|
|
23
|
-
|
|
24
|
-
def __init__(self):
|
|
25
|
-
self.__created_ts = None
|
|
26
|
-
self.__pickle_fp_exists = None
|
|
27
|
-
self.__num_tlds = None
|
|
28
|
-
self.__tlds = None
|
|
29
|
-
self.__data = None
|
|
30
|
-
self.__last_renewal_ts = None
|
|
31
|
-
self.__renewal_hist = None
|
|
32
|
-
|
|
33
|
-
def build(self):
|
|
34
|
-
self.__data = {
|
|
35
|
-
'created_ts': time(),
|
|
36
|
-
'renewal_data': {
|
|
37
|
-
'last_ts': None,
|
|
38
|
-
'history': [],
|
|
39
|
-
},
|
|
40
|
-
'tlds': self.fetch_from_source()
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return self.__data
|
|
44
|
-
|
|
45
|
-
@staticmethod
|
|
46
|
-
def load(self):
|
|
47
|
-
""" Load the pickle file for the cache.
|
|
48
|
-
|
|
49
|
-
Will attempt to load the pickle file into memory from the path indicated by :obj:`PICKLE_FILEPATH`
|
|
50
|
-
|
|
51
|
-
Raises:
|
|
52
|
-
:exception:`FileNotFoundError`: If the pickle file does not exist.
|
|
53
|
-
|
|
54
|
-
"""
|
|
55
|
-
with open(PICKLE_FILEPATH, 'rb') as pfp:
|
|
56
|
-
res = pkl_load(pfp)
|
|
57
|
-
|
|
58
|
-
return res
|
|
59
|
-
|
|
60
|
-
def write(self):
|
|
61
|
-
""" Write the pickle file.
|
|
62
|
-
|
|
63
|
-
Write the contents of the cache to the file-system path indicated by :obj:`PICKLE_FILEPATH`
|
|
64
|
-
|
|
65
|
-
Raises:
|
|
66
|
-
:exception:`PermissionError`: If the pickle file can't be written due to permissions writing the file to storage.
|
|
67
|
-
"""
|
|
68
|
-
|
|
69
|
-
if not self.parent_dir.exists():
|
|
70
|
-
makedirs(self.parent_dir, exist_ok=True)
|
|
71
|
-
|
|
72
|
-
with open(PICKLE_FILEPATH, 'wb') as pfp:
|
|
73
|
-
pkl_dump(self.__data, pfp)
|
|
74
|
-
|
|
75
|
-
@staticmethod
|
|
76
|
-
def fetch_from_source(self):
|
|
77
|
-
""" Fetch the top-level-domain list from the source
|
|
78
|
-
|
|
79
|
-
Returns:
|
|
80
|
-
:class:`list`: A list of all known top-level domain suffixes from the domain-suffixes package.
|
|
81
|
-
"""
|
|
82
|
-
suffixes = Suffixes()
|
|
83
|
-
return suffixes.get_all_tlds()
|
|
84
|
-
|
|
85
|
-
@property
|
|
86
|
-
def contents(self) -> dict:
|
|
87
|
-
if self.__data is None:
|
|
88
|
-
try:
|
|
89
|
-
self.__data = self.load()
|
|
90
|
-
except FileNotFoundError:
|
|
91
|
-
self.__data = self.build()
|
|
92
|
-
self.write()
|
|
93
|
-
|
|
94
|
-
return self.__data
|
|
95
|
-
|
|
96
|
-
@property
|
|
97
|
-
def TLDs(self) -> list:
|
|
98
|
-
""" Returns a list of TLDs (top-level domains) for validating against """
|
|
99
|
-
return self.contents['tlds']
|
|
100
|
-
|
|
101
|
-
@property
|
|
102
|
-
def created_timestamp(self) -> float:
|
|
103
|
-
"""
|
|
104
|
-
An alias for :attr:`created_ts`
|
|
105
|
-
|
|
106
|
-
Returns:
|
|
107
|
-
created_ts (float):
|
|
108
|
-
The time (in seconds since Epoch) when the cache was created.
|
|
109
|
-
|
|
110
|
-
"""
|
|
111
|
-
return self.created_ts
|
|
112
|
-
|
|
113
|
-
@property
|
|
114
|
-
def created_ts(self) -> float:
|
|
115
|
-
"""
|
|
116
|
-
The time (in seconds since Epoch) when the cache was created
|
|
117
|
-
"""
|
|
118
|
-
return self.contents['created_ts']
|
|
119
|
-
|
|
120
|
-
@property
|
|
121
|
-
def age_in_seconds(self) -> float:
|
|
122
|
-
"""
|
|
123
|
-
The number of seconds that have elapsed since creation of the cache.
|
|
124
|
-
"""
|
|
125
|
-
return time() - self.created_ts
|
|
126
|
-
|
|
127
|
-
@property
|
|
128
|
-
def age(self) -> str:
|
|
129
|
-
return precisedelta(self.age_in_seconds)
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
"""
|
|
133
|
-
File Change History:
|
|
134
|
-
|
|
135
|
-
11/5/22 - 4:24 AM (target: v2.1.2):
|
|
136
|
-
- Code cleanup
|
|
137
|
-
- Transform from class functions to static methods;
|
|
138
|
-
- `TLDCache.load`
|
|
139
|
-
- `TLDCache.fetch_from_source`
|
|
140
|
-
"""
|
|
@@ -1,287 +0,0 @@
|
|
|
1
|
-
import requests
|
|
2
|
-
import packaging
|
|
3
|
-
from packaging import version as pkg_version
|
|
4
|
-
|
|
5
|
-
RELEASE_MAP = {
|
|
6
|
-
'dev': 'Development Build',
|
|
7
|
-
'alpha': 'Alpha Build',
|
|
8
|
-
'beta': 'Beta Build',
|
|
9
|
-
'rc': 'Release Candidate Build',
|
|
10
|
-
'final': 'Final Release Build'
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
__VERSION__ = {
|
|
15
|
-
'major': 3,
|
|
16
|
-
'minor': 0,
|
|
17
|
-
'patch': 0,
|
|
18
|
-
'release': 'dev',
|
|
19
|
-
'release_num': 5
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def parse_version():
|
|
24
|
-
"""
|
|
25
|
-
Parses the version information into a string.
|
|
26
|
-
|
|
27
|
-
Returns:
|
|
28
|
-
str: The version information.
|
|
29
|
-
|
|
30
|
-
Since:
|
|
31
|
-
v1.0
|
|
32
|
-
"""
|
|
33
|
-
version = f'{__VERSION__["major"]}.{__VERSION__["minor"]}.{__VERSION__["patch"]}'
|
|
34
|
-
|
|
35
|
-
if __VERSION__['release'] != 'final':
|
|
36
|
-
version += f'-{__VERSION__["release"]}.{__VERSION__["release_num"]}'
|
|
37
|
-
|
|
38
|
-
return version
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
def get_full_version_name():
|
|
42
|
-
"""
|
|
43
|
-
Gets the full version name.
|
|
44
|
-
|
|
45
|
-
Returns:
|
|
46
|
-
str: The full version name.
|
|
47
|
-
|
|
48
|
-
Since:
|
|
49
|
-
v1.0
|
|
50
|
-
"""
|
|
51
|
-
ver = parse_version()
|
|
52
|
-
ver = ver.split('-')[0]
|
|
53
|
-
return f'v{ver} {RELEASE_MAP[__VERSION__["release"]]} ({__VERSION__["release_num"]})'
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
def get_pypi_info():
|
|
57
|
-
"""
|
|
58
|
-
Gets the latest version information from PyPI.
|
|
59
|
-
|
|
60
|
-
Returns:
|
|
61
|
-
dict: The latest version information.
|
|
62
|
-
|
|
63
|
-
Since:
|
|
64
|
-
v1.0
|
|
65
|
-
"""
|
|
66
|
-
url = 'https://pypi.org/pypi/inspy-logger/json'
|
|
67
|
-
resp = requests.get(url)
|
|
68
|
-
resp.raise_for_status()
|
|
69
|
-
resp = resp.json()
|
|
70
|
-
return resp
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
class PyPiVersionInfo:
|
|
74
|
-
"""
|
|
75
|
-
A class to represent the version information for this package from PyPi.
|
|
76
|
-
|
|
77
|
-
Attributes:
|
|
78
|
-
latest_stable (str):
|
|
79
|
-
The latest stable version of the package on PyPi.
|
|
80
|
-
|
|
81
|
-
latest_pre_release (str):
|
|
82
|
-
The latest pre-release version of the package.
|
|
83
|
-
Since:
|
|
84
|
-
v3.0
|
|
85
|
-
"""
|
|
86
|
-
__url = 'https://pypi.org/pypi/inspy-logger/json'
|
|
87
|
-
__queried = False
|
|
88
|
-
__installed = parse_version()
|
|
89
|
-
__include_pre_release_for_update_check = False
|
|
90
|
-
__new_version_available_num = None
|
|
91
|
-
__checked_for_update = False
|
|
92
|
-
__installed_newer_than_latest = None
|
|
93
|
-
|
|
94
|
-
def __init__(self, include_pre_release_for_update_check=__include_pre_release_for_update_check):
|
|
95
|
-
self.__latest_stable = None
|
|
96
|
-
self.__latest_pre_release = None
|
|
97
|
-
|
|
98
|
-
self.__all_versions = None
|
|
99
|
-
|
|
100
|
-
self.include_pre_release_for_update_check = include_pre_release_for_update_check
|
|
101
|
-
|
|
102
|
-
self.__query_versions()
|
|
103
|
-
|
|
104
|
-
@property
|
|
105
|
-
def all_versions(self):
|
|
106
|
-
return self.__all_versions
|
|
107
|
-
|
|
108
|
-
@property
|
|
109
|
-
def checked_for_update(self):
|
|
110
|
-
return self.__checked_for_update
|
|
111
|
-
|
|
112
|
-
@property
|
|
113
|
-
def include_pre_release_for_update_check(self):
|
|
114
|
-
"""
|
|
115
|
-
Gets whether pre-release versions should be included when checking for updates.
|
|
116
|
-
|
|
117
|
-
Returns:
|
|
118
|
-
bool:
|
|
119
|
-
True if pre-release versions should be included, False otherwise.
|
|
120
|
-
|
|
121
|
-
Since:
|
|
122
|
-
v3.0
|
|
123
|
-
|
|
124
|
-
"""
|
|
125
|
-
return self.__include_pre_release_for_update_check
|
|
126
|
-
|
|
127
|
-
@property
|
|
128
|
-
def installed_newer_than_latest(self):
|
|
129
|
-
return self.installed > self.latest_stable
|
|
130
|
-
|
|
131
|
-
@include_pre_release_for_update_check.setter
|
|
132
|
-
def include_pre_release_for_update_check(self, new):
|
|
133
|
-
if isinstance(new, bool):
|
|
134
|
-
self.__include_pre_release_for_update_check = new
|
|
135
|
-
else:
|
|
136
|
-
raise TypeError(f'Expected bool, received {type(new)}.')
|
|
137
|
-
|
|
138
|
-
@property
|
|
139
|
-
def installed(self):
|
|
140
|
-
"""
|
|
141
|
-
Gets the installed version of the package.
|
|
142
|
-
|
|
143
|
-
Returns:
|
|
144
|
-
packaging.version.Version:
|
|
145
|
-
The installed version of the package.
|
|
146
|
-
|
|
147
|
-
"""
|
|
148
|
-
return pkg_version.parse(self.__installed)
|
|
149
|
-
|
|
150
|
-
@property
|
|
151
|
-
def latest_stable(self):
|
|
152
|
-
"""
|
|
153
|
-
Gets the latest stable version of the package on PyPi.
|
|
154
|
-
|
|
155
|
-
Returns:
|
|
156
|
-
str: The latest stable version of the package on PyPi.
|
|
157
|
-
|
|
158
|
-
Since:
|
|
159
|
-
v3.0
|
|
160
|
-
"""
|
|
161
|
-
if self.__latest_stable is not None:
|
|
162
|
-
return pkg_version.parse(self.__latest_stable)
|
|
163
|
-
|
|
164
|
-
return self.__latest_stable
|
|
165
|
-
|
|
166
|
-
@property
|
|
167
|
-
def latest_pre_release(self):
|
|
168
|
-
"""
|
|
169
|
-
Gets the latest pre-release version of the package.
|
|
170
|
-
|
|
171
|
-
Returns:
|
|
172
|
-
str: The latest pre-release version of the package.
|
|
173
|
-
|
|
174
|
-
Since:
|
|
175
|
-
v3.0
|
|
176
|
-
"""
|
|
177
|
-
if self.all_versions is not None and self.__latest_pre_release is None:
|
|
178
|
-
most_recent = pkg_version.parse(self.all_versions[-1])
|
|
179
|
-
if most_recent.is_prerelease:
|
|
180
|
-
self.__latest_pre_release = most_recent
|
|
181
|
-
|
|
182
|
-
return self.__latest_pre_release
|
|
183
|
-
|
|
184
|
-
@property
|
|
185
|
-
def new_version_available_num(self):
|
|
186
|
-
"""
|
|
187
|
-
Gets the number of the latest version available on PyPi.
|
|
188
|
-
|
|
189
|
-
Returns:
|
|
190
|
-
int: The number of the latest version available on PyPi.
|
|
191
|
-
|
|
192
|
-
Since:
|
|
193
|
-
v3.0
|
|
194
|
-
"""
|
|
195
|
-
if not self.checked_for_update:
|
|
196
|
-
self.update_available
|
|
197
|
-
return self.__new_version_available_num
|
|
198
|
-
|
|
199
|
-
@property
|
|
200
|
-
def queried(self):
|
|
201
|
-
"""
|
|
202
|
-
Checks if the versions have been queried.
|
|
203
|
-
|
|
204
|
-
Returns:
|
|
205
|
-
bool: True if the versions have been queried, False otherwise.
|
|
206
|
-
|
|
207
|
-
Since:
|
|
208
|
-
v3.0
|
|
209
|
-
"""
|
|
210
|
-
return self.__queried
|
|
211
|
-
|
|
212
|
-
@property
|
|
213
|
-
def update_available(self):
|
|
214
|
-
"""
|
|
215
|
-
Checks if an update is available.
|
|
216
|
-
|
|
217
|
-
Returns:
|
|
218
|
-
bool: True if an update is available, False otherwise.
|
|
219
|
-
|
|
220
|
-
Since:
|
|
221
|
-
v3.0
|
|
222
|
-
"""
|
|
223
|
-
if not self.queried:
|
|
224
|
-
#print('Querying versions')
|
|
225
|
-
self.__query_versions()
|
|
226
|
-
|
|
227
|
-
if not self.checked_for_update:
|
|
228
|
-
#print('Checking for update')
|
|
229
|
-
self.__compare_latest()
|
|
230
|
-
self.__checked_for_update = True
|
|
231
|
-
|
|
232
|
-
if self.new_version_available_num is None and not self.queried:
|
|
233
|
-
#print('Getting latest')
|
|
234
|
-
self.__compare_latest()
|
|
235
|
-
|
|
236
|
-
return self.new_version_available_num is not None
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
def __query_versions(self):
|
|
242
|
-
"""
|
|
243
|
-
Queries the versions from PyPi.
|
|
244
|
-
|
|
245
|
-
Returns:
|
|
246
|
-
dict: The versions from PyPi.
|
|
247
|
-
|
|
248
|
-
Since:
|
|
249
|
-
v3.0
|
|
250
|
-
"""
|
|
251
|
-
if not self.queried:
|
|
252
|
-
resp = requests.get(self.__url)
|
|
253
|
-
resp.raise_for_status()
|
|
254
|
-
#print(resp.status_code)
|
|
255
|
-
resp = resp.json()
|
|
256
|
-
|
|
257
|
-
self.__all_versions = list(resp['releases'].keys())
|
|
258
|
-
#print(self.all_versions)
|
|
259
|
-
|
|
260
|
-
self.__latest_stable = resp['info']['version']
|
|
261
|
-
#print(self.latest_stable)
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
self.__queried = True
|
|
266
|
-
|
|
267
|
-
def __compare_latest(self):
|
|
268
|
-
latest = self.__get_latest()
|
|
269
|
-
|
|
270
|
-
if latest is not None and latest > self.installed:
|
|
271
|
-
self.__new_version_available_num = latest
|
|
272
|
-
|
|
273
|
-
def __get_latest(self):
|
|
274
|
-
if not self.queried:
|
|
275
|
-
#print('Querying versions')
|
|
276
|
-
self.__query_versions()
|
|
277
|
-
|
|
278
|
-
if self.include_pre_release_for_update_check:
|
|
279
|
-
latest = self.latest_pre_release
|
|
280
|
-
|
|
281
|
-
else:
|
|
282
|
-
latest = self.latest_stable
|
|
283
|
-
|
|
284
|
-
#print(f'Using latest {latest}')
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
return latest
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|