<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def select_action(self, pos1, pos2, ctrl, shift):
 """Return a `sc_pb.Action` with the selection filled."""

    assert pos1.surf.surf_type == pos2.surf.surf_type
    assert pos1.surf.world_to_obs == pos2.surf.world_to_obs

    action = sc_pb.Action()
    action_spatial = pos1.action_spatial(action)

    if pos1.world_pos == pos2.world_pos:  # select a point
      select = action_spatial.unit_selection_point
      pos1.obs_pos.assign_to(select.selection_screen_coord)
      mod = sc_spatial.ActionSpatialUnitSelectionPoint
      if ctrl:
        select.type = mod.AddAllType if shift else mod.AllType
      else:
        select.type = mod.Toggle if shift else mod.Select
    else:
      select = action_spatial.unit_selection_rect
      rect = select.selection_screen_coord.add()
      pos1.obs_pos.assign_to(rect.p0)
      pos2.obs_pos.assign_to(rect.p1)
      select.selection_add = shift

    # Clear the queued action if something will be selected. An alternative
    # implementation may check whether the selection changed next frame.
    units = self._units_in_area(point.Rect(pos1.world_pos, pos2.world_pos))
    if units:
      self.clear_queued_action()

    return action