nodes: 0, module; 1, function_definition; 2, function_name:_prepare_imports; 3, parameters; 4, block; 5, identifier:self; 6, identifier:dicts; 7, expression_statement; 8, comment:# all pseudo parent ids we've seen; 9, expression_statement; 10, comment:# pseudo matches; 11, expression_statement; 12, comment:# get prepared imports from parent; 13, expression_statement; 14, comment:# collect parent pseudo_ids; 15, for_statement; 16, comment:# turn pseudo_ids into a tuple of dictionaries; 17, expression_statement; 18, comment:# loop over all data again, finding the pseudo ids true json id; 19, for_statement; 20, comment:# toposort the nodes so parents are imported first; 21, expression_statement; 22, expression_statement; 23, expression_statement; 24, for_statement; 25, comment:# resolve the sorted import order; 26, for_statement; 27, comment:# ensure all data made it into network (paranoid check, should never fail); 28, if_statement; 29, return_statement; 30, comment:""" an override for prepare imports that sorts the imports by parent_id dependencies """; 31, assignment; 32, assignment; 33, assignment; 34, pattern_list; 35, call; 36, block; 37, assignment; 38, pattern_list; 39, call; 40, comment:# check if this matches one of our ppids; 41, block; 42, assignment; 43, assignment; 44, assignment; 45, pattern_list; 46, call; 47, block; 48, identifier:jid; 49, call; 50, block; 51, comparison_operator:in_network != set(prepared.keys()); 52, comment:# pragma: no cover; 53, block; 54, identifier:import_order; 55, identifier:pseudo_ids; 56, call; 57, identifier:pseudo_matches; 58, dictionary; 59, identifier:prepared; 60, call; 61, identifier:_; 62, identifier:data; 63, attribute; 64, argument_list; 65, expression_statement; 66, if_statement; 67, identifier:pseudo_ids; 68, list_comprehension; 69, identifier:json_id; 70, identifier:data; 71, attribute; 72, argument_list; 73, for_statement; 74, identifier:network; 75, call; 76, identifier:in_network; 77, call; 78, identifier:import_order; 79, list; 80, identifier:json_id; 81, identifier:data; 82, attribute; 83, argument_list; 84, expression_statement; 85, comment:# resolve pseudo_ids to their json id before building the network; 86, if_statement; 87, expression_statement; 88, if_statement; 89, attribute; 90, argument_list; 91, expression_statement; 92, expression_statement; 93, identifier:in_network; 94, call; 95, raise_statement; 96, identifier:set; 97, argument_list; 98, identifier:dict; 99, argument_list; 100, identifier:prepared; 101, identifier:items; 102, assignment; 103, call; 104, block; 105, tuple; 106, for_in_clause; 107, identifier:prepared; 108, identifier:items; 109, pattern_list; 110, identifier:pseudo_ids; 111, block; 112, identifier:Network; 113, argument_list; 114, identifier:set; 115, argument_list; 116, identifier:prepared; 117, identifier:items; 118, assignment; 119, comparison_operator:parent_id in pseudo_matches; 120, block; 121, call; 122, identifier:parent_id; 123, comment:# Right. There's an import dep. We need to add the edge from; 124, comment:# the parent to the current node, so that we import the parent; 125, comment:# before the current node.; 126, block; 127, identifier:network; 128, identifier:sort; 129, call; 130, call; 131, identifier:set; 132, argument_list; 133, call; 134, call; 135, identifier:parent_id; 136, boolean_operator; 137, attribute; 138, argument_list; 139, expression_statement; 140, identifier:ppid; 141, call; 142, identifier:ppid; 143, identifier:pseudo_ids; 144, identifier:ppid; 145, identifier:spec; 146, expression_statement; 147, for_statement; 148, if_statement; 149, identifier:parent_id; 150, call; 151, identifier:parent_id; 152, identifier:pseudo_matches; 153, expression_statement; 154, attribute; 155, argument_list; 156, expression_statement; 157, attribute; 158, argument_list; 159, attribute; 160, argument_list; 161, call; 162, identifier:PupaInternalError; 163, argument_list; 164, attribute; 165, argument_list; 166, call; 167, string; 168, identifier:parent_id; 169, identifier:startswith; 170, string; 171, call; 172, identifier:get_pseudo_id; 173, argument_list; 174, assignment; 175, pattern_list; 176, call; 177, block; 178, identifier:match; 179, block; 180, attribute; 181, argument_list; 182, assignment; 183, identifier:network; 184, identifier:add_node; 185, identifier:json_id; 186, call; 187, identifier:import_order; 188, identifier:append; 189, tuple; 190, identifier:in_network; 191, identifier:add; 192, identifier:jid; 193, attribute; 194, argument_list; 195, string:"import is missing nodes in network set"; 196, call; 197, identifier:_prepare_imports; 198, identifier:dicts; 199, attribute; 200, argument_list; 201, string_content:~; 202, attribute; 203, argument_list; 204, identifier:ppid; 205, identifier:match; 206, True; 207, identifier:k; 208, identifier:v; 209, attribute; 210, argument_list; 211, if_statement; 212, if_statement; 213, expression_statement; 214, identifier:data; 215, identifier:get; 216, string; 217, None; 218, identifier:parent_id; 219, subscript; 220, attribute; 221, argument_list; 222, identifier:jid; 223, subscript; 224, identifier:prepared; 225, identifier:keys; 226, identifier:super; 227, argument_list; 228, identifier:data; 229, identifier:get; 230, string; 231, None; 232, identifier:pseudo_ids; 233, identifier:add; 234, identifier:parent_id; 235, identifier:spec; 236, identifier:items; 237, comparison_operator:data[k] != v; 238, block; 239, comparison_operator:ppid in pseudo_matches; 240, block; 241, assignment; 242, string_content:parent_id; 243, identifier:pseudo_matches; 244, identifier:parent_id; 245, identifier:network; 246, identifier:add_edge; 247, identifier:parent_id; 248, identifier:json_id; 249, identifier:prepared; 250, identifier:jid; 251, identifier:OrganizationImporter; 252, identifier:self; 253, string_content:parent_id; 254, subscript; 255, identifier:v; 256, expression_statement; 257, break_statement; 258, identifier:ppid; 259, identifier:pseudo_matches; 260, raise_statement; 261, subscript; 262, identifier:json_id; 263, identifier:data; 264, identifier:k; 265, assignment; 266, call; 267, identifier:pseudo_matches; 268, identifier:ppid; 269, identifier:match; 270, False; 271, identifier:UnresolvedIdError; 272, argument_list; 273, binary_operator:'multiple matches for pseudo id: ' + ppid; 274, string; 275, identifier:ppid; 276, string_content:multiple matches for pseudo id:
code: def _prepare_imports(self, dicts):
          """ an override for prepare imports that sorts the imports by parent_id dependencies """
          # all pseudo parent ids we've seen
          pseudo_ids = set()
          # pseudo matches
          pseudo_matches = {}
  
          # get prepared imports from parent
          prepared = dict(super(OrganizationImporter, self)._prepare_imports(dicts))
  
          # collect parent pseudo_ids
          for _, data in prepared.items():
              parent_id = data.get('parent_id', None) or ''
              if parent_id.startswith('~'):
                  pseudo_ids.add(parent_id)
  
          # turn pseudo_ids into a tuple of dictionaries
          pseudo_ids = [(ppid, get_pseudo_id(ppid)) for ppid in pseudo_ids]
  
          # loop over all data again, finding the pseudo ids true json id
          for json_id, data in prepared.items():
              # check if this matches one of our ppids
              for ppid, spec in pseudo_ids:
                  match = True
                  for k, v in spec.items():
                      if data[k] != v:
                          match = False
                          break
                  if match:
                      if ppid in pseudo_matches:
                          raise UnresolvedIdError('multiple matches for pseudo id: ' + ppid)
                      pseudo_matches[ppid] = json_id
  
          # toposort the nodes so parents are imported first
          network = Network()
          in_network = set()
          import_order = []
  
          for json_id, data in prepared.items():
              parent_id = data.get('parent_id', None)
  
              # resolve pseudo_ids to their json id before building the network
              if parent_id in pseudo_matches:
                  parent_id = pseudo_matches[parent_id]
  
              network.add_node(json_id)
              if parent_id:
                  # Right. There's an import dep. We need to add the edge from
                  # the parent to the current node, so that we import the parent
                  # before the current node.
                  network.add_edge(parent_id, json_id)
  
          # resolve the sorted import order
          for jid in network.sort():
              import_order.append((jid, prepared[jid]))
              in_network.add(jid)
  
          # ensure all data made it into network (paranoid check, should never fail)
          if in_network != set(prepared.keys()):    # pragma: no cover
              raise PupaInternalError("import is missing nodes in network set")
  
          return import_order