Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/boto3/resources/base.py: 25%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

57 statements  

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. 

13 

14import logging 

15 

16import boto3 

17 

18logger = logging.getLogger(__name__) 

19 

20 

21class ResourceMeta: 

22 """ 

23 An object containing metadata about a resource. 

24 """ 

25 

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 

36 

37 if identifiers is None: 

38 identifiers = [] 

39 #: (``list``) List of identifier names 

40 self.identifiers = identifiers 

41 

42 #: (:py:class:`~botocore.client.BaseClient`) Low-level Botocore client 

43 self.client = client 

44 #: (``dict``) Loaded resource data attributes 

45 self.data = data 

46 

47 # The resource model for that resource 

48 self.resource_model = resource_model 

49 

50 def __repr__(self): 

51 return f'ResourceMeta(\'{self.service_name}\', identifiers={self.identifiers})' 

52 

53 def __eq__(self, other): 

54 # Two metas are equal if their components are all equal 

55 if other.__class__.__name__ != self.__class__.__name__: 

56 return False 

57 

58 return self.__dict__ == other.__dict__ 

59 

60 def copy(self): 

61 """ 

62 Create a copy of this metadata object. 

63 """ 

64 params = self.__dict__.copy() 

65 service_name = params.pop('service_name') 

66 return ResourceMeta(service_name, **params) 

67 

68 

69class ServiceResource: 

70 """ 

71 A base class for resources. 

72 

73 :type client: botocore.client 

74 :param client: A low-level Botocore client instance 

75 """ 

76 

77 meta = None 

78 """ 

79 Stores metadata about this resource instance, such as the 

80 ``service_name``, the low-level ``client`` and any cached ``data`` 

81 from when the instance was hydrated. For example:: 

82 

83 # Get a low-level client from a resource instance 

84 client = resource.meta.client 

85 response = client.operation(Param='foo') 

86 

87 # Print the resource instance's service short name 

88 print(resource.meta.service_name) 

89 

90 See :py:class:`ResourceMeta` for more information. 

91 """ 

92 

93 def __init__(self, *args, **kwargs): 

94 # Always work on a copy of meta, otherwise we would affect other 

95 # instances of the same subclass. 

96 self.meta = self.meta.copy() 

97 

98 # Create a default client if none was passed 

99 if kwargs.get('client') is not None: 

100 self.meta.client = kwargs.get('client') 

101 else: 

102 self.meta.client = boto3.client(self.meta.service_name) 

103 

104 # Allow setting identifiers as positional arguments in the order 

105 # in which they were defined in the ResourceJSON. 

106 for i, value in enumerate(args): 

107 setattr(self, '_' + self.meta.identifiers[i], value) 

108 

109 # Allow setting identifiers via keyword arguments. Here we need 

110 # extra logic to ignore other keyword arguments like ``client``. 

111 for name, value in kwargs.items(): 

112 if name == 'client': 

113 continue 

114 

115 if name not in self.meta.identifiers: 

116 raise ValueError(f'Unknown keyword argument: {name}') 

117 

118 setattr(self, '_' + name, value) 

119 

120 # Validate that all identifiers have been set. 

121 for identifier in self.meta.identifiers: 

122 if getattr(self, identifier) is None: 

123 raise ValueError(f'Required parameter {identifier} not set') 

124 

125 def __repr__(self): 

126 identifiers = [] 

127 for identifier in self.meta.identifiers: 

128 identifiers.append( 

129 f'{identifier}={repr(getattr(self, identifier))}' 

130 ) 

131 return "{}({})".format( 

132 self.__class__.__name__, 

133 ', '.join(identifiers), 

134 ) 

135 

136 def __eq__(self, other): 

137 # Should be instances of the same resource class 

138 if other.__class__.__name__ != self.__class__.__name__: 

139 return False 

140 

141 # Each of the identifiers should have the same value in both 

142 # instances, e.g. two buckets need the same name to be equal. 

143 for identifier in self.meta.identifiers: 

144 if getattr(self, identifier) != getattr(other, identifier): 

145 return False 

146 

147 return True 

148 

149 def __hash__(self): 

150 identifiers = [] 

151 for identifier in self.meta.identifiers: 

152 identifiers.append(getattr(self, identifier)) 

153 return hash((self.__class__.__name__, tuple(identifiers)))