hud-python 0.4.1__py3-none-any.whl → 0.4.3__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.
Potentially problematic release.
This version of hud-python might be problematic. Click here for more details.
- hud/__init__.py +22 -22
- hud/agents/__init__.py +13 -15
- hud/agents/base.py +599 -599
- hud/agents/claude.py +373 -373
- hud/agents/langchain.py +261 -250
- hud/agents/misc/__init__.py +7 -7
- hud/agents/misc/response_agent.py +82 -80
- hud/agents/openai.py +352 -352
- hud/agents/openai_chat_generic.py +154 -154
- hud/agents/tests/__init__.py +1 -1
- hud/agents/tests/test_base.py +742 -742
- hud/agents/tests/test_claude.py +324 -324
- hud/agents/tests/test_client.py +363 -363
- hud/agents/tests/test_openai.py +237 -237
- hud/cli/__init__.py +617 -617
- hud/cli/__main__.py +8 -8
- hud/cli/analyze.py +371 -371
- hud/cli/analyze_metadata.py +230 -230
- hud/cli/build.py +498 -427
- hud/cli/clone.py +185 -185
- hud/cli/cursor.py +92 -92
- hud/cli/debug.py +392 -392
- hud/cli/docker_utils.py +83 -83
- hud/cli/init.py +280 -281
- hud/cli/interactive.py +353 -353
- hud/cli/mcp_server.py +764 -756
- hud/cli/pull.py +330 -336
- hud/cli/push.py +404 -370
- hud/cli/remote_runner.py +311 -311
- hud/cli/runner.py +160 -160
- hud/cli/tests/__init__.py +3 -3
- hud/cli/tests/test_analyze.py +284 -284
- hud/cli/tests/test_cli_init.py +265 -265
- hud/cli/tests/test_cli_main.py +27 -27
- hud/cli/tests/test_clone.py +142 -142
- hud/cli/tests/test_cursor.py +253 -253
- hud/cli/tests/test_debug.py +453 -453
- hud/cli/tests/test_mcp_server.py +139 -139
- hud/cli/tests/test_utils.py +388 -388
- hud/cli/utils.py +263 -263
- hud/clients/README.md +143 -143
- hud/clients/__init__.py +16 -16
- hud/clients/base.py +378 -379
- hud/clients/fastmcp.py +222 -222
- hud/clients/mcp_use.py +298 -278
- hud/clients/tests/__init__.py +1 -1
- hud/clients/tests/test_client_integration.py +111 -111
- hud/clients/tests/test_fastmcp.py +342 -342
- hud/clients/tests/test_protocol.py +188 -188
- hud/clients/utils/__init__.py +1 -1
- hud/clients/utils/retry_transport.py +160 -160
- hud/datasets.py +327 -322
- hud/misc/__init__.py +1 -1
- hud/misc/claude_plays_pokemon.py +292 -292
- hud/otel/__init__.py +35 -35
- hud/otel/collector.py +142 -142
- hud/otel/config.py +164 -164
- hud/otel/context.py +536 -536
- hud/otel/exporters.py +366 -366
- hud/otel/instrumentation.py +97 -97
- hud/otel/processors.py +118 -118
- hud/otel/tests/__init__.py +1 -1
- hud/otel/tests/test_processors.py +197 -197
- hud/server/__init__.py +5 -5
- hud/server/context.py +114 -114
- hud/server/helper/__init__.py +5 -5
- hud/server/low_level.py +132 -132
- hud/server/server.py +170 -166
- hud/server/tests/__init__.py +3 -3
- hud/settings.py +73 -73
- hud/shared/__init__.py +5 -5
- hud/shared/exceptions.py +180 -180
- hud/shared/requests.py +264 -264
- hud/shared/tests/test_exceptions.py +157 -157
- hud/shared/tests/test_requests.py +275 -275
- hud/telemetry/__init__.py +25 -25
- hud/telemetry/instrument.py +379 -379
- hud/telemetry/job.py +309 -309
- hud/telemetry/replay.py +74 -74
- hud/telemetry/trace.py +83 -83
- hud/tools/__init__.py +33 -33
- hud/tools/base.py +365 -365
- hud/tools/bash.py +161 -161
- hud/tools/computer/__init__.py +15 -15
- hud/tools/computer/anthropic.py +437 -437
- hud/tools/computer/hud.py +376 -376
- hud/tools/computer/openai.py +295 -295
- hud/tools/computer/settings.py +82 -82
- hud/tools/edit.py +314 -314
- hud/tools/executors/__init__.py +30 -30
- hud/tools/executors/base.py +539 -539
- hud/tools/executors/pyautogui.py +621 -621
- hud/tools/executors/tests/__init__.py +1 -1
- hud/tools/executors/tests/test_base_executor.py +338 -338
- hud/tools/executors/tests/test_pyautogui_executor.py +165 -165
- hud/tools/executors/xdo.py +511 -511
- hud/tools/playwright.py +412 -412
- hud/tools/tests/__init__.py +3 -3
- hud/tools/tests/test_base.py +282 -282
- hud/tools/tests/test_bash.py +158 -158
- hud/tools/tests/test_bash_extended.py +197 -197
- hud/tools/tests/test_computer.py +425 -425
- hud/tools/tests/test_computer_actions.py +34 -34
- hud/tools/tests/test_edit.py +259 -259
- hud/tools/tests/test_init.py +27 -27
- hud/tools/tests/test_playwright_tool.py +183 -183
- hud/tools/tests/test_tools.py +145 -145
- hud/tools/tests/test_utils.py +156 -156
- hud/tools/types.py +72 -72
- hud/tools/utils.py +50 -50
- hud/types.py +136 -136
- hud/utils/__init__.py +10 -10
- hud/utils/async_utils.py +65 -65
- hud/utils/design.py +236 -168
- hud/utils/mcp.py +55 -55
- hud/utils/progress.py +149 -149
- hud/utils/telemetry.py +66 -66
- hud/utils/tests/test_async_utils.py +173 -173
- hud/utils/tests/test_init.py +17 -17
- hud/utils/tests/test_progress.py +261 -261
- hud/utils/tests/test_telemetry.py +82 -82
- hud/utils/tests/test_version.py +8 -8
- hud/version.py +7 -7
- {hud_python-0.4.1.dist-info → hud_python-0.4.3.dist-info}/METADATA +10 -8
- hud_python-0.4.3.dist-info/RECORD +131 -0
- {hud_python-0.4.1.dist-info → hud_python-0.4.3.dist-info}/licenses/LICENSE +21 -21
- hud/agents/art.py +0 -101
- hud_python-0.4.1.dist-info/RECORD +0 -132
- {hud_python-0.4.1.dist-info → hud_python-0.4.3.dist-info}/WHEEL +0 -0
- {hud_python-0.4.1.dist-info → hud_python-0.4.3.dist-info}/entry_points.txt +0 -0
hud/cli/tests/test_clone.py
CHANGED
|
@@ -1,142 +1,142 @@
|
|
|
1
|
-
"""Tests for the clone command."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
import subprocess
|
|
6
|
-
from unittest.mock import MagicMock, mock_open, patch
|
|
7
|
-
|
|
8
|
-
from hud.cli.clone import clone_repository, get_clone_message
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def test_clone_repository_success():
|
|
12
|
-
"""Test successful repository cloning."""
|
|
13
|
-
with patch("subprocess.run") as mock_run:
|
|
14
|
-
mock_run.return_value = MagicMock(returncode=0, stdout="", stderr="")
|
|
15
|
-
|
|
16
|
-
success, result = clone_repository("https://github.com/user/repo.git")
|
|
17
|
-
|
|
18
|
-
assert success is True
|
|
19
|
-
assert "repo" in result
|
|
20
|
-
mock_run.assert_called_once()
|
|
21
|
-
|
|
22
|
-
# Check command includes quiet flag
|
|
23
|
-
cmd = mock_run.call_args[0][0]
|
|
24
|
-
assert "git" in cmd
|
|
25
|
-
assert "clone" in cmd
|
|
26
|
-
assert "--quiet" in cmd
|
|
27
|
-
assert "https://github.com/user/repo.git" in cmd
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def test_clone_repository_failure():
|
|
31
|
-
"""Test failed repository cloning."""
|
|
32
|
-
with patch("subprocess.run") as mock_run:
|
|
33
|
-
mock_run.side_effect = subprocess.CalledProcessError(
|
|
34
|
-
128, ["git", "clone"], stderr="fatal: repository not found"
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
success, result = clone_repository("https://github.com/user/nonexistent.git")
|
|
38
|
-
|
|
39
|
-
assert success is False
|
|
40
|
-
assert "repository not found" in result
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
def test_get_clone_message_from_pyproject():
|
|
44
|
-
"""Test reading clone message from pyproject.toml."""
|
|
45
|
-
toml_content = """
|
|
46
|
-
[tool.hud.clone]
|
|
47
|
-
title = "Test Project"
|
|
48
|
-
message = "Welcome to the test project!"
|
|
49
|
-
"""
|
|
50
|
-
|
|
51
|
-
with (
|
|
52
|
-
patch("pathlib.Path.exists") as mock_exists,
|
|
53
|
-
patch("builtins.open", mock_open(read_data=toml_content.encode())),
|
|
54
|
-
patch("tomllib.load") as mock_load,
|
|
55
|
-
):
|
|
56
|
-
mock_exists.return_value = True
|
|
57
|
-
mock_load.return_value = {
|
|
58
|
-
"tool": {
|
|
59
|
-
"hud": {
|
|
60
|
-
"clone": {"title": "Test Project", "message": "Welcome to the test project!"}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
config = get_clone_message("/path/to/repo")
|
|
66
|
-
|
|
67
|
-
assert config is not None
|
|
68
|
-
assert config["title"] == "Test Project"
|
|
69
|
-
assert config["message"] == "Welcome to the test project!"
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
def test_get_clone_message_from_hud_toml():
|
|
73
|
-
"""Test reading clone message from .hud.toml."""
|
|
74
|
-
toml_content = """
|
|
75
|
-
[clone]
|
|
76
|
-
title = "HUD Project"
|
|
77
|
-
markdown = "## Welcome!"
|
|
78
|
-
style = "cyan"
|
|
79
|
-
"""
|
|
80
|
-
|
|
81
|
-
with (
|
|
82
|
-
patch("pathlib.Path.exists") as mock_exists,
|
|
83
|
-
patch("builtins.open", mock_open(read_data=toml_content.encode())),
|
|
84
|
-
patch("tomllib.load") as mock_load,
|
|
85
|
-
):
|
|
86
|
-
# First call for pyproject.toml returns False
|
|
87
|
-
# Second call for .hud.toml returns True
|
|
88
|
-
mock_exists.side_effect = [False, True]
|
|
89
|
-
mock_load.return_value = {
|
|
90
|
-
"clone": {"title": "HUD Project", "markdown": "## Welcome!", "style": "cyan"}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
config = get_clone_message("/path/to/repo")
|
|
94
|
-
|
|
95
|
-
assert config is not None
|
|
96
|
-
assert config["title"] == "HUD Project"
|
|
97
|
-
assert config["markdown"] == "## Welcome!"
|
|
98
|
-
assert config["style"] == "cyan"
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
def test_get_clone_message_none():
|
|
102
|
-
"""Test when no clone message configuration exists."""
|
|
103
|
-
with patch("pathlib.Path.exists") as mock_exists:
|
|
104
|
-
mock_exists.return_value = False
|
|
105
|
-
|
|
106
|
-
config = get_clone_message("/path/to/repo")
|
|
107
|
-
|
|
108
|
-
assert config is None
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
# The following tests are commented out as print_success and print_error
|
|
112
|
-
# functions are no longer part of the clone module
|
|
113
|
-
|
|
114
|
-
# def test_print_success(capsys):
|
|
115
|
-
# """Test success message printing."""
|
|
116
|
-
# print_success("https://github.com/user/repo.git", "/home/user/repo")
|
|
117
|
-
|
|
118
|
-
# captured = capsys.readouterr()
|
|
119
|
-
# assert "Successfully cloned" in captured.out
|
|
120
|
-
# assert "repo" in captured.out
|
|
121
|
-
# assert "/home/user/repo" in captured.out
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
# def test_print_success_with_config(capsys):
|
|
125
|
-
# """Test success message with configuration."""
|
|
126
|
-
# config = {"title": "My Project", "message": "Thanks for cloning!"}
|
|
127
|
-
|
|
128
|
-
# print_success("https://github.com/user/repo.git", "/home/user/repo", config)
|
|
129
|
-
|
|
130
|
-
# captured = capsys.readouterr()
|
|
131
|
-
# assert "Successfully cloned" in captured.out
|
|
132
|
-
# assert "My Project" in captured.out
|
|
133
|
-
# assert "Thanks for cloning!" in captured.out
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
# def test_print_error(capsys):
|
|
137
|
-
# """Test error message printing."""
|
|
138
|
-
# print_error("Repository not found")
|
|
139
|
-
|
|
140
|
-
# captured = capsys.readouterr()
|
|
141
|
-
# assert "Repository not found" in captured.out
|
|
142
|
-
# assert "Clone Failed" in captured.out
|
|
1
|
+
"""Tests for the clone command."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import subprocess
|
|
6
|
+
from unittest.mock import MagicMock, mock_open, patch
|
|
7
|
+
|
|
8
|
+
from hud.cli.clone import clone_repository, get_clone_message
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def test_clone_repository_success():
|
|
12
|
+
"""Test successful repository cloning."""
|
|
13
|
+
with patch("subprocess.run") as mock_run:
|
|
14
|
+
mock_run.return_value = MagicMock(returncode=0, stdout="", stderr="")
|
|
15
|
+
|
|
16
|
+
success, result = clone_repository("https://github.com/user/repo.git")
|
|
17
|
+
|
|
18
|
+
assert success is True
|
|
19
|
+
assert "repo" in result
|
|
20
|
+
mock_run.assert_called_once()
|
|
21
|
+
|
|
22
|
+
# Check command includes quiet flag
|
|
23
|
+
cmd = mock_run.call_args[0][0]
|
|
24
|
+
assert "git" in cmd
|
|
25
|
+
assert "clone" in cmd
|
|
26
|
+
assert "--quiet" in cmd
|
|
27
|
+
assert "https://github.com/user/repo.git" in cmd
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def test_clone_repository_failure():
|
|
31
|
+
"""Test failed repository cloning."""
|
|
32
|
+
with patch("subprocess.run") as mock_run:
|
|
33
|
+
mock_run.side_effect = subprocess.CalledProcessError(
|
|
34
|
+
128, ["git", "clone"], stderr="fatal: repository not found"
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
success, result = clone_repository("https://github.com/user/nonexistent.git")
|
|
38
|
+
|
|
39
|
+
assert success is False
|
|
40
|
+
assert "repository not found" in result
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def test_get_clone_message_from_pyproject():
|
|
44
|
+
"""Test reading clone message from pyproject.toml."""
|
|
45
|
+
toml_content = """
|
|
46
|
+
[tool.hud.clone]
|
|
47
|
+
title = "Test Project"
|
|
48
|
+
message = "Welcome to the test project!"
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
with (
|
|
52
|
+
patch("pathlib.Path.exists") as mock_exists,
|
|
53
|
+
patch("builtins.open", mock_open(read_data=toml_content.encode())),
|
|
54
|
+
patch("tomllib.load") as mock_load,
|
|
55
|
+
):
|
|
56
|
+
mock_exists.return_value = True
|
|
57
|
+
mock_load.return_value = {
|
|
58
|
+
"tool": {
|
|
59
|
+
"hud": {
|
|
60
|
+
"clone": {"title": "Test Project", "message": "Welcome to the test project!"}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
config = get_clone_message("/path/to/repo")
|
|
66
|
+
|
|
67
|
+
assert config is not None
|
|
68
|
+
assert config["title"] == "Test Project"
|
|
69
|
+
assert config["message"] == "Welcome to the test project!"
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def test_get_clone_message_from_hud_toml():
|
|
73
|
+
"""Test reading clone message from .hud.toml."""
|
|
74
|
+
toml_content = """
|
|
75
|
+
[clone]
|
|
76
|
+
title = "HUD Project"
|
|
77
|
+
markdown = "## Welcome!"
|
|
78
|
+
style = "cyan"
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
with (
|
|
82
|
+
patch("pathlib.Path.exists") as mock_exists,
|
|
83
|
+
patch("builtins.open", mock_open(read_data=toml_content.encode())),
|
|
84
|
+
patch("tomllib.load") as mock_load,
|
|
85
|
+
):
|
|
86
|
+
# First call for pyproject.toml returns False
|
|
87
|
+
# Second call for .hud.toml returns True
|
|
88
|
+
mock_exists.side_effect = [False, True]
|
|
89
|
+
mock_load.return_value = {
|
|
90
|
+
"clone": {"title": "HUD Project", "markdown": "## Welcome!", "style": "cyan"}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
config = get_clone_message("/path/to/repo")
|
|
94
|
+
|
|
95
|
+
assert config is not None
|
|
96
|
+
assert config["title"] == "HUD Project"
|
|
97
|
+
assert config["markdown"] == "## Welcome!"
|
|
98
|
+
assert config["style"] == "cyan"
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def test_get_clone_message_none():
|
|
102
|
+
"""Test when no clone message configuration exists."""
|
|
103
|
+
with patch("pathlib.Path.exists") as mock_exists:
|
|
104
|
+
mock_exists.return_value = False
|
|
105
|
+
|
|
106
|
+
config = get_clone_message("/path/to/repo")
|
|
107
|
+
|
|
108
|
+
assert config is None
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
# The following tests are commented out as print_success and print_error
|
|
112
|
+
# functions are no longer part of the clone module
|
|
113
|
+
|
|
114
|
+
# def test_print_success(capsys):
|
|
115
|
+
# """Test success message printing."""
|
|
116
|
+
# print_success("https://github.com/user/repo.git", "/home/user/repo")
|
|
117
|
+
|
|
118
|
+
# captured = capsys.readouterr()
|
|
119
|
+
# assert "Successfully cloned" in captured.out
|
|
120
|
+
# assert "repo" in captured.out
|
|
121
|
+
# assert "/home/user/repo" in captured.out
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
# def test_print_success_with_config(capsys):
|
|
125
|
+
# """Test success message with configuration."""
|
|
126
|
+
# config = {"title": "My Project", "message": "Thanks for cloning!"}
|
|
127
|
+
|
|
128
|
+
# print_success("https://github.com/user/repo.git", "/home/user/repo", config)
|
|
129
|
+
|
|
130
|
+
# captured = capsys.readouterr()
|
|
131
|
+
# assert "Successfully cloned" in captured.out
|
|
132
|
+
# assert "My Project" in captured.out
|
|
133
|
+
# assert "Thanks for cloning!" in captured.out
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
# def test_print_error(capsys):
|
|
137
|
+
# """Test error message printing."""
|
|
138
|
+
# print_error("Repository not found")
|
|
139
|
+
|
|
140
|
+
# captured = capsys.readouterr()
|
|
141
|
+
# assert "Repository not found" in captured.out
|
|
142
|
+
# assert "Clone Failed" in captured.out
|