9
9
import subprocess
10
10
import sys
11
11
import types
12
+ import typing
12
13
import re
13
14
from urllib .request import Request , urlopen
14
15
from urllib .error import HTTPError
@@ -210,6 +211,9 @@ def add_subparser(cls, parent_parser, subparsers):
210
211
)
211
212
parser .add_argument ("base" , help = "Ex: wpiutil" )
212
213
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
+ )
213
217
return parser
214
218
215
219
def _rel (self , base : str , compiled : str ) -> str :
@@ -220,16 +224,18 @@ def _rel(self, base: str, compiled: str) -> str:
220
224
return f".{ '.' .join (elems )} "
221
225
222
226
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 ):
223
230
# Runtime Dependency Check
224
231
try :
225
232
import black
226
233
except :
227
234
print ("Error, The following module is required to run this tool: black" )
228
235
exit (1 )
229
236
230
- compiled = args .compiled
231
237
if not compiled :
232
- compiled = f"{ args . base } ._{ args . base .split ('.' )[- 1 ]} "
238
+ compiled = f"{ base } ._{ base .split ('.' )[- 1 ]} "
233
239
234
240
# TODO: could probably generate this from parsed code, but seems hard
235
241
ctx = {}
@@ -238,25 +244,57 @@ def run(self, args):
238
244
if isinstance (ctx [k ], types .ModuleType ):
239
245
del ctx [k ]
240
246
241
- relimport = self ._rel (args . base , compiled )
247
+ relimport = self ._rel (base , compiled )
242
248
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 } "
244
251
245
252
stmt = inspect .cleandoc (
246
253
f"""
247
254
248
- # autogenerated by 'robotpy-build create-imports { args . base } { stmt_compiled } '
255
+ { begin_stmt } { stmt_compiled } '
249
256
from { relimport } import { ',' .join (sorted (ctx .keys ()))}
250
257
__all__ = ["{ '", "' .join (sorted (ctx .keys ()))} "]
251
258
252
259
"""
253
260
)
254
261
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 )
260
298
261
299
262
300
class PlatformInfo :
0 commit comments