inspy-logger 3.0.1__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.
Files changed (21) hide show
  1. {inspy_logger-3.0.1 → inspy_logger-3.0.2.dev1}/PKG-INFO +1 -1
  2. inspy_logger-3.0.2.dev1/inspy_logger/Scripts/main.py +105 -0
  3. {inspy_logger-3.0.1 → inspy_logger-3.0.2.dev1}/inspy_logger/__about__.py +0 -2
  4. {inspy_logger-3.0.1 → inspy_logger-3.0.2.dev1}/inspy_logger/helpers/base_classes.py +10 -0
  5. inspy_logger-3.0.2.dev1/inspy_logger/helpers/debug/__init__.py +0 -0
  6. inspy_logger-3.0.2.dev1/inspy_logger/helpers/debug/environment.py +179 -0
  7. inspy_logger-3.0.2.dev1/inspy_logger/helpers/debug/system/__init__.py +0 -0
  8. inspy_logger-3.0.2.dev1/inspy_logger/helpers/debug/system/processor/__init__.py +64 -0
  9. inspy_logger-3.0.2.dev1/inspy_logger/helpers/debug/system/winx/__init__.py +25 -0
  10. inspy_logger-3.0.2.dev1/inspy_logger/helpers/units.py +57 -0
  11. inspy_logger-3.0.2.dev1/inspy_logger/version.py +240 -0
  12. {inspy_logger-3.0.1 → inspy_logger-3.0.2.dev1}/pyproject.toml +5 -1
  13. inspy_logger-3.0.1/inspy_logger/Scripts/main.py +0 -91
  14. inspy_logger-3.0.1/inspy_logger/version.py +0 -290
  15. {inspy_logger-3.0.1 → inspy_logger-3.0.2.dev1}/LICENSE.md +0 -0
  16. {inspy_logger-3.0.1 → inspy_logger-3.0.2.dev1}/README.md +0 -0
  17. {inspy_logger-3.0.1 → inspy_logger-3.0.2.dev1}/inspy_logger/__init__.py +0 -0
  18. {inspy_logger-3.0.1 → inspy_logger-3.0.2.dev1}/inspy_logger/errors/__init__.py +0 -0
  19. {inspy_logger-3.0.1 → inspy_logger-3.0.2.dev1}/inspy_logger/helpers/__init__.py +0 -0
  20. {inspy_logger-3.0.1 → inspy_logger-3.0.2.dev1}/inspy_logger/helpers/network.py +0 -0
  21. {inspy_logger-3.0.1 → inspy_logger-3.0.2.dev1}/inspy_logger/manifest.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: inspy-logger
3
- Version: 3.0.1
3
+ Version: 3.0.2.dev1
4
4
  Summary: Colorable, scalable logger for CLI
5
5
  Home-page: https://github.com/Inspyre-Softworks/inSPy-Logger
6
6
  License: MIT
@@ -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,5 +19,3 @@ __authors__ = [
19
19
  ('Inspyre-Softworks', 'https://inspyre.tech'),
20
20
  ('Taylor-Jayde Blackstone', '<t.blackstone@inspyre.tech')
21
21
  ]
22
-
23
- '
@@ -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:
@@ -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
@@ -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
+ }
@@ -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.1"
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,290 +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': 1,
18
- 'release': 'final',
19
- 'release_num': 0
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
-
54
- release_type = RELEASE_MAP[__VERSION__["release"]]
55
- release_num = __VERSION__["release_num"]
56
- release_str = f" {release_type} {'' if __VERSION__['release'].lower() == 'final' else f'({release_num})'}"
57
- return f'v{ver}{release_str}'
58
-
59
- def get_pypi_info():
60
- """
61
- Gets the latest version information from PyPI.
62
-
63
- Returns:
64
- dict: The latest version information.
65
-
66
- Since:
67
- v1.0
68
- """
69
- url = 'https://pypi.org/pypi/inspy-logger/json'
70
- resp = requests.get(url)
71
- resp.raise_for_status()
72
- resp = resp.json()
73
- return resp
74
-
75
-
76
- class PyPiVersionInfo:
77
- """
78
- A class to represent the version information for this package from PyPi.
79
-
80
- Attributes:
81
- latest_stable (str):
82
- The latest stable version of the package on PyPi.
83
-
84
- latest_pre_release (str):
85
- The latest pre-release version of the package.
86
- Since:
87
- v3.0
88
- """
89
- __url = 'https://pypi.org/pypi/inspy-logger/json'
90
- __queried = False
91
- __installed = parse_version()
92
- __include_pre_release_for_update_check = False
93
- __new_version_available_num = None
94
- __checked_for_update = False
95
- __installed_newer_than_latest = None
96
-
97
- def __init__(self, include_pre_release_for_update_check=__include_pre_release_for_update_check):
98
- self.__latest_stable = None
99
- self.__latest_pre_release = None
100
-
101
- self.__all_versions = None
102
-
103
- self.include_pre_release_for_update_check = include_pre_release_for_update_check
104
-
105
- self.__query_versions()
106
-
107
- @property
108
- def all_versions(self):
109
- return self.__all_versions
110
-
111
- @property
112
- def checked_for_update(self):
113
- return self.__checked_for_update
114
-
115
- @property
116
- def include_pre_release_for_update_check(self):
117
- """
118
- Gets whether pre-release versions should be included when checking for updates.
119
-
120
- Returns:
121
- bool:
122
- True if pre-release versions should be included, False otherwise.
123
-
124
- Since:
125
- v3.0
126
-
127
- """
128
- return self.__include_pre_release_for_update_check
129
-
130
- @property
131
- def installed_newer_than_latest(self):
132
- return self.installed > self.latest_stable
133
-
134
- @include_pre_release_for_update_check.setter
135
- def include_pre_release_for_update_check(self, new):
136
- if isinstance(new, bool):
137
- self.__include_pre_release_for_update_check = new
138
- else:
139
- raise TypeError(f'Expected bool, received {type(new)}.')
140
-
141
- @property
142
- def installed(self):
143
- """
144
- Gets the installed version of the package.
145
-
146
- Returns:
147
- packaging.version.Version:
148
- The installed version of the package.
149
-
150
- """
151
- return pkg_version.parse(self.__installed)
152
-
153
- @property
154
- def latest_stable(self):
155
- """
156
- Gets the latest stable version of the package on PyPi.
157
-
158
- Returns:
159
- str: The latest stable version of the package on PyPi.
160
-
161
- Since:
162
- v3.0
163
- """
164
- if self.__latest_stable is not None:
165
- return pkg_version.parse(self.__latest_stable)
166
-
167
- return self.__latest_stable
168
-
169
- @property
170
- def latest_pre_release(self):
171
- """
172
- Gets the latest pre-release version of the package.
173
-
174
- Returns:
175
- str: The latest pre-release version of the package.
176
-
177
- Since:
178
- v3.0
179
- """
180
- if self.all_versions is not None and self.__latest_pre_release is None:
181
- most_recent = pkg_version.parse(self.all_versions[-1])
182
- if most_recent.is_prerelease:
183
- self.__latest_pre_release = most_recent
184
-
185
- return self.__latest_pre_release
186
-
187
- @property
188
- def new_version_available_num(self):
189
- """
190
- Gets the number of the latest version available on PyPi.
191
-
192
- Returns:
193
- int: The number of the latest version available on PyPi.
194
-
195
- Since:
196
- v3.0
197
- """
198
- if not self.checked_for_update:
199
- self.update_available
200
- return self.__new_version_available_num
201
-
202
- @property
203
- def queried(self):
204
- """
205
- Checks if the versions have been queried.
206
-
207
- Returns:
208
- bool: True if the versions have been queried, False otherwise.
209
-
210
- Since:
211
- v3.0
212
- """
213
- return self.__queried
214
-
215
- @property
216
- def update_available(self):
217
- """
218
- Checks if an update is available.
219
-
220
- Returns:
221
- bool: True if an update is available, False otherwise.
222
-
223
- Since:
224
- v3.0
225
- """
226
- if not self.queried:
227
- #print('Querying versions')
228
- self.__query_versions()
229
-
230
- if not self.checked_for_update:
231
- #print('Checking for update')
232
- self.__compare_latest()
233
- self.__checked_for_update = True
234
-
235
- if self.new_version_available_num is None and not self.queried:
236
- #print('Getting latest')
237
- self.__compare_latest()
238
-
239
- return self.new_version_available_num is not None
240
-
241
-
242
-
243
-
244
- def __query_versions(self):
245
- """
246
- Queries the versions from PyPi.
247
-
248
- Returns:
249
- dict: The versions from PyPi.
250
-
251
- Since:
252
- v3.0
253
- """
254
- if not self.queried:
255
- resp = requests.get(self.__url)
256
- resp.raise_for_status()
257
- #print(resp.status_code)
258
- resp = resp.json()
259
-
260
- self.__all_versions = list(resp['releases'].keys())
261
- #print(self.all_versions)
262
-
263
- self.__latest_stable = resp['info']['version']
264
- #print(self.latest_stable)
265
-
266
-
267
-
268
- self.__queried = True
269
-
270
- def __compare_latest(self):
271
- latest = self.__get_latest()
272
-
273
- if latest is not None and latest > self.installed:
274
- self.__new_version_available_num = latest
275
-
276
- def __get_latest(self):
277
- if not self.queried:
278
- #print('Querying versions')
279
- self.__query_versions()
280
-
281
- if self.include_pre_release_for_update_check:
282
- latest = self.latest_pre_release
283
-
284
- else:
285
- latest = self.latest_stable
286
-
287
- #print(f'Using latest {latest}')
288
-
289
-
290
- return latest