HEX
Server: Apache/2.4.65 (Ubuntu)
System: Linux ielts-store-v2 6.8.0-1036-gcp #38~22.04.1-Ubuntu SMP Thu Aug 14 01:19:18 UTC 2025 x86_64
User: root (0)
PHP: 7.2.34-54+ubuntu20.04.1+deb.sury.org+1
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,
Upload Files
File: //snap/google-cloud-cli/current/lib/googlecloudsdk/calliope/command_release_tracks.py
# -*- coding: utf-8 -*- #
# Copyright 2019 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Helpers to separate release tracks in declarative commands."""

from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals

import copy

from googlecloudsdk.calliope import base

ALL_TRACKS = [t.id for t in base.ReleaseTrack.AllValues()]
RELEASE_TRACKS = 'release_tracks'
GROUP = 'group'


class DoesNotExistForTrackError(Exception):
  pass


# This function should be kept in sync with function in
# cloud/sdk/surface_specs/release_tracks.py
def _SetValuesForTrack(obj, track):
  """Recursively modify an object to have only values for the provided track.

  Args:
    obj: The object to modify.
    track: The track to extract the values for.

  Returns:
    The modified object
  Raises:
    DoesNotExistForTrackError: if the object does not exist for the track.
  """
  if isinstance(obj, dict):
    is_group = GROUP in obj
    # Check if it exists for this track, and raise an Exception if it doesn't.
    if RELEASE_TRACKS in obj:
      if track not in obj[RELEASE_TRACKS]:
        raise DoesNotExistForTrackError()
      del obj[RELEASE_TRACKS]
    # Copy tracked properties for this track to the object itself.
    if track in obj:
      for key, value in obj[track].items():
        obj[key] = value
    # Remove all tracked properties
    for track_key in ALL_TRACKS:
      if track_key in obj:
        del obj[track_key]
    # Recursively update all children.
    # Remove them if they don't exist for the track.
    for key, child in list(obj.items()):
      try:
        _SetValuesForTrack(child, track)
      except DoesNotExistForTrackError:
        del obj[key]
    if is_group and not obj:
      # All of the children have been omitted for an arg group nested under the
      # `group` key.
      raise DoesNotExistForTrackError()
  elif isinstance(obj, list):
    # Recursively update all children.
    # Remove them if they don't exist for the track.
    children = list(obj)
    obj[:] = []
    for child in children:
      try:
        obj.append(_SetValuesForTrack(child, track))
      except DoesNotExistForTrackError:
        pass
  return obj


def SeparateDeclarativeCommandTracks(command_impls):
  """Separate combined track definitions.

  If a file does not specify tracks, the same implementation may be used for
  all track implementations the command is present in.

  Args:
    command_impls: A single or list of declarative command implementation(s).

  Yields:
    One implementation for each distinct track implmentation in a file.
  """
  if not isinstance(command_impls, list):
    command_impls = [command_impls]
  for impl in command_impls:
    release_tracks = impl.get(RELEASE_TRACKS)
    if not release_tracks:
      release_tracks = ['ALPHA', 'BETA', 'GA']
    for track in release_tracks:
      track_impl = copy.deepcopy(impl)
      try:
        _SetValuesForTrack(track_impl, track)
      except DoesNotExistForTrackError:
        # The implementation doesn't have any keys left.
        # continue
        pass
      track_impl[RELEASE_TRACKS] = [track]
      yield track_impl