Skip to content

Commit 4cfe057

Browse files
committed
fix: cross-platform path handling for Windows and Mac
1 parent 550233f commit 4cfe057

File tree

2 files changed

+19
-17
lines changed

2 files changed

+19
-17
lines changed

src/devcode.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ def resolve_template_search_path() -> list[str]:
9797
default = os.path.join(xdg, "dev-code", "templates")
9898
if not new_var:
9999
return [default]
100-
dirs = [d for d in new_var.split(":") if d]
100+
dirs = [d for d in new_var.split(os.pathsep) if d]
101101
return dirs if dirs else [default]
102102

103103

@@ -223,6 +223,8 @@ def _has_path_prefix(p: str) -> bool:
223223
"""
224224
if p.startswith("~"):
225225
p = str(Path(p).expanduser())
226+
if os.path.isabs(p):
227+
return True
226228
parents = Path(p).parents
227229
return not len(parents) or p.startswith(str(parents[-1]))
228230

tests/test_dev_code.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -165,26 +165,26 @@ def test_single_path(self):
165165
self.assertEqual(devcode.resolve_template_search_path(), ["/a/b"])
166166

167167
def test_multiple_paths(self):
168-
env = self._clean_env({"DEVCODE_TEMPLATE_PATH": "/a:/b:/c"})
168+
env = self._clean_env({"DEVCODE_TEMPLATE_PATH": os.pathsep.join(["/a", "/b", "/c"])})
169169
with patch.dict(os.environ, env, clear=True):
170170
self.assertEqual(devcode.resolve_template_search_path(), ["/a", "/b", "/c"])
171171

172172
def test_empty_entries_skipped(self):
173-
env = self._clean_env({"DEVCODE_TEMPLATE_PATH": "/a::/b:"})
173+
env = self._clean_env({"DEVCODE_TEMPLATE_PATH": f"/a{os.pathsep}{os.pathsep}/b{os.pathsep}"})
174174
with patch.dict(os.environ, env, clear=True):
175175
self.assertEqual(devcode.resolve_template_search_path(), ["/a", "/b"])
176176

177177
def test_all_empty_entries_falls_back_to_xdg(self):
178-
env = self._clean_env({"DEVCODE_TEMPLATE_PATH": ":::", "XDG_DATA_HOME": "/xdg"})
178+
env = self._clean_env({"DEVCODE_TEMPLATE_PATH": os.pathsep * 3, "XDG_DATA_HOME": "/xdg"})
179179
with patch.dict(os.environ, env, clear=True):
180180
result = devcode.resolve_template_search_path()
181-
self.assertEqual(result, ["/xdg/dev-code/templates"])
181+
self.assertEqual(result, [os.path.join("/xdg", "dev-code", "templates")])
182182

183183
def test_unset_uses_xdg_data_home(self):
184184
env = self._clean_env({"XDG_DATA_HOME": "/xdg"})
185185
with patch.dict(os.environ, env, clear=True):
186186
result = devcode.resolve_template_search_path()
187-
self.assertEqual(result, ["/xdg/dev-code/templates"])
187+
self.assertEqual(result, [os.path.join("/xdg", "dev-code", "templates")])
188188

189189
def test_unset_uses_default_xdg(self):
190190
env = self._clean_env()
@@ -194,7 +194,7 @@ def test_unset_uses_default_xdg(self):
194194

195195

196196
def test_write_template_dir_returns_first_entry(self):
197-
env = self._clean_env({"DEVCODE_TEMPLATE_PATH": "/first:/second"})
197+
env = self._clean_env({"DEVCODE_TEMPLATE_PATH": os.pathsep.join(["/first", "/second"])})
198198
with patch.dict(os.environ, env, clear=True):
199199
self.assertEqual(devcode._write_template_dir(), "/first")
200200

@@ -338,7 +338,7 @@ def test_dot_slash_prefix_resolves_as_path_not_template(self):
338338
result = devcode.resolve_template("./mydev")
339339
finally:
340340
os.chdir(old_cwd)
341-
self.assertEqual(result, local_cfg)
341+
self.assertEqual(result, os.path.realpath(local_cfg))
342342

343343
def test_absolute_path_resolves_as_path_not_template(self):
344344
"""An absolute path resolves as path even if its basename matches a template."""
@@ -436,7 +436,7 @@ def test_finds_in_second_search_dir(self):
436436
os.makedirs(tpath)
437437
cfg = os.path.join(tpath, "devcontainer.json")
438438
open(cfg, "w").close()
439-
with patch.dict(os.environ, {"DEVCODE_TEMPLATE_PATH": f"{d1}:{d2}"}):
439+
with patch.dict(os.environ, {"DEVCODE_TEMPLATE_PATH": os.pathsep.join([d1, d2])}):
440440
result = devcode.resolve_template("mytemplate")
441441
self.assertEqual(result, cfg)
442442

@@ -1109,7 +1109,7 @@ def test_uses_write_template_dir(self):
11091109
with tempfile.TemporaryDirectory() as d1:
11101110
with tempfile.TemporaryDirectory() as d2:
11111111
with patch.object(devcode, "__file__", os.path.join(pkg_dir, "devcode.py")):
1112-
with patch.dict(os.environ, {"DEVCODE_TEMPLATE_PATH": f"{d1}:{d2}"}):
1112+
with patch.dict(os.environ, {"DEVCODE_TEMPLATE_PATH": os.pathsep.join([d1, d2])}):
11131113
args = argparse.Namespace(subcommand="init", verbose=False)
11141114
devcode.cmd_init(args)
11151115
self.assertTrue(os.path.isdir(os.path.join(d1, "dev-code")))
@@ -1159,15 +1159,15 @@ def test_short_deduplicates_across_dirs(self):
11591159
with tempfile.TemporaryDirectory() as d2:
11601160
self._make_template(d1, "shared")
11611161
self._make_template(d2, "shared")
1162-
lines = self._run_list(f"{d1}:{d2}")
1162+
lines = self._run_list(os.pathsep.join([d1, d2]))
11631163
self.assertEqual(lines.count("shared"), 1)
11641164

11651165
def test_long_shows_one_section_per_dir(self):
11661166
with tempfile.TemporaryDirectory() as d1:
11671167
with tempfile.TemporaryDirectory() as d2:
11681168
self._make_template(d1, "alpha")
11691169
self._make_template(d2, "beta")
1170-
lines = self._run_list(f"{d1}:{d2}", long=True)
1170+
lines = self._run_list(os.pathsep.join([d1, d2]), long=True)
11711171
combined = "\n".join(lines)
11721172
self.assertIn(d1, combined)
11731173
self.assertIn(d2, combined)
@@ -1184,7 +1184,7 @@ def test_long_omits_nonexistent_dirs(self):
11841184
with tempfile.TemporaryDirectory() as d:
11851185
self._make_template(d, "mytemplate")
11861186
nonexistent = os.path.join(d, "no-such-dir")
1187-
lines = self._run_list(f"{d}:{nonexistent}", long=True)
1187+
lines = self._run_list(os.pathsep.join([d, nonexistent]), long=True)
11881188
combined = "\n".join(lines)
11891189
self.assertNotIn(nonexistent, combined)
11901190

@@ -1285,7 +1285,7 @@ def test_base_found_in_second_search_dir(self):
12851285
open(os.path.join(base, "devcontainer.json"), "w").close()
12861286
args = MagicMock(subcommand="new", verbose=False, base="mybase", edit=False)
12871287
args.name = "myapp"
1288-
with patch.dict(os.environ, {"DEVCODE_TEMPLATE_PATH": f"{d1}:{d2}"}):
1288+
with patch.dict(os.environ, {"DEVCODE_TEMPLATE_PATH": os.pathsep.join([d1, d2])}):
12891289
devcode.cmd_new(args)
12901290
# writes to first dir
12911291
self.assertTrue(os.path.isdir(os.path.join(d1, "myapp")))
@@ -1313,7 +1313,7 @@ def test_no_arg_opens_first_existing_search_dir(self):
13131313
with tempfile.TemporaryDirectory() as d2:
13141314
nonexistent = "/nonexistent/path"
13151315
args = MagicMock(subcommand="edit", verbose=False, template=None)
1316-
with patch.dict(os.environ, {"DEVCODE_TEMPLATE_PATH": f"{nonexistent}:{d1}:{d2}"}):
1316+
with patch.dict(os.environ, {"DEVCODE_TEMPLATE_PATH": os.pathsep.join([nonexistent, d1, d2])}):
13171317
with patch("subprocess.run") as mock_run:
13181318
devcode.cmd_edit(args)
13191319
mock_run.assert_called_once_with(["code", d1])
@@ -1323,7 +1323,7 @@ def test_named_template_found_in_second_dir(self):
13231323
with tempfile.TemporaryDirectory() as d2:
13241324
root = self._make_template(d2, "mytemplate")
13251325
args = MagicMock(subcommand="edit", verbose=False, template="mytemplate")
1326-
with patch.dict(os.environ, {"DEVCODE_TEMPLATE_PATH": f"{d1}:{d2}"}):
1326+
with patch.dict(os.environ, {"DEVCODE_TEMPLATE_PATH": os.pathsep.join([d1, d2])}):
13271327
with patch("subprocess.run") as mock_run:
13281328
devcode.cmd_edit(args)
13291329
mock_run.assert_called_once_with(["code", root])
@@ -1337,7 +1337,7 @@ def test_named_template_not_found_exits(self):
13371337

13381338
def test_no_arg_no_existing_dir_exits(self):
13391339
args = MagicMock(subcommand="edit", verbose=False, template=None)
1340-
with patch.dict(os.environ, {"DEVCODE_TEMPLATE_PATH": "/nonexistent/a:/nonexistent/b"}):
1340+
with patch.dict(os.environ, {"DEVCODE_TEMPLATE_PATH": os.pathsep.join(["/nonexistent/a", "/nonexistent/b"])}):
13411341
with self.assertRaises(SystemExit):
13421342
devcode.cmd_edit(args)
13431343

0 commit comments

Comments
 (0)