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

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 'ResourceMeta(\'{}\', identifiers={})'.format( 

52 self.service_name, self.identifiers 

53 ) 

54 

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 

59 

60 return self.__dict__ == other.__dict__ 

61 

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) 

69 

70 

71class ServiceResource: 

72 """ 

73 A base class for resources. 

74 

75 :type client: botocore.client 

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

77 """ 

78 

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:: 

84 

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

86 client = resource.meta.client 

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

88 

89 # Print the resource instance's service short name 

90 print(resource.meta.service_name) 

91 

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

93 """ 

94 

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() 

99 

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) 

105 

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) 

110 

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 

116 

117 if name not in self.meta.identifiers: 

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

119 

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

121 

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') 

126 

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 ) 

137 

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 

142 

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 

148 

149 return True 

150 

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)))