ephys-link 2.0.0b1__tar.gz → 2.0.0b2__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.
- {ephys_link-2.0.0b1 → ephys_link-2.0.0b2}/PKG-INFO +2 -1
- {ephys_link-2.0.0b1 → ephys_link-2.0.0b2}/pyproject.toml +5 -1
- ephys_link-2.0.0b2/qodana.yaml +29 -0
- ephys_link-2.0.0b2/scripts/logger_test.py +17 -0
- ephys_link-2.0.0b2/src/ephys_link/__about__.py +1 -0
- {ephys_link-2.0.0b1 → ephys_link-2.0.0b2}/src/ephys_link/back_end/platform_handler.py +3 -3
- {ephys_link-2.0.0b1 → ephys_link-2.0.0b2}/src/ephys_link/back_end/server.py +6 -4
- {ephys_link-2.0.0b1 → ephys_link-2.0.0b2}/src/ephys_link/bindings/ump_4_bindings.py +0 -2
- {ephys_link-2.0.0b1 → ephys_link-2.0.0b2}/src/ephys_link/util/common.py +2 -3
- ephys_link-2.0.0b2/src/ephys_link/util/console.py +133 -0
- ephys_link-2.0.0b1/src/ephys_link/__about__.py +0 -1
- ephys_link-2.0.0b1/src/ephys_link/util/console.py +0 -112
- {ephys_link-2.0.0b1 → ephys_link-2.0.0b2}/.gitignore +0 -0
- {ephys_link-2.0.0b1 → ephys_link-2.0.0b2}/LICENSE +0 -0
- {ephys_link-2.0.0b1 → ephys_link-2.0.0b2}/README.md +0 -0
- {ephys_link-2.0.0b1 → ephys_link-2.0.0b2}/assets/icon.ico +0 -0
- {ephys_link-2.0.0b1 → ephys_link-2.0.0b2}/ephys_link.spec +0 -0
- {ephys_link-2.0.0b1 → ephys_link-2.0.0b2}/scripts/__init__.py +0 -0
- {ephys_link-2.0.0b1 → ephys_link-2.0.0b2}/scripts/move_tester.py +0 -0
- {ephys_link-2.0.0b1 → ephys_link-2.0.0b2}/scripts/server_tester.py +0 -0
- {ephys_link-2.0.0b1 → ephys_link-2.0.0b2}/src/ephys_link/__init__.py +0 -0
- {ephys_link-2.0.0b1 → ephys_link-2.0.0b2}/src/ephys_link/__main__.py +0 -0
- {ephys_link-2.0.0b1 → ephys_link-2.0.0b2}/src/ephys_link/back_end/__init__.py +0 -0
- {ephys_link-2.0.0b1 → ephys_link-2.0.0b2}/src/ephys_link/bindings/__init__.py +0 -0
- {ephys_link-2.0.0b1 → ephys_link-2.0.0b2}/src/ephys_link/bindings/fake_bindings.py +0 -0
- {ephys_link-2.0.0b1 → ephys_link-2.0.0b2}/src/ephys_link/front_end/__init__.py +0 -0
- {ephys_link-2.0.0b1 → ephys_link-2.0.0b2}/src/ephys_link/front_end/cli.py +0 -0
- {ephys_link-2.0.0b1 → ephys_link-2.0.0b2}/src/ephys_link/front_end/gui.py +0 -0
- {ephys_link-2.0.0b1 → ephys_link-2.0.0b2}/src/ephys_link/resources/CP210xManufacturing.dll +0 -0
- {ephys_link-2.0.0b1 → ephys_link-2.0.0b2}/src/ephys_link/resources/NstMotorCtrl.dll +0 -0
- {ephys_link-2.0.0b1 → ephys_link-2.0.0b2}/src/ephys_link/resources/SiUSBXp.dll +0 -0
- {ephys_link-2.0.0b1 → ephys_link-2.0.0b2}/src/ephys_link/resources/libum.dll +0 -0
- {ephys_link-2.0.0b1 → ephys_link-2.0.0b2}/src/ephys_link/util/__init__.py +0 -0
- {ephys_link-2.0.0b1 → ephys_link-2.0.0b2}/src/ephys_link/util/base_bindings.py +0 -0
- {ephys_link-2.0.0b1 → ephys_link-2.0.0b2}/tests/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: ephys-link
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.0b2
|
|
4
4
|
Summary: A Python Socket.IO server that allows any Socket.IO-compliant application to communicate with manipulators used in electrophysiology experiments.
|
|
5
5
|
Project-URL: Documentation, https://virtualbrainlab.org/ephys_link/installation_and_use.html
|
|
6
6
|
Project-URL: Issues, https://github.com/VirtualBrainLab/ephys-link/issues
|
|
@@ -33,6 +33,7 @@ Requires-Dist: pyserial==3.5
|
|
|
33
33
|
Requires-Dist: python-socketio[asyncio-client]==5.11.3
|
|
34
34
|
Requires-Dist: pythonnet==3.0.3
|
|
35
35
|
Requires-Dist: requests==2.32.3
|
|
36
|
+
Requires-Dist: rich==13.7.1
|
|
36
37
|
Requires-Dist: sensapex==1.400.1
|
|
37
38
|
Requires-Dist: vbl-aquarium==0.0.19
|
|
38
39
|
Description-Content-Type: text/markdown
|
|
@@ -38,6 +38,7 @@ dependencies = [
|
|
|
38
38
|
"pythonnet==3.0.3",
|
|
39
39
|
"requests==2.32.3",
|
|
40
40
|
"sensapex==1.400.1",
|
|
41
|
+
"rich==13.7.1",
|
|
41
42
|
"vbl-aquarium==0.0.19"
|
|
42
43
|
]
|
|
43
44
|
|
|
@@ -114,4 +115,7 @@ exclude_lines = [
|
|
|
114
115
|
"no cov",
|
|
115
116
|
"if __name__ == .__main__.:",
|
|
116
117
|
"if TYPE_CHECKING:",
|
|
117
|
-
]
|
|
118
|
+
]
|
|
119
|
+
|
|
120
|
+
[tool.ruff.lint]
|
|
121
|
+
extend-ignore = ["DTZ005"]
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#-------------------------------------------------------------------------------#
|
|
2
|
+
# Qodana analysis is configured by qodana.yaml file #
|
|
3
|
+
# https://www.jetbrains.com/help/qodana/qodana-yaml.html #
|
|
4
|
+
#-------------------------------------------------------------------------------#
|
|
5
|
+
version: "1.0"
|
|
6
|
+
|
|
7
|
+
#Specify inspection profile for code analysis
|
|
8
|
+
profile:
|
|
9
|
+
name: qodana.starter
|
|
10
|
+
|
|
11
|
+
#Enable inspections
|
|
12
|
+
#include:
|
|
13
|
+
# - name: <SomeEnabledInspectionId>
|
|
14
|
+
|
|
15
|
+
#Disable inspections
|
|
16
|
+
#exclude:
|
|
17
|
+
# - name: <SomeDisabledInspectionId>
|
|
18
|
+
# paths:
|
|
19
|
+
# - <path/where/not/run/inspection>
|
|
20
|
+
|
|
21
|
+
#Execute shell command before Qodana execution (Applied in CI/CD pipeline)
|
|
22
|
+
#bootstrap: sh ./prepare-qodana.sh
|
|
23
|
+
|
|
24
|
+
#Install IDE plugins before Qodana execution (Applied in CI/CD pipeline)
|
|
25
|
+
#plugins:
|
|
26
|
+
# - id: <plugin.id> #(plugin id can be found at https://plugins.jetbrains.com)
|
|
27
|
+
|
|
28
|
+
#Specify Qodana linter for analysis (Applied in CI/CD pipeline)
|
|
29
|
+
linter: jetbrains/qodana-python:latest
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
from rich.logging import RichHandler
|
|
4
|
+
|
|
5
|
+
logging.basicConfig(level="NOTSET", format="%(message)s", datefmt="[%X]", handlers=[RichHandler(rich_tracebacks=True)])
|
|
6
|
+
|
|
7
|
+
log = logging.getLogger("rich")
|
|
8
|
+
log.debug("This message should go to the log file")
|
|
9
|
+
log.info("So should this")
|
|
10
|
+
log.warning("And this, too")
|
|
11
|
+
log.error("And non-ASCII stuff, too, like Øresund and Malmö")
|
|
12
|
+
log.error("[bold red blink]Server is shutting down!", extra={"markup": True})
|
|
13
|
+
log.critical("Critical error! [b red]Server is shutting down!", extra={"markup": True})
|
|
14
|
+
try:
|
|
15
|
+
print(1 / 0)
|
|
16
|
+
except Exception:
|
|
17
|
+
log.exception("[b magenta]unable print![/] [i magenta]asdf", extra={"markup": True})
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.0.0b2"
|
|
@@ -71,7 +71,7 @@ class PlatformHandler:
|
|
|
71
71
|
return FakeBindings()
|
|
72
72
|
case _:
|
|
73
73
|
error_message = f'Platform type "{platform_type}" not recognized.'
|
|
74
|
-
self._console.
|
|
74
|
+
self._console.critical_print(error_message)
|
|
75
75
|
raise ValueError(error_message)
|
|
76
76
|
|
|
77
77
|
# Ephys Link metadata.
|
|
@@ -185,7 +185,7 @@ class PlatformHandler:
|
|
|
185
185
|
# Disallow setting manipulator position while inside the brain.
|
|
186
186
|
if request.manipulator_id in self._inside_brain:
|
|
187
187
|
error_message = 'Can not move manipulator while inside the brain. Set the depth ("set_depth") instead.'
|
|
188
|
-
self._console.error_print(error_message)
|
|
188
|
+
self._console.error_print("Set Position", error_message)
|
|
189
189
|
return PositionalResponse(error=error_message)
|
|
190
190
|
|
|
191
191
|
# Move to the new position.
|
|
@@ -209,7 +209,7 @@ class PlatformHandler:
|
|
|
209
209
|
f" position on axis {list(Vector4.model_fields.keys())[index]}."
|
|
210
210
|
f"Requested: {request.position}, got: {final_unified_position}."
|
|
211
211
|
)
|
|
212
|
-
self._console.error_print(error_message)
|
|
212
|
+
self._console.error_print("Set Position", error_message)
|
|
213
213
|
return PositionalResponse(error=error_message)
|
|
214
214
|
except Exception as e:
|
|
215
215
|
self._console.exception_error_print("Set Position", e)
|
|
@@ -75,7 +75,7 @@ class Server:
|
|
|
75
75
|
# Helper functions.
|
|
76
76
|
def _malformed_request_response(self, request: str, data: tuple[tuple[Any], ...]) -> str:
|
|
77
77
|
"""Return a response for a malformed request."""
|
|
78
|
-
self._console.
|
|
78
|
+
self._console.error_print("MALFORMED REQUEST", f"{request}: {data}")
|
|
79
79
|
return dumps({"error": "Malformed request."})
|
|
80
80
|
|
|
81
81
|
async def _run_if_data_available(
|
|
@@ -127,7 +127,9 @@ class Server:
|
|
|
127
127
|
self._console.info_print("CONNECTION GRANTED", sid)
|
|
128
128
|
return True
|
|
129
129
|
|
|
130
|
-
self._console.error_print(
|
|
130
|
+
self._console.error_print(
|
|
131
|
+
"CONNECTION REFUSED", f"Cannot connect {sid} as {self._client_sid} is already connected."
|
|
132
|
+
)
|
|
131
133
|
return False
|
|
132
134
|
|
|
133
135
|
async def disconnect(self, sid: str) -> None:
|
|
@@ -142,7 +144,7 @@ class Server:
|
|
|
142
144
|
if self._client_sid == sid:
|
|
143
145
|
self._client_sid = ""
|
|
144
146
|
else:
|
|
145
|
-
self._console.error_print(f"Client {sid} disconnected without being connected.")
|
|
147
|
+
self._console.error_print("DISCONNECTION", f"Client {sid} disconnected without being connected.")
|
|
146
148
|
|
|
147
149
|
# noinspection PyTypeChecker
|
|
148
150
|
async def platform_event_handler(self, event: str, *args: tuple[Any]) -> str:
|
|
@@ -196,5 +198,5 @@ class Server:
|
|
|
196
198
|
case "stop_all":
|
|
197
199
|
return await self._platform_handler.stop_all()
|
|
198
200
|
case _:
|
|
199
|
-
self._console.error_print(f"Unknown event: {event}.")
|
|
201
|
+
self._console.error_print("EVENT", f"Unknown event: {event}.")
|
|
200
202
|
return dumps({"error": "Unknown event."})
|
|
@@ -10,7 +10,6 @@ from vbl_aquarium.models.unity import Vector3, Vector4
|
|
|
10
10
|
|
|
11
11
|
from ephys_link.util.base_bindings import BaseBindings
|
|
12
12
|
from ephys_link.util.common import RESOURCES_PATH, array_to_vector4, mm_to_um, mmps_to_umps, um_to_mm, vector4_to_array
|
|
13
|
-
from ephys_link.util.console import Console
|
|
14
13
|
|
|
15
14
|
|
|
16
15
|
class Ump4Bindings(BaseBindings):
|
|
@@ -24,7 +23,6 @@ class Ump4Bindings(BaseBindings):
|
|
|
24
23
|
self._ump = UMP.get_ump()
|
|
25
24
|
if self._ump is None:
|
|
26
25
|
error_message = "Unable to connect to uMp"
|
|
27
|
-
Console.error_print(error_message)
|
|
28
26
|
raise ValueError(error_message)
|
|
29
27
|
|
|
30
28
|
async def get_manipulators(self) -> list[str]:
|
|
@@ -9,7 +9,6 @@ from requests import get
|
|
|
9
9
|
from vbl_aquarium.models.unity import Vector4
|
|
10
10
|
|
|
11
11
|
from ephys_link.__about__ import __version__
|
|
12
|
-
from ephys_link.util.console import Console
|
|
13
12
|
|
|
14
13
|
# Ephys Link ASCII.
|
|
15
14
|
ASCII = r"""
|
|
@@ -47,8 +46,8 @@ def check_for_updates() -> None:
|
|
|
47
46
|
response = get("https://api.github.com/repos/VirtualBrainLab/ephys-link/tags", timeout=10)
|
|
48
47
|
latest_version = response.json()[0]["name"]
|
|
49
48
|
if parse(latest_version) > parse(__version__):
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
print(f"Update available: {latest_version} !")
|
|
50
|
+
print("Download at: https://github.com/VirtualBrainLab/ephys-link/releases/latest")
|
|
52
51
|
|
|
53
52
|
|
|
54
53
|
# Unit conversions
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# ruff: noqa: T201
|
|
2
|
+
"""Console class for printing messages to the console.
|
|
3
|
+
|
|
4
|
+
Configure the console to print error and debug messages.
|
|
5
|
+
|
|
6
|
+
Usage: Create a Console object and call the appropriate method to print messages.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from logging import DEBUG, ERROR, INFO, basicConfig, getLogger
|
|
10
|
+
|
|
11
|
+
from rich.logging import RichHandler
|
|
12
|
+
from rich.traceback import install
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Console:
|
|
16
|
+
def __init__(self, *, enable_debug: bool) -> None:
|
|
17
|
+
"""Initialize console properties.
|
|
18
|
+
|
|
19
|
+
:param enable_debug: Enable debug mode.
|
|
20
|
+
:type enable_debug: bool
|
|
21
|
+
"""
|
|
22
|
+
# Repeat message fields.
|
|
23
|
+
self._last_message = (0, "", "")
|
|
24
|
+
self._repeat_counter = 0
|
|
25
|
+
|
|
26
|
+
# Config logger.
|
|
27
|
+
basicConfig(
|
|
28
|
+
level=DEBUG if enable_debug else INFO,
|
|
29
|
+
format="%(message)s",
|
|
30
|
+
datefmt="[%I:%M:%S %p]",
|
|
31
|
+
handlers=[RichHandler(rich_tracebacks=True)],
|
|
32
|
+
)
|
|
33
|
+
self._log = getLogger("rich")
|
|
34
|
+
|
|
35
|
+
# Install Rich traceback.
|
|
36
|
+
install()
|
|
37
|
+
|
|
38
|
+
def debug_print(self, label: str, msg: str) -> None:
|
|
39
|
+
"""Print a debug message to the console.
|
|
40
|
+
|
|
41
|
+
:param label: Label for the debug message.
|
|
42
|
+
:type label: str
|
|
43
|
+
:param msg: Debug message to print.
|
|
44
|
+
:type msg: str
|
|
45
|
+
"""
|
|
46
|
+
self._repeatable_log(DEBUG, f"[b green]{label}", f"[green]{msg}")
|
|
47
|
+
|
|
48
|
+
def info_print(self, label: str, msg: str) -> None:
|
|
49
|
+
"""Print info to console.
|
|
50
|
+
|
|
51
|
+
:param label: Label for the message.
|
|
52
|
+
:type label: str
|
|
53
|
+
:param msg: Message to print.
|
|
54
|
+
:type msg: str
|
|
55
|
+
"""
|
|
56
|
+
self._repeatable_log(INFO, f"[b blue]{label}", msg)
|
|
57
|
+
|
|
58
|
+
def error_print(self, label: str, msg: str) -> None:
|
|
59
|
+
"""Print an error message to the console.
|
|
60
|
+
|
|
61
|
+
:param label: Label for the error message.
|
|
62
|
+
:type label: str
|
|
63
|
+
:param msg: Error message to print.
|
|
64
|
+
:type msg: str
|
|
65
|
+
"""
|
|
66
|
+
self._repeatable_log(ERROR, f"[b red]{label}", f"[red]{msg}")
|
|
67
|
+
|
|
68
|
+
def critical_print(self, msg: str) -> None:
|
|
69
|
+
"""Print a critical message to the console.
|
|
70
|
+
|
|
71
|
+
:param msg: Critical message to print.
|
|
72
|
+
:type msg: str
|
|
73
|
+
"""
|
|
74
|
+
self._log.critical(f"[b i red]{msg}", extra={"markup": True})
|
|
75
|
+
|
|
76
|
+
@staticmethod
|
|
77
|
+
def pretty_exception(exception: Exception) -> str:
|
|
78
|
+
"""Pretty print an exception.
|
|
79
|
+
|
|
80
|
+
:param exception: Exception to pretty print.
|
|
81
|
+
:type exception: Exception
|
|
82
|
+
:return: Pretty printed exception.
|
|
83
|
+
:rtype: str
|
|
84
|
+
"""
|
|
85
|
+
return f"{type(exception).__name__}: {exception}"
|
|
86
|
+
|
|
87
|
+
def exception_error_print(self, label: str, exception: Exception) -> None:
|
|
88
|
+
"""Print an error message with exception details to the console.
|
|
89
|
+
|
|
90
|
+
:param label: Label for the error message.
|
|
91
|
+
:type label: str
|
|
92
|
+
:param exception: Exception to print.
|
|
93
|
+
:type exception: Exception
|
|
94
|
+
"""
|
|
95
|
+
self._log.exception(
|
|
96
|
+
f"[b magenta]{label}:[/] [magenta]{Console.pretty_exception(exception)}", extra={"markup": True}
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
# Helper methods.
|
|
100
|
+
def _repeatable_log(self, log_type: int, label: str, message: str) -> None:
|
|
101
|
+
"""Add a row to the output table.
|
|
102
|
+
|
|
103
|
+
:param log_type: Type of log.
|
|
104
|
+
:type log_type: int
|
|
105
|
+
:param label: Label for the message.
|
|
106
|
+
:type label: str
|
|
107
|
+
:param message: Message.
|
|
108
|
+
:type message: str
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
# Compute if this is a repeated message.
|
|
112
|
+
message_set = (log_type, label, message)
|
|
113
|
+
if message_set == self._last_message:
|
|
114
|
+
# Handle repeat.
|
|
115
|
+
self._repeat_counter += 1
|
|
116
|
+
|
|
117
|
+
# Add an ellipsis row for first repeat.
|
|
118
|
+
if self._repeat_counter == 1:
|
|
119
|
+
self._log.log(log_type, "...")
|
|
120
|
+
else:
|
|
121
|
+
# Handle novel message.
|
|
122
|
+
if self._repeat_counter > 0:
|
|
123
|
+
# Complete previous repeat.
|
|
124
|
+
self._log.log(
|
|
125
|
+
self._last_message[0],
|
|
126
|
+
f"{self._last_message[1]}:[/] {self._last_message[2]}[/] x {self._repeat_counter}",
|
|
127
|
+
extra={"markup": True},
|
|
128
|
+
)
|
|
129
|
+
self._repeat_counter = 0
|
|
130
|
+
|
|
131
|
+
# Log new message.
|
|
132
|
+
self._log.log(log_type, f"{label}:[/] {message}", extra={"markup": True})
|
|
133
|
+
self._last_message = message_set
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "2.0.0b1"
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
# ruff: noqa: T201
|
|
2
|
-
"""Console class for printing messages to the console.
|
|
3
|
-
|
|
4
|
-
Configure the console to print error and debug messages.
|
|
5
|
-
|
|
6
|
-
Usage: Create a Console object and call the appropriate method to print messages.
|
|
7
|
-
"""
|
|
8
|
-
|
|
9
|
-
from traceback import print_exc
|
|
10
|
-
|
|
11
|
-
from colorama import Back, Fore, Style, init
|
|
12
|
-
|
|
13
|
-
# Constants.
|
|
14
|
-
TAB_BLOCK = "\t\t"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
class Console:
|
|
18
|
-
def __init__(self, *, enable_debug: bool) -> None:
|
|
19
|
-
"""Initialize console properties.
|
|
20
|
-
|
|
21
|
-
:param enable_debug: Enable debug mode.
|
|
22
|
-
:type enable_debug: bool
|
|
23
|
-
"""
|
|
24
|
-
self._enable_debug = enable_debug
|
|
25
|
-
|
|
26
|
-
# Repeat message fields.
|
|
27
|
-
self._last_message = ""
|
|
28
|
-
self._repeat_counter = 1
|
|
29
|
-
|
|
30
|
-
# Initialize colorama.
|
|
31
|
-
init(autoreset=True)
|
|
32
|
-
|
|
33
|
-
@staticmethod
|
|
34
|
-
def error_print(msg: str) -> None:
|
|
35
|
-
"""Print an error message to the console.
|
|
36
|
-
|
|
37
|
-
:param msg: Error message to print.
|
|
38
|
-
:type msg: str
|
|
39
|
-
"""
|
|
40
|
-
print(f"\n{Back.RED}{Style.BRIGHT} ERROR {Style.RESET_ALL}{TAB_BLOCK}{Fore.RED}{msg}")
|
|
41
|
-
|
|
42
|
-
@staticmethod
|
|
43
|
-
def labeled_error_print(label: str, msg: str) -> None:
|
|
44
|
-
"""Print an error message with a label to the console.
|
|
45
|
-
|
|
46
|
-
:param label: Label for the error message.
|
|
47
|
-
:type label: str
|
|
48
|
-
:param msg: Error message to print.
|
|
49
|
-
:type msg: str
|
|
50
|
-
"""
|
|
51
|
-
print(f"\n{Back.RED}{Style.BRIGHT} ERROR {label} {Style.RESET_ALL}{TAB_BLOCK}{Fore.RED}{msg}")
|
|
52
|
-
|
|
53
|
-
@staticmethod
|
|
54
|
-
def pretty_exception(exception: Exception) -> str:
|
|
55
|
-
"""Pretty print an exception.
|
|
56
|
-
|
|
57
|
-
:param exception: Exception to pretty print.
|
|
58
|
-
:type exception: Exception
|
|
59
|
-
:return: Pretty printed exception.
|
|
60
|
-
:rtype: str
|
|
61
|
-
"""
|
|
62
|
-
return f"{type(exception).__name__}: {exception}"
|
|
63
|
-
|
|
64
|
-
@staticmethod
|
|
65
|
-
def exception_error_print(label: str, exception: Exception) -> None:
|
|
66
|
-
"""Print an error message with exception details to the console.
|
|
67
|
-
|
|
68
|
-
:param label: Label for the error message.
|
|
69
|
-
:type label: str
|
|
70
|
-
:param exception: Exception to print.
|
|
71
|
-
:type exception: Exception
|
|
72
|
-
"""
|
|
73
|
-
Console.labeled_error_print(label, Console.pretty_exception(exception))
|
|
74
|
-
print_exc()
|
|
75
|
-
|
|
76
|
-
def debug_print(self, label: str, msg: str) -> None:
|
|
77
|
-
"""Print a debug message to the console.
|
|
78
|
-
|
|
79
|
-
:param label: Label for the debug message.
|
|
80
|
-
:type label: str
|
|
81
|
-
:param msg: Debug message to print.
|
|
82
|
-
:type msg: str
|
|
83
|
-
"""
|
|
84
|
-
if self._enable_debug:
|
|
85
|
-
self._repeat_print(f"{Back.BLUE}{Style.BRIGHT} DEBUG {label} {Style.RESET_ALL}{TAB_BLOCK}{Fore.BLUE}{msg}")
|
|
86
|
-
|
|
87
|
-
@staticmethod
|
|
88
|
-
def info_print(label: str, msg: str) -> None:
|
|
89
|
-
"""Print info to console.
|
|
90
|
-
|
|
91
|
-
:param label: Label for the message.
|
|
92
|
-
:type label: str
|
|
93
|
-
:param msg: Message to print.
|
|
94
|
-
:type msg: str
|
|
95
|
-
"""
|
|
96
|
-
print(f"\n{Back.GREEN}{Style.BRIGHT} {label} {Style.RESET_ALL}{TAB_BLOCK}{Fore.GREEN}{msg}")
|
|
97
|
-
|
|
98
|
-
# Helper methods.
|
|
99
|
-
def _repeat_print(self, msg: str) -> None:
|
|
100
|
-
"""Print a message to the console with repeat counter.
|
|
101
|
-
|
|
102
|
-
:param msg: Message to print.
|
|
103
|
-
:type msg: str
|
|
104
|
-
"""
|
|
105
|
-
if msg == self._last_message:
|
|
106
|
-
self._repeat_counter += 1
|
|
107
|
-
else:
|
|
108
|
-
self._repeat_counter = 1
|
|
109
|
-
self._last_message = msg
|
|
110
|
-
print()
|
|
111
|
-
|
|
112
|
-
print(f"\r{msg}{f" (x{self._repeat_counter})" if self._repeat_counter > 1 else ""}", end="")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|