MCP: Embedded server reliability and UX\n\n- Embed-first installer: copies embedded server, adds RepairPythonEnvironment() (deletes .venv, runs 'uv sync'); robust uv path discovery; macOS install path -> Application Support\n- UI: Server Status shows Installed(Embedded); Python missing warning with install link; Repair button tooltip; header Show Debug Logs; cleaned layout\n- Python: unpin .python-version; set requires-python >=3.10 in both pyprojects\n- Dev: improved package/dev path resolution
parent
06f271926b
commit
f24e124c15
|
|
@ -75,14 +75,11 @@ namespace UnityMcpBridge.Editor.Helpers
|
|||
}
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
||||
{
|
||||
string path = "/usr/local/bin";
|
||||
return !Directory.Exists(path) || !IsDirectoryWritable(path)
|
||||
? Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
|
||||
"Applications",
|
||||
RootFolder
|
||||
)
|
||||
: Path.Combine(path, RootFolder);
|
||||
// Use Application Support for a stable, user-writable location
|
||||
return Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
||||
"UnityMCP"
|
||||
);
|
||||
}
|
||||
throw new Exception("Unsupported operating system.");
|
||||
}
|
||||
|
|
@ -213,5 +210,189 @@ namespace UnityMcpBridge.Editor.Helpers
|
|||
CopyDirectoryRecursive(dirPath, destSubDir);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool RepairPythonEnvironment()
|
||||
{
|
||||
try
|
||||
{
|
||||
string serverSrc = GetServerPath();
|
||||
bool hasServer = File.Exists(Path.Combine(serverSrc, "server.py"));
|
||||
if (!hasServer)
|
||||
{
|
||||
// In dev mode or if not installed yet, try the embedded/dev source
|
||||
if (TryGetEmbeddedServerSource(out string embeddedSrc) && File.Exists(Path.Combine(embeddedSrc, "server.py")))
|
||||
{
|
||||
serverSrc = embeddedSrc;
|
||||
hasServer = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Attempt to install then retry
|
||||
EnsureServerInstalled();
|
||||
serverSrc = GetServerPath();
|
||||
hasServer = File.Exists(Path.Combine(serverSrc, "server.py"));
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasServer)
|
||||
{
|
||||
Debug.LogWarning("RepairPythonEnvironment: server.py not found; ensure server is installed first.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove stale venv and pinned version file if present
|
||||
string venvPath = Path.Combine(serverSrc, ".venv");
|
||||
if (Directory.Exists(venvPath))
|
||||
{
|
||||
try { Directory.Delete(venvPath, recursive: true); } catch (Exception ex) { Debug.LogWarning($"Failed to delete .venv: {ex.Message}"); }
|
||||
}
|
||||
string pyPin = Path.Combine(serverSrc, ".python-version");
|
||||
if (File.Exists(pyPin))
|
||||
{
|
||||
try { File.Delete(pyPin); } catch (Exception ex) { Debug.LogWarning($"Failed to delete .python-version: {ex.Message}"); }
|
||||
}
|
||||
|
||||
string uvPath = FindUvPath();
|
||||
if (uvPath == null)
|
||||
{
|
||||
Debug.LogError("UV not found. Please install uv (https://docs.astral.sh/uv/)." );
|
||||
return false;
|
||||
}
|
||||
|
||||
var psi = new System.Diagnostics.ProcessStartInfo
|
||||
{
|
||||
FileName = uvPath,
|
||||
Arguments = "sync",
|
||||
WorkingDirectory = serverSrc,
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
|
||||
using var p = System.Diagnostics.Process.Start(psi);
|
||||
string stdout = p.StandardOutput.ReadToEnd();
|
||||
string stderr = p.StandardError.ReadToEnd();
|
||||
p.WaitForExit(60000);
|
||||
|
||||
if (p.ExitCode != 0)
|
||||
{
|
||||
Debug.LogError($"uv sync failed: {stderr}\n{stdout}");
|
||||
return false;
|
||||
}
|
||||
|
||||
Debug.Log("Unity MCP: Python environment repaired successfully.");
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"RepairPythonEnvironment failed: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static string FindUvPath()
|
||||
{
|
||||
// Allow user override via EditorPrefs
|
||||
try
|
||||
{
|
||||
string overridePath = EditorPrefs.GetString("UnityMCP.UvPath", string.Empty);
|
||||
if (!string.IsNullOrEmpty(overridePath) && File.Exists(overridePath))
|
||||
{
|
||||
if (ValidateUvBinary(overridePath)) return overridePath;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
string home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) ?? string.Empty;
|
||||
string[] candidates =
|
||||
{
|
||||
"/opt/homebrew/bin/uv",
|
||||
"/usr/local/bin/uv",
|
||||
"/usr/bin/uv",
|
||||
"/opt/local/bin/uv",
|
||||
Path.Combine(home, ".local", "bin", "uv"),
|
||||
"/opt/homebrew/opt/uv/bin/uv",
|
||||
// Framework Python installs
|
||||
"/Library/Frameworks/Python.framework/Versions/3.13/bin/uv",
|
||||
"/Library/Frameworks/Python.framework/Versions/3.12/bin/uv",
|
||||
// Fallback to PATH resolution by name
|
||||
"uv"
|
||||
};
|
||||
foreach (string c in candidates)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (ValidateUvBinary(c)) return c;
|
||||
}
|
||||
catch { /* ignore */ }
|
||||
}
|
||||
|
||||
// Try which uv (explicit path)
|
||||
try
|
||||
{
|
||||
var whichPsi = new System.Diagnostics.ProcessStartInfo
|
||||
{
|
||||
FileName = "/usr/bin/which",
|
||||
Arguments = "uv",
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
using var wp = System.Diagnostics.Process.Start(whichPsi);
|
||||
string output = wp.StandardOutput.ReadToEnd().Trim();
|
||||
wp.WaitForExit(3000);
|
||||
if (wp.ExitCode == 0 && !string.IsNullOrEmpty(output) && File.Exists(output))
|
||||
{
|
||||
if (ValidateUvBinary(output)) return output;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
// Manual PATH scan
|
||||
try
|
||||
{
|
||||
string pathEnv = Environment.GetEnvironmentVariable("PATH") ?? string.Empty;
|
||||
string[] parts = pathEnv.Split(Path.PathSeparator);
|
||||
foreach (string part in parts)
|
||||
{
|
||||
try
|
||||
{
|
||||
string candidate = Path.Combine(part, "uv");
|
||||
if (File.Exists(candidate) && ValidateUvBinary(candidate)) return candidate;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static bool ValidateUvBinary(string uvPath)
|
||||
{
|
||||
try
|
||||
{
|
||||
var psi = new System.Diagnostics.ProcessStartInfo
|
||||
{
|
||||
FileName = uvPath,
|
||||
Arguments = "--version",
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
using var p = System.Diagnostics.Process.Start(psi);
|
||||
if (!p.WaitForExit(5000)) { try { p.Kill(); } catch { } return false; }
|
||||
if (p.ExitCode == 0)
|
||||
{
|
||||
string output = p.StandardOutput.ReadToEnd().Trim();
|
||||
return output.StartsWith("uv ");
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,9 +102,21 @@ namespace UnityMcpBridge.Editor.Windows
|
|||
|
||||
private void UpdatePythonServerInstallationStatus()
|
||||
{
|
||||
string serverPath = ServerInstaller.GetServerPath();
|
||||
try
|
||||
{
|
||||
string installedPath = ServerInstaller.GetServerPath();
|
||||
bool installedOk = !string.IsNullOrEmpty(installedPath) && File.Exists(Path.Combine(installedPath, "server.py"));
|
||||
if (installedOk)
|
||||
{
|
||||
pythonServerInstallationStatus = "Installed";
|
||||
pythonServerInstallationStatusColor = Color.green;
|
||||
return;
|
||||
}
|
||||
|
||||
if (File.Exists(Path.Combine(serverPath, "server.py")))
|
||||
// Fall back to embedded/dev source via our existing resolution logic
|
||||
string embeddedPath = FindPackagePythonDirectory();
|
||||
bool embeddedOk = !string.IsNullOrEmpty(embeddedPath) && File.Exists(Path.Combine(embeddedPath, "server.py"));
|
||||
if (embeddedOk)
|
||||
{
|
||||
pythonServerInstallationStatus = "Installed (Embedded)";
|
||||
pythonServerInstallationStatusColor = Color.green;
|
||||
|
|
@ -115,6 +127,12 @@ namespace UnityMcpBridge.Editor.Windows
|
|||
pythonServerInstallationStatusColor = Color.red;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
pythonServerInstallationStatus = "Not Installed";
|
||||
pythonServerInstallationStatusColor = Color.red;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void DrawStatusDot(Rect statusRect, Color statusColor, float size = 12)
|
||||
|
|
@ -215,6 +233,16 @@ namespace UnityMcpBridge.Editor.Windows
|
|||
"Unity MCP Editor",
|
||||
titleStyle
|
||||
);
|
||||
|
||||
// Place the Show Debug Logs toggle on the same header row, right-aligned
|
||||
float toggleWidth = 160f;
|
||||
Rect toggleRect = new Rect(titleRect.xMax - toggleWidth - 12f, titleRect.y + 10f, toggleWidth, 20f);
|
||||
bool newDebug = GUI.Toggle(toggleRect, debugLogsEnabled, "Show Debug Logs");
|
||||
if (newDebug != debugLogsEnabled)
|
||||
{
|
||||
debugLogsEnabled = newDebug;
|
||||
EditorPrefs.SetBool("UnityMCP.DebugLogs", debugLogsEnabled);
|
||||
}
|
||||
EditorGUILayout.Space(15);
|
||||
}
|
||||
|
||||
|
|
@ -243,7 +271,6 @@ namespace UnityMcpBridge.Editor.Windows
|
|||
|
||||
EditorGUILayout.Space(5);
|
||||
|
||||
// Connection mode
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
bool isAutoMode = UnityMcpBridge.IsAutoConnectMode();
|
||||
GUIStyle modeStyle = new GUIStyle(EditorStyles.miniLabel) { fontSize = 11 };
|
||||
|
|
@ -251,7 +278,6 @@ namespace UnityMcpBridge.Editor.Windows
|
|||
GUILayout.FlexibleSpace();
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
// Current ports display
|
||||
int currentUnityPort = UnityMcpBridge.GetCurrentPort();
|
||||
GUIStyle portStyle = new GUIStyle(EditorStyles.miniLabel)
|
||||
{
|
||||
|
|
@ -260,7 +286,7 @@ namespace UnityMcpBridge.Editor.Windows
|
|||
EditorGUILayout.LabelField($"Ports: Unity {currentUnityPort}, MCP {mcpPort}", portStyle);
|
||||
EditorGUILayout.Space(5);
|
||||
|
||||
// Auto-Setup button below ports
|
||||
/// Auto-Setup button below ports
|
||||
string setupButtonText = (lastClientRegisteredOk && lastBridgeVerifiedOk) ? "Connected ✓" : "Auto-Setup";
|
||||
if (GUILayout.Button(setupButtonText, GUILayout.Height(24)))
|
||||
{
|
||||
|
|
@ -268,20 +294,47 @@ namespace UnityMcpBridge.Editor.Windows
|
|||
}
|
||||
EditorGUILayout.Space(4);
|
||||
|
||||
// Debug logs toggle inside Server Status
|
||||
// Repair Python Env button with tooltip tag
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
GUILayout.FlexibleSpace();
|
||||
bool newDebug = EditorGUILayout.ToggleLeft("Show Debug Logs", debugLogsEnabled, GUILayout.Width(150));
|
||||
if (newDebug != debugLogsEnabled)
|
||||
GUIContent repairLabel = new GUIContent(
|
||||
"Repair Python Env",
|
||||
"Deletes the server's .venv and runs 'uv sync' to rebuild a clean environment. Use this if modules are missing or Python upgraded."
|
||||
);
|
||||
if (GUILayout.Button(repairLabel, GUILayout.Width(160), GUILayout.Height(22)))
|
||||
{
|
||||
debugLogsEnabled = newDebug;
|
||||
EditorPrefs.SetBool("UnityMCP.DebugLogs", debugLogsEnabled);
|
||||
bool ok = global::UnityMcpBridge.Editor.Helpers.ServerInstaller.RepairPythonEnvironment();
|
||||
if (ok)
|
||||
{
|
||||
EditorUtility.DisplayDialog("Unity MCP", "Python environment repaired.", "OK");
|
||||
UpdatePythonServerInstallationStatus();
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorUtility.DisplayDialog("Unity MCP", "Repair failed. Please check Console for details.", "OK");
|
||||
}
|
||||
}
|
||||
}
|
||||
// (Removed descriptive tool tag under the Repair button)
|
||||
|
||||
// (Show Debug Logs toggle moved to header)
|
||||
EditorGUILayout.Space(2);
|
||||
|
||||
// Removed redundant inline badges to streamline UI
|
||||
// Python detection warning with link
|
||||
if (!IsPythonDetected())
|
||||
{
|
||||
GUIStyle warnStyle = new GUIStyle(EditorStyles.label) { richText = true, wordWrap = true };
|
||||
EditorGUILayout.LabelField("<color=#cc3333><b>Warning:</b></color> No Python installation found.", warnStyle);
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
if (GUILayout.Button("Open install instructions", GUILayout.Width(200)))
|
||||
{
|
||||
Application.OpenURL("https://www.python.org/downloads/");
|
||||
}
|
||||
}
|
||||
EditorGUILayout.Space(4);
|
||||
}
|
||||
|
||||
// Troubleshooting helpers
|
||||
if (pythonServerInstallationStatusColor != Color.green)
|
||||
|
|
@ -369,16 +422,7 @@ namespace UnityMcpBridge.Editor.Windows
|
|||
string description = GetValidationLevelDescription(validationLevelIndex);
|
||||
EditorGUILayout.HelpBox(description, MessageType.Info);
|
||||
EditorGUILayout.Space(4);
|
||||
// Inline debug logs toggle under Script Validation
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.FlexibleSpace();
|
||||
bool newDebug = EditorGUILayout.ToggleLeft("Show Debug Logs", debugLogsEnabled, GUILayout.Width(150));
|
||||
if (newDebug != debugLogsEnabled)
|
||||
{
|
||||
debugLogsEnabled = newDebug;
|
||||
EditorPrefs.SetBool("UnityMCP.DebugLogs", debugLogsEnabled);
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
// (Show Debug Logs toggle moved to header)
|
||||
EditorGUILayout.Space(2);
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
|
@ -845,7 +889,10 @@ namespace UnityMcpBridge.Editor.Windows
|
|||
return "Configured successfully";
|
||||
}
|
||||
|
||||
private void ShowManualConfigurationInstructions(string configPath, McpClient mcpClient)
|
||||
private void ShowManualConfigurationInstructions(
|
||||
string configPath,
|
||||
McpClient mcpClient
|
||||
)
|
||||
{
|
||||
mcpClient.SetStatus(McpStatus.Error, "Manual configuration required");
|
||||
|
||||
|
|
@ -1938,5 +1985,45 @@ namespace UnityMcpBridge.Editor.Windows
|
|||
mcpClient.SetStatus(McpStatus.Error, e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsPythonDetected()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Common absolute paths
|
||||
string home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) ?? string.Empty;
|
||||
string[] candidates =
|
||||
{
|
||||
"/opt/homebrew/bin/python3",
|
||||
"/usr/local/bin/python3",
|
||||
"/usr/bin/python3",
|
||||
"/opt/local/bin/python3",
|
||||
Path.Combine(home, ".local", "bin", "python3"),
|
||||
"/Library/Frameworks/Python.framework/Versions/3.13/bin/python3",
|
||||
"/Library/Frameworks/Python.framework/Versions/3.12/bin/python3",
|
||||
};
|
||||
foreach (string c in candidates)
|
||||
{
|
||||
if (File.Exists(c)) return true;
|
||||
}
|
||||
|
||||
// Try 'which python3'
|
||||
var psi = new ProcessStartInfo
|
||||
{
|
||||
FileName = "/usr/bin/which",
|
||||
Arguments = "python3",
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
using var p = Process.Start(psi);
|
||||
string outp = p.StandardOutput.ReadToEnd().Trim();
|
||||
p.WaitForExit(2000);
|
||||
if (p.ExitCode == 0 && !string.IsNullOrEmpty(outp) && File.Exists(outp)) return true;
|
||||
}
|
||||
catch { }
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
3.12
|
||||
|
|
@ -3,7 +3,7 @@ name = "UnityMcpServer"
|
|||
version = "2.0.0"
|
||||
description = "Unity MCP Server: A Unity package for Unity Editor integration via the Model Context Protocol (MCP)."
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
requires-python = ">=3.10"
|
||||
dependencies = ["httpx>=0.27.2", "mcp[cli]>=1.4.1"]
|
||||
|
||||
[build-system]
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
3.12
|
||||
|
|
@ -3,7 +3,7 @@ name = "UnityMcpServer"
|
|||
version = "2.0.0"
|
||||
description = "Unity MCP Server: A Unity package for Unity Editor integration via the Model Context Protocol (MCP)."
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
requires-python = ">=3.10"
|
||||
dependencies = ["httpx>=0.27.2", "mcp[cli]>=1.4.1"]
|
||||
|
||||
[build-system]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
version = 1
|
||||
revision = 1
|
||||
requires-python = ">=3.12"
|
||||
requires-python = ">=3.10"
|
||||
|
||||
[[package]]
|
||||
name = "annotated-types"
|
||||
|
|
@ -16,6 +16,7 @@ name = "anyio"
|
|||
version = "4.9.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "exceptiongroup", marker = "python_full_version < '3.11'" },
|
||||
{ name = "idna" },
|
||||
{ name = "sniffio" },
|
||||
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
|
||||
|
|
@ -55,6 +56,18 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "exceptiongroup"
|
||||
version = "1.3.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/36/f4/c6e662dade71f56cd2f3735141b265c3c79293c109549c1e6933b0651ffc/exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10", size = 16674 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "h11"
|
||||
version = "0.14.0"
|
||||
|
|
@ -179,6 +192,33 @@ dependencies = [
|
|||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/fc/01/f3e5ac5e7c25833db5eb555f7b7ab24cd6f8c322d3a3ad2d67a952dc0abc/pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39", size = 413443 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/3a/bc/fed5f74b5d802cf9a03e83f60f18864e90e3aed7223adaca5ffb7a8d8d64/pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa", size = 1895938 },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/2a/185aff24ce844e39abb8dd680f4e959f0006944f4a8a0ea372d9f9ae2e53/pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c", size = 1815684 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c3/43/fafabd3d94d159d4f1ed62e383e264f146a17dd4d48453319fd782e7979e/pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a", size = 1829169 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a2/d1/f2dfe1a2a637ce6800b799aa086d079998959f6f1215eb4497966efd2274/pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5", size = 1867227 },
|
||||
{ url = "https://files.pythonhosted.org/packages/7d/39/e06fcbcc1c785daa3160ccf6c1c38fea31f5754b756e34b65f74e99780b5/pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c", size = 2037695 },
|
||||
{ url = "https://files.pythonhosted.org/packages/7a/67/61291ee98e07f0650eb756d44998214231f50751ba7e13f4f325d95249ab/pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7", size = 2741662 },
|
||||
{ url = "https://files.pythonhosted.org/packages/32/90/3b15e31b88ca39e9e626630b4c4a1f5a0dfd09076366f4219429e6786076/pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a", size = 1993370 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/83/c06d333ee3a67e2e13e07794995c1535565132940715931c1c43bfc85b11/pydantic_core-2.27.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236", size = 1996813 },
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/f7/89be1c8deb6e22618a74f0ca0d933fdcb8baa254753b26b25ad3acff8f74/pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962", size = 2005287 },
|
||||
{ url = "https://files.pythonhosted.org/packages/b7/7d/8eb3e23206c00ef7feee17b83a4ffa0a623eb1a9d382e56e4aa46fd15ff2/pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9", size = 2128414 },
|
||||
{ url = "https://files.pythonhosted.org/packages/4e/99/fe80f3ff8dd71a3ea15763878d464476e6cb0a2db95ff1c5c554133b6b83/pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af", size = 2155301 },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/a3/e50460b9a5789ca1451b70d4f52546fa9e2b420ba3bfa6100105c0559238/pydantic_core-2.27.2-cp310-cp310-win32.whl", hash = "sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4", size = 1816685 },
|
||||
{ url = "https://files.pythonhosted.org/packages/57/4c/a8838731cb0f2c2a39d3535376466de6049034d7b239c0202a64aaa05533/pydantic_core-2.27.2-cp310-cp310-win_amd64.whl", hash = "sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31", size = 1982876 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/89/f3450af9d09d44eea1f2c369f49e8f181d742f28220f88cc4dfaae91ea6e/pydantic_core-2.27.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc", size = 1893421 },
|
||||
{ url = "https://files.pythonhosted.org/packages/9e/e3/71fe85af2021f3f386da42d291412e5baf6ce7716bd7101ea49c810eda90/pydantic_core-2.27.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7", size = 1814998 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a6/3c/724039e0d848fd69dbf5806894e26479577316c6f0f112bacaf67aa889ac/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15", size = 1826167 },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/5b/1b29e8c1fb5f3199a9a57c1452004ff39f494bbe9bdbe9a81e18172e40d3/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306", size = 1865071 },
|
||||
{ url = "https://files.pythonhosted.org/packages/89/6c/3985203863d76bb7d7266e36970d7e3b6385148c18a68cc8915fd8c84d57/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99", size = 2036244 },
|
||||
{ url = "https://files.pythonhosted.org/packages/0e/41/f15316858a246b5d723f7d7f599f79e37493b2e84bfc789e58d88c209f8a/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459", size = 2737470 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a8/7c/b860618c25678bbd6d1d99dbdfdf0510ccb50790099b963ff78a124b754f/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048", size = 1992291 },
|
||||
{ url = "https://files.pythonhosted.org/packages/bf/73/42c3742a391eccbeab39f15213ecda3104ae8682ba3c0c28069fbcb8c10d/pydantic_core-2.27.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d", size = 1994613 },
|
||||
{ url = "https://files.pythonhosted.org/packages/94/7a/941e89096d1175d56f59340f3a8ebaf20762fef222c298ea96d36a6328c5/pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b", size = 2002355 },
|
||||
{ url = "https://files.pythonhosted.org/packages/6e/95/2359937a73d49e336a5a19848713555605d4d8d6940c3ec6c6c0ca4dcf25/pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474", size = 2126661 },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/4c/ca02b7bdb6012a1adef21a50625b14f43ed4d11f1fc237f9d7490aa5078c/pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6", size = 2153261 },
|
||||
{ url = "https://files.pythonhosted.org/packages/72/9d/a241db83f973049a1092a079272ffe2e3e82e98561ef6214ab53fe53b1c7/pydantic_core-2.27.2-cp311-cp311-win32.whl", hash = "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c", size = 1812361 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e8/ef/013f07248041b74abd48a385e2110aa3a9bbfef0fbd97d4e6d07d2f5b89a/pydantic_core-2.27.2-cp311-cp311-win_amd64.whl", hash = "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc", size = 1982484 },
|
||||
{ url = "https://files.pythonhosted.org/packages/10/1c/16b3a3e3398fd29dca77cea0a1d998d6bde3902fa2706985191e2313cc76/pydantic_core-2.27.2-cp311-cp311-win_arm64.whl", hash = "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4", size = 1867102 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d6/74/51c8a5482ca447871c93e142d9d4a92ead74de6c8dc5e66733e22c9bba89/pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0", size = 1893127 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d3/f3/c97e80721735868313c58b89d2de85fa80fe8dfeeed84dc51598b92a135e/pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef", size = 1811340 },
|
||||
{ url = "https://files.pythonhosted.org/packages/9e/91/840ec1375e686dbae1bd80a9e46c26a1e0083e1186abc610efa3d9a36180/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7", size = 1822900 },
|
||||
|
|
@ -207,6 +247,15 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/a4/99/bddde3ddde76c03b65dfd5a66ab436c4e58ffc42927d4ff1198ffbf96f5f/pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130", size = 1834387 },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/47/82b5e846e01b26ac6f1893d3c5f9f3a2eb6ba79be26eef0b759b4fe72946/pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee", size = 1990453 },
|
||||
{ url = "https://files.pythonhosted.org/packages/51/b2/b2b50d5ecf21acf870190ae5d093602d95f66c9c31f9d5de6062eb329ad1/pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b", size = 1885186 },
|
||||
{ url = "https://files.pythonhosted.org/packages/46/72/af70981a341500419e67d5cb45abe552a7c74b66326ac8877588488da1ac/pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e", size = 1891159 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ad/3d/c5913cccdef93e0a6a95c2d057d2c2cba347815c845cda79ddd3c0f5e17d/pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8", size = 1768331 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f6/f0/a3ae8fbee269e4934f14e2e0e00928f9346c5943174f2811193113e58252/pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3", size = 1822467 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d7/7a/7bbf241a04e9f9ea24cd5874354a83526d639b02674648af3f350554276c/pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f", size = 1979797 },
|
||||
{ url = "https://files.pythonhosted.org/packages/4f/5f/4784c6107731f89e0005a92ecb8a2efeafdb55eb992b8e9d0a2be5199335/pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133", size = 1987839 },
|
||||
{ url = "https://files.pythonhosted.org/packages/6d/a7/61246562b651dff00de86a5f01b6e4befb518df314c54dec187a78d81c84/pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc", size = 1998861 },
|
||||
{ url = "https://files.pythonhosted.org/packages/86/aa/837821ecf0c022bbb74ca132e117c358321e72e7f9702d1b6a03758545e2/pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50", size = 2116582 },
|
||||
{ url = "https://files.pythonhosted.org/packages/81/b0/5e74656e95623cbaa0a6278d16cf15e10a51f6002e3ec126541e95c29ea3/pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9", size = 2151985 },
|
||||
{ url = "https://files.pythonhosted.org/packages/63/37/3e32eeb2a451fddaa3898e2163746b0cffbbdbb4740d38372db0490d67f3/pydantic_core-2.27.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151", size = 2004715 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -247,6 +296,7 @@ source = { registry = "https://pypi.org/simple" }
|
|||
dependencies = [
|
||||
{ name = "markdown-it-py" },
|
||||
{ name = "pygments" },
|
||||
{ name = "typing-extensions", marker = "python_full_version < '3.11'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ab/3a/0316b28d0761c6734d6bc14e770d85506c986c85ffb239e688eeaab2c2bc/rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098", size = 223149 }
|
||||
wheels = [
|
||||
|
|
@ -342,6 +392,7 @@ source = { registry = "https://pypi.org/simple" }
|
|||
dependencies = [
|
||||
{ name = "click" },
|
||||
{ name = "h11" },
|
||||
{ name = "typing-extensions", marker = "python_full_version < '3.11'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/4b/4d/938bd85e5bf2edeec766267a5015ad969730bb91e31b44021dfe8b22df6c/uvicorn-0.34.0.tar.gz", hash = "sha256:404051050cd7e905de2c9a7e61790943440b3416f49cb409f965d9dcd0fa73e9", size = 76568 }
|
||||
wheels = [
|
||||
|
|
|
|||
Loading…
Reference in New Issue