Skip to content

Commit 0248681

Browse files
committed
compile: separate project directory and file path in compile_file()
mpy-cross saves the file path as part of the binary file. To keep things small and not leak host computer details, we want to only include the portion of the path that is relative to the project directory. Previously, this could only be done by changing the current working directory to the project directory before calling compile_file(). Now, that is no longer necessary and the project directory is passed as a separate argument. This fixes not being able to compile files piped from stdin when using the cli tool.
1 parent 843a3eb commit 0248681

File tree

6 files changed

+32
-14
lines changed

6 files changed

+32
-14
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [Unreleased]
88

9+
### Fixed
10+
- Fix crash when running `pybricksdev run ble -` (bug introduced in alpha.49).
11+
912
## [1.0.0-alpha.52] - 2024-11-29
1013

1114
### Added

pybricksdev/cli/flash.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import hashlib
66
import json
77
import logging
8+
import os
89
import struct
910
import sys
1011
import zipfile
@@ -117,7 +118,9 @@ async def download_and_run(client: BleakClient, script: str, abi: int) -> None:
117118
# file has to be closed so mpy-cross can open it
118119
temp.file.close()
119120

120-
mpy = await compile_file(temp.name, abi)
121+
mpy = await compile_file(
122+
os.path.dirname(temp.name), os.path.basename(temp.name), abi
123+
)
121124

122125
recv_queue = asyncio.Queue()
123126

pybricksdev/compile.py

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,17 @@ def make_build_dir():
2929
raise FileExistsError("A file named build already exists.")
3030

3131

32-
async def compile_file(path: str, abi: int, compile_args: Optional[List[str]] = None):
32+
async def compile_file(
33+
proj_dir: str, proj_path: str, abi: int, compile_args: Optional[List[str]] = None
34+
):
3335
"""Compiles a Python file with ``mpy-cross``.
3436
3537
Arguments:
36-
path:
37-
Path to script that is to be compiled.
38+
proj_dir:
39+
Path to project containing the script to be compiled
40+
proj_path:
41+
Path to script that is to be compiled relative to proj_dir. This is
42+
the portion of the name that is passed to ``mpy-cross``.
3843
abi:
3944
Expected MPY ABI version.
4045
compile_args:
@@ -50,22 +55,22 @@ async def compile_file(path: str, abi: int, compile_args: Optional[List[str]] =
5055
"""
5156

5257
# Get version info
53-
with open(path, "r") as f:
58+
with open(os.path.join(proj_dir, proj_path), "r") as f:
5459
loop = asyncio.get_running_loop()
5560
script = f.read()
5661

5762
if abi == 5:
5863
proc, mpy = await loop.run_in_executor(
5964
None,
6065
lambda: mpy_cross_v5.mpy_cross_compile(
61-
path, script, no_unicode=True, extra_args=compile_args
66+
proj_path, script, no_unicode=True, extra_args=compile_args
6267
),
6368
)
6469
elif abi == 6:
6570
proc, mpy = await loop.run_in_executor(
6671
None,
6772
lambda: mpy_cross_v6.mpy_cross_compile(
68-
path, script, extra_args=compile_args
73+
proj_path, script, extra_args=compile_args
6974
),
7075
)
7176
else:
@@ -114,7 +119,8 @@ async def compile_multi_file(path: str, abi: Union[int, Tuple[int, int]]):
114119
"""
115120

116121
# compile files using Python to find imports contained within the same directory as path
117-
search_path = [os.path.dirname(path)]
122+
proj_path = os.path.dirname(path)
123+
search_path = [proj_path]
118124
finder = ModuleFinder(search_path)
119125

120126
try:
@@ -136,9 +142,9 @@ async def compile_multi_file(path: str, abi: Union[int, Tuple[int, int]]):
136142
if not module.__file__:
137143
continue
138144

139-
relative_file = os.path.relpath(module.__file__, os.path.dirname(path))
140-
141-
mpy = await compile_file(relative_file, abi_major)
145+
mpy = await compile_file(
146+
proj_path, os.path.relpath(module.__file__, proj_path), abi_major
147+
)
142148

143149
parts.append(len(mpy).to_bytes(4, "little"))
144150
parts.append(name.encode() + b"\x00")

pybricksdev/connections/pybricks.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -582,7 +582,9 @@ async def _legacy_run(self, py_path: str, wait: bool) -> None:
582582
Version of :meth:`run` for compatibility with older firmware ()
583583
"""
584584
# Compile the script to mpy format
585-
mpy = await compile_file(py_path, self._mpy_abi_version)
585+
mpy = await compile_file(
586+
os.path.dirname(py_path), os.path.basename(py_path), self._mpy_abi_version
587+
)
586588

587589
try:
588590
self._downloading_via_nus = True

pybricksdev/firmware.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,11 @@ async def _create_firmware_v1(
133133

134134
if "main.py" in archive.namelist():
135135
main_py = io.TextIOWrapper(archive.open("main.py"))
136+
main_py_path = save_script(main_py.read())
136137

137138
mpy = await compile_file(
138-
save_script(main_py.read()),
139+
os.path.dirname(main_py_path),
140+
os.path.basename(main_py_path),
139141
metadata["mpy-abi-version"],
140142
metadata["mpy-cross-options"],
141143
)

tests/test_compile.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ async def test_compile_file(abi: int):
1919
f.write("print('test')")
2020
f.close()
2121

22-
mpy = await compile_file(f.name, abi=abi)
22+
mpy = await compile_file(
23+
os.path.dirname(f.name), os.path.basename(f.name), abi=abi
24+
)
2325

2426
magic, abi_ver, flags, int_bits = struct.unpack_from("<BBBB", mpy)
2527

0 commit comments

Comments
 (0)