Skip to content

Commit 4510e6f

Browse files
authored
Merge pull request #20 from Josverl/Josverl/issue17
Allow mounting a local folder during cell magic
2 parents 2874806 + 29aad00 commit 4510e6f

File tree

2 files changed

+73
-19
lines changed

2 files changed

+73
-19
lines changed

src/micropython_magic/mpr.py

Lines changed: 61 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,12 @@
2020

2121

2222
class MPRemote2:
23-
def __init__(self, shell: InteractiveShell, port: str = "auto", resume: bool = True,):
23+
def __init__(
24+
self,
25+
shell: InteractiveShell,
26+
port: str = "auto",
27+
resume: bool = True,
28+
):
2429
self.shell: InteractiveShell = shell
2530
self.port: str = port # by default connect to the first device
2631
self.resume = resume # by default resume the device to maintain state
@@ -53,7 +58,9 @@ def run_cmd(
5358
else:
5459
log.warning(f"cmd is not a string: {cmd}")
5560
log.debug(cmd)
56-
return ipython_run(cmd, stream_out=stream_out, shell=shell, timeout=timeout or self.timeout, follow=follow)
61+
return ipython_run(
62+
cmd, stream_out=stream_out, shell=shell, timeout=timeout or self.timeout, follow=follow
63+
)
5764

5865
# output = self.shell.getoutput(cmd, split=True)
5966
# assert isinstance(output, SList)
@@ -75,23 +82,62 @@ def select_device(self, port: Optional[str], verify: bool = False):
7582
output = e
7683
return output
7784

78-
def run_cell(self, cell: str, *, timeout: Union[int, float] = TIMEOUT, follow: bool = True):
85+
def run_cell(
86+
self,
87+
cell: str,
88+
*,
89+
timeout: Union[int, float] = TIMEOUT,
90+
follow: bool = True,
91+
mount: Optional[str] = None,
92+
):
7993
"""run a codeblock on the device and return the output"""
80-
# # TODO: if the cell is small enough, concat the cell with \n and use exec instead of copy
81-
# # - may need escaping quotes and newlines
82-
# copy the cell to a file on the device
83-
self.cell_to_mcu_file(cell, "__magic.py")
84-
# run the transferred cell/file
85-
result = self.run_mcu_file("__magic.py", stream_out=True, timeout=timeout, follow=follow)
86-
return result # ?
87-
88-
def run_mcu_file(self, filename: str, stream_out: bool = True, timeout: Union[int, float] = 0, follow: bool = True):
89-
exec_cmd = f"exec \"exec( open('{filename}').read() , globals() )\""
94+
"""copy cell to a file and run it on the MCU"""
95+
with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f:
96+
f.write(
97+
"# Jupyter cell\n"
98+
) # add a line to replace the cell magic to keep the line numbers aligned
99+
f.write(cell)
100+
f.close()
101+
# copy the file to the device
102+
run_cmd = f"run {f.name}"
103+
if mount:
104+
# prefix the run command with a mount command
105+
run_cmd = f'mount "{Path(mount).as_posix()}" ' + run_cmd
106+
107+
# TODO: detect / retry / report errors copying the file
108+
result = self.run_cmd(
109+
run_cmd,
110+
stream_out=True,
111+
timeout=timeout,
112+
follow=follow,
113+
)
114+
# log.info(_)
115+
# log.info(f.name, "copied to device")
116+
Path(f.name).unlink()
117+
return result
118+
119+
def run_mcu_file(
120+
self,
121+
filename: str,
122+
*,
123+
stream_out: bool = True,
124+
timeout: Union[int, float] = 0,
125+
follow: bool = True,
126+
mount: Optional[str] = None,
127+
):
128+
"""run a file on the device and return the output"""
129+
exec_cmd = ""
130+
if mount:
131+
exec_cmd = f'mount "{mount}" '
132+
exec_cmd += f"exec \"exec( open('{filename}').read() , globals() )\""
90133
return self.run_cmd(exec_cmd, stream_out=stream_out, timeout=timeout, follow=follow)
91134

92-
def cell_to_mcu_file(self, cell, filename):
135+
def copy_cell_to_mcu(self, cell, *, filename: str):
136+
"""copy cell to a file to the MCU"""
93137
with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f:
94-
f.write("# Jupyter cell\n") # add a line to replace the cell magic to keep the line numbers aligned
138+
f.write(
139+
"# Jupyter cell\n"
140+
) # add a line to replace the cell magic to keep the line numbers aligned
95141
f.write(cell)
96142
f.close()
97143
# copy the file to the device

src/micropython_magic/octarine.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ class MpyMagics(Magics):
8888
"""A class to define the magic functions for Micropython."""
8989

9090
# The default timeout
91-
timeout = Float_(TIMEOUT).tag(config=True)
91+
timeout = Float_(TIMEOUT).tag(config=True) # type: ignore
9292

9393
def __init__(self, shell: InteractiveShell):
9494
# first call the parent constructor
@@ -116,6 +116,13 @@ def MCU(self) -> MPRemote2:
116116
@cell_magic("mpy")
117117
@magic_arguments("%micropython") # add additional % to display two %% in help
118118
#
119+
@argument_group("Mount")
120+
@argument(
121+
"--mount",
122+
type=str,
123+
help="Host folder to mount on the MCU",
124+
metavar="A/FOLDER",
125+
)
119126
@argument_group("Code execution")
120127
@argument(
121128
"--writefile",
@@ -183,7 +190,7 @@ def micropython(self, line: str, cell: str = ""):
183190
log.debug(f"{args.writefile=}")
184191
if args.new:
185192
log.warning(f"{args.new=} not implemented")
186-
self.MCU.cell_to_mcu_file(cell, args.writefile)
193+
self.MCU.copy_cell_to_mcu(cell,filename= args.writefile)
187194
return
188195

189196
if args.readfile:
@@ -201,7 +208,9 @@ def micropython(self, line: str, cell: str = ""):
201208

202209
if not cell:
203210
raise UsageError("Please specify some MicroPython code to execute")
204-
output = self.MCU.run_cell(cell, timeout=args.timeout, follow=args.follow)
211+
output = self.MCU.run_cell(
212+
cell, timeout=args.timeout, follow=args.follow, mount=args.mount
213+
)
205214
# return PrettyOutput(output)
206215

207216
# -------------------------------------------------------------------------
@@ -223,7 +232,6 @@ def micropython(self, line: str, cell: str = ""):
223232
@argument("--hard-reset", action="store_true", help="reset device.")
224233
@argument("--info", action="store_true", help="get boardinfo from device")
225234
@argument("--bootloader", action="store_true", help="make the device enter its bootloader")
226-
227235
@output_can_be_silenced
228236
def mpy_line(self, line: str):
229237
"""

0 commit comments

Comments
 (0)