Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/boto3/resources/base.py: 25%
57 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-08 06:51 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-08 06:51 +0000
1# Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"). You
4# may not use this file except in compliance with the License. A copy of
5# the License is located at
6#
7# https://aws.amazon.com/apache2.0/
8#
9# or in the "license" file accompanying this file. This file is
10# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11# ANY KIND, either express or implied. See the License for the specific
12# language governing permissions and limitations under the License.
14import logging
16import boto3
18logger = logging.getLogger(__name__)
21class ResourceMeta:
22 """
23 An object containing metadata about a resource.
24 """
26 def __init__(
27 self,
28 service_name,
29 identifiers=None,
30 client=None,
31 data=None,
32 resource_model=None,
33 ):
34 #: (``string``) The service name, e.g. 's3'
35 self.service_name = service_name
37 if identifiers is None:
38 identifiers = []
39 #: (``list``) List of identifier names
40 self.identifiers = identifiers
42 #: (:py:class:`~botocore.client.BaseClient`) Low-level Botocore client
43 self.client = client
44 #: (``dict``) Loaded resource data attributes
45 self.data = data
47 # The resource model for that resource
48 self.resource_model = resource_model
50 def __repr__(self):
51 return 'ResourceMeta(\'{}\', identifiers={})'.format(
52 self.service_name, self.identifiers
53 )
55 def __eq__(self, other):
56 # Two metas are equal if their components are all equal
57 if other.__class__.__name__ != self.__class__.__name__:
58 return False
60 return self.__dict__ == other.__dict__
62 def copy(self):
63 """
64 Create a copy of this metadata object.
65 """
66 params = self.__dict__.copy()
67 service_name = params.pop('service_name')
68 return ResourceMeta(service_name, **params)
71class ServiceResource:
72 """
73 A base class for resources.
75 :type client: botocore.client
76 :param client: A low-level Botocore client instance
77 """
79 meta = None
80 """
81 Stores metadata about this resource instance, such as the
82 ``service_name``, the low-level ``client`` and any cached ``data``
83 from when the instance was hydrated. For example::
85 # Get a low-level client from a resource instance
86 client = resource.meta.client
87 response = client.operation(Param='foo')
89 # Print the resource instance's service short name
90 print(resource.meta.service_name)
92 See :py:class:`ResourceMeta` for more information.
93 """
95 def __init__(self, *args, **kwargs):
96 # Always work on a copy of meta, otherwise we would affect other
97 # instances of the same subclass.
98 self.meta = self.meta.copy()
100 # Create a default client if none was passed
101 if kwargs.get('client') is not None:
102 self.meta.client = kwargs.get('client')
103 else:
104 self.meta.client = boto3.client(self.meta.service_name)
106 # Allow setting identifiers as positional arguments in the order
107 # in which they were defined in the ResourceJSON.
108 for i, value in enumerate(args):
109 setattr(self, '_' + self.meta.identifiers[i], value)
111 # Allow setting identifiers via keyword arguments. Here we need
112 # extra logic to ignore other keyword arguments like ``client``.
113 for name, value in kwargs.items():
114 if name == 'client':
115 continue
117 if name not in self.meta.identifiers:
118 raise ValueError(f'Unknown keyword argument: {name}')
120 setattr(self, '_' + name, value)
122 # Validate that all identifiers have been set.
123 for identifier in self.meta.identifiers:
124 if getattr(self, identifier) is None:
125 raise ValueError(f'Required parameter {identifier} not set')
127 def __repr__(self):
128 identifiers = []
129 for identifier in self.meta.identifiers:
130 identifiers.append(
131 f'{identifier}={repr(getattr(self, identifier))}'
132 )
133 return "{}({})".format(
134 self.__class__.__name__,
135 ', '.join(identifiers),
136 )
138 def __eq__(self, other):
139 # Should be instances of the same resource class
140 if other.__class__.__name__ != self.__class__.__name__:
141 return False
143 # Each of the identifiers should have the same value in both
144 # instances, e.g. two buckets need the same name to be equal.
145 for identifier in self.meta.identifiers:
146 if getattr(self, identifier) != getattr(other, identifier):
147 return False
149 return True
151 def __hash__(self):
152 identifiers = []
153 for identifier in self.meta.identifiers:
154 identifiers.append(getattr(self, identifier))
155 return hash((self.__class__.__name__, tuple(identifiers)))