Total Complexity | 50 |
Total Lines | 118 |
Duplicated Lines | 0 % |
Complex classes like ResultSets often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
1 | import boto |
||
140 | class ResultSets(object): |
||
141 | |||
142 | def __init__(self): |
||
143 | self.foo = '' |
||
144 | |||
145 | def selector(self, output): |
||
146 | if isinstance(output, boto.ec2.instance.Reservation): |
||
147 | return self.parseReservation(output) |
||
148 | elif isinstance(output, boto.ec2.instance.Instance): |
||
149 | return self.parseInstance(output) |
||
150 | elif isinstance(output, boto.ec2.volume.Volume): |
||
151 | return self.parseVolume(output) |
||
152 | elif isinstance(output, boto.ec2.blockdevicemapping.BlockDeviceType): |
||
153 | return self.parseBlockDeviceType(output) |
||
154 | elif isinstance(output, boto.ec2.zone.Zone): |
||
155 | return self.parseEC2Zone(output) |
||
156 | elif isinstance(output, boto.ec2.address.Address): |
||
157 | return self.parseAddress(output) |
||
158 | elif isinstance(output, boto.route53.record.Record): |
||
159 | return self.parseRecord(output) |
||
160 | elif isinstance(output, boto.route53.zone.Zone): |
||
161 | return self.parseR53Zone(output) |
||
162 | elif isinstance(output, boto.route53.status.Status): |
||
163 | return self.parseR53Status(output) |
||
164 | elif isinstance(output, boto.ec2.tag.Tag): |
||
165 | return self.parseTag(output) |
||
166 | elif isinstance(output, boto.ec2.ec2object.EC2Object): |
||
167 | return self.parseEC2Object(output) |
||
168 | elif isinstance(output, boto.cloudformation.stack.Stack): |
||
169 | return self.parseStackObject(output) |
||
170 | else: |
||
171 | return output |
||
172 | |||
173 | def formatter(self, output): |
||
174 | if isinstance(output, list): |
||
175 | return [self.formatter(item) for item in output] |
||
176 | elif isinstance(output, dict): |
||
177 | return {key: self.formatter(value) for key, value in six.iteritems(output)} |
||
178 | else: |
||
179 | return self.selector(output) |
||
180 | |||
181 | def parseReservation(self, output): |
||
182 | instance_list = [] |
||
183 | for instance in output.instances: |
||
184 | instance_data = self.parseInstance(instance) |
||
185 | instance_data['owner_id'] = output.owner_id |
||
186 | instance_list.append(instance_data) |
||
187 | return instance_list |
||
188 | |||
189 | def parseAddress(self, output): |
||
190 | instance_data = {field: getattr(output, field) for field in FieldLists.ADDRESS} |
||
191 | return instance_data |
||
192 | |||
193 | def parseInstance(self, output): |
||
194 | instance_data = {field: getattr(output, field) for field in FieldLists.INSTANCE} |
||
195 | return instance_data |
||
196 | |||
197 | def parseVolume(self, output): |
||
198 | volume_data = {field: getattr(output, field) for field in FieldLists.VOLUME} |
||
199 | return volume_data |
||
200 | |||
201 | def parseBlockDeviceType(self, output): |
||
202 | data = {field: getattr(output, field) for field in FieldLists.BLOCK_DEVICE_TYPE} |
||
203 | return data |
||
204 | |||
205 | def parseEC2Zone(self, output): |
||
206 | zone_data = {field: getattr(output, field) for field in FieldLists.EC2ZONE} |
||
207 | return zone_data |
||
208 | |||
209 | def parseRecord(self, output): |
||
210 | record_data = {field: getattr(output, field) for field in FieldLists.RECORD} |
||
211 | return record_data |
||
212 | |||
213 | def parseR53Zone(self, output): |
||
214 | zone_data = {field: getattr(output, field) for field in FieldLists.R53ZONE} |
||
215 | return zone_data |
||
216 | |||
217 | def parseR53Status(self, output): |
||
218 | status_data = {field: getattr(output, field) for field in FieldLists.R53STATUS} |
||
219 | return status_data |
||
220 | |||
221 | def parseBucket(self, output): |
||
222 | bucket_data = {field: getattr(output, field) for field in FieldLists.BUCKET} |
||
223 | return bucket_data |
||
224 | |||
225 | def parseTag(self, output): |
||
226 | tag_data = {field: getattr(output, field) for field in FieldLists.TAG} |
||
227 | return tag_data |
||
228 | |||
229 | def parseStackObject(self, output): |
||
230 | stack_data = {field: getattr(output, field) for field in FieldLists.STACK} |
||
231 | return stack_data |
||
232 | |||
233 | def parseEC2Object(self, output): |
||
234 | # Looks like everything that is an EC2Object pretty much only has these extra |
||
235 | # 'unparseable' properties so handle region and connection specially. |
||
236 | output = vars(output) |
||
237 | del output['connection'] |
||
238 | # special handling for region since name here is better than id. |
||
239 | region = output.get('region', None) |
||
240 | output['region'] = region.name if region else '' |
||
241 | # now anything that is an EC2Object get some special marshalling care. |
||
242 | for k, v in six.iteritems(output): |
||
243 | if isinstance(v, boto.ec2.ec2object.EC2Object): |
||
244 | # Better not to assume each EC2Object has an id. If not found |
||
245 | # resort to the str of the object which should have something meaningful. |
||
246 | output[k] = getattr(v, 'id', str(v)) |
||
247 | # Generally unmarshallable object might be hiding in list so better to |
||
248 | if isinstance(v, list): |
||
249 | v_list = [] |
||
250 | for item in v: |
||
251 | # avoid touching the basic types. |
||
252 | if isinstance(item, (basestring, bool, int, long, float)): |
||
253 | v_list.append(v) |
||
254 | else: |
||
255 | v_list.append(str(item)) |
||
256 | output[k] = v_list |
||
257 | return output |
||
258 |