eric6/DebugClients/Python/DebugUtilities.py

branch
multi_processing
changeset 7871
eb65864ca038
parent 7646
39e3db2b4936
child 7873
cb2badbdf26c
equal deleted inserted replaced
7870:ab8f95bc7d2d 7871:eb65864ca038
226 isExecutable(program) and 226 isExecutable(program) and
227 startsWithShebang(program) 227 startsWithShebang(program)
228 ) 228 )
229 229
230 230
231 def removeQuotesFromArgs(args):
232 """
233 Function to remove quotes from the arguments list.
234
235 @param args list of arguments
236 @type list of str
237 @return list of unquoted strings
238 @rtype list of str
239 """
240 if isWindowsPlatform():
241 newArgs = []
242 for x in args:
243 if len(x) > 1 and x.startswith('"') and x.endswith('"'):
244 x = x[1:-1]
245 newArgs.append(x)
246 return newArgs
247 else:
248 return args
249
250
251 def quoteArgs(args):
252 """
253 Function to quote the given list of arguments.
254
255 @param args list of arguments to be quoted
256 @type list of str
257 @return list of quoted arguments
258 @rtype list of str
259 """
260 if isWindowsPlatform():
261 quotedArgs = []
262 for x in args:
263 if x.startswith('"') and x.endswith('"'):
264 quotedArgs.append(x)
265 else:
266 if ' ' in x:
267 x = x.replace('"', '\\"')
268 quotedArgs.append('"{0}"'.format(x))
269 else:
270 quotedArgs.append(x)
271 return quotedArgs
272 else:
273 return args
274
275
231 def patchArguments(debugClient, arguments, noRedirect=False): 276 def patchArguments(debugClient, arguments, noRedirect=False):
232 """ 277 """
233 Function to patch the arguments given to start a program in order to 278 Function to patch the arguments given to start a program in order to
234 execute it in our debugger. 279 execute it in our debugger.
235 280
241 @type bool 286 @type bool
242 @return modified argument list 287 @return modified argument list
243 @rtype list of str 288 @rtype list of str
244 """ 289 """
245 args = list(arguments[:]) # create a copy of the arguments list 290 args = list(arguments[:]) # create a copy of the arguments list
291 args = removeQuotesFromArgs(args)
246 292
247 # support for shebang line 293 # support for shebang line
248 program = os.path.basename(args[0]).lower() 294 program = os.path.basename(args[0]).lower()
249 for pyname in PYTHON_NAMES: 295 for pyname in PYTHON_NAMES:
250 if pyname in program: 296 if pyname in program:
252 else: 298 else:
253 if not isWindowsPlatform() and startsWithShebang(args[0]): 299 if not isWindowsPlatform() and startsWithShebang(args[0]):
254 # insert our interpreter as first argument 300 # insert our interpreter as first argument
255 args.insert(0, sys.executable) 301 args.insert(0, sys.executable)
256 302
257 # check for -c or -m invocation => debugging not supported yet 303 # check for -m invocation => debugging not supported yet
258 if "-c" in args: 304 if "-m" in args:
259 cm_position = args.index("-c")
260 elif "-m" in args:
261 cm_position = args.index("-m") 305 cm_position = args.index("-m")
262 else: 306 else:
263 cm_position = 0 307 cm_position = 0
264 if cm_position > 0: 308 if cm_position > 0:
265 # check if it belongs to the interpreter or program 309 # check if it belongs to the interpreter or program
270 break 314 break
271 else: 315 else:
272 found = False 316 found = False
273 if found and cm_position < pos: 317 if found and cm_position < pos:
274 # it belongs to the interpreter 318 # it belongs to the interpreter
275 return arguments 319 return quoteArgs(arguments)
276 320
277 # extract list of interpreter arguments, i.e. all arguments before the 321 # extract list of interpreter arguments, i.e. all arguments before the
278 # first one not starting with '-'. 322 # first one not starting with '-'.
279 interpreter = args.pop(0) 323 interpreter = args.pop(0)
280 interpreterArgs = [] 324 interpreterArgs = []
325 hasCode = False
281 while args: 326 while args:
282 if args[0].startswith("-"): 327 if args[0].startswith("-"):
283 if args[0] in ("-W", "-X"): 328 if args[0] in ("-W", "-X"):
284 # take two elements off the list 329 # take two elements off the list
285 interpreterArgs.append(args.pop(0)) 330 interpreterArgs.append(args.pop(0))
286 interpreterArgs.append(args.pop(0)) 331 interpreterArgs.append(args.pop(0))
332 elif args[0] == "-c":
333 # -c indicates code to be executed and ends the
334 # arguments list
335 args.pop(0)
336 hasCode = True
337 break
287 else: 338 else:
288 interpreterArgs.append(args.pop(0)) 339 interpreterArgs.append(args.pop(0))
289 else: 340 else:
290 break 341 break
291 342
311 modifiedArguments.append("-n") 362 modifiedArguments.append("-n")
312 if noencoding: 363 if noencoding:
313 modifiedArguments.append("--no-encoding") 364 modifiedArguments.append("--no-encoding")
314 if debugClient.multiprocessSupport: 365 if debugClient.multiprocessSupport:
315 modifiedArguments.append("--multiprocess") 366 modifiedArguments.append("--multiprocess")
367 if hasCode:
368 modifiedArguments.append("--code")
316 modifiedArguments.append("--") 369 modifiedArguments.append("--")
317 # end the arguments for DebugClient 370 # end the arguments for DebugClient
318 371
319 # append the arguments for the program to be debugged 372 # append the arguments for the program to be debugged
320 modifiedArguments.extend(args) 373 modifiedArguments.extend(args)
374 modifiedArguments = quoteArgs(modifiedArguments)
321 375
322 return modifiedArguments 376 return modifiedArguments
377
378
379 def stringToArgumentsWindows(args):
380 """
381 Function to prepare a string of arguments for Windows platform.
382
383 @param args list of command arguments
384 @type str
385 @return list of command arguments
386 @rtype list of str
387 @exception RuntimeError raised to indicate an illegal arguments parsing
388 condition
389 """
390 # see http:#msdn.microsoft.com/en-us/library/a1y7w461.aspx
391 result = []
392
393 DEFAULT = 0
394 ARG = 1
395 IN_DOUBLE_QUOTE = 2
396
397 state = DEFAULT
398 backslashes = 0
399 buf = ''
400
401 argsLen = len(args)
402 for i in range(argsLen):
403 ch = args[i]
404 if ch == '\\':
405 backslashes += 1
406 continue
407 elif backslashes != 0:
408 if ch == '"':
409 while backslashes >= 2:
410 backslashes -= 2
411 buf += '\\'
412 if backslashes == 1:
413 if state == DEFAULT:
414 state = ARG
415
416 buf += '"'
417 backslashes = 0
418 continue
419 else:
420 # false alarm, treat passed backslashes literally...
421 if state == DEFAULT:
422 state = ARG
423
424 while backslashes > 0:
425 backslashes -= 1
426 buf += '\\'
427
428 if ch in (' ', '\t'):
429 if state == DEFAULT:
430 # skip
431 continue
432 elif state == ARG:
433 state = DEFAULT
434 result.append(buf)
435 buf = ''
436 continue
437
438 if state in (DEFAULT, ARG):
439 if ch == '"':
440 state = IN_DOUBLE_QUOTE
441 else:
442 state = ARG
443 buf += ch
444
445 elif state == IN_DOUBLE_QUOTE:
446 if ch == '"':
447 if i + 1 < argsLen and args[i + 1] == '"':
448 # Undocumented feature in Windows:
449 # Two consecutive double quotes inside a double-quoted
450 # argument are interpreted as a single double quote.
451 buf += '"'
452 i += 1
453 elif len(buf) == 0:
454 result.append("\"\"")
455 state = DEFAULT
456 else:
457 state = ARG
458 else:
459 buf += ch
460
461 else:
462 raise RuntimeError('Illegal condition')
463
464 if len(buf) > 0 or state != DEFAULT:
465 result.append(buf)
466
467 return result
468
469
470 def patchArgumentStringWindows(debugClient, argStr):
471 """
472 Function to patch an argument string for Windows.
473
474 @param debugClient reference to the debug client object
475 @type DebugClient
476 @param argStr argument string
477 @type str
478 @return patched argument string
479 @rtype str
480 """
481 args = stringToArgumentsWindows(argStr)
482 if not args or not isPythonProgram(args[0]):
483 return argStr
484
485 argStr = ' '.join(patchArguments(debugClient, args))
486 return argStr

eric ide

mercurial