codekingpro/portable-devtools
114k
1#-------------------------------------------------------------------------2# Copyright (c) Microsoft Corporation. All rights reserved.3# Licensed under the MIT License. See License.txt in the project root for4# license information.5#--------------------------------------------------------------------------6from . import KnownProfiles, ProfileDefinition7 8class InvalidMultiApiClientError(Exception):9 """If the mixin is not used with a compatible class.10 """11 pass12 13class MultiApiClientMixin(object):14 """Mixin that contains multi-api version profile management.15 16 To use this mixin, a client must define two class attributes:17 - LATEST_PROFILE : a ProfileDefinition correspond to latest profile18 - _PROFILE_TAG : a tag that filter a full profile for this particular client19 20 This should not be used directly and will only provide private methods.21 """22 23 def __init__(self, *args, **kwargs):24 # Consume "api_version" and "profile", to avoid sending them to base class25 api_version = kwargs.pop("api_version", None)26 profile = kwargs.pop("profile", KnownProfiles.default)27 28 # Can't do "super" call here all the time, or I would break old client with:29 # TypeError: object.__init__() takes no parameters30 # So I try to detect if I correctly use this class as a Mixin, or the messed-up31 # approach like before. If I think it's the messed-up old approach,32 # don't call super33 if args or "creds" in kwargs or "config" in kwargs:34 super(MultiApiClientMixin, self).__init__(*args, **kwargs)35 36 try:37 type(self).LATEST_PROFILE38 except AttributeError:39 raise InvalidMultiApiClientError("To use this mixin, main client MUST define LATEST_PROFILE class attribute")40 41 try:42 type(self)._PROFILE_TAG43 except AttributeError:44 raise InvalidMultiApiClientError("To use this mixin, main client MUST define _PROFILE_TAG class attribute")45 46 if api_version and profile is not KnownProfiles.default:47 raise ValueError("Cannot use api-version and profile parameters at the same time")48 49 if api_version:50 self.profile = ProfileDefinition({51 self._PROFILE_TAG: {52 None: api_version53 }},54 self._PROFILE_TAG + " " + api_version55 )56 elif isinstance(profile, dict):57 self.profile = ProfileDefinition({58 self._PROFILE_TAG: profile,59 },60 self._PROFILE_TAG + " dict"61 )62 if api_version:63 self.profile._profile_dict[self._PROFILE_TAG][None] = api_version64 else:65 self.profile = profile66 67 def _get_api_version(self, operation_group_name):68 current_profile = self.profile69 if self.profile is KnownProfiles.default:70 current_profile = KnownProfiles.default.value.definition()71 72 if current_profile is KnownProfiles.latest:73 current_profile = self.LATEST_PROFILE74 elif isinstance(current_profile, KnownProfiles):75 current_profile = current_profile.value76 elif isinstance(current_profile, ProfileDefinition):77 pass # I expect that78 else:79 raise ValueError("Cannot determine a ProfileDefinition from {}".format(self.profile))80 81 local_profile_dict = current_profile.get_profile_dict()82 if self._PROFILE_TAG not in local_profile_dict:83 raise ValueError("This profile doesn't define {}".format(self._PROFILE_TAG))84 85 local_profile = local_profile_dict[self._PROFILE_TAG]86 if operation_group_name in local_profile:87 return local_profile[operation_group_name]88 try:89 return local_profile[None]90 except KeyError:91 raise ValueError("This profile definition does not contain a default API version")92 