Mercurial > repos > bcclaywell > argo_navis
comparison venv/lib/python2.7/site-packages/boto/ec2/instance.py @ 0:d67268158946 draft
planemo upload commit a3f181f5f126803c654b3a66dd4e83a48f7e203b
author | bcclaywell |
---|---|
date | Mon, 12 Oct 2015 17:43:33 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:d67268158946 |
---|---|
1 # Copyright (c) 2006-2012 Mitch Garnaat http://garnaat.org/ | |
2 # Copyright (c) 2010, Eucalyptus Systems, Inc. | |
3 # Copyright (c) 2012 Amazon.com, Inc. or its affiliates. All Rights Reserved | |
4 # | |
5 # Permission is hereby granted, free of charge, to any person obtaining a | |
6 # copy of this software and associated documentation files (the | |
7 # "Software"), to deal in the Software without restriction, including | |
8 # without limitation the rights to use, copy, modify, merge, publish, dis- | |
9 # tribute, sublicense, and/or sell copies of the Software, and to permit | |
10 # persons to whom the Software is furnished to do so, subject to the fol- | |
11 # lowing conditions: | |
12 # | |
13 # The above copyright notice and this permission notice shall be included | |
14 # in all copies or substantial portions of the Software. | |
15 # | |
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
17 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- | |
18 # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT | |
19 # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
20 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
21 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | |
22 # IN THE SOFTWARE. | |
23 | |
24 """ | |
25 Represents an EC2 Instance | |
26 """ | |
27 import boto | |
28 from boto.ec2.ec2object import EC2Object, TaggedEC2Object | |
29 from boto.resultset import ResultSet | |
30 from boto.ec2.address import Address | |
31 from boto.ec2.blockdevicemapping import BlockDeviceMapping | |
32 from boto.ec2.image import ProductCodes | |
33 from boto.ec2.networkinterface import NetworkInterface | |
34 from boto.ec2.group import Group | |
35 import base64 | |
36 | |
37 | |
38 class InstanceState(object): | |
39 """ | |
40 The state of the instance. | |
41 | |
42 :ivar code: The low byte represents the state. The high byte is an | |
43 opaque internal value and should be ignored. Valid values: | |
44 | |
45 * 0 (pending) | |
46 * 16 (running) | |
47 * 32 (shutting-down) | |
48 * 48 (terminated) | |
49 * 64 (stopping) | |
50 * 80 (stopped) | |
51 | |
52 :ivar name: The name of the state of the instance. Valid values: | |
53 | |
54 * "pending" | |
55 * "running" | |
56 * "shutting-down" | |
57 * "terminated" | |
58 * "stopping" | |
59 * "stopped" | |
60 """ | |
61 def __init__(self, code=0, name=None): | |
62 self.code = code | |
63 self.name = name | |
64 | |
65 def __repr__(self): | |
66 return '%s(%d)' % (self.name, self.code) | |
67 | |
68 def startElement(self, name, attrs, connection): | |
69 pass | |
70 | |
71 def endElement(self, name, value, connection): | |
72 if name == 'code': | |
73 self.code = int(value) | |
74 elif name == 'name': | |
75 self.name = value | |
76 else: | |
77 setattr(self, name, value) | |
78 | |
79 | |
80 class InstancePlacement(object): | |
81 """ | |
82 The location where the instance launched. | |
83 | |
84 :ivar zone: The Availability Zone of the instance. | |
85 :ivar group_name: The name of the placement group the instance is | |
86 in (for cluster compute instances). | |
87 :ivar tenancy: The tenancy of the instance (if the instance is | |
88 running within a VPC). An instance with a tenancy of dedicated | |
89 runs on single-tenant hardware. | |
90 """ | |
91 def __init__(self, zone=None, group_name=None, tenancy=None): | |
92 self.zone = zone | |
93 self.group_name = group_name | |
94 self.tenancy = tenancy | |
95 | |
96 def __repr__(self): | |
97 return self.zone | |
98 | |
99 def startElement(self, name, attrs, connection): | |
100 pass | |
101 | |
102 def endElement(self, name, value, connection): | |
103 if name == 'availabilityZone': | |
104 self.zone = value | |
105 elif name == 'groupName': | |
106 self.group_name = value | |
107 elif name == 'tenancy': | |
108 self.tenancy = value | |
109 else: | |
110 setattr(self, name, value) | |
111 | |
112 | |
113 class Reservation(EC2Object): | |
114 """ | |
115 Represents a Reservation response object. | |
116 | |
117 :ivar id: The unique ID of the Reservation. | |
118 :ivar owner_id: The unique ID of the owner of the Reservation. | |
119 :ivar groups: A list of Group objects representing the security | |
120 groups associated with launched instances. | |
121 :ivar instances: A list of Instance objects launched in this | |
122 Reservation. | |
123 """ | |
124 def __init__(self, connection=None): | |
125 super(Reservation, self).__init__(connection) | |
126 self.id = None | |
127 self.owner_id = None | |
128 self.groups = [] | |
129 self.instances = [] | |
130 | |
131 def __repr__(self): | |
132 return 'Reservation:%s' % self.id | |
133 | |
134 def startElement(self, name, attrs, connection): | |
135 if name == 'instancesSet': | |
136 self.instances = ResultSet([('item', Instance)]) | |
137 return self.instances | |
138 elif name == 'groupSet': | |
139 self.groups = ResultSet([('item', Group)]) | |
140 return self.groups | |
141 else: | |
142 return None | |
143 | |
144 def endElement(self, name, value, connection): | |
145 if name == 'reservationId': | |
146 self.id = value | |
147 elif name == 'ownerId': | |
148 self.owner_id = value | |
149 else: | |
150 setattr(self, name, value) | |
151 | |
152 def stop_all(self, dry_run=False): | |
153 for instance in self.instances: | |
154 instance.stop(dry_run=dry_run) | |
155 | |
156 | |
157 class Instance(TaggedEC2Object): | |
158 """ | |
159 Represents an instance. | |
160 | |
161 :ivar id: The unique ID of the Instance. | |
162 :ivar groups: A list of Group objects representing the security | |
163 groups associated with the instance. | |
164 :ivar public_dns_name: The public dns name of the instance. | |
165 :ivar private_dns_name: The private dns name of the instance. | |
166 :ivar state: The string representation of the instance's current state. | |
167 :ivar state_code: An integer representation of the instance's | |
168 current state. | |
169 :ivar previous_state: The string representation of the instance's | |
170 previous state. | |
171 :ivar previous_state_code: An integer representation of the | |
172 instance's current state. | |
173 :ivar key_name: The name of the SSH key associated with the instance. | |
174 :ivar instance_type: The type of instance (e.g. m1.small). | |
175 :ivar launch_time: The time the instance was launched. | |
176 :ivar image_id: The ID of the AMI used to launch this instance. | |
177 :ivar placement: The availability zone in which the instance is running. | |
178 :ivar placement_group: The name of the placement group the instance | |
179 is in (for cluster compute instances). | |
180 :ivar placement_tenancy: The tenancy of the instance, if the instance | |
181 is running within a VPC. An instance with a tenancy of dedicated | |
182 runs on a single-tenant hardware. | |
183 :ivar kernel: The kernel associated with the instance. | |
184 :ivar ramdisk: The ramdisk associated with the instance. | |
185 :ivar architecture: The architecture of the image (i386|x86_64). | |
186 :ivar hypervisor: The hypervisor used. | |
187 :ivar virtualization_type: The type of virtualization used. | |
188 :ivar product_codes: A list of product codes associated with this instance. | |
189 :ivar ami_launch_index: This instances position within it's launch group. | |
190 :ivar monitored: A boolean indicating whether monitoring is enabled or not. | |
191 :ivar monitoring_state: A string value that contains the actual value | |
192 of the monitoring element returned by EC2. | |
193 :ivar spot_instance_request_id: The ID of the spot instance request | |
194 if this is a spot instance. | |
195 :ivar subnet_id: The VPC Subnet ID, if running in VPC. | |
196 :ivar vpc_id: The VPC ID, if running in VPC. | |
197 :ivar private_ip_address: The private IP address of the instance. | |
198 :ivar ip_address: The public IP address of the instance. | |
199 :ivar platform: Platform of the instance (e.g. Windows) | |
200 :ivar root_device_name: The name of the root device. | |
201 :ivar root_device_type: The root device type (ebs|instance-store). | |
202 :ivar block_device_mapping: The Block Device Mapping for the instance. | |
203 :ivar state_reason: The reason for the most recent state transition. | |
204 :ivar groups: List of security Groups associated with the instance. | |
205 :ivar interfaces: List of Elastic Network Interfaces associated with | |
206 this instance. | |
207 :ivar ebs_optimized: Whether instance is using optimized EBS volumes | |
208 or not. | |
209 :ivar instance_profile: A Python dict containing the instance | |
210 profile id and arn associated with this instance. | |
211 """ | |
212 | |
213 def __init__(self, connection=None): | |
214 super(Instance, self).__init__(connection) | |
215 self.id = None | |
216 self.dns_name = None | |
217 self.public_dns_name = None | |
218 self.private_dns_name = None | |
219 self.key_name = None | |
220 self.instance_type = None | |
221 self.launch_time = None | |
222 self.image_id = None | |
223 self.kernel = None | |
224 self.ramdisk = None | |
225 self.product_codes = ProductCodes() | |
226 self.ami_launch_index = None | |
227 self.monitored = False | |
228 self.monitoring_state = None | |
229 self.spot_instance_request_id = None | |
230 self.subnet_id = None | |
231 self.vpc_id = None | |
232 self.private_ip_address = None | |
233 self.ip_address = None | |
234 self.requester_id = None | |
235 self._in_monitoring_element = False | |
236 self.persistent = False | |
237 self.root_device_name = None | |
238 self.root_device_type = None | |
239 self.block_device_mapping = None | |
240 self.state_reason = None | |
241 self.group_name = None | |
242 self.client_token = None | |
243 self.eventsSet = None | |
244 self.groups = [] | |
245 self.platform = None | |
246 self.interfaces = [] | |
247 self.hypervisor = None | |
248 self.virtualization_type = None | |
249 self.architecture = None | |
250 self.instance_profile = None | |
251 self._previous_state = None | |
252 self._state = InstanceState() | |
253 self._placement = InstancePlacement() | |
254 | |
255 def __repr__(self): | |
256 return 'Instance:%s' % self.id | |
257 | |
258 @property | |
259 def state(self): | |
260 return self._state.name | |
261 | |
262 @property | |
263 def state_code(self): | |
264 return self._state.code | |
265 | |
266 @property | |
267 def previous_state(self): | |
268 if self._previous_state: | |
269 return self._previous_state.name | |
270 return None | |
271 | |
272 @property | |
273 def previous_state_code(self): | |
274 if self._previous_state: | |
275 return self._previous_state.code | |
276 return 0 | |
277 | |
278 @property | |
279 def placement(self): | |
280 return self._placement.zone | |
281 | |
282 @property | |
283 def placement_group(self): | |
284 return self._placement.group_name | |
285 | |
286 @property | |
287 def placement_tenancy(self): | |
288 return self._placement.tenancy | |
289 | |
290 def startElement(self, name, attrs, connection): | |
291 retval = super(Instance, self).startElement(name, attrs, connection) | |
292 if retval is not None: | |
293 return retval | |
294 if name == 'monitoring': | |
295 self._in_monitoring_element = True | |
296 elif name == 'blockDeviceMapping': | |
297 self.block_device_mapping = BlockDeviceMapping() | |
298 return self.block_device_mapping | |
299 elif name == 'productCodes': | |
300 return self.product_codes | |
301 elif name == 'stateReason': | |
302 self.state_reason = SubParse('stateReason') | |
303 return self.state_reason | |
304 elif name == 'groupSet': | |
305 self.groups = ResultSet([('item', Group)]) | |
306 return self.groups | |
307 elif name == "eventsSet": | |
308 self.eventsSet = SubParse('eventsSet') | |
309 return self.eventsSet | |
310 elif name == 'networkInterfaceSet': | |
311 self.interfaces = ResultSet([('item', NetworkInterface)]) | |
312 return self.interfaces | |
313 elif name == 'iamInstanceProfile': | |
314 self.instance_profile = SubParse('iamInstanceProfile') | |
315 return self.instance_profile | |
316 elif name == 'currentState': | |
317 return self._state | |
318 elif name == 'previousState': | |
319 self._previous_state = InstanceState() | |
320 return self._previous_state | |
321 elif name == 'instanceState': | |
322 return self._state | |
323 elif name == 'placement': | |
324 return self._placement | |
325 return None | |
326 | |
327 def endElement(self, name, value, connection): | |
328 if name == 'instanceId': | |
329 self.id = value | |
330 elif name == 'imageId': | |
331 self.image_id = value | |
332 elif name == 'dnsName' or name == 'publicDnsName': | |
333 self.dns_name = value # backwards compatibility | |
334 self.public_dns_name = value | |
335 elif name == 'privateDnsName': | |
336 self.private_dns_name = value | |
337 elif name == 'keyName': | |
338 self.key_name = value | |
339 elif name == 'amiLaunchIndex': | |
340 self.ami_launch_index = value | |
341 elif name == 'previousState': | |
342 self.previous_state = value | |
343 elif name == 'instanceType': | |
344 self.instance_type = value | |
345 elif name == 'rootDeviceName': | |
346 self.root_device_name = value | |
347 elif name == 'rootDeviceType': | |
348 self.root_device_type = value | |
349 elif name == 'launchTime': | |
350 self.launch_time = value | |
351 elif name == 'platform': | |
352 self.platform = value | |
353 elif name == 'kernelId': | |
354 self.kernel = value | |
355 elif name == 'ramdiskId': | |
356 self.ramdisk = value | |
357 elif name == 'state': | |
358 if self._in_monitoring_element: | |
359 self.monitoring_state = value | |
360 if value == 'enabled': | |
361 self.monitored = True | |
362 self._in_monitoring_element = False | |
363 elif name == 'spotInstanceRequestId': | |
364 self.spot_instance_request_id = value | |
365 elif name == 'subnetId': | |
366 self.subnet_id = value | |
367 elif name == 'vpcId': | |
368 self.vpc_id = value | |
369 elif name == 'privateIpAddress': | |
370 self.private_ip_address = value | |
371 elif name == 'ipAddress': | |
372 self.ip_address = value | |
373 elif name == 'requesterId': | |
374 self.requester_id = value | |
375 elif name == 'persistent': | |
376 if value == 'true': | |
377 self.persistent = True | |
378 else: | |
379 self.persistent = False | |
380 elif name == 'groupName': | |
381 if self._in_monitoring_element: | |
382 self.group_name = value | |
383 elif name == 'clientToken': | |
384 self.client_token = value | |
385 elif name == "eventsSet": | |
386 self.events = value | |
387 elif name == 'hypervisor': | |
388 self.hypervisor = value | |
389 elif name == 'virtualizationType': | |
390 self.virtualization_type = value | |
391 elif name == 'architecture': | |
392 self.architecture = value | |
393 elif name == 'ebsOptimized': | |
394 self.ebs_optimized = (value == 'true') | |
395 else: | |
396 setattr(self, name, value) | |
397 | |
398 def _update(self, updated): | |
399 self.__dict__.update(updated.__dict__) | |
400 | |
401 def update(self, validate=False, dry_run=False): | |
402 """ | |
403 Update the instance's state information by making a call to fetch | |
404 the current instance attributes from the service. | |
405 | |
406 :type validate: bool | |
407 :param validate: By default, if EC2 returns no data about the | |
408 instance the update method returns quietly. If | |
409 the validate param is True, however, it will | |
410 raise a ValueError exception if no data is | |
411 returned from EC2. | |
412 """ | |
413 rs = self.connection.get_all_reservations([self.id], dry_run=dry_run) | |
414 if len(rs) > 0: | |
415 r = rs[0] | |
416 for i in r.instances: | |
417 if i.id == self.id: | |
418 self._update(i) | |
419 elif validate: | |
420 raise ValueError('%s is not a valid Instance ID' % self.id) | |
421 return self.state | |
422 | |
423 def terminate(self, dry_run=False): | |
424 """ | |
425 Terminate the instance | |
426 """ | |
427 rs = self.connection.terminate_instances([self.id], dry_run=dry_run) | |
428 if len(rs) > 0: | |
429 self._update(rs[0]) | |
430 | |
431 def stop(self, force=False, dry_run=False): | |
432 """ | |
433 Stop the instance | |
434 | |
435 :type force: bool | |
436 :param force: Forces the instance to stop | |
437 | |
438 :rtype: list | |
439 :return: A list of the instances stopped | |
440 """ | |
441 rs = self.connection.stop_instances([self.id], force, dry_run=dry_run) | |
442 if len(rs) > 0: | |
443 self._update(rs[0]) | |
444 | |
445 def start(self, dry_run=False): | |
446 """ | |
447 Start the instance. | |
448 """ | |
449 rs = self.connection.start_instances([self.id], dry_run=dry_run) | |
450 if len(rs) > 0: | |
451 self._update(rs[0]) | |
452 | |
453 def reboot(self, dry_run=False): | |
454 return self.connection.reboot_instances([self.id], dry_run=dry_run) | |
455 | |
456 def get_console_output(self, dry_run=False): | |
457 """ | |
458 Retrieves the console output for the instance. | |
459 | |
460 :rtype: :class:`boto.ec2.instance.ConsoleOutput` | |
461 :return: The console output as a ConsoleOutput object | |
462 """ | |
463 return self.connection.get_console_output(self.id, dry_run=dry_run) | |
464 | |
465 def confirm_product(self, product_code, dry_run=False): | |
466 return self.connection.confirm_product_instance( | |
467 self.id, | |
468 product_code, | |
469 dry_run=dry_run | |
470 ) | |
471 | |
472 def use_ip(self, ip_address, dry_run=False): | |
473 """ | |
474 Associates an Elastic IP to the instance. | |
475 | |
476 :type ip_address: Either an instance of | |
477 :class:`boto.ec2.address.Address` or a string. | |
478 :param ip_address: The IP address to associate | |
479 with the instance. | |
480 | |
481 :rtype: bool | |
482 :return: True if successful | |
483 """ | |
484 | |
485 if isinstance(ip_address, Address): | |
486 ip_address = ip_address.public_ip | |
487 return self.connection.associate_address( | |
488 self.id, | |
489 ip_address, | |
490 dry_run=dry_run | |
491 ) | |
492 | |
493 def monitor(self, dry_run=False): | |
494 return self.connection.monitor_instance(self.id, dry_run=dry_run) | |
495 | |
496 def unmonitor(self, dry_run=False): | |
497 return self.connection.unmonitor_instance(self.id, dry_run=dry_run) | |
498 | |
499 def get_attribute(self, attribute, dry_run=False): | |
500 """ | |
501 Gets an attribute from this instance. | |
502 | |
503 :type attribute: string | |
504 :param attribute: The attribute you need information about | |
505 Valid choices are: | |
506 | |
507 * instanceType | |
508 * kernel | |
509 * ramdisk | |
510 * userData | |
511 * disableApiTermination | |
512 * instanceInitiatedShutdownBehavior | |
513 * rootDeviceName | |
514 * blockDeviceMapping | |
515 * productCodes | |
516 * sourceDestCheck | |
517 * groupSet | |
518 * ebsOptimized | |
519 | |
520 :rtype: :class:`boto.ec2.image.InstanceAttribute` | |
521 :return: An InstanceAttribute object representing the value of the | |
522 attribute requested | |
523 """ | |
524 return self.connection.get_instance_attribute( | |
525 self.id, | |
526 attribute, | |
527 dry_run=dry_run | |
528 ) | |
529 | |
530 def modify_attribute(self, attribute, value, dry_run=False): | |
531 """ | |
532 Changes an attribute of this instance | |
533 | |
534 :type attribute: string | |
535 :param attribute: The attribute you wish to change. | |
536 | |
537 * instanceType - A valid instance type (m1.small) | |
538 * kernel - Kernel ID (None) | |
539 * ramdisk - Ramdisk ID (None) | |
540 * userData - Base64 encoded String (None) | |
541 * disableApiTermination - Boolean (true) | |
542 * instanceInitiatedShutdownBehavior - stop|terminate | |
543 * sourceDestCheck - Boolean (true) | |
544 * groupSet - Set of Security Groups or IDs | |
545 * ebsOptimized - Boolean (false) | |
546 | |
547 :type value: string | |
548 :param value: The new value for the attribute | |
549 | |
550 :rtype: bool | |
551 :return: Whether the operation succeeded or not | |
552 """ | |
553 return self.connection.modify_instance_attribute( | |
554 self.id, | |
555 attribute, | |
556 value, | |
557 dry_run=dry_run | |
558 ) | |
559 | |
560 def reset_attribute(self, attribute, dry_run=False): | |
561 """ | |
562 Resets an attribute of this instance to its default value. | |
563 | |
564 :type attribute: string | |
565 :param attribute: The attribute to reset. Valid values are: | |
566 kernel|ramdisk | |
567 | |
568 :rtype: bool | |
569 :return: Whether the operation succeeded or not | |
570 """ | |
571 return self.connection.reset_instance_attribute( | |
572 self.id, | |
573 attribute, | |
574 dry_run=dry_run | |
575 ) | |
576 | |
577 def create_image(self, name, description=None, no_reboot=False, | |
578 dry_run=False): | |
579 """ | |
580 Will create an AMI from the instance in the running or stopped | |
581 state. | |
582 | |
583 :type name: string | |
584 :param name: The name of the new image | |
585 | |
586 :type description: string | |
587 :param description: An optional human-readable string describing | |
588 the contents and purpose of the AMI. | |
589 | |
590 :type no_reboot: bool | |
591 :param no_reboot: An optional flag indicating that the bundling process | |
592 should not attempt to shutdown the instance before | |
593 bundling. If this flag is True, the responsibility | |
594 of maintaining file system integrity is left to the | |
595 owner of the instance. | |
596 | |
597 :rtype: string | |
598 :return: The new image id | |
599 """ | |
600 return self.connection.create_image( | |
601 self.id, | |
602 name, | |
603 description, | |
604 no_reboot, | |
605 dry_run=dry_run | |
606 ) | |
607 | |
608 | |
609 class ConsoleOutput(object): | |
610 def __init__(self, parent=None): | |
611 self.parent = parent | |
612 self.instance_id = None | |
613 self.timestamp = None | |
614 self.output = None | |
615 | |
616 def startElement(self, name, attrs, connection): | |
617 return None | |
618 | |
619 def endElement(self, name, value, connection): | |
620 if name == 'instanceId': | |
621 self.instance_id = value | |
622 elif name == 'timestamp': | |
623 self.timestamp = value | |
624 elif name == 'output': | |
625 self.output = base64.b64decode(value) | |
626 else: | |
627 setattr(self, name, value) | |
628 | |
629 | |
630 class InstanceAttribute(dict): | |
631 ValidValues = ['instanceType', 'kernel', 'ramdisk', 'userData', | |
632 'disableApiTermination', | |
633 'instanceInitiatedShutdownBehavior', | |
634 'rootDeviceName', 'blockDeviceMapping', 'sourceDestCheck', | |
635 'groupSet'] | |
636 | |
637 def __init__(self, parent=None): | |
638 dict.__init__(self) | |
639 self.instance_id = None | |
640 self.request_id = None | |
641 self._current_value = None | |
642 | |
643 def startElement(self, name, attrs, connection): | |
644 if name == 'blockDeviceMapping': | |
645 self[name] = BlockDeviceMapping() | |
646 return self[name] | |
647 elif name == 'groupSet': | |
648 self[name] = ResultSet([('item', Group)]) | |
649 return self[name] | |
650 else: | |
651 return None | |
652 | |
653 def endElement(self, name, value, connection): | |
654 if name == 'instanceId': | |
655 self.instance_id = value | |
656 elif name == 'requestId': | |
657 self.request_id = value | |
658 elif name == 'value': | |
659 if value == 'true': | |
660 value = True | |
661 elif value == 'false': | |
662 value = False | |
663 self._current_value = value | |
664 elif name in self.ValidValues: | |
665 self[name] = self._current_value | |
666 | |
667 | |
668 class SubParse(dict): | |
669 def __init__(self, section, parent=None): | |
670 dict.__init__(self) | |
671 self.section = section | |
672 | |
673 def startElement(self, name, attrs, connection): | |
674 return None | |
675 | |
676 def endElement(self, name, value, connection): | |
677 if name != self.section: | |
678 self[name] = value |