Skip to content

Commit 621a658

Browse files
committed
create-gen: add --write flag to update __init__.py directly
1 parent 85c5f10 commit 621a658

File tree

1 file changed

+48
-10
lines changed

1 file changed

+48
-10
lines changed

robotpy_build/tool.py

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import subprocess
1010
import sys
1111
import types
12+
import typing
1213
import re
1314
from urllib.request import Request, urlopen
1415
from urllib.error import HTTPError
@@ -210,6 +211,9 @@ def add_subparser(cls, parent_parser, subparsers):
210211
)
211212
parser.add_argument("base", help="Ex: wpiutil")
212213
parser.add_argument("compiled", nargs="?", help="Ex: wpiutil._impl.wpiutil")
214+
parser.add_argument(
215+
"--write", "-w", action="store_true", help="Modify existing __init__.py"
216+
)
213217
return parser
214218

215219
def _rel(self, base: str, compiled: str) -> str:
@@ -220,16 +224,18 @@ def _rel(self, base: str, compiled: str) -> str:
220224
return f".{'.'.join(elems)}"
221225

222226
def run(self, args):
227+
self.create(args.base, args.compiled, args.write)
228+
229+
def create(self, base: str, compiled: typing.Optional[str], write: bool):
223230
# Runtime Dependency Check
224231
try:
225232
import black
226233
except:
227234
print("Error, The following module is required to run this tool: black")
228235
exit(1)
229236

230-
compiled = args.compiled
231237
if not compiled:
232-
compiled = f"{args.base}._{args.base.split('.')[-1]}"
238+
compiled = f"{base}._{base.split('.')[-1]}"
233239

234240
# TODO: could probably generate this from parsed code, but seems hard
235241
ctx = {}
@@ -238,25 +244,57 @@ def run(self, args):
238244
if isinstance(ctx[k], types.ModuleType):
239245
del ctx[k]
240246

241-
relimport = self._rel(args.base, compiled)
247+
relimport = self._rel(base, compiled)
242248

243-
stmt_compiled = "" if not args.compiled else f" {args.compiled}"
249+
stmt_compiled = "" if not compiled else f" {compiled}"
250+
begin_stmt = f"# autogenerated by 'robotpy-build create-imports {base}"
244251

245252
stmt = inspect.cleandoc(
246253
f"""
247254
248-
# autogenerated by 'robotpy-build create-imports {args.base}{stmt_compiled}'
255+
{begin_stmt}{stmt_compiled}'
249256
from {relimport} import {','.join(sorted(ctx.keys()))}
250257
__all__ = ["{'", "'.join(sorted(ctx.keys()))}"]
251258
252259
"""
253260
)
254261

255-
print(
256-
subprocess.check_output(
257-
["black", "-", "-q"], input=stmt.encode("utf-8")
258-
).decode("utf-8")
259-
)
262+
content = subprocess.check_output(
263+
["black", "-", "-q"], input=stmt.encode("utf-8")
264+
).decode("utf-8")
265+
266+
if write:
267+
fctx = {}
268+
exec(f"from {base} import __file__", {}, fctx)
269+
fname = fctx["__file__"]
270+
271+
with open(fname) as fp:
272+
fcontent = orig_content = fp.read()
273+
274+
# Find the beginning statement
275+
idx = startidx = fcontent.find(begin_stmt)
276+
if startidx != -1:
277+
for to_find in ("from", "__all__", "[", "]", "\n"):
278+
idx = fcontent.find(to_find, idx)
279+
if idx == -1:
280+
startidx = -1
281+
break
282+
283+
if startidx == -1:
284+
# If not present, just append and let the user figure it out
285+
fcontent = fcontent + "\n" + content
286+
else:
287+
fcontent = fcontent[:startidx] + content + fcontent[idx + 1 :]
288+
289+
if fcontent != orig_content:
290+
with open(fname, "w") as fp:
291+
fp.write(fcontent)
292+
print("MOD", base)
293+
else:
294+
print("OK", base)
295+
296+
else:
297+
print(content)
260298

261299

262300
class PlatformInfo:

0 commit comments

Comments
 (0)