code: def test_get_pending_observation_features_hss(self) -> None:
      # Pending observations should be none if there aren't any.
      self.assertIsNone(get_pending_observation_features(self.hss_exp))
      self.hss_trial.mark_running(no_runner_required=True)
      # Now that the trial is deployed, it should become a pending trial on the
      # experiment and appear as pending for all metrics.
      pending = get_pending_observation_features(self.hss_exp)
      self.assertEqual(
          pending,
          {
              "m1": [self.hss_obs_feat],
              "m2": [self.hss_obs_feat],
          },
      )
  
      # Check that transforming observation features works correctly (it should inject
      # full parameterization into resulting obs.feats.)
      for p in none_throws(pending).values():
          for pf in p:
              self.assertEqual(
                  none_throws(pf.metadata),
                  none_throws(
                      self.hss_gr.candidate_metadata_by_arm_signature
                  )[self.hss_arm.signature],
              )
  
      # With `fetch_data` on trial returning data for metric "m2", that metric
      # should no longer have pending observation features.
      with patch.object(
          self.hss_trial,
          "lookup_data",
          return_value=Data.from_evaluations(
              {self.hss_trial.arm.name: {"m2": (1, 0)}},
              trial_index=self.hss_trial.index,
          ),
      ):
          self.assertEqual(
              get_pending_observation_features(self.hss_exp),
              {"m2": [], "m1": [self.hss_obs_feat]},
          )
      # When a trial is marked failed, it should no longer appear in pending.
      self.hss_trial.mark_failed()
      self.assertIsNone(get_pending_observation_features(self.hss_exp))
  
      # When an arm is abandoned, it should appear in pending features whether
      # or not there is data for it.
      hss_exp = get_hierarchical_search_space_experiment()
      hss_batch_trial = hss_exp.new_batch_trial(
          generator_run=self.hss_gr
      )
      hss_batch_trial.mark_arm_abandoned(hss_batch_trial.arms[0].name)
      # Checking with data for all metrics.
      with patch.object(
          hss_batch_trial,
          "fetch_data",
          return_value=Metric._wrap_trial_data_multi(
              data=Data.from_evaluations(
                  {
                      hss_batch_trial.arms[0].name: {
                          "m1": (1, 0),
                          "m2": (1, 0),
                      }
                  },
                  trial_index=hss_batch_trial.index,
              ),
          ),
      ):
          pending = get_pending_observation_features(hss_exp)
          self.assertEqual(
              pending,
              {
                  "m1": [self.hss_obs_feat],
                  "m2": [self.hss_obs_feat],
              },
          )
          # Check that candidate metadata is property propagated for abandoned arm.
          for p in none_throws(pending).values():
              for pf in p:
                  self.assertEqual(
                      none_throws(pf.metadata),
                      none_throws(
                          self.hss_gr.candidate_metadata_by_arm_signature
                      )[self.hss_arm.signature],
                  )
  
      # Checking with data for all metrics.
      with patch.object(
          hss_batch_trial,
          "fetch_data",
          return_value=Metric._wrap_trial_data_multi(
              data=Data.from_evaluations(
                  {
                      hss_batch_trial.arms[0].name: {
                          "m1": (1, 0),
                          "m2": (1, 0),
                      }
                  },
                  trial_index=hss_batch_trial.index,
              ),
          ),
      ):
          self.assertEqual(
              get_pending_observation_features(hss_exp),
              {
                  "m2": [self.hss_obs_feat],
                  "m1": [self.hss_obs_feat],
              },
          )
  
imports: from copy import deepcopy
  from unittest.mock import patch
  import numpy
  import pandas
  from ax.core.arm import Arm
  from ax.core.base_trial import TrialStatus
  from ax.core.data import Data
  from ax.core.generator_run import GeneratorRun
  from ax.core.metric import Metric
  from ax.core.objective import Objective
  from ax.core.observation import ObservationFeatures
  from ax.core.optimization_config import OptimizationConfig
  from ax.core.outcome_constraint import OutcomeConstraint
  from ax.core.types import ComparisonOp
  from ax.core.utils import best_feasible_objective, extract_pending_observations, get_missing_metrics, get_missing_metrics_by_name, get_model_times, get_model_trace_of_times, get_pending_observation_features, get_pending_observation_features_based_on_trial_status, MissingMetrics
  from ax.utils.common.constants import Keys
  from ax.utils.common.testutils import TestCase
  from ax.utils.testing.core_stubs import get_experiment, get_hierarchical_search_space_experiment, get_robust_branin_experiment
  from pyre_extensions import none_throws
label_desc: Use image node_id 7 for calling the UtilsTest obj's underlying member method code with example usage: obj.test_get_pending_observation_features_hss() without return types