docs: def assemble_changes(self, keys, resolve_keys, sql_state):
          """
          Accepts keys of SQL items available, sorts them and adds additional dependencies.
          Uses graph of `sql_state` nodes to build `keys` and `resolve_keys` into sequence that
          starts with leaves (items that have not dependents) and ends with roots.
  
          Changes `resolve_keys` argument as dependencies are added to the result.
  
          Args:
              keys (list): List of migration keys, that are one of create/delete operations, and
                  dont require respective reverse operations.
              resolve_keys (list): List of migration keys, that are changing existing items,
                  and may require respective reverse operations.
              sql_sate (graph.SQLStateGraph): State of SQL items.
          Returns:
              (list) Sorted sequence of migration keys, enriched with dependencies.
          """
          result_keys = []
          all_keys = keys | resolve_keys
          for key in all_keys:
              node = sql_state.node_map[key]
              sql_item = sql_state.nodes[key]
              ancs = node.ancestors()[:-1]
              ancs.reverse()
              pos = next((i for i, k in enumerate(result_keys) if k in ancs), len(result_keys))
              result_keys.insert(pos, key)
  
              if key in resolve_keys and not sql_item.replace:
                  # ancestors() and descendants() include key itself, need to cut it out.
                  descs = reversed(node.descendants()[:-1])
                  for desc in descs:
                      if desc not in all_keys and desc not in result_keys:
                          result_keys.insert(pos, desc)
                          # these items added may also need reverse operations.
                          resolve_keys.add(desc)
          return result_keys