File size: 3,943 Bytes
ab4488b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#-------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for
# license information.
#--------------------------------------------------------------------------
from . import KnownProfiles, ProfileDefinition

class InvalidMultiApiClientError(Exception):
    """If the mixin is not used with a compatible class.
    """
    pass

class MultiApiClientMixin(object):
    """Mixin that contains multi-api version profile management.

    To use this mixin, a client must define two class attributes:
    - LATEST_PROFILE : a ProfileDefinition correspond to latest profile
    - _PROFILE_TAG : a tag that filter a full profile for this particular client

    This should not be used directly and will only provide private methods.
    """

    def __init__(self, *args, **kwargs):
        # Consume "api_version" and "profile", to avoid sending them to base class
        api_version = kwargs.pop("api_version", None)
        profile = kwargs.pop("profile", KnownProfiles.default)

        # Can't do "super" call here all the time, or I would break old client with:
        # TypeError: object.__init__() takes no parameters
        # So I try to detect if I correctly use this class as a Mixin, or the messed-up
        # approach like before. If I think it's the messed-up old approach,
        # don't call super
        if args or "creds" in kwargs or "config" in kwargs:
            super(MultiApiClientMixin, self).__init__(*args, **kwargs)

        try:
            type(self).LATEST_PROFILE
        except AttributeError:
            raise InvalidMultiApiClientError("To use this mixin, main client MUST define LATEST_PROFILE class attribute")

        try:
            type(self)._PROFILE_TAG
        except AttributeError:
            raise InvalidMultiApiClientError("To use this mixin, main client MUST define _PROFILE_TAG class attribute")

        if api_version and profile is not KnownProfiles.default:
            raise ValueError("Cannot use api-version and profile parameters at the same time")

        if api_version:
            self.profile = ProfileDefinition({
                self._PROFILE_TAG: {
                    None: api_version
                }},
                self._PROFILE_TAG + " " + api_version
            )
        elif isinstance(profile, dict):
            self.profile = ProfileDefinition({
                self._PROFILE_TAG: profile,
                },
                self._PROFILE_TAG + " dict"
            )
            if api_version:
                self.profile._profile_dict[self._PROFILE_TAG][None] = api_version
        else:
            self.profile = profile

    def _get_api_version(self, operation_group_name):
        current_profile = self.profile
        if self.profile is KnownProfiles.default:
            current_profile = KnownProfiles.default.value.definition()

        if current_profile is KnownProfiles.latest:
            current_profile = self.LATEST_PROFILE
        elif isinstance(current_profile, KnownProfiles):
            current_profile = current_profile.value
        elif isinstance(current_profile, ProfileDefinition):
            pass  # I expect that
        else:
            raise ValueError("Cannot determine a ProfileDefinition from {}".format(self.profile))

        local_profile_dict = current_profile.get_profile_dict()
        if self._PROFILE_TAG not in local_profile_dict:
            raise ValueError("This profile doesn't define {}".format(self._PROFILE_TAG))

        local_profile = local_profile_dict[self._PROFILE_TAG]
        if operation_group_name in local_profile:
            return local_profile[operation_group_name]
        try:
            return local_profile[None]
        except KeyError:
            raise ValueError("This profile definition does not contain a default API version")