Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@
# TODO

## Backports from openscad_cpp_parser

Triaged 2026-09-24 against cpp 33a78ca..9524bdc. `#N` are cpp PRs. Library search, backslash-newline
in strings, argument-list line comments, `render()` expressions and the range step flag are done.

- Libraries shipped beside the binary (#10's third search dir, OpenSCAD's
`resourcePath("libraries")`) are not searched; a pip-installed package has no such directory,
so this only matters if something ever bundles this parser with libraries next to it

## Comment round-trip

Reformatting with `include_comments=True` gives code that parses, is the same program, keeps
Expand Down
9 changes: 8 additions & 1 deletion src/openscad_lalr_parser/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -809,10 +809,15 @@ def _windows_documents_dir() -> str:
return os.path.join(os.path.expanduser("~"), "Documents")


_BUNDLED_LIBRARY_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "libraries")


def librarySearchDirs(currfile: str) -> list[str]:
"""The directories `include`/`use` search, in order, as OpenSCAD's
parser_init() builds them: the including file's own directory, then
every OPENSCADPATH entry, then the user's libraries folder.
every OPENSCADPATH entry, then the user's libraries folder, then
libraries shipped beside this package (OpenSCAD's
resourcePath("libraries")).

OPENSCADPATH adds to the libraries folder rather than replacing it --
it used to replace it, so setting it for one library hid every other
Expand All @@ -835,6 +840,8 @@ def librarySearchDirs(currfile: str) -> list[str]:
dirs.append(os.path.expanduser("~/Documents/OpenSCAD/libraries"))
elif system == "Linux":
dirs.append(os.path.expanduser("~/.local/share/OpenSCAD/libraries"))
# ponytail: only the folder beside the package, no ../share/openscad walk
dirs.append(_BUNDLED_LIBRARY_DIR)
return dirs


Expand Down
24 changes: 21 additions & 3 deletions tests/test_cpp_backports.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import os
import platform

import openscad_lalr_parser

import pytest

from openscad_lalr_parser import (
Expand Down Expand Up @@ -51,6 +53,9 @@ def test_slashes_after_it_are_not_a_comment(self):
assert [type(n).__name__ for n in ast] == ["Assignment", "Assignment"]


BUNDLED = os.path.join(os.path.dirname(os.path.abspath(openscad_lalr_parser.__file__)), "libraries")


class TestLibrarySearch:
@pytest.fixture
def home(self, tmp_path, monkeypatch):
Expand All @@ -71,7 +76,7 @@ def test_openscadpath_comes_first_and_keeps_the_default(self, home, monkeypatch)
(default / "both.scad").write_text("x = 1;")
(env_dir / "both.scad").write_text("x = 2;")
main = home / "main.scad"
assert librarySearchDirs(str(main)) == [str(home), str(env_dir), str(default)]
assert librarySearchDirs(str(main)) == [str(home), str(env_dir), str(default), BUNDLED]
assert findLibraryFile(str(main), "BOSL2.scad") == str(default / "BOSL2.scad") # was hidden
assert findLibraryFile(str(main), "both.scad") == str(env_dir / "both.scad")

Expand All @@ -80,15 +85,28 @@ def test_windows_asks_for_documents(self, monkeypatch):
monkeypatch.setattr(platform, "system", lambda: "Windows")
monkeypatch.setattr(p, "_windows_documents_dir", lambda: "D:\\OneDrive\\Documents")
monkeypatch.delenv("OPENSCADPATH", raising=False)
assert librarySearchDirs("") == [os.path.join("D:\\OneDrive\\Documents", "OpenSCAD", "libraries")]
assert librarySearchDirs("") == [os.path.join("D:\\OneDrive\\Documents", "OpenSCAD", "libraries"), BUNDLED]

def test_not_found_lists_every_directory(self, home):
main = home / "main.scad"
main.write_text("")
with pytest.raises(FileNotFoundError) as e:
getASTfromLibraryFile(str(main), "nope.scad")
assert str(e.value) == ("Library file 'nope.scad' not found. Searched:\n"
f" {home}\n {home / 'Documents' / 'OpenSCAD' / 'libraries'}")
f" {home}\n {home / 'Documents' / 'OpenSCAD' / 'libraries'}\n {BUNDLED}")

def test_libraries_beside_the_package_are_searched_last(self, home, monkeypatch):
import openscad_lalr_parser as p
bundled = home / "pkg" / "libraries"
bundled.mkdir(parents=True)
(bundled / "shipped.scad").write_text("x = 1;")
(bundled / "both.scad").write_text("x = 2;")
default = home / "Documents" / "OpenSCAD" / "libraries"
(default / "both.scad").write_text("x = 1;")
monkeypatch.setattr(p, "_BUNDLED_LIBRARY_DIR", str(bundled))
main = str(home / "main.scad")
assert findLibraryFile(main, "shipped.scad") == str(bundled / "shipped.scad")
assert findLibraryFile(main, "both.scad") == str(default / "both.scad")


class TestRangeStepWritten:
Expand Down
Loading