docs: def from_code(cls, code_object):
          """
          Disassemble a Python code object and make a Code object from the bits.
          This is the expected way to make a Code instance. But you are welcome
          to call Code() directly if you wish.
          """
          # It's an annoyance to keep having to add ".__code__" to a function
          # name, so let's automate that when needed.
          if isinstance( code_object, types.FunctionType ) :
              code_object = code_object.__code__
  
          # get the actual bytecode string out of the code object
          co_code = code_object.co_code
  
          # Use dis.findlabels to locate the labeled bytecodes, that is, the
          # ones that are jump targets. (They are "labeled" in a disassembly
          # printout.) Store the list as a dict{ addr: Label object} for easy
          # lookup.
  
          labels = dict((addr, Label()) for addr in findlabels(co_code))
  
          # Make a dict{ source_line : offset } for the source lines in the code.
  
          linestarts = dict(cls._findlinestarts(code_object))
  
          cellfree = code_object.co_cellvars + code_object.co_freevars
  
          # Create a CodeList object to represent the bytecode string.
  
          code = CodeList()   # receives (op,arg) tuples
          n = len(co_code)    # number bytes in the bytecode string
          i = 0               # index over the bytecode string
          extended_arg = 0    # upper 16 bits of an extended arg
  
          # Iterate over the bytecode string expanding it into (Opcode,arg) tuples.
  
          while i < n:
              # First byte is the opcode
              op = Opcode( co_code[i] )
  
              # If this op is a jump-target, insert (Label,) ahead of it.
              if i in labels:
                  code.append((labels[i], None))
  
              # If this op is the first from a source line, insert
              # (SetLineno, line#) ahead of it.
              if i in linestarts:
                  code.append((SetLineno, linestarts[i]))
  
              i += 1 # step index to the argument if any
  
              if op not in hasargx :
                  # No argument, push the minimal tuple, done.
                  code.append((op, None))
              else:
                  # op takes an argument. Look for MAKE_FUNCTION or MAKE_CLOSURE.
                  if op in hascode :
                      # special case: with these opcodes, at runtime, TOS1 should
                      # be a code object. We require the normal opcode sequence:
                      #    LOAD_CONST the code object
                      #    LOAD_CONST the name of the function
                      #    MAKE_FUNCTION/CLOSURE
                      # When this exists, go back and convert the argument of the
                      # first LOAD_CONST from a code object to a Code object.
                      if len(code) >= 2 \
                         and code[-2][0] == LOAD_CONST \
                         and code[-1][0] == LOAD_CONST \
                         and isinstance( code[-2][1], types.CodeType ) :
                          code[-2] = ( Opcode(LOAD_CONST), Code.from_code( code[-2][1] ) )
                      else :
                          raise ValueError(
                              'Invalid opcode sequence for MAKE_FUNCTION/MAKE_CLOSURE'
                          )
                      # now continue and handle the argument of MAKE_F/C normally.
  
                  # Assemble the argument value from two bytes plus an extended
                  # arg when present.
                  arg = co_code[i] + co_code[i+1]*256 + extended_arg
                  extended_arg = 0 # clear extended arg bits if any
                  i += 2 # Step over the argument
  
                  if op == opcode.EXTENDED_ARG:
                      # The EXTENDED_ARG op is just a way of storing the upper
                      # 16 bits of a 32-bit arg in the bytestream. Collect
                      # those bits, but generate no code tuple.
                      extended_arg = arg << 16
  
                  elif op in hasconst:
                      # When the argument is a constant, put the constant
                      # itself in the opcode tuple. If that constant is a code
                      # object, the test above (if op in hascode) will later
                      # convert it into a Code object.
                      code.append((op, code_object.co_consts[arg]))
  
                  elif op in hasname:
                      # When the argument is a name, put the name string itself
                      # in the opcode tuple.
                      code.append((op, code_object.co_names[arg]))
  
                  elif op in hasjabs:
                      # When the argument is an absolute jump, put the label
                      # in the tuple (in place of the label list index)
                      code.append((op, labels[arg]))
  
                  elif op in hasjrel:
                      # When the argument is a relative jump, put the label
                      # in the tuple in place of the forward offset.
                      code.append((op, labels[i + arg]))
  
                  elif op in haslocal:
                      # When the argument is a local var, put the name string
                      # in the tuple.
                      code.append((op, code_object.co_varnames[arg]))
  
                  elif op in hascompare:
                      # When the argument is a relation (like ">=") put that
                      # string in the tuple instead.
                      code.append((op, cmp_op[arg]))
  
                  elif op in hasfree:
                      code.append((op, cellfree[arg]))
  
                  else:
                      # whatever, just put the arg in the tuple
                      code.append((op, arg))
  
          # Store certain flags from the code object as booleans for convenient
          # reference as Code members.
  
          varargs = bool(code_object.co_flags & CO_VARARGS)
          varkwargs = bool(code_object.co_flags & CO_VARKEYWORDS)
          newlocals = bool(code_object.co_flags & CO_NEWLOCALS)
  
          # Get the names of arguments as strings, from the varnames tuple. The
          # order of name strings in co_varnames is:
          #   co_argcount names of regular (positional-or-keyword) arguments
          #   names of co_kwonlyargcount keyword-only arguments if any
          #   name of a *vararg argument
          #   name of a **kwarg argument if any (not present if kwonlyargs > 0)
          #   names of other local variables
          # Hence the count of argument names is
          #   co_argcount + co_kwonlyargcount + varargs + varkwargs
          nargs = code_object.co_argcount + code_object.co_kwonlyargcount + varargs + varkwargs
          args = code_object.co_varnames[ : nargs ]
  
          # Preserve a docstring if any. If there are constants and the first
          # constant is a string, Python assumes that's a docstring.
          docstring = None
          if code_object.co_consts and isinstance(code_object.co_consts[0], str):
              docstring = code_object.co_consts[0]
  
          # Funnel all the collected bits through the Code.__init__() method.
          return cls( code = code,
                      freevars = code_object.co_freevars,
                      args = args,
                      varargs = varargs,
                      varkwargs = varkwargs,
                      kwonlyargcount = code_object.co_kwonlyargcount,
                      newlocals = newlocals,
                      coflags = code_object.co_flags,
                      name = code_object.co_name,
                      filename = code_object.co_filename,
                      firstlineno = code_object.co_firstlineno,
                      docstring = docstring
                      )