153
154
' or win32process')
156
# using base-2 units (see HACKING.txt).
157
trace.note('WorkingSize %7dKiB'
158
'\tPeakWorking %7dKiB\t%s',
157
trace.note('WorkingSize %7dKB'
158
'\tPeakWorking %7dKB\t%s',
159
159
info['WorkingSetSize'] / 1024,
160
160
info['PeakWorkingSetSize'] / 1024,
164
164
trace.note('%s', message)
165
trace.note('WorkingSize %8d KiB', info['WorkingSetSize'] / 1024)
166
trace.note('PeakWorking %8d KiB', info['PeakWorkingSetSize'] / 1024)
167
trace.note('PagefileUsage %8d KiB', info.get('PagefileUsage', 0) / 1024)
168
trace.note('PeakPagefileUsage %8d KiB',
169
info.get('PeakPagefileUsage', 0) / 1024)
170
trace.note('PrivateUsage %8d KiB', info.get('PrivateUsage', 0) / 1024)
165
trace.note('WorkingSize %8d KB', info['WorkingSetSize'] / 1024)
166
trace.note('PeakWorking %8d KB', info['PeakWorkingSetSize'] / 1024)
167
trace.note('PagefileUsage %8d KB', info.get('PagefileUsage', 0) / 1024)
168
trace.note('PeakPagefileUsage %8d KB', info.get('PeakPagefileUsage', 0) / 1024)
169
trace.note('PrivateUsage %8d KB', info.get('PrivateUsage', 0) / 1024)
171
170
trace.note('PageFaultCount %8d', info.get('PageFaultCount', 0))
522
520
trace.mutter('Unable to set hidden attribute on %r: %s', path, e)
525
def _command_line_to_argv(command_line, argv, single_quotes_allowed=False):
526
"""Convert a Unicode command line into a list of argv arguments.
528
It performs wildcard expansion to make wildcards act closer to how they
529
work in posix shells, versus how they work by default on Windows. Quoted
530
arguments are left untouched.
532
:param command_line: The unicode string to split into an arg list.
533
:param single_quotes_allowed: Whether single quotes are accepted as quoting
534
characters like double quotes. False by
536
:return: A list of unicode strings.
538
# First, spit the command line
539
s = cmdline.Splitter(command_line, single_quotes_allowed=single_quotes_allowed)
541
# Bug #587868 Now make sure that the length of s agrees with sys.argv
542
# we do this by simply counting the number of arguments in each. The counts should
543
# agree no matter what encoding sys.argv is in (AFAIK)
544
# len(arguments) < len(sys.argv) should be an impossibility since python gets
545
# args from the very same PEB as does GetCommandLineW
548
# Now shorten the command line we get from GetCommandLineW to match sys.argv
549
if len(arguments) < len(argv):
550
raise AssertionError("Split command line can't be shorter than argv")
551
arguments = arguments[len(arguments) - len(argv):]
553
# Carry on to process globs (metachars) in the command line
554
# expand globs if necessary
524
class UnicodeShlex(object):
525
"""This is a very simplified version of shlex.shlex.
527
The main change is that it supports non-ascii input streams. The internal
528
structure is quite simplified relative to shlex.shlex, since we aren't
529
trying to handle multiple input streams, etc. In fact, we don't use a
530
file-like api either.
533
def __init__(self, uni_string):
534
self._input = uni_string
535
self._input_iter = iter(self._input)
536
self._whitespace_match = re.compile(u'\s').match
537
self._word_match = re.compile(u'\S').match
538
self._quote_chars = u'"'
539
# self._quote_match = re.compile(u'[\'"]').match
540
self._escape_match = lambda x: None # Never matches
543
# ' ' - after whitespace, starting a new token
544
# 'a' - after text, currently working on a token
545
# '"' - after ", currently in a "-delimited quoted section
546
# "\" - after '\', checking the next char
548
self._token = [] # Current token being parsed
550
def _get_token(self):
551
# Were there quote chars as part of this token?
554
for nextchar in self._input_iter:
555
if self._state == ' ':
556
if self._whitespace_match(nextchar):
557
# if self._token: return token
559
elif nextchar in self._quote_chars:
560
self._state = nextchar # quoted state
561
elif self._word_match(nextchar):
562
self._token.append(nextchar)
565
raise AssertionError('wtttf?')
566
elif self._state in self._quote_chars:
568
if nextchar == self._state: # End of quote
569
self._state = 'a' # posix allows 'foo'bar to translate to
571
elif self._state == '"' and nextchar == self._escape:
572
quoted_state = self._state
573
self._state = nextchar
575
self._token.append(nextchar)
576
elif self._state == self._escape:
578
self._token.append('\\')
579
elif nextchar == '"':
580
self._token.append(nextchar)
582
self._token.append('\\' + nextchar)
583
self._state = quoted_state
584
elif self._state == 'a':
585
if self._whitespace_match(nextchar):
587
break # emit this token
589
continue # no token to emit
590
elif nextchar in self._quote_chars:
591
# Start a new quoted section
592
self._state = nextchar
594
elif (self._word_match(nextchar)
595
or nextchar in self._quote_chars
596
# or whitespace_split?
598
self._token.append(nextchar)
600
raise AssertionError('state == "a", char: %r'
603
raise AssertionError('unknown state: %r' % (self._state,))
604
result = ''.join(self._token)
606
if not quoted and result == '':
608
return quoted, result
614
quoted, token = self._get_token()
620
def _command_line_to_argv(command_line):
621
"""Convert a Unicode command line into a set of argv arguments.
623
This does wildcard expansion, etc. It is intended to make wildcards act
624
closer to how they work in posix shells, versus how they work by default on
627
s = UnicodeShlex(command_line)
628
# Now that we've split the content, expand globs
555
629
# TODO: Use 'globbing' instead of 'glob.glob', this gives us stuff like
556
630
# '**/' style globs
558
for is_quoted, arg in arguments:
632
for is_quoted, arg in s:
559
633
if is_quoted or not glob.has_magic(arg):
566
640
if has_ctypes and winver != 'Windows 98':
567
641
def get_unicode_argv():
568
prototype = ctypes.WINFUNCTYPE(ctypes.c_wchar_p)
569
GetCommandLineW = prototype(("GetCommandLineW",
570
ctypes.windll.kernel32))
571
command_line = GetCommandLineW()
572
if command_line is None:
573
raise ctypes.WinError()
642
LPCWSTR = ctypes.c_wchar_p
644
POINTER = ctypes.POINTER
645
prototype = ctypes.WINFUNCTYPE(LPCWSTR)
646
GetCommandLine = prototype(("GetCommandLineW",
647
ctypes.windll.kernel32))
648
prototype = ctypes.WINFUNCTYPE(POINTER(LPCWSTR), LPCWSTR, POINTER(INT))
649
command_line = GetCommandLine()
574
650
# Skip the first argument, since we only care about parameters
575
argv = _command_line_to_argv(command_line, sys.argv)[1:]
651
argv = _command_line_to_argv(GetCommandLine())[1:]
652
if getattr(sys, 'frozen', None) is None:
653
# Invoked via 'python.exe' which takes the form:
654
# python.exe [PYTHON_OPTIONS] C:\Path\bzr [BZR_OPTIONS]
655
# we need to get only BZR_OPTIONS part,
656
# We already removed 'python.exe' so we remove everything up to and
657
# including the first non-option ('-') argument.
658
for idx in xrange(len(argv)):
659
if argv[idx][:1] != '-':
578
664
get_unicode_argv = None
582
def _pywin32_is_local_pid_dead(pid):
583
"""True if pid doesn't correspond to live process on this machine"""
585
handle = win32api.OpenProcess(1, False, pid) # PROCESS_TERMINATE
586
except pywintypes.error, e:
587
if e[0] == 5: # ERROR_ACCESS_DENIED
588
# Probably something alive we're not allowed to kill
590
elif e[0] == 87: # ERROR_INVALID_PARAMETER
595
is_local_pid_dead = _pywin32_is_local_pid_dead
596
elif has_ctypes and sys.platform == 'win32':
597
from ctypes.wintypes import BOOL, DWORD, HANDLE
598
_kernel32 = ctypes.windll.kernel32
599
_CloseHandle = ctypes.WINFUNCTYPE(BOOL, HANDLE)(
600
("CloseHandle", _kernel32))
601
_OpenProcess = ctypes.WINFUNCTYPE(HANDLE, DWORD, BOOL, DWORD)(
602
("OpenProcess", _kernel32))
603
def _ctypes_is_local_pid_dead(pid):
604
"""True if pid doesn't correspond to live process on this machine"""
605
handle = _OpenProcess(1, False, pid) # PROCESS_TERMINATE
607
errorcode = ctypes.GetLastError()
608
if errorcode == 5: # ERROR_ACCESS_DENIED
609
# Probably something alive we're not allowed to kill
611
elif errorcode == 87: # ERROR_INVALID_PARAMETER
613
raise ctypes.WinError(errorcode)
616
is_local_pid_dead = _ctypes_is_local_pid_dead