116 lines
3.6 KiB
Python
116 lines
3.6 KiB
Python
# -*- 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
|