Skip to content

Commit d71238e

Browse files
committed
B12: normalise traceback paths; make tests pass on Windows
1 parent 67fb403 commit d71238e

8 files changed

Lines changed: 19 additions & 10 deletions

File tree

‎.github/workflows/windows-tests.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,4 @@ jobs:
3232
- name: pyflakes
3333
run: python -m pyflakes medha
3434
- name: pytest (offline)
35-
run: python -m pytest -q
35+
run: python -m pytest -q -rs

‎docs/MEDHA-v2-PLAN.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Release rule: fix and push all month, publish to the Store **once** at the end (
2626
| B9 | High | Closing an edited tab discarded unsaved work without confirmation. | `app.py` close_tab/closeEvent | Save/Discard/Cancel guard, including cancelled Save As. |
2727
| B10 | Medium | `ProjectExplorerWidget.__init__` doesn't call `load_workspace()`, so workspace projects aren't loaded and fallback logic creates a project with the workspace directory name. | `medha/project_manager.py` line 192 | Add `self.workspace_manager.load_workspace(workspace_path)` in `__init__`. |
2828
| B11 | **High** | Windows terminal never used ConPTY: code imported `pywinpty` (real module is `winpty`), wrong `spawn` args, blocking `read()` on the GUI thread, `send_control` doesn't exist; pywinpty not in build deps. Fallback never set `_shell_started` (commands stuck) and its Ctrl+C killed the shell. | `medha/terminal.py`, `requirements.txt`, spec | Fixed: `winpty` import, reader thread, `sendintr()`, fallback sets started + Ctrl+C terminates only shell children (psutil); `windows-tests.yml` runs the real-ConPTY test on windows-latest. |
29+
| B12 | Low | Python traceback line was wrong on Windows: frame-path filter compared paths without abspath/normcase on both sides. | `medha/runner.py` parse_python_traceback | Fixed: normalise both sides. Tests made path-portable for the Windows CI job. |
2930
More bugs come from Track B (section 3) — append them to this table with the same columns.
3031

3132
## 2. Track A — New UI like VS Code / Antigravity (ChatGPT)

‎medha/runner.py‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,12 @@ def parse_diagnostics(self, text):
161161

162162
def parse_python_traceback(self, text):
163163
"""Last frame inside the user's own files + the exception line → one diagnostic."""
164+
# Keep only frames from the user's own folder. Both sides go through
165+
# abspath+normcase, so Windows drive letters, "\\" vs "/" and letter case
166+
# can't make a user frame look foreign (was B12: wrong line on Windows).
167+
mine = os.path.normcase(os.path.dirname(os.path.abspath(self.active_file)))
164168
frames = [(f, int(l)) for f, l in PY_FRAME_RE.findall(text)
165-
if not f.startswith("<") and os.path.abspath(f).startswith(os.path.dirname(self.active_file))]
169+
if not f.startswith("<") and os.path.normcase(os.path.abspath(f)).startswith(mine)]
166170
errs = PY_ERROR_RE.findall(text)
167171
if not errs:
168172
return

‎tests/test_debugger.py‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
- Clean termination
1212
"""
1313

14+
import os
1415
import json
1516
import socket
1617
import time
@@ -318,7 +319,7 @@ def test_set_breakpoint_debugpy_sends_setBreakpoints(self):
318319
session.send_dap_request.assert_called_once()
319320
args = session.send_dap_request.call_args[0]
320321
assert args[0] == "setBreakpoints"
321-
assert args[1]["source"]["path"] == "/tmp/test.py"
322+
assert args[1]["source"]["path"] == os.path.abspath("/tmp/test.py")
322323
assert args[1]["breakpoints"][0]["line"] == 42
323324

324325
def test_set_breakpoint_debugpy_fails_on_unverified(self):
@@ -416,7 +417,7 @@ class TestDebugSessionCommon:
416417
def test_init_sets_attributes(self):
417418
"""DebugSession.__init__ sets target path and kind."""
418419
session = DebugSession("/tmp/test", kind="gdb")
419-
assert session.target == "/tmp/test"
420+
assert session.target == os.path.abspath("/tmp/test")
420421
assert session.kind == "gdb"
421422
assert session.proc is None
422423
assert session.sock is None

‎tests/test_release_metadata.py‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@ def test_package_versions_agree():
1414
assert identity.attrib['Version'] == __version__ + '.0'
1515
appstream = ET.parse(ROOT / 'packaging/io.github.Kanak234.Medha.metainfo.xml')
1616
assert appstream.find('releases/release').attrib['version'] == __version__
17-
assert f'**Prepared version:** {__version__}' in (ROOT / 'store/listing.md').read_text()
18-
snap = (ROOT / 'snap/snapcraft.yaml').read_text()
17+
assert f'**Prepared version:** {__version__}' in (ROOT / 'store/listing.md').read_text(encoding='utf-8')
18+
snap = (ROOT / 'snap/snapcraft.yaml').read_text(encoding='utf-8')
1919
assert 'adopt-info: medha-app' in snap
2020
assert 'craftctl set version="$VERSION"' in snap
2121
# Snap derives its version from the same app constant instead of a second literal.
2222

2323

2424
def test_partner_center_copy_is_short_and_does_not_claim_pending_terminal():
25-
listing = (ROOT / 'store/listing.md').read_text()
25+
listing = (ROOT / 'store/listing.md').read_text(encoding='utf-8')
2626
copy = listing.split('<!-- WHATS_NEW_START -->')[1].split('<!-- WHATS_NEW_END -->')[0].strip()
2727
assert 0 < len(copy) < 1500
2828
assert all(line.startswith('- ') for line in copy.splitlines())

‎tests/test_terminal_pty.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ def test_ctrl_c_stops_command_not_shell(self, qapp):
218218
# ---------------------------------------------------------------------------
219219

220220
class TestCreatePtyBackend:
221+
@pytest.mark.skipif(sys.platform == "win32", reason="the pty module needs termios (POSIX only)")
221222
@patch("medha.terminal.P")
222223
def test_unix_chooses_unix_pty(self, mock_P, qapp):
223224
"""On Linux/macOS, factory returns _UnixPtyProcess."""

‎tests/test_toolchains.py‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,12 @@ def test_bundled_before_path(self, mock_probe, mock_bundled_dir, mock_settings):
182182
# Mock EXE suffix for the platform (imported at module level in toolchains)
183183
with patch("medha.toolchains.EXE", ".exe"):
184184
with patch("os.path.isfile") as mock_isfile:
185-
mock_isfile.side_effect = lambda p: p == "/app/toolchains/mingw64/bin/gcc.exe"
185+
# Path() gives native separators, so build the expectation the same way (Windows uses "\\").
186+
expected = str(Path("/app/toolchains") / "mingw64" / "bin" / "gcc.exe")
187+
mock_isfile.side_effect = lambda p: str(p) == expected
186188
with patch("shutil.which", return_value="/usr/bin/gcc"):
187189
tool = find("gcc")
188-
assert tool.path == "/app/toolchains/mingw64/bin/gcc.exe"
190+
assert str(tool.path) == expected
189191
assert tool.source == "bundled"
190192

191193
@patch("medha.toolchains.settings.get", return_value={})

‎tests/test_ui_smoke.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ def test_menu_order_and_existing_actions_preserved(window):
9494
from medha.command_palette import collect_actions
9595
menus = [a.text().replace('&', '') for a in window.menuBar().actions()]
9696
assert menus == ['File', 'Edit', 'Selection', 'View', 'Go', 'Run', 'Terminal', 'Help']
97-
original = json.loads((Path(__file__).parent / 'fixtures/v1_actions.json').read_text())
97+
original = json.loads((Path(__file__).parent / 'fixtures/v1_actions.json').read_text(encoding='utf-8'))
9898
before = Counter(text.replace('&', '') for text in original)
9999
after = Counter(action.text().replace('&', '') for _, action in collect_actions(window.menuBar()))
100100
assert not (before - after)

0 commit comments

Comments
 (0)