classification
Title: Refactor the dis module to provide better building blocks for bytecode analysis
Type: enhancement Stage: resolved
Components: Library (Lib) Versions: Python 3.4
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: ncoghlan Nosy List: alex, belopolsky, eric.snow, haypo, jcea, loewis, meador.inge, ncoghlan, neologix, pitrou, python-dev, rfk, rhettinger, ron_adam, takluyver, yselivanov
Priority: normal Keywords: patch

Created on 2011-04-10 00:20 by eltoder, last changed 2013-05-07 09:55 by ncoghlan. This issue is now closed.

Files
File name Uploaded Description Edit
issue11816_get_opinfo_branch_20111204.diff ncoghlan, 2011-12-04 07:36 Remote diff against python.org after merging from default review
5ce60675e572.diff ncoghlan, 2011-12-05 00:00 review
dis_api.diff takluyver, 2013-02-12 17:49 review
dis_api2.diff takluyver, 2013-02-18 13:40 Updated patch after review review
dis_api3.diff takluyver, 2013-04-06 19:14 + Bytecode docs and tests review
test_peepholer.diff takluyver, 2013-04-06 19:15 use bytecode_helper in test_peepholer review
Repositories containing patches
https://bitbucket.org/ncoghlan/cpython_sandbox#get_opinfo
Messages (47)
msg133437 - (view) Author: Eugene Toder (eltoder) Date: 2011-04-10 00:20
As discussed in Issue11549 a couple of tests need to inspect disassembly of some code. Currently they have to override sys.stdout, run dis and restore stdout back. It would be much nicer if dis module provided functions that return disassembly as a string.

Provided is a patch that adds file argument to most dis functions, defaulting to sys.stdout. On top of that there are 2 new functions: dis_to_str and disassembly_to_str that return disassembly as a string instead of writing it to a file.
msg133438 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2011-04-10 02:08
Inspecting the text disassembly is a bit fragile for testing.  It would be better to scan a list of (opcode, oparg) pairs for given pattern (i.e. (LOAD_CONST, 3) where consts[3] --> some target value).
msg133439 - (view) Author: Eugene Toder (eltoder) Date: 2011-04-10 02:17
Agreed, but that would require rewriting of all tests in test_peepholer.
msg133441 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2011-04-10 02:44
Yep!
msg133464 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2011-04-10 13:55
I really like the idea of adding some lower level infrastructure to dis to make it generator based, making the disassembly more amenable to programmatic manipulation.

Consider if, for each line disassemble() currently prints, we had an underlying iterator that yielded a named tuple consisting of (index, opcode, oparg, linestart, details). I've created a proof-of-concept for that in my sandbox (http://hg.python.org/sandbox/ncoghlan/file/get_opinfo/Lib/dis.py) which adds a get_opinfo() function that does exactly. With disassemble() rewritten to use that, test_dis and test_peepholer still pass as currently written.

Near-term, test_peepholer could easily continue to do what it does now (i.e. use the higher level dis() function and redirect sys.stdout). Longer term, it could be written to analyse the opcode stream instead of doing string comparisons.
msg133465 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2011-04-10 13:57
Changed issue title to cover ideas like get_opinfo().
msg133466 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2011-04-10 13:58
Oops, I forgot to edit my comment to match the OpInfo definition I used in the proof-of-concept:

OpInfo = collections.namedtuple("OpInfo",
            "opindex opcode opname oparg details starts_line is_jump_target")
msg133467 - (view) Author: Eugene Toder (eltoder) Date: 2011-04-10 14:05
So in the near term, dis-based tests should continue to copy/paste sys.stdout redirection code?
msg133471 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2011-04-10 15:46
If we decide our long term goal is the use of the opcode stream for programmatic access, then yes.
msg133479 - (view) Author: Alex Gaynor (alex) * (Python committer) Date: 2011-04-10 20:28
FWIW in PyPy we have https://bitbucket.org/pypy/pypy/src/default/lib_pypy/disassembler.py which we use for some of our tools.
msg133521 - (view) Author: Jesús Cea Avión (jcea) * (Python committer) Date: 2011-04-11 14:18
Do not forget to update docs too.
msg142825 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2011-08-23 13:50
Nick, I still want to work on this one.
msg142831 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2011-08-23 14:50
The diff generator didn't work - I've uploaded the current patch manually to make it easier to review than it is in my bitbucket repo.

I just noticed there's a missing element in the docs patch at the moment - to make testing easier, Ryan added a 'file' argument to the various print-based dis functions so the output can easily be captured in a StringIO object. The docs updates don't currently reflect that, they only cover the OpInfo and get_opinfo additions (along with a clarification of the dis module's slightly odd use of the term 'free').

Aside from that, the core concept of the patch is pretty simple:
- add dis.OpInfo and dis.get_opinfo() to make it easier to walk the bytecode programmatically
- eliminate a lot of the logic duplication inside dis by refactoring more of the operations to internally rely on get_opinfo()
- add a new test.bytecode_helper.BytecodeTestCase with some convenient assertions for checking code generation
- update test_peepholer to be independent of the disassembly formatting details
- add tests for the new features to test_dis (but keep the old detailed formatting tests)

One potential criticism is the complexity of the 'expected output' for the new OpInfoTestCase, but it seemed worth it to vet the way the new code handles several cases. The programmatic nature makes the opcode sequences much easier to read and maintain than the corresponding formatted output tests would have been.

These new tests also cover an error that the previous incarnation of the test suite missed completely (I had a bug at one point where I had incorrectly omitted the second half of the list of cell names - there was no test to check that the disassembler handled references to such names correctly)
msg143491 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2011-09-04 11:07
Regenerated the get_opinfo patch against current 3.3 tip.

Still haven't fixed the missing doc updates mentioned in my last message, though.
msg144322 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2011-09-20 09:26
Attached patch should now be complete, including the documentation for the new keyword-only 'file' parameter on various dis module functions.
msg144400 - (view) Author: Meador Inge (meador.inge) * (Python committer) Date: 2011-09-22 04:02
I took a quick look over the final patch (I will do a more thorough
review later).  I like the general idea a lot.  The first thing that
popped out at me are the names 'OpInfo' and 'get_opinfo'.

'OpInfo' makes it sound like information concerning only the opcode, but
these objects really represent bytecode instructions.  I see a lot
of code in the future like:

    for opinfo in dis.get_opinfo(thing):
        process(opinfo)

which seems vague.  The following seems clearer to me:

    for instr in dis.bytecode_instructions(thing):
        process(instr)

And instead of 'OpInfo' perhaps 'ByteCodeInstruction'.  Even the current
'dis' documentation uses the terminology "Byte Code Instruction".
msg144401 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2011-09-22 04:28
'Op' is just an abbreviation of 'operation'. So 'operation code' becomes 'opcode' and 'operation information' becomes 'opinfo'. The fact that it comes for the 'dis' module gives the context that the *kind* of operation we're talking about is a Python byte code instruction.

When people are hacking on bytecode in the future, they'll likely end up using get_opinfo() a fair bit, so swapping the succinct 'opinfo' for the verbose 'bytecode_instruction' strikes me as a poor trade-off.
msg144409 - (view) Author: Meador Inge (meador.inge) * (Python committer) Date: 2011-09-22 14:30
I agree that 'bytecode_instructions' is a long-winded.  FWIW, I
have worked on or with a fair amount instruction level things and
"instruction" or "instr" seem to be the established domain terminology.

Here are a few examples:

* Java ASM - http://asm.ow2.org/asm33/javadoc/user/index.html
   - Classes named 'InsnList', 'InsnNode'
* PyPy - https://bitbucket.org/pypy/pypy/src/default/pypy/interpreter/astcompiler/assemble.py
   - class named 'Instruction'
* Python - http://hg.python.org/cpython/file/a06ef7ab7321/Python/compile.c#l45
   - struct named 'instr'
* binutils - http://sourceware.org/git/?p=binutils.git;a=tree
   - structs, variables, etc ... with use of 'insn' and 'instruction'
* gcc - http://gcc.gnu.org/git/?p=gcc.git;a=tree
   - structs, variables, etc ... with use of 'insn' and 'instruction'
msg146694 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2011-10-31 12:51
Bitbucket repo and attached patch updated relative to current tip.
msg148227 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2011-11-24 03:56
Meador's suggested name change has grown on me, so I plan to switch the name of the new API to "get_instructions()" and the new class to "Instruction".
msg148382 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2011-11-26 06:41
Somewhat inevitably, the detailed disassembler tests broke when Antoine updated the code generation for function definitions (as part of PEP 3155). (At least, the tests broke, and PEP 3155 seems the most likely culprit).

I subsequently realised there's a potential opportunity here: if Instruction objects define an __eq__ method instead of relying on the custom "assertBytecodeExactlyMatches" helper method the new disassembly tests currently use, then the sequence diffing functionality in unittest could be very helpful in identifying and fixing discrepancies between actual output and expected output.

However, the assertBytecodeExactlyMatches() API has this concept of a "line_offset" which it uses to cope with some of the introspection fodder moving around in the files, so the question then becomes how to deal with that in the context of an __eq__ implementation.

Accordingly, my current plan is to offer "line_offset" as a keyword-only argument to get_instructions() itself. That way, the entire sequence of generated bytecode can easily be adjusted to (for example), be based around the first line being line 1, even if the actual code object being disassembled is located elsewhere in the original source file.
msg148383 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2011-11-26 08:38
I have updated my BitBucket repo with the following changes:

- the main API is now dis.get_instructions()
- the info class is now dis.Instruction
- get_instructions() accepts a 'line_offset' argument that is added to any source code line numbers
- the printing of individual lines in all the disassembly operations is now handled by a private Instruction._disassemble() helper method
- assertBytecodeExactlyMatches now relies on the list comparison machinery in unittest, as well as the Instruction.__eq__ implementation provide by collections.namedtuple (this gives *much* better error messages when discrepancies are found)
- to further improve error messages reported by unittest (which can truncate representations), the order of the Instruction fields now has 'opname' first, then 'opcode', then the remaining fields.
msg148833 - (view) Author: Ron Adam (ron_adam) * Date: 2011-12-04 04:17
Instead of a get_instructions() function, How about using a DisCode class that defines the API for accessing Opinfo tuples of a disassembled object.

So instead of...

    for instr in dis.bytecode_instructions(thing):
        process(instr)

You could use...

    for instr in dis.DisCode(thing):
        process(instr)

And I would like to be able to do...

    assertEqual(DisCode(thing1), DisCode(thing2))


It could also have a .dis() method that returns formatted output that matches what dis() currently prints.  That would allow tests that use dis.dis() to get rid of capturing stdout with minimal changes.

     result = DisCode(func).dis()  # return a dis compatible string.

A DisCode object also offers a nice place to put documentation for the various pieces and an overall view of the new API without getting it confused with the current dis.dis() API.

It's easier for me to remember an object with methods than several separate but related functions. (YMMV)

This is very near a version of dis I did a while back where I removed the prints and returned a list of list object from dis.dis().  The returned object had __repr__ that formatted the data so it matched the current dis output.  That made it work the same in a python shell. But I could still access and alter individual lines and fields by indexing or iterating it.  While it worked nicely, it wouldn't be backwards compatible.
msg148839 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2011-12-04 05:16
OK, there's something crazy going on with "Create Patch" failing to pick up the latest changes. I've removed all the obsolete patches, and am doing another merge from default to see if I can get it to pick things up correctly.
msg148840 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2011-12-04 05:59
Grr, "Create Patch" insists on trying to produce a patch based on https://bitbucket.org/ncoghlan/cpython_sandbox/changesets/9512712044a6.

That checkin is from *September* and ignores all my recent changes :P

Relevant meta-tracker issue: http://psf.upfronthosting.co.za/roundup/meta/issue429

Manual patch upload coming shortly...
msg148841 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2011-12-04 07:36
OK, manual up-to-date patch attached.
msg148842 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2011-12-04 07:45
@Ron: Now that it has a reasonably clear signature, I could see my way clear to making the Instruction._disassemble() method public, which makes it easy for people to compose their own disassembly output.

For all the other display methods, I prefer Ryan Kelly's suggestion of supporting a "file" argument which is then passed through to the underlying "print()" calls.

This is inconsistent with what I originally did for the code_info() APIs (where I made a separate "give me the string" function), but it's the lowest impact change that avoids the need to capture stdout.
msg148859 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2011-12-05 00:05
MvL pointed out I hadn't updated the Hg repo reference when I moved my sandbox over to BitBucket - the diff it was generating was from the last time I updated my pydotorg sandbox in order to try something on the buildbots.
msg163018 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2012-06-17 05:53
Given the imminent 3.3 beta 1 feature freeze and the fact I would like to explore Ron's suggestion of a higher level ByteCode object to encapsulate a sequence of instructions (along with additional information from the code object), postponing this one.
msg179260 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2013-01-07 12:20
To clarify the vague allusion in my last comment, Ron's suggestion was along the lines of creating a dis.Bytecode object that encapsulated everything the dis module can figure out about a piece of compiled code.

That would mean exposing the kind of info reported in a string by dis.code_info() as attributes/properties, and have the proposed "get_opinfo()" be the __iter__ method on the disassembled Bytecode objects.
msg181970 - (view) Author: Thomas Kluyver (takluyver) * Date: 2013-02-12 17:49
I've updated Nick's patch so that test_dis and test_peephole pass again, and added a prototype ByteCode class (without any docs or tests for now, to allow for API discussion).

The prototype ByteCode is instantiated with any of the objects that get_instructions already accepts (functions, methods, code strings & code objects). Iterating over it yields Instruction objects. It has info(), show_info() and display_code() methods, which correspond to the code_info(), show_code() and disassemble() functions.

I've tried to go for names that make sense, rather than names that fit the existing pattern, because the existing pattern feels a bit messy. E.g. the show_code() function doesn't actually show the code, so I've called its method equivalent show_info().
msg181998 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2013-02-13 07:06
Thanks Thomas! It's a promising start - a few more detailed comments in the patch review.

I like the idea of creating the initial version as an object-oriented wrapper around the existing APIs, rather than completely refactoring the module to make everything else a functional wrapper around an underlying object-oriented implementation.
msg182321 - (view) Author: Thomas Kluyver (takluyver) * Date: 2013-02-18 13:40
Updated version of the patch.

Changed from review:
- Included test.bytecode_helper module used by some tests
- Updated docs to indicate that the changes are new in 3.4
- ByteCode -> Bytecode
- Added meaningful repr for Bytecode

Still to do:
- ? Re-expose attributes from code object on Bytecode instance
- Tests & documentation for Bytecode class
- Split changes into multiple patches
msg186148 - (view) Author: Thomas Kluyver (takluyver) * Date: 2013-04-06 19:14
I've added docs and tests, and split the changes to test_peepholer into a separate patch.

I haven't re-exposed details of the code object as attributes of Bytecode instances, because they're already available as e.g. bytecode.codeobj.co_names . I think it would be more confusing than useful to offer the same values in two places, though I'm open to discussion on this.

I've re-organised the dis module docs a bit. I've put Bytecode at the top, as I think it's a more intuitive API than the functions, which have somewhat counter-intuitive names due to the module's history.
msg188502 - (view) Author: Thomas Kluyver (takluyver) * Date: 2013-05-06 09:47
Ping - the latest patches (dis_api3 & test_peepholer) are ready for review when someone's got a moment. Thanks!
msg188529 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2013-05-06 13:02
I created issue 17916 after realising that the new OO API doesn't yet provide an equivalent to dis.distb that returns an appropriate Bytecode object.

(I don't think it makes sense to hold up this patch for that change)
msg188536 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2013-05-06 13:53
Good thing test_peepholer was moved out to a separate patch - a failure of that picked up a bug in the new disassembly output (unifying the handling of name and constant dereferences had changed the way constant strings were reported in the disassembly, and the error was consistent in both the new implementation and in the new tests due to the way the expected test results had been generated)
msg188537 - (view) Author: Roundup Robot (python-dev) Date: 2013-05-06 13:59
New changeset f65b867ce817 by Nick Coghlan in branch 'default':
Issue #11816: multiple improvements to the dis module
http://hg.python.org/cpython/rev/f65b867ce817
msg188538 - (view) Author: Roundup Robot (python-dev) Date: 2013-05-06 14:03
New changeset d3fee4c64654 by Nick Coghlan in branch 'default':
Issue #11816: switch test_peepholer to bytecode_helper
http://hg.python.org/cpython/rev/d3fee4c64654
msg188539 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2013-05-06 14:05
And two-and-a-bit years later, we're done - thanks all, any further feedback or problems can be filed as a new issue :)
msg188572 - (view) Author: Charles-François Natali (neologix) * (Python committer) Date: 2013-05-06 19:34
test_dis is failing on some buildbots:

http://buildbot.python.org/all/builders/AMD64 Ubuntu LTS 3.x/builds/1674/steps/test/logs/stdio

Re-running test 'test_dis' in verbose mode
test test_dis crashed -- Traceback (most recent call last):
  File "/opt/python/3.x.langa-ubuntu/build/Lib/test/regrtest.py", line 1294, in runtest_inner
    the_module = importlib.import_module(abstest)
  File "/opt/python/3.x.langa-ubuntu/build/Lib/importlib/__init__.py", line 92, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1603, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1584, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1551, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 591, in _check_name_wrapper
  File "<frozen importlib._bootstrap>", line 1053, in load_module
  File "<frozen importlib._bootstrap>", line 1034, in load_module
  File "<frozen importlib._bootstrap>", line 567, in module_for_loader_wrapper
  File "<frozen importlib._bootstrap>", line 901, in _load_module
  File "<frozen importlib._bootstrap>", line 297, in _call_with_frames_removed
  File "/opt/python/3.x.langa-ubuntu/build/Lib/test/test_dis.py", line 4, in <module>
    from test.bytecode_helper import BytecodeTestCase
ImportError: No module named 'test.bytecode_helper'
msg188573 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2013-05-06 19:37
Yes, this is bytecode_helper hasn't been added to the repository.
msg188574 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2013-05-06 19:37
(this is *because*, sorry)
msg188601 - (view) Author: STINNER Victor (haypo) * (Python committer) Date: 2013-05-06 22:14
Ping! The test is still failing.
msg188602 - (view) Author: Thomas Kluyver (takluyver) * Date: 2013-05-06 22:21
bytecode_helper is there in dis_api3.diff - anyone with commit rights should be able to add it to the repository.
msg188604 - (view) Author: Roundup Robot (python-dev) Date: 2013-05-06 22:28
New changeset 84d1a0e32d3b by Nick Coghlan in branch 'default':
Issue #11816: Add missing test helper
http://hg.python.org/cpython/rev/84d1a0e32d3b
msg188637 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2013-05-07 09:55
I checked in the missing file after I woke up this morning. Maybe I'll learn to use hg import instead of patch some day...

Sorry for the noise.
History
Date User Action Args
2013-05-07 09:55:08ncoghlansetstatus: open -> closed

messages: + msg188637
2013-05-06 22:28:39python-devsetmessages: + msg188604
2013-05-06 22:21:39takluyversetmessages: + msg188602
2013-05-06 22:14:56hayposetnosy: + haypo
messages: + msg188601
2013-05-06 19:37:30pitrousetmessages: + msg188574
2013-05-06 19:37:11pitrousetnosy: + pitrou
messages: + msg188573
2013-05-06 19:34:45neologixsetstatus: closed -> open
nosy: + neologix
messages: + msg188572

2013-05-06 14:05:23ncoghlansetstatus: open -> closed
resolution: fixed
messages: + msg188539

stage: commit review -> resolved
2013-05-06 14:03:12python-devsetmessages: + msg188538
2013-05-06 13:59:47python-devsetnosy: + python-dev
messages: + msg188537
2013-05-06 13:53:16ncoghlansetmessages: + msg188536
2013-05-06 13:02:50ncoghlansetstage: patch review -> commit review
2013-05-06 13:02:42ncoghlansetassignee: ncoghlan
messages: + msg188529
2013-05-06 12:54:32ncoghlanlinkissue17916 dependencies
2013-05-06 09:47:42takluyversetmessages: + msg188502
2013-04-06 19:15:32takluyversetfiles: + test_peepholer.diff
2013-04-06 19:14:46takluyversetfiles: + dis_api3.diff

messages: + msg186148
2013-02-18 13:40:10takluyversetfiles: + dis_api2.diff

messages: + msg182321
2013-02-13 07:06:22ncoghlansetmessages: + msg181998
2013-02-12 17:50:01takluyversetfiles: + dis_api.diff
nosy: + takluyver
messages: + msg181970

2013-01-07 12:20:48ncoghlansetmessages: + msg179260
2012-07-20 11:54:48yselivanovsetnosy: + yselivanov
2012-06-17 05:53:24ncoghlansetassignee: ncoghlan -> (no value)
messages: + msg163018
versions: + Python 3.4, - Python 3.3
2012-01-12 14:33:11ncoghlanunlinkissue11682 dependencies
2011-12-05 00:05:29ncoghlansetmessages: + msg148859
2011-12-05 00:00:50ncoghlansetfiles: + 5ce60675e572.diff
2011-12-05 00:00:09ncoghlansethgrepos: + hgrepo94
2011-12-04 23:59:55ncoghlansethgrepos: - hgrepo93
2011-12-04 07:45:55ncoghlansetmessages: + msg148842
2011-12-04 07:36:01ncoghlansetfiles: + issue11816_get_opinfo_branch_20111204.diff

messages: + msg148841
2011-12-04 05:59:34ncoghlansetnosy: + loewis
messages: + msg148840
2011-12-04 05:16:37ncoghlansetfiles: - 9512712044a6.diff
2011-12-04 05:16:27ncoghlansetmessages: + msg148839
2011-12-04 05:04:32ncoghlansetfiles: + 9512712044a6.diff
2011-12-04 05:03:58ncoghlansethgrepos: + hgrepo93
2011-12-04 05:03:49ncoghlansetfiles: - 9512712044a6.diff
2011-12-04 05:03:36ncoghlansethgrepos: - hgrepo17
2011-12-04 05:01:06ncoghlansetfiles: - issue11816_get_opinfo_branch_20111031.diff
2011-12-04 04:17:09ron_adamsetnosy: + ron_adam
messages: + msg148833
2011-11-26 08:38:33ncoghlansetmessages: + msg148383
2011-11-26 08:26:38ncoghlansetfiles: + 9512712044a6.diff
2011-11-26 08:16:39ncoghlansetfiles: - 9512712044a6.diff
2011-11-26 06:41:38ncoghlansetmessages: + msg148382
2011-11-24 22:20:48ncoghlansetfiles: + 9512712044a6.diff
2011-11-24 03:56:08ncoghlansetassignee: rhettinger -> ncoghlan
messages: + msg148227
2011-10-31 12:51:46ncoghlansetfiles: - dis.patch
2011-10-31 12:51:43ncoghlansetfiles: - issue11816_get_opinfo_branch_20110824.diff
2011-10-31 12:51:39ncoghlansetfiles: - issue11816_get_opinfo_branch_20110904.diff
2011-10-31 12:51:36ncoghlansetfiles: - issue11816_get_opinfo_branch_20110920.diff
2011-10-31 12:51:16ncoghlansetfiles: + issue11816_get_opinfo_branch_20111031.diff

messages: + msg146694
2011-10-03 16:33:08eric.snowsetnosy: + eric.snow
2011-09-22 14:30:21meador.ingesetmessages: + msg144409
2011-09-22 04:28:04ncoghlansetmessages: + msg144401
2011-09-22 04:02:33meador.ingesetnosy: + meador.inge
messages: + msg144400
2011-09-20 14:02:44meador.ingesetstage: patch review
2011-09-20 09:26:48ncoghlansetfiles: + issue11816_get_opinfo_branch_20110920.diff

messages: + msg144322
2011-09-04 11:07:49ncoghlansetfiles: + issue11816_get_opinfo_branch_20110904.diff

messages: + msg143491
2011-08-23 14:50:49ncoghlansetfiles: + issue11816_get_opinfo_branch_20110824.diff
assignee: ncoghlan -> rhettinger
messages: + msg142831
2011-08-23 14:33:47ncoghlansetfiles: - 7cead6bf5832.diff
2011-08-23 14:29:41ncoghlansetfiles: + 7cead6bf5832.diff
2011-08-23 13:56:34eltodersetnosy: - eltoder
2011-08-23 13:50:23rhettingersetmessages: + msg142825
2011-08-23 02:57:46ncoghlansetassignee: rhettinger -> ncoghlan
2011-08-22 11:39:37rfksetnosy: + rfk
2011-07-11 12:53:00ncoghlanlinkissue11682 dependencies
2011-04-11 14:28:12belopolskysetnosy: + belopolsky
2011-04-11 14:18:42jceasetmessages: + msg133521
2011-04-11 14:16:06jceasetnosy: + jcea
2011-04-10 23:40:37rhettingersetassignee: rhettinger
2011-04-10 20:28:30alexsetnosy: + alex
messages: + msg133479
2011-04-10 15:46:21ncoghlansetmessages: + msg133471
2011-04-10 14:05:19eltodersetmessages: + msg133467
2011-04-10 13:58:46ncoghlansetmessages: + msg133466
2011-04-10 13:57:19ncoghlansetmessages: + msg133465
title: Add functions to return disassembly as string -> Refactor the dis module to provide better building blocks for bytecode analysis
2011-04-10 13:55:09ncoghlansethgrepos: + hgrepo17
messages: + msg133464
2011-04-10 02:44:13rhettingersetmessages: + msg133441
2011-04-10 02:17:28eltodersetmessages: + msg133439
2011-04-10 02:08:58rhettingersetnosy: + rhettinger
messages: + msg133438
2011-04-10 00:24:39eltodersetnosy: + ncoghlan
2011-04-10 00:23:23eltodersetfiles: + dis.patch
2011-04-10 00:23:11eltodersetfiles: - dis.diff
2011-04-10 00:20:08eltodercreate