@@ -426,25 +426,35 @@ def __str__(self): |
426 | 426 |
|
427 | 427 | class Formatter: |
428 | 428 |
|
429 | | - def __init__(self, file=None, lineno_width=0, offset_width=0, label_width=0, |
430 | | - line_offset=0, show_caches=False, *, positions_width=0): |
| 429 | + def __init__(self, file=None, lineno_width=None, offset_width=0, label_width=0, |
| 430 | + line_offset=0, show_caches=False, *, locations_width=0, |
| 431 | + show_positions=False): |
431 | 432 | """Create a Formatter |
432 | 433 |
|
433 | 434 | *file* where to write the output |
434 | | - *lineno_width* sets the width of the line number field (0 omits it) |
| 435 | + *lineno_width* sets the width of the line number field (deprecated) |
435 | 436 | *offset_width* sets the width of the instruction offset field |
436 | 437 | *label_width* sets the width of the label field |
437 | 438 | *show_caches* is a boolean indicating whether to display cache lines |
438 | | - *positions_width* sets the width of the instruction positions field (0 omits it) |
439 | | -
|
440 | | - If *positions_width* is specified, *lineno_width* is ignored. |
| 439 | + *locations_width* sets the width of the instruction locations (0 omits it) |
| 440 | + *show_positions* is a boolean indicating whether positions should be |
| 441 | + reported instead of line numbers |
441 | 442 | """ |
| 443 | + if lineno_width is not None: |
| 444 | + import warnings |
| 445 | + warnings.warn("The 'lineno_width' parameter is deprecated. It is " |
| 446 | + "now ignored and will be removed in Python 3.16. " |
| 447 | + "Use 'locations_width' instead.", |
| 448 | + DeprecationWarning, stacklevel=2) |
| 449 | + |
442 | 450 | self.file = file |
443 | | - self.lineno_width = lineno_width |
| 451 | + # keep the attribute in case someone is still using it |
| 452 | + self.lineno_width = 0 if lineno_width is None else lineno_width |
| 453 | + self.locations_width = locations_width |
444 | 454 | self.offset_width = offset_width |
445 | 455 | self.label_width = label_width |
446 | 456 | self.show_caches = show_caches |
447 | | - self.positions_width = positions_width |
| 457 | + self.show_positions = show_positions |
448 | 458 |
|
449 | 459 | def print_instruction(self, instr, mark_as_current=False): |
450 | 460 | self.print_instruction_line(instr, mark_as_current) |
@@ -466,35 +476,35 @@ def print_instruction(self, instr, mark_as_current=False): |
466 | 476 |
|
467 | 477 | def print_instruction_line(self, instr, mark_as_current): |
468 | 478 | """Format instruction details for inclusion in disassembly output.""" |
469 | | - lineno_width = self.lineno_width |
470 | | - positions_width = self.positions_width |
| 479 | + locations_width = self.locations_width |
471 | 480 | offset_width = self.offset_width |
472 | 481 | label_width = self.label_width |
473 | 482 |
|
474 | | - new_source_line = ((lineno_width > 0 or positions_width > 0) and |
| 483 | + new_source_line = ((locations_width > 0) and |
475 | 484 | instr.starts_line and |
476 | 485 | instr.offset > 0) |
477 | 486 | if new_source_line: |
478 | 487 | print(file=self.file) |
479 | 488 |
|
480 | 489 | fields = [] |
481 | | - # Column: Source code line number |
482 | | - if positions_width: |
483 | | - # reporting positions instead of just line numbers |
484 | | - if instr_positions := instr.positions: |
485 | | - ps = tuple('?' if p is None else p for p in instr_positions) |
486 | | - positions_str = f"{ps[0]}:{ps[2]}-{ps[1]}:{ps[3]}" |
487 | | - fields.append(f'{positions_str:{positions_width}}') |
488 | | - else: |
489 | | - fields.append(' ' * positions_width) |
490 | | - elif lineno_width: |
491 | | - if instr.starts_line: |
492 | | - lineno_fmt = "%%%dd" if instr.line_number is not None else "%%%ds" |
493 | | - lineno_fmt = lineno_fmt % lineno_width |
494 | | - lineno = _NO_LINENO if instr.line_number is None else instr.line_number |
495 | | - fields.append(lineno_fmt % lineno) |
| 490 | + # Column: Source code locations information |
| 491 | + if locations_width: |
| 492 | + if self.show_positions: |
| 493 | + # reporting positions instead of just line numbers |
| 494 | + if instr_positions := instr.positions: |
| 495 | + ps = tuple('?' if p is None else p for p in instr_positions) |
| 496 | + positions_str = f"{ps[0]}:{ps[2]}-{ps[1]}:{ps[3]}" |
| 497 | + fields.append(f'{positions_str:{locations_width}}') |
| 498 | + else: |
| 499 | + fields.append(' ' * locations_width) |
496 | 500 | else: |
497 | | - fields.append(' ' * lineno_width) |
| 501 | + if instr.starts_line: |
| 502 | + lineno_fmt = "%%%dd" if instr.line_number is not None else "%%%ds" |
| 503 | + lineno_fmt = lineno_fmt % locations_width |
| 504 | + lineno = _NO_LINENO if instr.line_number is None else instr.line_number |
| 505 | + fields.append(lineno_fmt % lineno) |
| 506 | + else: |
| 507 | + fields.append(' ' * locations_width) |
498 | 508 | # Column: Label |
499 | 509 | if instr.label is not None: |
500 | 510 | lbl = f"L{instr.label}:" |
@@ -785,15 +795,18 @@ def disassemble(co, lasti=-1, *, file=None, show_caches=False, adaptive=False, |
785 | 795 | """Disassemble a code object.""" |
786 | 796 | linestarts = dict(findlinestarts(co)) |
787 | 797 | exception_entries = _parse_exception_table(co) |
788 | | - positions_width = _get_positions_width(co) if show_positions else 0 |
| 798 | + if show_positions: |
| 799 | + locations_width = _get_positions_width(co) |
| 800 | + else: |
| 801 | + locations_width = _get_lineno_width(linestarts) |
789 | 802 | labels_map = _make_labels_map(co.co_code, exception_entries=exception_entries) |
790 | 803 | label_width = 4 + len(str(len(labels_map))) |
791 | 804 | formatter = Formatter(file=file, |
792 | | - lineno_width=_get_lineno_width(linestarts), |
793 | 805 | offset_width=len(str(max(len(co.co_code) - 2, 9999))) if show_offsets else 0, |
794 | | - positions_width=positions_width, |
| 806 | + locations_width=locations_width, |
795 | 807 | label_width=label_width, |
796 | | - show_caches=show_caches) |
| 808 | + show_caches=show_caches, |
| 809 | + show_positions=show_positions) |
797 | 810 | arg_resolver = ArgResolver(co_consts=co.co_consts, |
798 | 811 | names=co.co_names, |
799 | 812 | varname_from_oparg=co._varname_from_oparg, |
@@ -1065,17 +1078,19 @@ def dis(self): |
1065 | 1078 | with io.StringIO() as output: |
1066 | 1079 | code = _get_code_array(co, self.adaptive) |
1067 | 1080 | offset_width = len(str(max(len(code) - 2, 9999))) if self.show_offsets else 0 |
1068 | | - positions_width = _get_positions_width(co) if self.show_positions else 0 |
1069 | | - |
| 1081 | + if self.show_positions: |
| 1082 | + locations_width = _get_positions_width(co) |
| 1083 | + else: |
| 1084 | + locations_width = _get_lineno_width(self._linestarts) |
1070 | 1085 | labels_map = _make_labels_map(co.co_code, self.exception_entries) |
1071 | 1086 | label_width = 4 + len(str(len(labels_map))) |
1072 | 1087 | formatter = Formatter(file=output, |
1073 | | - lineno_width=_get_lineno_width(self._linestarts), |
1074 | 1088 | offset_width=offset_width, |
1075 | | - positions_width=positions_width, |
| 1089 | + locations_width=locations_width, |
1076 | 1090 | label_width=label_width, |
1077 | 1091 | line_offset=self._line_offset, |
1078 | | - show_caches=self.show_caches) |
| 1092 | + show_caches=self.show_caches, |
| 1093 | + show_positions=self.show_positions) |
1079 | 1094 |
|
1080 | 1095 | arg_resolver = ArgResolver(co_consts=co.co_consts, |
1081 | 1096 | names=co.co_names, |
|