Mercurial > public > mercurial-scm > hg
comparison mercurial/statprof.py @ 43077:687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Done with
python3.7 contrib/byteify-strings.py -i $(hg files 'set:mercurial/**.py - mercurial/thirdparty/** + hgext/**.py - hgext/fsmonitor/pywatchman/** - mercurial/__init__.py')
black -l 80 -t py33 -S $(hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**" - hgext/fsmonitor/pywatchman/**')
# skip-blame mass-reformatting only
Differential Revision: https://phab.mercurial-scm.org/D6972
author | Augie Fackler <augie@google.com> |
---|---|
date | Sun, 06 Oct 2019 09:48:39 -0400 |
parents | 2372284d9457 |
children | eef9a2d67051 |
comparison
equal
deleted
inserted
replaced
43076:2372284d9457 | 43077:687b865b95ad |
---|---|
120 ) | 120 ) |
121 | 121 |
122 defaultdict = collections.defaultdict | 122 defaultdict = collections.defaultdict |
123 contextmanager = contextlib.contextmanager | 123 contextmanager = contextlib.contextmanager |
124 | 124 |
125 __all__ = ['start', 'stop', 'reset', 'display', 'profile'] | 125 __all__ = [b'start', b'stop', b'reset', b'display', b'profile'] |
126 | 126 |
127 skips = { | 127 skips = { |
128 r"util.py:check", | 128 r"util.py:check", |
129 r"extensions.py:closure", | 129 r"extensions.py:closure", |
130 r"color.py:colorcmd", | 130 r"color.py:colorcmd", |
155 | 155 |
156 | 156 |
157 class ProfileState(object): | 157 class ProfileState(object): |
158 def __init__(self, frequency=None): | 158 def __init__(self, frequency=None): |
159 self.reset(frequency) | 159 self.reset(frequency) |
160 self.track = 'cpu' | 160 self.track = b'cpu' |
161 | 161 |
162 def reset(self, frequency=None): | 162 def reset(self, frequency=None): |
163 # total so far | 163 # total so far |
164 self.accumulated_time = (0.0, 0.0) | 164 self.accumulated_time = (0.0, 0.0) |
165 # start_time when timer is active | 165 # start_time when timer is active |
192 def seconds_per_sample(self): | 192 def seconds_per_sample(self): |
193 return self.accumulated_time[self.timeidx] / len(self.samples) | 193 return self.accumulated_time[self.timeidx] / len(self.samples) |
194 | 194 |
195 @property | 195 @property |
196 def timeidx(self): | 196 def timeidx(self): |
197 if self.track == 'real': | 197 if self.track == b'real': |
198 return 1 | 198 return 1 |
199 return 0 | 199 return 0 |
200 | 200 |
201 | 201 |
202 state = ProfileState() | 202 state = ProfileState() |
236 | 236 |
237 def getsource(self, length): | 237 def getsource(self, length): |
238 if self.source is None: | 238 if self.source is None: |
239 lineno = self.lineno - 1 | 239 lineno = self.lineno - 1 |
240 try: | 240 try: |
241 with open(self.path, 'rb') as fp: | 241 with open(self.path, b'rb') as fp: |
242 for i, line in enumerate(fp): | 242 for i, line in enumerate(fp): |
243 if i == lineno: | 243 if i == lineno: |
244 self.source = line.strip() | 244 self.source = line.strip() |
245 break | 245 break |
246 except: | 246 except: |
247 pass | 247 pass |
248 if self.source is None: | 248 if self.source is None: |
249 self.source = '' | 249 self.source = b'' |
250 | 250 |
251 source = self.source | 251 source = self.source |
252 if len(source) > length: | 252 if len(source) > length: |
253 source = source[: (length - 3)] + "..." | 253 source = source[: (length - 3)] + b"..." |
254 return source | 254 return source |
255 | 255 |
256 def filename(self): | 256 def filename(self): |
257 return os.path.basename(self.path) | 257 return os.path.basename(self.path) |
258 | 258 |
328 | 328 |
329 | 329 |
330 lastmechanism = None | 330 lastmechanism = None |
331 | 331 |
332 | 332 |
333 def start(mechanism='thread', track='cpu'): | 333 def start(mechanism=b'thread', track=b'cpu'): |
334 '''Install the profiling signal handler, and start profiling.''' | 334 '''Install the profiling signal handler, and start profiling.''' |
335 state.track = track # note: nesting different mode won't work | 335 state.track = track # note: nesting different mode won't work |
336 state.profile_level += 1 | 336 state.profile_level += 1 |
337 if state.profile_level == 1: | 337 if state.profile_level == 1: |
338 state.last_start_time = clock() | 338 state.last_start_time = clock() |
340 state.remaining_prof_time = None | 340 state.remaining_prof_time = None |
341 | 341 |
342 global lastmechanism | 342 global lastmechanism |
343 lastmechanism = mechanism | 343 lastmechanism = mechanism |
344 | 344 |
345 if mechanism == 'signal': | 345 if mechanism == b'signal': |
346 signal.signal(signal.SIGPROF, profile_signal_handler) | 346 signal.signal(signal.SIGPROF, profile_signal_handler) |
347 signal.setitimer( | 347 signal.setitimer( |
348 signal.ITIMER_PROF, rpt or state.sample_interval, 0.0 | 348 signal.ITIMER_PROF, rpt or state.sample_interval, 0.0 |
349 ) | 349 ) |
350 elif mechanism == 'thread': | 350 elif mechanism == b'thread': |
351 frame = inspect.currentframe() | 351 frame = inspect.currentframe() |
352 tid = [k for k, f in sys._current_frames().items() if f == frame][0] | 352 tid = [k for k, f in sys._current_frames().items() if f == frame][0] |
353 state.thread = threading.Thread( | 353 state.thread = threading.Thread( |
354 target=samplerthread, args=(tid,), name="samplerthread" | 354 target=samplerthread, args=(tid,), name=b"samplerthread" |
355 ) | 355 ) |
356 state.thread.start() | 356 state.thread.start() |
357 | 357 |
358 | 358 |
359 def stop(): | 359 def stop(): |
360 '''Stop profiling, and uninstall the profiling signal handler.''' | 360 '''Stop profiling, and uninstall the profiling signal handler.''' |
361 state.profile_level -= 1 | 361 state.profile_level -= 1 |
362 if state.profile_level == 0: | 362 if state.profile_level == 0: |
363 if lastmechanism == 'signal': | 363 if lastmechanism == b'signal': |
364 rpt = signal.setitimer(signal.ITIMER_PROF, 0.0, 0.0) | 364 rpt = signal.setitimer(signal.ITIMER_PROF, 0.0, 0.0) |
365 signal.signal(signal.SIGPROF, signal.SIG_IGN) | 365 signal.signal(signal.SIGPROF, signal.SIG_IGN) |
366 state.remaining_prof_time = rpt[0] | 366 state.remaining_prof_time = rpt[0] |
367 elif lastmechanism == 'thread': | 367 elif lastmechanism == b'thread': |
368 stopthread.set() | 368 stopthread.set() |
369 state.thread.join() | 369 state.thread.join() |
370 | 370 |
371 state.accumulate_time(clock()) | 371 state.accumulate_time(clock()) |
372 state.last_start_time = None | 372 state.last_start_time = None |
373 statprofpath = encoding.environ.get('STATPROF_DEST') | 373 statprofpath = encoding.environ.get(b'STATPROF_DEST') |
374 if statprofpath: | 374 if statprofpath: |
375 save_data(statprofpath) | 375 save_data(statprofpath) |
376 | 376 |
377 return state | 377 return state |
378 | 378 |
379 | 379 |
380 def save_data(path): | 380 def save_data(path): |
381 with open(path, 'w+') as file: | 381 with open(path, b'w+') as file: |
382 file.write("%f %f\n" % state.accumulated_time) | 382 file.write(b"%f %f\n" % state.accumulated_time) |
383 for sample in state.samples: | 383 for sample in state.samples: |
384 time = sample.time | 384 time = sample.time |
385 stack = sample.stack | 385 stack = sample.stack |
386 sites = [ | 386 sites = [ |
387 '\1'.join([s.path, b'%d' % s.lineno, s.function]) for s in stack | 387 b'\1'.join([s.path, b'%d' % s.lineno, s.function]) |
388 for s in stack | |
388 ] | 389 ] |
389 file.write("%d\0%s\n" % (time, '\0'.join(sites))) | 390 file.write(b"%d\0%s\n" % (time, b'\0'.join(sites))) |
390 | 391 |
391 | 392 |
392 def load_data(path): | 393 def load_data(path): |
393 lines = open(path, 'rb').read().splitlines() | 394 lines = open(path, b'rb').read().splitlines() |
394 | 395 |
395 state.accumulated_time = [float(value) for value in lines[0].split()] | 396 state.accumulated_time = [float(value) for value in lines[0].split()] |
396 state.samples = [] | 397 state.samples = [] |
397 for line in lines[1:]: | 398 for line in lines[1:]: |
398 parts = line.split('\0') | 399 parts = line.split(b'\0') |
399 time = float(parts[0]) | 400 time = float(parts[0]) |
400 rawsites = parts[1:] | 401 rawsites = parts[1:] |
401 sites = [] | 402 sites = [] |
402 for rawsite in rawsites: | 403 for rawsite in rawsites: |
403 siteparts = rawsite.split('\1') | 404 siteparts = rawsite.split(b'\1') |
404 sites.append( | 405 sites.append( |
405 CodeSite.get(siteparts[0], int(siteparts[1]), siteparts[2]) | 406 CodeSite.get(siteparts[0], int(siteparts[1]), siteparts[2]) |
406 ) | 407 ) |
407 | 408 |
408 state.samples.append(Sample(sites, time)) | 409 state.samples.append(Sample(sites, time)) |
412 '''Clear out the state of the profiler. Do not call while the | 413 '''Clear out the state of the profiler. Do not call while the |
413 profiler is running. | 414 profiler is running. |
414 | 415 |
415 The optional frequency argument specifies the number of samples to | 416 The optional frequency argument specifies the number of samples to |
416 collect per second.''' | 417 collect per second.''' |
417 assert state.profile_level == 0, "Can't reset() while statprof is running" | 418 assert state.profile_level == 0, b"Can't reset() while statprof is running" |
418 CodeSite.cache.clear() | 419 CodeSite.cache.clear() |
419 state.reset(frequency) | 420 state.reset(frequency) |
420 | 421 |
421 | 422 |
422 @contextmanager | 423 @contextmanager |
512 elif format == DisplayFormats.Json: | 513 elif format == DisplayFormats.Json: |
513 write_to_json(data, fp) | 514 write_to_json(data, fp) |
514 elif format == DisplayFormats.Chrome: | 515 elif format == DisplayFormats.Chrome: |
515 write_to_chrome(data, fp, **kwargs) | 516 write_to_chrome(data, fp, **kwargs) |
516 else: | 517 else: |
517 raise Exception("Invalid display format") | 518 raise Exception(b"Invalid display format") |
518 | 519 |
519 if format not in (DisplayFormats.Json, DisplayFormats.Chrome): | 520 if format not in (DisplayFormats.Json, DisplayFormats.Chrome): |
520 fp.write(b'---\n') | 521 fp.write(b'---\n') |
521 fp.write(b'Sample count: %d\n' % len(data.samples)) | 522 fp.write(b'Sample count: %d\n' % len(data.samples)) |
522 fp.write(b'Total time: %f seconds (%f wall)\n' % data.accumulated_time) | 523 fp.write(b'Total time: %f seconds (%f wall)\n' % data.accumulated_time) |
537 % (b"time", b"seconds", b"seconds", b"name") | 538 % (b"time", b"seconds", b"seconds", b"name") |
538 ) | 539 ) |
539 | 540 |
540 for stat in stats: | 541 for stat in stats: |
541 site = stat.site | 542 site = stat.site |
542 sitelabel = '%s:%d:%s' % (site.filename(), site.lineno, site.function) | 543 sitelabel = b'%s:%d:%s' % (site.filename(), site.lineno, site.function) |
543 fp.write( | 544 fp.write( |
544 b'%6.2f %9.2f %9.2f %s\n' | 545 b'%6.2f %9.2f %9.2f %s\n' |
545 % ( | 546 % ( |
546 stat.selfpercent(), | 547 stat.selfpercent(), |
547 stat.totalseconds(), | 548 stat.totalseconds(), |
554 def display_by_method(data, fp): | 555 def display_by_method(data, fp): |
555 '''Print the profiler data with each sample function represented | 556 '''Print the profiler data with each sample function represented |
556 as one row in a table. Important lines within that function are | 557 as one row in a table. Important lines within that function are |
557 output as nested rows. Sorted by self-time per line.''' | 558 output as nested rows. Sorted by self-time per line.''' |
558 fp.write( | 559 fp.write( |
559 b'%5.5s %10.10s %7.7s %-8.8s\n' % ('% ', 'cumulative', 'self', '') | 560 b'%5.5s %10.10s %7.7s %-8.8s\n' |
561 % (b'% ', b'cumulative', b'self', b'') | |
560 ) | 562 ) |
561 fp.write( | 563 fp.write( |
562 b'%5.5s %9.9s %8.8s %-8.8s\n' | 564 b'%5.5s %9.9s %8.8s %-8.8s\n' |
563 % ("time", "seconds", "seconds", "name") | 565 % (b"time", b"seconds", b"seconds", b"name") |
564 ) | 566 ) |
565 | 567 |
566 stats = SiteStats.buildstats(data.samples) | 568 stats = SiteStats.buildstats(data.samples) |
567 | 569 |
568 grouped = defaultdict(list) | 570 grouped = defaultdict(list) |
620 fp.write(b'%33.0f%% %6.2f line %d: %s\n' % stattuple) | 622 fp.write(b'%33.0f%% %6.2f line %d: %s\n' % stattuple) |
621 | 623 |
622 | 624 |
623 def display_about_method(data, fp, function=None, **kwargs): | 625 def display_about_method(data, fp, function=None, **kwargs): |
624 if function is None: | 626 if function is None: |
625 raise Exception("Invalid function") | 627 raise Exception(b"Invalid function") |
626 | 628 |
627 filename = None | 629 filename = None |
628 if ':' in function: | 630 if b':' in function: |
629 filename, function = function.split(':') | 631 filename, function = function.split(b':') |
630 | 632 |
631 relevant_samples = 0 | 633 relevant_samples = 0 |
632 parents = {} | 634 parents = {} |
633 children = {} | 635 children = {} |
634 | 636 |
683 total_cum_percent += stat.totalpercent() | 685 total_cum_percent += stat.totalpercent() |
684 | 686 |
685 fp.write( | 687 fp.write( |
686 b'\n %s:%s Total: %0.2fs (%0.2f%%) Self: %0.2fs (%0.2f%%)\n\n' | 688 b'\n %s:%s Total: %0.2fs (%0.2f%%) Self: %0.2fs (%0.2f%%)\n\n' |
687 % ( | 689 % ( |
688 pycompat.sysbytes(filename or '___'), | 690 pycompat.sysbytes(filename or b'___'), |
689 pycompat.sysbytes(function), | 691 pycompat.sysbytes(function), |
690 total_cum_sec, | 692 total_cum_sec, |
691 total_cum_percent, | 693 total_cum_percent, |
692 total_self_sec, | 694 total_self_sec, |
693 total_self_percent, | 695 total_self_percent, |
744 for c in node.children.itervalues() | 746 for c in node.children.itervalues() |
745 if c.count >= (limit * root.count) | 747 if c.count >= (limit * root.count) |
746 ] | 748 ] |
747 if site: | 749 if site: |
748 indent = depth * 2 - 1 | 750 indent = depth * 2 - 1 |
749 filename = '' | 751 filename = b'' |
750 function = '' | 752 function = b'' |
751 if len(node.children) > 0: | 753 if len(node.children) > 0: |
752 childsite = list(node.children.itervalues())[0].site | 754 childsite = list(node.children.itervalues())[0].site |
753 filename = (childsite.filename() + ':').ljust(15) | 755 filename = (childsite.filename() + b':').ljust(15) |
754 function = childsite.function | 756 function = childsite.function |
755 | 757 |
756 # lots of string formatting | 758 # lots of string formatting |
757 listpattern = ( | 759 listpattern = ( |
758 ''.ljust(indent) | 760 b''.ljust(indent) |
759 + ('\\' if multiple_siblings else '|') | 761 + (b'\\' if multiple_siblings else b'|') |
760 + ' %4.1f%%' | 762 + b' %4.1f%%' |
761 + (' %5.2fs' % node.count if showtime else '') | 763 + (b' %5.2fs' % node.count if showtime else b'') |
762 + ' %s %s' | 764 + b' %s %s' |
763 ) | 765 ) |
764 liststring = listpattern % ( | 766 liststring = listpattern % ( |
765 node.count / root.count * 100, | 767 node.count / root.count * 100, |
766 filename, | 768 filename, |
767 function, | 769 function, |
768 ) | 770 ) |
769 codepattern = '%' + ('%d' % (55 - len(liststring))) + 's %d: %s' | 771 codepattern = b'%' + (b'%d' % (55 - len(liststring))) + b's %d: %s' |
770 codestring = codepattern % ('line', site.lineno, site.getsource(30)) | 772 codestring = codepattern % ( |
773 b'line', | |
774 site.lineno, | |
775 site.getsource(30), | |
776 ) | |
771 | 777 |
772 finalstring = liststring + codestring | 778 finalstring = liststring + codestring |
773 childrensamples = sum([c.count for c in node.children.itervalues()]) | 779 childrensamples = sum([c.count for c in node.children.itervalues()]) |
774 # Make frames that performed more than 10% of the operation red | 780 # Make frames that performed more than 10% of the operation red |
775 if node.count - childrensamples > (0.1 * root.count): | 781 if node.count - childrensamples > (0.1 * root.count): |
776 finalstring = '\033[91m' + finalstring + '\033[0m' | 782 finalstring = b'\033[91m' + finalstring + b'\033[0m' |
777 # Make frames that didn't actually perform work dark grey | 783 # Make frames that didn't actually perform work dark grey |
778 elif node.count - childrensamples == 0: | 784 elif node.count - childrensamples == 0: |
779 finalstring = '\033[90m' + finalstring + '\033[0m' | 785 finalstring = b'\033[90m' + finalstring + b'\033[0m' |
780 fp.write(finalstring + b'\n') | 786 fp.write(finalstring + b'\n') |
781 | 787 |
782 newdepth = depth | 788 newdepth = depth |
783 if len(visiblechildren) > 1 or multiple_siblings: | 789 if len(visiblechildren) > 1 or multiple_siblings: |
784 newdepth += 1 | 790 newdepth += 1 |
791 _write(root, 0, False) | 797 _write(root, 0, False) |
792 | 798 |
793 | 799 |
794 def write_to_flame(data, fp, scriptpath=None, outputfile=None, **kwargs): | 800 def write_to_flame(data, fp, scriptpath=None, outputfile=None, **kwargs): |
795 if scriptpath is None: | 801 if scriptpath is None: |
796 scriptpath = encoding.environ['HOME'] + '/flamegraph.pl' | 802 scriptpath = encoding.environ[b'HOME'] + b'/flamegraph.pl' |
797 if not os.path.exists(scriptpath): | 803 if not os.path.exists(scriptpath): |
798 fp.write(b'error: missing %s\n' % scriptpath) | 804 fp.write(b'error: missing %s\n' % scriptpath) |
799 fp.write(b'get it here: https://github.com/brendangregg/FlameGraph\n') | 805 fp.write(b'get it here: https://github.com/brendangregg/FlameGraph\n') |
800 return | 806 return |
801 | 807 |
802 lines = {} | 808 lines = {} |
803 for sample in data.samples: | 809 for sample in data.samples: |
804 sites = [s.function for s in sample.stack] | 810 sites = [s.function for s in sample.stack] |
805 sites.reverse() | 811 sites.reverse() |
806 line = ';'.join(sites) | 812 line = b';'.join(sites) |
807 if line in lines: | 813 if line in lines: |
808 lines[line] = lines[line] + 1 | 814 lines[line] = lines[line] + 1 |
809 else: | 815 else: |
810 lines[line] = 1 | 816 lines[line] = 1 |
811 | 817 |
812 fd, path = pycompat.mkstemp() | 818 fd, path = pycompat.mkstemp() |
813 | 819 |
814 with open(path, "w+") as file: | 820 with open(path, b"w+") as file: |
815 for line, count in lines.iteritems(): | 821 for line, count in lines.iteritems(): |
816 file.write("%s %d\n" % (line, count)) | 822 file.write(b"%s %d\n" % (line, count)) |
817 | 823 |
818 if outputfile is None: | 824 if outputfile is None: |
819 outputfile = '~/flamegraph.svg' | 825 outputfile = b'~/flamegraph.svg' |
820 | 826 |
821 os.system("perl ~/flamegraph.pl %s > %s" % (path, outputfile)) | 827 os.system(b"perl ~/flamegraph.pl %s > %s" % (path, outputfile)) |
822 fp.write(b'Written to %s\n' % outputfile) | 828 fp.write(b'Written to %s\n' % outputfile) |
823 | 829 |
824 | 830 |
825 _pathcache = {} | 831 _pathcache = {} |
826 | 832 |
981 ) | 987 ) |
982 data = json.dumps(dict(traceEvents=events, stackFrames=frames), indent=1) | 988 data = json.dumps(dict(traceEvents=events, stackFrames=frames), indent=1) |
983 if not isinstance(data, bytes): | 989 if not isinstance(data, bytes): |
984 data = data.encode('utf-8') | 990 data = data.encode('utf-8') |
985 fp.write(data) | 991 fp.write(data) |
986 fp.write('\n') | 992 fp.write(b'\n') |
987 | 993 |
988 | 994 |
989 def printusage(): | 995 def printusage(): |
990 print( | 996 print( |
991 r""" | 997 r""" |
1018 return 0 | 1024 return 0 |
1019 | 1025 |
1020 displayargs = {} | 1026 displayargs = {} |
1021 | 1027 |
1022 optstart = 2 | 1028 optstart = 2 |
1023 displayargs['function'] = None | 1029 displayargs[b'function'] = None |
1024 if argv[1] == r'hotpath': | 1030 if argv[1] == r'hotpath': |
1025 displayargs['format'] = DisplayFormats.Hotpath | 1031 displayargs[b'format'] = DisplayFormats.Hotpath |
1026 elif argv[1] == r'lines': | 1032 elif argv[1] == r'lines': |
1027 displayargs['format'] = DisplayFormats.ByLine | 1033 displayargs[b'format'] = DisplayFormats.ByLine |
1028 elif argv[1] == r'functions': | 1034 elif argv[1] == r'functions': |
1029 displayargs['format'] = DisplayFormats.ByMethod | 1035 displayargs[b'format'] = DisplayFormats.ByMethod |
1030 elif argv[1] == r'function': | 1036 elif argv[1] == r'function': |
1031 displayargs['format'] = DisplayFormats.AboutMethod | 1037 displayargs[b'format'] = DisplayFormats.AboutMethod |
1032 displayargs['function'] = argv[2] | 1038 displayargs[b'function'] = argv[2] |
1033 optstart = 3 | 1039 optstart = 3 |
1034 elif argv[1] == r'flame': | 1040 elif argv[1] == r'flame': |
1035 displayargs['format'] = DisplayFormats.FlameGraph | 1041 displayargs[b'format'] = DisplayFormats.FlameGraph |
1036 else: | 1042 else: |
1037 printusage() | 1043 printusage() |
1038 return 0 | 1044 return 0 |
1039 | 1045 |
1040 # process options | 1046 # process options |
1041 try: | 1047 try: |
1042 opts, args = pycompat.getoptb( | 1048 opts, args = pycompat.getoptb( |
1043 sys.argv[optstart:], | 1049 sys.argv[optstart:], |
1044 "hl:f:o:p:", | 1050 b"hl:f:o:p:", |
1045 ["help", "limit=", "file=", "output-file=", "script-path="], | 1051 [b"help", b"limit=", b"file=", b"output-file=", b"script-path="], |
1046 ) | 1052 ) |
1047 except getopt.error as msg: | 1053 except getopt.error as msg: |
1048 print(msg) | 1054 print(msg) |
1049 printusage() | 1055 printusage() |
1050 return 2 | 1056 return 2 |
1051 | 1057 |
1052 displayargs['limit'] = 0.05 | 1058 displayargs[b'limit'] = 0.05 |
1053 path = None | 1059 path = None |
1054 for o, value in opts: | 1060 for o, value in opts: |
1055 if o in (r"-l", r"--limit"): | 1061 if o in (r"-l", r"--limit"): |
1056 displayargs['limit'] = float(value) | 1062 displayargs[b'limit'] = float(value) |
1057 elif o in (r"-f", r"--file"): | 1063 elif o in (r"-f", r"--file"): |
1058 path = value | 1064 path = value |
1059 elif o in (r"-o", r"--output-file"): | 1065 elif o in (r"-o", r"--output-file"): |
1060 displayargs['outputfile'] = value | 1066 displayargs[b'outputfile'] = value |
1061 elif o in (r"-p", r"--script-path"): | 1067 elif o in (r"-p", r"--script-path"): |
1062 displayargs['scriptpath'] = value | 1068 displayargs[b'scriptpath'] = value |
1063 elif o in (r"-h", r"help"): | 1069 elif o in (r"-h", r"help"): |
1064 printusage() | 1070 printusage() |
1065 return 0 | 1071 return 0 |
1066 else: | 1072 else: |
1067 assert False, "unhandled option %s" % o | 1073 assert False, b"unhandled option %s" % o |
1068 | 1074 |
1069 if not path: | 1075 if not path: |
1070 print(r'must specify --file to load') | 1076 print(r'must specify --file to load') |
1071 return 1 | 1077 return 1 |
1072 | 1078 |