Issue 6507: accept source strings directly in dis.dis(). Original patch by Daniel Urban
diff --git a/Lib/dis.py b/Lib/dis.py
index 2c4e828..2f46774 100644
--- a/Lib/dis.py
+++ b/Lib/dis.py
@@ -12,6 +12,22 @@
 
 _have_code = (types.MethodType, types.FunctionType, types.CodeType, type)
 
+def _try_compile(source, name):
+    """Attempts to compile the given source, first as an expression and
+       then as a statement if the first approach fails.
+
+       Utility function to accept strings in functions that otherwise
+       expect code objects
+    """
+    # ncoghlan: currently only used by dis(), but plan to add an
+    # equivalent for show_code() as well (but one that returns a
+    # string rather than printing directly to the console)
+    try:
+        c = compile(source, name, 'eval')
+    except SyntaxError:
+        c = compile(source, name, 'exec')
+    return c
+
 def dis(x=None):
     """Disassemble classes, methods, functions, or code.
 
@@ -38,7 +54,9 @@
     elif hasattr(x, 'co_code'):
         disassemble(x)
     elif isinstance(x, (bytes, bytearray)):
-        disassemble_string(x)
+        _disassemble_bytes(x)
+    elif isinstance(x, str):
+        _disassemble_str(x)
     else:
         raise TypeError("don't know how to disassemble %s objects" %
                         type(x).__name__)
@@ -157,7 +175,7 @@
                 print('(' + free[oparg] + ')', end=' ')
         print()
 
-def disassemble_string(code, lasti=-1, varnames=None, names=None,
+def _disassemble_bytes(code, lasti=-1, varnames=None, names=None,
                        constants=None):
     labels = findlabels(code)
     n = len(code)
@@ -196,6 +214,10 @@
                 print('(' + cmp_op[oparg] + ')', end=' ')
         print()
 
+def _disassemble_str(source):
+    """Compile the source string, then disassemble the code object."""
+    disassemble(_try_compile(source, '<dis>'))
+
 disco = disassemble                     # XXX For backwards compatibility
 
 def findlabels(code):