Skip to content

Fix module resolution for subdirectory paths (top and required modules)#237

Open
pedjaradenkovic wants to merge 1 commit into
mainfrom
fix/relative-module-path
Open

Fix module resolution for subdirectory paths (top and required modules)#237
pedjaradenkovic wants to merge 1 commit into
mainfrom
fix/relative-module-path

Conversation

@pedjaradenkovic

@pedjaradenkovic pedjaradenkovic commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Problem

Two related failures when a .plain module lives in / references a subdirectory:

  1. Running the CLI with a relative path containing a subdirectory fails:
    $ python plain2code.py examples/example_hello_world_python/hello_world_python.plain
    Error: Module does not exist (examples/example_hello_world_python/hello_world_python).
    
  2. A top module that requires a module in a subdirectory (requires: [dir_name/b]), rendered from outside its folder, fails when the PlainModule tree is built:
    Error: Module does not exist (b).
    

Root cause

get_template_directories always folds dirname(filename) into template_dirs[0]. But the full top-module filename was still passed to plain_file_parser, so the directory was counted twice when opening the file (open_from joins template_dirs[0] + the module name).

  • Required/imported modules are already passed as template-relative names (dir_name/b.plain), so they must keep their subdirectory prefix to resolve.
  • The top module must drop its directory prefix (it's already in template_dirs).

An earlier attempt fixed only the top module by forcing the bare stem — but that stripped the subdirectory from required modules too, breaking case 2.

Fix

  • plain2code.py: normalize the top module to os.path.basename(args.filename) at the call sites (its directory is already in template_dirs). This is the frame the parser expects.
  • plain_file.py: plain_file_parser preserves the relative subdirectory prefix in module_name (so dir_name/b resolves and is retained in build/conformance paths); absolute paths fall back to the stem.

With this, both the top module and required modules in subdirectories resolve correctly, and required-module subdirectory structure is preserved under the build folder (build/dir_name/b).

Tests

tests/test_plainfileparser.py (fixtures in tests/data/requires_subdir/):

  • test_parser_keeps_subdirectory_in_module_name — parser keeps nested/leaf for a template-relative name.
  • test_requires_module_in_subdirectory_resolves — builds the full PlainModule tree with a required subdirectory module (the path that broke) and asserts module names + build folder (build/nested/leaf).

Verification

  • Full suite: 217 passed; black / flake8 / mypy clean.
  • Original relative-subfolder CLI invocation works.
  • requires: [dir_name/b] from outside the folder now builds the module tree and reaches the API instead of failing at "Module does not exist".

@pedjaradenkovic pedjaradenkovic changed the title Fix module resolution for relative subdirectory paths Fix module resolution for subdirectory paths (top and required modules) Jul 8, 2026
The top module's directory is already folded into template_dirs by
get_template_directories, so passing the full filename to plain_file_parser
double-counted the directory (relative subdirectory paths failed with
'Module does not exist'). Normalize the top module to its basename at the
call sites in plain2code.py; plain_file_parser keeps preserving relative
subdirectory prefixes so required/imported modules (e.g. 'dir_name/b') resolve.

Add PlainModule-tree and parser-level regression tests.
@pedjaradenkovic pedjaradenkovic force-pushed the fix/relative-module-path branch from 92cb325 to 7722cea Compare July 8, 2026 13:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant