mc5-api-client 1.0.16__py3-none-any.whl → 1.0.18__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mc5_api_client/__init__.py +297 -8
- mc5_api_client/account.py +352 -0
- mc5_api_client/account_quick.py +246 -0
- mc5_api_client/alerts.py +336 -0
- mc5_api_client/alerts_quick.py +210 -0
- mc5_api_client/client.py +898 -34
- mc5_api_client/debug.py +259 -0
- mc5_api_client/easy_mc5.py +682 -0
- mc5_api_client/federation.py +257 -0
- mc5_api_client/federation_quick.py +198 -0
- mc5_api_client/pc_storage_client.py +229 -0
- mc5_api_client/pc_storage_quick.py +234 -0
- mc5_api_client/platform.py +108 -0
- mc5_api_client/simple_client.py +563 -19
- mc5_api_client/squad_battle.py +439 -0
- mc5_api_client/squad_battle_quick.py +223 -0
- mc5_api_client/storage_admin.py +285 -0
- mc5_api_client/telemetry.py +344 -0
- mc5_api_client/transfer.py +348 -0
- mc5_api_client/transfer_quick.py +280 -0
- {mc5_api_client-1.0.16.dist-info → mc5_api_client-1.0.18.dist-info}/METADATA +730 -11
- mc5_api_client-1.0.18.dist-info/RECORD +32 -0
- mc5_api_client-1.0.16.dist-info/RECORD +0 -15
- {mc5_api_client-1.0.16.dist-info → mc5_api_client-1.0.18.dist-info}/WHEEL +0 -0
- {mc5_api_client-1.0.16.dist-info → mc5_api_client-1.0.18.dist-info}/entry_points.txt +0 -0
- {mc5_api_client-1.0.16.dist-info → mc5_api_client-1.0.18.dist-info}/licenses/LICENSE +0 -0
- {mc5_api_client-1.0.16.dist-info → mc5_api_client-1.0.18.dist-info}/top_level.txt +0 -0
mc5_api_client/debug.py
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# ────────────[ CHIZOBA ]────────────────────────────
|
|
3
|
+
# | Email : chizoba2026@hotmail.com
|
|
4
|
+
# | File : debug.py
|
|
5
|
+
# | License | MIT License © 2026 Chizoba
|
|
6
|
+
# | Brief | Enhanced debugging utilities for MC5 API Client
|
|
7
|
+
# ────────────────★─────────────────────────────────
|
|
8
|
+
|
|
9
|
+
import sys
|
|
10
|
+
import traceback
|
|
11
|
+
import json
|
|
12
|
+
from typing import Optional, Dict, Any, Callable
|
|
13
|
+
from datetime import datetime
|
|
14
|
+
from .telemetry import is_telemetry_enabled, report_error
|
|
15
|
+
|
|
16
|
+
class DebugContext:
|
|
17
|
+
"""Context manager for debugging function calls."""
|
|
18
|
+
|
|
19
|
+
def __init__(self, function_name: str, **kwargs):
|
|
20
|
+
self.function_name = function_name
|
|
21
|
+
self.kwargs = kwargs
|
|
22
|
+
self.start_time = None
|
|
23
|
+
|
|
24
|
+
def __enter__(self):
|
|
25
|
+
self.start_time = datetime.now()
|
|
26
|
+
# if is_telemetry_enabled():
|
|
27
|
+
# print(f"🔍 Debug: Starting {self.function_name}")
|
|
28
|
+
# if self.kwargs:
|
|
29
|
+
# print(f"🔍 Debug: Parameters: {json.dumps(self.kwargs, indent=2)}")
|
|
30
|
+
return self
|
|
31
|
+
|
|
32
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
33
|
+
duration = (datetime.now() - self.start_time).total_seconds()
|
|
34
|
+
|
|
35
|
+
if exc_type is None:
|
|
36
|
+
# if is_telemetry_enabled():
|
|
37
|
+
# print(f"✅ Debug: {self.function_name} completed successfully ({duration:.2f}s)")
|
|
38
|
+
pass
|
|
39
|
+
else:
|
|
40
|
+
# if is_telemetry_enabled():
|
|
41
|
+
# print(f"❌ Debug: {self.function_name} failed after {duration:.2f}s")
|
|
42
|
+
# print(f"❌ Debug: Error: {exc_type.__name__}: {exc_val}")
|
|
43
|
+
# print(f"❌ Debug: Traceback:\n{traceback.format_exc()}")
|
|
44
|
+
|
|
45
|
+
# Report the error
|
|
46
|
+
report_error(exc_val, self.function_name, {
|
|
47
|
+
"duration": duration,
|
|
48
|
+
"parameters": self.kwargs
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
def debug_function(func: Callable) -> Callable:
|
|
52
|
+
"""
|
|
53
|
+
Decorator to add debugging to any function.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
func: Function to debug
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
Wrapped function with debugging
|
|
60
|
+
"""
|
|
61
|
+
def wrapper(*args, **kwargs):
|
|
62
|
+
function_name = f"{func.__module__}.{func.__name__}"
|
|
63
|
+
|
|
64
|
+
# Sanitize arguments for JSON serialization
|
|
65
|
+
safe_args = []
|
|
66
|
+
for arg in args:
|
|
67
|
+
if hasattr(arg, '__dict__'):
|
|
68
|
+
safe_args.append(f"<{type(arg).__name__} object>")
|
|
69
|
+
else:
|
|
70
|
+
safe_args.append(str(arg))
|
|
71
|
+
|
|
72
|
+
safe_kwargs = {}
|
|
73
|
+
for key, value in kwargs.items():
|
|
74
|
+
if hasattr(value, '__dict__'):
|
|
75
|
+
safe_kwargs[key] = f"<{type(value).__name__} object>"
|
|
76
|
+
else:
|
|
77
|
+
safe_kwargs[key] = str(value)
|
|
78
|
+
|
|
79
|
+
with DebugContext(function_name, args=safe_args, kwargs=safe_kwargs):
|
|
80
|
+
try:
|
|
81
|
+
result = func(*args, **kwargs)
|
|
82
|
+
return result
|
|
83
|
+
except Exception as e:
|
|
84
|
+
# Re-raise the exception after reporting
|
|
85
|
+
raise
|
|
86
|
+
|
|
87
|
+
return wrapper
|
|
88
|
+
|
|
89
|
+
def debug_print(message: str, level: str = "info") -> None:
|
|
90
|
+
"""
|
|
91
|
+
Print debug message with timestamp and level.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
message: Message to print
|
|
95
|
+
level: Debug level (info, warning, error, success)
|
|
96
|
+
"""
|
|
97
|
+
timestamp = datetime.now().strftime("%H:%M:%S")
|
|
98
|
+
|
|
99
|
+
icons = {
|
|
100
|
+
"info": "🔍",
|
|
101
|
+
"warning": "⚠️",
|
|
102
|
+
"error": "❌",
|
|
103
|
+
"success": "✅",
|
|
104
|
+
"request": "📤",
|
|
105
|
+
"response": "📥"
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
icon = icons.get(level, "🔍")
|
|
109
|
+
print(f"[{timestamp}] {icon} {message}")
|
|
110
|
+
|
|
111
|
+
def debug_request(method: str, url: str, data: Optional[Dict[str, Any]] = None) -> None:
|
|
112
|
+
"""
|
|
113
|
+
Debug HTTP request information.
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
method: HTTP method
|
|
117
|
+
url: Request URL
|
|
118
|
+
data: Request data
|
|
119
|
+
"""
|
|
120
|
+
debug_print(f"{method} {url}", "request")
|
|
121
|
+
if data:
|
|
122
|
+
debug_print(f"Data: {json.dumps(data, indent=2)}", "info")
|
|
123
|
+
|
|
124
|
+
def debug_response(status_code: int, data: Optional[Dict[str, Any]] = None) -> None:
|
|
125
|
+
"""
|
|
126
|
+
Debug HTTP response information.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
status_code: HTTP status code
|
|
130
|
+
data: Response data
|
|
131
|
+
"""
|
|
132
|
+
if 200 <= status_code < 300:
|
|
133
|
+
debug_print(f"Response {status_code}: Success", "success")
|
|
134
|
+
else:
|
|
135
|
+
debug_print(f"Response {status_code}: Error", "error")
|
|
136
|
+
|
|
137
|
+
if data:
|
|
138
|
+
# Truncate large responses for readability
|
|
139
|
+
data_str = json.dumps(data, indent=2)
|
|
140
|
+
if len(data_str) > 500:
|
|
141
|
+
data_str = data_str[:500] + "...\n[Response truncated]"
|
|
142
|
+
debug_print(f"Response data: {data_str}", "response")
|
|
143
|
+
|
|
144
|
+
def analyze_error(error: Exception) -> Dict[str, Any]:
|
|
145
|
+
"""
|
|
146
|
+
Analyze an error and provide debugging information.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
error: Exception to analyze
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
Dictionary with error analysis
|
|
153
|
+
"""
|
|
154
|
+
error_type = type(error).__name__
|
|
155
|
+
error_message = str(error)
|
|
156
|
+
traceback_str = traceback.format_exc()
|
|
157
|
+
|
|
158
|
+
analysis = {
|
|
159
|
+
"error_type": error_type,
|
|
160
|
+
"error_message": error_message,
|
|
161
|
+
"traceback": traceback_str,
|
|
162
|
+
"suggestions": []
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
# Provide specific suggestions based on error type
|
|
166
|
+
if "AuthenticationError" in error_type or "401" in error_message:
|
|
167
|
+
analysis["suggestions"].extend([
|
|
168
|
+
"Check your username and password",
|
|
169
|
+
"Verify your account is not banned",
|
|
170
|
+
"Try re-authenticating with a fresh token"
|
|
171
|
+
])
|
|
172
|
+
|
|
173
|
+
elif "RateLimitError" in error_type or "429" in error_message:
|
|
174
|
+
analysis["suggestions"].extend([
|
|
175
|
+
"Wait before making more requests",
|
|
176
|
+
"Implement exponential backoff",
|
|
177
|
+
"Check rate limit headers for retry time"
|
|
178
|
+
])
|
|
179
|
+
|
|
180
|
+
elif "NetworkError" in error_type or "timeout" in error_message.lower():
|
|
181
|
+
analysis["suggestions"].extend([
|
|
182
|
+
"Check your internet connection",
|
|
183
|
+
"Try increasing timeout value",
|
|
184
|
+
"Verify MC5 servers are accessible"
|
|
185
|
+
])
|
|
186
|
+
|
|
187
|
+
elif "TokenExpiredError" in error_type:
|
|
188
|
+
analysis["suggestions"].extend([
|
|
189
|
+
"Enable auto_refresh in client",
|
|
190
|
+
"Call authenticate() again",
|
|
191
|
+
"Check token expiration time"
|
|
192
|
+
])
|
|
193
|
+
|
|
194
|
+
return analysis
|
|
195
|
+
|
|
196
|
+
def print_error_analysis(error: Exception) -> None:
|
|
197
|
+
"""
|
|
198
|
+
Print detailed error analysis with suggestions.
|
|
199
|
+
|
|
200
|
+
Args:
|
|
201
|
+
error: Exception to analyze
|
|
202
|
+
"""
|
|
203
|
+
analysis = analyze_error(error)
|
|
204
|
+
|
|
205
|
+
debug_print(f"Error Analysis: {analysis['error_type']}", "error")
|
|
206
|
+
debug_print(f"Message: {analysis['error_message']}", "error")
|
|
207
|
+
|
|
208
|
+
if analysis["suggestions"]:
|
|
209
|
+
debug_print("Suggestions:", "warning")
|
|
210
|
+
for i, suggestion in enumerate(analysis["suggestions"], 1):
|
|
211
|
+
debug_print(f" {i}. {suggestion}", "warning")
|
|
212
|
+
|
|
213
|
+
def create_debug_report() -> Dict[str, Any]:
|
|
214
|
+
"""
|
|
215
|
+
Create a comprehensive debug report.
|
|
216
|
+
|
|
217
|
+
Returns:
|
|
218
|
+
Debug report dictionary
|
|
219
|
+
"""
|
|
220
|
+
import platform
|
|
221
|
+
import sys
|
|
222
|
+
|
|
223
|
+
report = {
|
|
224
|
+
"timestamp": datetime.now().isoformat(),
|
|
225
|
+
"python_version": sys.version,
|
|
226
|
+
"platform": platform.platform(),
|
|
227
|
+
"architecture": platform.architecture(),
|
|
228
|
+
"system": platform.system(),
|
|
229
|
+
"mc5_client_version": "1.0.16",
|
|
230
|
+
"telemetry_enabled": is_telemetry_enabled()
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return report
|
|
234
|
+
|
|
235
|
+
def print_debug_report() -> None:
|
|
236
|
+
"""Print a comprehensive debug report."""
|
|
237
|
+
report = create_debug_report()
|
|
238
|
+
|
|
239
|
+
debug_print("MC5 API Client Debug Report", "info")
|
|
240
|
+
debug_print("=" * 40, "info")
|
|
241
|
+
|
|
242
|
+
for key, value in report.items():
|
|
243
|
+
debug_print(f"{key}: {value}", "info")
|
|
244
|
+
|
|
245
|
+
# Convenience function for quick debugging
|
|
246
|
+
def debug_mode(enable: bool = False) -> None:
|
|
247
|
+
"""
|
|
248
|
+
Enable or disable debug mode.
|
|
249
|
+
|
|
250
|
+
Args:
|
|
251
|
+
enable: Whether to enable debug mode (default: False)
|
|
252
|
+
"""
|
|
253
|
+
if enable:
|
|
254
|
+
telemetry(True)
|
|
255
|
+
print_debug_report()
|
|
256
|
+
print("✅ Debug mode enabled")
|
|
257
|
+
else:
|
|
258
|
+
telemetry(False)
|
|
259
|
+
print("🔇 Debug mode disabled")
|