1# Copyright (c) 2012-2013 Mitch Garnaat http://garnaat.org/
2# Copyright 2012-2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"). You
5# may not use this file except in compliance with the License. A copy of
6# the License is located at
7#
8# http://aws.amazon.com/apache2.0/
9#
10# or in the "license" file accompanying this file. This file is
11# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
12# ANY KIND, either express or implied. See the License for the specific
13# language governing permissions and limitations under the License.
14
15import logging
16import os
17import re
18from logging import NullHandler
19
20__version__ = '1.40.17'
21
22
23# Configure default logger to do nothing
24log = logging.getLogger('botocore')
25log.addHandler(NullHandler())
26
27_INITIALIZERS = []
28
29_first_cap_regex = re.compile('(.)([A-Z][a-z]+)')
30_end_cap_regex = re.compile('([a-z0-9])([A-Z])')
31# The regex below handles the special case where some acronym
32# name is pluralized, e.g GatewayARNs, ListWebACLs, SomeCNAMEs.
33_special_case_transform = re.compile('[A-Z]{2,}s$')
34# Prepopulate the cache with special cases that don't match
35# our regular transformation.
36_xform_cache = {
37 ('CreateCachediSCSIVolume', '_'): 'create_cached_iscsi_volume',
38 ('CreateCachediSCSIVolume', '-'): 'create-cached-iscsi-volume',
39 ('DescribeCachediSCSIVolumes', '_'): 'describe_cached_iscsi_volumes',
40 ('DescribeCachediSCSIVolumes', '-'): 'describe-cached-iscsi-volumes',
41 ('DescribeStorediSCSIVolumes', '_'): 'describe_stored_iscsi_volumes',
42 ('DescribeStorediSCSIVolumes', '-'): 'describe-stored-iscsi-volumes',
43 ('CreateStorediSCSIVolume', '_'): 'create_stored_iscsi_volume',
44 ('CreateStorediSCSIVolume', '-'): 'create-stored-iscsi-volume',
45 ('ListHITsForQualificationType', '_'): 'list_hits_for_qualification_type',
46 ('ListHITsForQualificationType', '-'): 'list-hits-for-qualification-type',
47 ('ExecutePartiQLStatement', '_'): 'execute_partiql_statement',
48 ('ExecutePartiQLStatement', '-'): 'execute-partiql-statement',
49 ('ExecutePartiQLTransaction', '_'): 'execute_partiql_transaction',
50 ('ExecutePartiQLTransaction', '-'): 'execute-partiql-transaction',
51 ('ExecutePartiQLBatch', '_'): 'execute_partiql_batch',
52 ('ExecutePartiQLBatch', '-'): 'execute-partiql-batch',
53 (
54 'AssociateWhatsAppBusinessAccount',
55 '_',
56 ): 'associate_whatsapp_business_account',
57 (
58 'AssociateWhatsAppBusinessAccount',
59 '-',
60 ): 'associate-whatsapp-business-account',
61 ('CreateWhatsAppMessageTemplate', '_'): 'create_whatsapp_message_template',
62 ('CreateWhatsAppMessageTemplate', '-'): 'create-whatsapp-message-template',
63 (
64 'CreateWhatsAppMessageTemplateFromLibrary',
65 '_',
66 ): 'create_whatsapp_message_template_from_library',
67 (
68 'CreateWhatsAppMessageTemplateFromLibrary',
69 '-',
70 ): 'create-whatsapp-message-template-from-library',
71 (
72 'CreateWhatsAppMessageTemplateMedia',
73 '_',
74 ): 'create_whatsapp_message_template_media',
75 (
76 'CreateWhatsAppMessageTemplateMedia',
77 '-',
78 ): 'create-whatsapp-message-template-media',
79 ('DeleteWhatsAppMessageMedia', '_'): 'delete_whatsapp_message_media',
80 ('DeleteWhatsAppMessageMedia', '-'): 'delete-whatsapp-message-media',
81 ('DeleteWhatsAppMessageTemplate', '_'): 'delete_whatsapp_message_template',
82 ('DeleteWhatsAppMessageTemplate', '-'): 'delete-whatsapp-message-template',
83 (
84 'DisassociateWhatsAppBusinessAccount',
85 '_',
86 ): 'disassociate_whatsapp_business_account',
87 (
88 'DisassociateWhatsAppBusinessAccount',
89 '-',
90 ): 'disassociate-whatsapp-business-account',
91 (
92 'GetLinkedWhatsAppBusinessAccount',
93 '_',
94 ): 'get_linked_whatsapp_business_account',
95 (
96 'GetLinkedWhatsAppBusinessAccount',
97 '-',
98 ): 'get-linked-whatsapp-business-account',
99 (
100 'GetLinkedWhatsAppBusinessAccountPhoneNumber',
101 '_',
102 ): 'get_linked_whatsapp_business_account_phone_number',
103 (
104 'GetLinkedWhatsAppBusinessAccountPhoneNumber',
105 '-',
106 ): 'get-linked-whatsapp-business-account-phone-number',
107 ('GetWhatsAppMessageMedia', '_'): 'get_whatsapp_message_media',
108 ('GetWhatsAppMessageMedia', '-'): 'get-whatsapp-message-media',
109 ('GetWhatsAppMessageTemplate', '_'): 'get_whatsapp_message_template',
110 ('GetWhatsAppMessageTemplate', '-'): 'get-whatsapp-message-template',
111 (
112 'ListLinkedWhatsAppBusinessAccounts',
113 '_',
114 ): 'list_linked_whatsapp_business_accounts',
115 (
116 'ListLinkedWhatsAppBusinessAccounts',
117 '-',
118 ): 'list-linked-whatsapp-business-accounts',
119 ('ListWhatsAppMessageTemplates', '_'): 'list_whatsapp_message_templates',
120 ('ListWhatsAppMessageTemplates', '-'): 'list-whatsapp-message-templates',
121 ('ListWhatsAppTemplateLibrary', '_'): 'list_whatsapp_template_library',
122 ('ListWhatsAppTemplateLibrary', '-'): 'list-whatsapp-template-library',
123 ('PostWhatsAppMessageMedia', '_'): 'post_whatsapp_message_media',
124 ('PostWhatsAppMessageMedia', '-'): 'post-whatsapp-message-media',
125 (
126 'PutWhatsAppBusinessAccountEventDestinations',
127 '_',
128 ): 'put_whatsapp_business_account_event_destinations',
129 (
130 'PutWhatsAppBusinessAccountEventDestinations',
131 '-',
132 ): 'put-whatsapp-business-account-event-destinations',
133 ('SendWhatsAppMessage', '_'): 'send_whatsapp_message',
134 ('SendWhatsAppMessage', '-'): 'send-whatsapp-message',
135 ('UpdateWhatsAppMessageTemplate', '_'): 'update_whatsapp_message_template',
136 ('UpdateWhatsAppMessageTemplate', '-'): 'update-whatsapp-message-template',
137}
138ScalarTypes = ('string', 'integer', 'boolean', 'timestamp', 'float', 'double')
139
140BOTOCORE_ROOT = os.path.dirname(os.path.abspath(__file__))
141
142
143# Used to specify anonymous (unsigned) request signature
144class UNSIGNED:
145 def __copy__(self):
146 return self
147
148 def __deepcopy__(self, memodict):
149 return self
150
151
152UNSIGNED = UNSIGNED()
153
154
155def xform_name(name, sep='_', _xform_cache=_xform_cache):
156 """Convert camel case to a "pythonic" name.
157
158 If the name contains the ``sep`` character, then it is
159 returned unchanged.
160
161 """
162 if sep in name:
163 # If the sep is in the name, assume that it's already
164 # transformed and return the string unchanged.
165 return name
166 key = (name, sep)
167 if key not in _xform_cache:
168 if _special_case_transform.search(name) is not None:
169 is_special = _special_case_transform.search(name)
170 matched = is_special.group()
171 # Replace something like ARNs, ACLs with _arns, _acls.
172 name = f"{name[: -len(matched)]}{sep}{matched.lower()}"
173 s1 = _first_cap_regex.sub(r'\1' + sep + r'\2', name)
174 transformed = _end_cap_regex.sub(r'\1' + sep + r'\2', s1).lower()
175 _xform_cache[key] = transformed
176 return _xform_cache[key]
177
178
179def register_initializer(callback):
180 """Register an initializer function for session creation.
181
182 This initializer function will be invoked whenever a new
183 `botocore.session.Session` is instantiated.
184
185 :type callback: callable
186 :param callback: A callable that accepts a single argument
187 of type `botocore.session.Session`.
188
189 """
190 _INITIALIZERS.append(callback)
191
192
193def unregister_initializer(callback):
194 """Unregister an initializer function.
195
196 :type callback: callable
197 :param callback: A callable that was previously registered
198 with `botocore.register_initializer`.
199
200 :raises ValueError: If a callback is provided that is not currently
201 registered as an initializer.
202
203 """
204 _INITIALIZERS.remove(callback)
205
206
207def invoke_initializers(session):
208 """Invoke all initializers for a session.
209
210 :type session: botocore.session.Session
211 :param session: The session to initialize.
212
213 """
214 for initializer in _INITIALIZERS:
215 initializer(session)