docs: def _connect_mv_node(network, node, target_obj):
      """Connects MV node to target object in MV grid
  
      If the target object is a node, a new line is created to it.
      If the target object is a line, the node is connected to a newly created branch tee
      (using perpendicular projection) on this line.
      New lines are created using standard equipment.
  
      Parameters
      ----------
      network : :class:`~.grid.network.Network`
          The eDisGo container object
      node : :class:`~.grid.components.Component`
          Node to connect (e.g. :class:`~.grid.components.Generator`)
          Node must be a member of MV grid's graph (network.mv_grid.graph)
      target_obj : :class:`~.grid.components.Component`
          Object that node shall be connected to
  
      Returns
      -------
      :class:`~.grid.components.Component` or None
          Node that node was connected to
  
      Notes
      -----
      Adapted from `Ding0 <https://github.com/openego/ding0/blob/\
          21a52048f84ec341fe54e0204ac62228a9e8a32a/\
          ding0/grid/mv_grid/mv_connect.py#L311>`_.
      """
  
      # get standard equipment
      std_line_type = network.equipment_data['mv_cables'].loc[
          network.config['grid_expansion_standard_equipment']['mv_line']]
      std_line_kind = 'cable'
  
      target_obj_result = None
  
      node_shp = transform(proj2equidistant(network), node.geom)
  
      # MV line is nearest connection point
      if isinstance(target_obj['shp'], LineString):
  
          adj_node1 = target_obj['obj']['adj_nodes'][0]
          adj_node2 = target_obj['obj']['adj_nodes'][1]
  
          # find nearest point on MV line
          conn_point_shp = target_obj['shp'].interpolate(target_obj['shp'].project(node_shp))
          conn_point_shp = transform(proj2conformal(network), conn_point_shp)
  
          line = network.mv_grid.graph.edge[adj_node1][adj_node2]
  
          # target MV line does currently not connect a load area of type aggregated
          if not line['type'] == 'line_aggr':
  
              # create branch tee and add it to grid
              branch_tee = BranchTee(geom=conn_point_shp,
                                     grid=network.mv_grid,
                                     in_building=False)
              network.mv_grid.graph.add_node(branch_tee,
                                             type='branch_tee')
  
              # split old branch into 2 segments
              # (delete old branch and create 2 new ones along cable_dist)
              # ==========================================================
  
              # backup kind and type of branch
              line_kind = line['line'].kind
              line_type = line['line'].type
  
              # remove line from graph
              network.mv_grid.graph.remove_edge(adj_node1, adj_node2)
  
              # delete line from equipment changes if existing
              _del_cable_from_equipment_changes(network=network,
                                                line=line['line'])
  
              line_length = calc_geo_dist_vincenty(network=network,
                                                   node_source=adj_node1,
                                                   node_target=branch_tee)
              line = Line(id=random.randint(10 ** 8, 10 ** 9),
                          length=line_length / 1e3,
                          quantity=1,
                          kind=line_kind,
                          type=line_type,
                          grid=network.mv_grid)
  
              network.mv_grid.graph.add_edge(adj_node1,
                                             branch_tee,
                                             line=line,
                                             type='line')
  
              # add line to equipment changes to track costs
              _add_cable_to_equipment_changes(network=network,
                                              line=line)
  
              line_length = calc_geo_dist_vincenty(network=network,
                                                   node_source=adj_node2,
                                                   node_target=branch_tee)
              line = Line(id=random.randint(10 ** 8, 10 ** 9),
                          length=line_length / 1e3,
                          quantity=1,
                          kind=line_kind,
                          type=line_type,
                          grid=network.mv_grid)
  
              network.mv_grid.graph.add_edge(adj_node2,
                                             branch_tee,
                                             line=line,
                                             type='line')
  
              # add line to equipment changes to track costs
              _add_cable_to_equipment_changes(network=network,
                                              line=line)
  
              # add new branch for new node (node to branch tee)
              # ================================================
              line_length = calc_geo_dist_vincenty(network=network,
                                                   node_source=node,
                                                   node_target=branch_tee)
              line = Line(id=random.randint(10 ** 8, 10 ** 9),
                          length=line_length / 1e3,
                          quantity=1,
                          kind=std_line_kind,
                          type=std_line_type,
                          grid=network.mv_grid)
  
              network.mv_grid.graph.add_edge(node,
                                             branch_tee,
                                             line=line,
                                             type='line')
  
              # add line to equipment changes to track costs
              _add_cable_to_equipment_changes(network=network,
                                              line=line)
  
              target_obj_result = branch_tee
  
      # node ist nearest connection point
      else:
  
          # what kind of node is to be connected? (which type is node of?)
          #   LVStation: Connect to LVStation or BranchTee
          #   Generator: Connect to LVStation, BranchTee or Generator
          if isinstance(node, LVStation):
              valid_conn_objects = (LVStation, BranchTee)
          elif isinstance(node, Generator):
              valid_conn_objects = (LVStation, BranchTee, Generator)
          else:
              raise ValueError('Oops, the node you are trying to connect is not a valid connection object')
  
          # if target is generator or Load, check if it is aggregated (=> connection not allowed)
          if isinstance(target_obj['obj'], (Generator, Load)):
              target_is_aggregated = any([_ for _ in network.mv_grid.graph.edge[target_obj['obj']].values()
                                          if _['type'] == 'line_aggr'])
          else:
              target_is_aggregated = False
  
          # target node is not a load area of type aggregated
          if isinstance(target_obj['obj'], valid_conn_objects) and not target_is_aggregated:
  
              # add new branch for satellite (station to station)
              line_length = calc_geo_dist_vincenty(network=network,
                                                   node_source=node,
                                                   node_target=target_obj['obj'])
  
              line = Line(id=random.randint(10 ** 8, 10 ** 9),
                          type=std_line_type,
                          kind=std_line_kind,
                          quantity=1,
                          length=line_length / 1e3,
                          grid=network.mv_grid)
  
              network.mv_grid.graph.add_edge(node,
                                             target_obj['obj'],
                                             line=line,
                                             type='line')
  
              # add line to equipment changes to track costs
              _add_cable_to_equipment_changes(network=network,
                                              line=line)
  
              target_obj_result = target_obj['obj']
  
      return target_obj_result