1 #!/usr/bin/env python 2 3 """ 4 Data classes. 5 6 Copyright (C) 2007, 2008, 2009 Paul Boddie <paul@boddie.org.uk> 7 8 This program is free software; you can redistribute it and/or modify it under 9 the terms of the GNU General Public License as published by the Free Software 10 Foundation; either version 3 of the License, or (at your option) any later 11 version. 12 13 This program is distributed in the hope that it will be useful, but WITHOUT 14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 16 details. 17 18 You should have received a copy of the GNU General Public License along with 19 this program. If not, see <http://www.gnu.org/licenses/>. 20 21 -------- 22 23 The central data structure classes in this module are the following: 24 25 * Class 26 * Function 27 * Module 28 29 All of the above support the Naming interface either explicitly or through 30 general conformance, meaning that all can be asked to provide their 'full_name' 31 using the method of that name. 32 33 Additionally, all of the above also support a dictionary interface in order to 34 access names within their defined scopes. Specific methods also exist in order 35 to distinguish between certain kinds of attributes: 36 37 * Class: class_attributes, all_class_attributes, instance_attributes, all_attributes 38 * Function: parameters, locals, all_locals 39 * Module: module_attributes 40 41 These specific methods are useful in certain situations. 42 43 The above classes also provide an 'astnode' attribute, indicating the AST node 44 where each such object is defined. 45 """ 46 47 from micropython.program import DataObject, DataValue, ReplaceableContext, PlaceholderContext 48 49 def shortrepr(obj): 50 if obj is None: 51 return repr(None) 52 else: 53 return obj.__shortrepr__() 54 55 # Special representations. 56 57 class AtLeast: 58 59 "A special representation for numbers of a given value or greater." 60 61 def __init__(self, count): 62 self.count = count 63 64 def __eq__(self, other): 65 return 0 66 67 __lt__ = __le__ = __eq__ 68 69 def __ne__(self, other): 70 return 1 71 72 def __gt__(self, other): 73 if isinstance(other, AtLeast): 74 return 0 75 else: 76 return self.count > other 77 78 def __ge__(self, other): 79 if isinstance(other, AtLeast): 80 return 0 81 else: 82 return self.count >= other 83 84 def __iadd__(self, other): 85 if isinstance(other, AtLeast): 86 self.count += other.count 87 else: 88 self.count += other 89 return self 90 91 def __radd__(self, other): 92 if isinstance(other, AtLeast): 93 return AtLeast(self.count + other.count) 94 else: 95 return AtLeast(self.count + other) 96 97 def __repr__(self): 98 return "AtLeast(%r)" % self.count 99 100 # Mix-ins and abstract classes. 101 102 class Naming: 103 104 "A mix-in providing naming conveniences." 105 106 def full_name(self): 107 if self.name is not None: 108 return self.parent.full_name() + "." + self.name 109 else: 110 return self.parent.full_name() 111 112 class NamespaceDict: 113 114 "A mix-in providing dictionary methods." 115 116 def __init__(self, module=None): 117 self.namespace = {} 118 self.globals = set() 119 self.module = module 120 self.finalised = 0 121 122 def __delitem__(self, name): 123 del self.namespace[name] 124 125 def has_key(self, name): 126 return self.namespace.has_key(name) 127 128 def keys(self): 129 return self.namespace.keys() 130 131 def values(self): 132 return self.namespace.values() 133 134 def items(self): 135 return self.namespace.items() 136 137 def __getitem__(self, name): 138 return self.namespace[name] 139 140 def get(self, name, default=None): 141 return self.namespace.get(name, default) 142 143 def __setitem__(self, name, value): 144 self.set(name, value) 145 146 def set(self, name, value, single_assignment=1): 147 148 """ 149 A more powerful set operation, making 'name' refer to 'value' whilst 150 indicating whether a 'single_assignment' (true by default) occurs in 151 this operation (or whether the operation covers potentially many 152 assignments in the lifetime of a program). 153 """ 154 155 if name in self.globals: 156 self.module.set(name, value, 0) 157 else: 158 self._set(name, value, single_assignment) 159 160 def set_module(self, name, value): 161 162 """ 163 A specialised set operation, making 'name' refer to 'value' in the 164 context of making a module reference available in association with 165 'name' as part of the import of that module or a submodule of that 166 module. 167 """ 168 169 self._set(name, value, 1) 170 171 def _set(self, name, attr_or_value, single_assignment=1): 172 173 """ 174 The underlying set operation associating 'name' with the given 175 'attr_or_value'. 176 See: docs/assignment.txt 177 """ 178 179 # Add and/or obtain the namespace entry. 180 181 if not self.namespace.has_key(name): 182 self.namespace[name] = Attr(None, self, name) 183 184 attr = self.namespace[name] 185 186 # Handle attribute assignment as well as assignment of basic objects. 187 # Attempt to fix the context if not explicitly defined. 188 189 if isinstance(attr_or_value, Attr): 190 context_values = self.get_updated_context_values(attr_or_value.context_values) 191 else: 192 context_values = self.get_updated_context_values([self.get_context_and_value(attr_or_value)]) 193 194 attr.update(context_values, single_assignment) 195 196 def get_context_and_value(self, value): 197 198 "Return a context, value tuple for the given 'value'." 199 200 # Functions have a replaceable context. 201 202 if isinstance(value, Function): 203 return (ReplaceableContext, value) 204 205 # Classes use placeholder contexts which cannot be replaced but which 206 # do not communicate useful contextual information. 207 208 elif isinstance(value, Class): 209 return (PlaceholderContext, value) 210 211 # Other values employ themselves as the context. 212 213 else: 214 return (value, value) 215 216 def get_updated_context_values(self, context_values): 217 218 """ 219 Adapt the contexts found in the given 'context_values', returning a new 220 set. 221 See: docs/assignment.txt 222 """ 223 224 results = set() 225 226 for context, value in context_values: 227 228 # Set the context of instances to themselves. 229 230 if isinstance(value, Instance): 231 results.add((value, value)) 232 else: 233 results.add((context, value)) 234 235 return results 236 237 def make_global(self, name): 238 if not self.namespace.has_key(name): 239 self.globals.add(name) 240 return 1 241 else: 242 return 0 243 244 def attributes_as_list(self): 245 246 "Return the attributes in a list." 247 248 self.finalise_attributes() 249 l = [None] * len(self.keys()) 250 for attr in self.values(): 251 l[attr.position] = attr 252 return l 253 254 def finalise_attributes(self): 255 256 "Make sure all attributes are fully defined." 257 258 if self.finalised: 259 return 260 261 # The default action is to assign attribute positions sequentially. 262 263 for i, attr in enumerate(self.values()): 264 attr.position = i 265 266 self.finalised = 1 267 268 # Program data structures. There are two separate kinds of structures: those 269 # with context, which are the values manipulated by programs, and those without 270 # context, which are typically constant things which are stored alongside the 271 # program but which are wrapped in context-dependent structures in the running 272 # program. 273 274 class Attr: 275 276 "An attribute entry having a context." 277 278 def __init__(self, position, parent, name): 279 280 """ 281 Initialise the attribute with the given 'position' within the collection 282 of attributes of its 'parent', indicating its 'name'. 283 """ 284 285 self.position = position 286 self.parent = parent 287 self.name = name 288 289 # Attribute usage. 290 291 self.attributes_used = set() 292 293 # Possible values. 294 295 self.context_values = set() 296 297 # Number of assignments per name. 298 299 self.assignments = None 300 301 # Attribute usage methods. 302 303 def use_attribute(self, attrname): 304 self.attributes_used.add(attrname) 305 return self.attributes_used 306 307 # Value-related methods. 308 309 def get_contexts(self): 310 return [c for (c, v) in self.context_values] 311 312 def get_values(self): 313 return [v for (c, v) in self.context_values] 314 315 def get_context(self): 316 if len(self.context_values) == 1: 317 return self.get_contexts()[0] 318 else: 319 return None 320 321 def get_value(self): 322 if len(self.context_values) == 1: 323 return self.get_values()[0] 324 else: 325 return None 326 327 def update(self, context_values, single_assignment): 328 329 """ 330 Update the attribute, adding the 'context_values' provided to the 331 known details associated with the attribute, changing the number of 332 assignments according to the 'single_assignment' status of the 333 operation, where a true value indicates that only one assignment is 334 associated with the update, and a false value indicates that potentially 335 many assignments may be involved. 336 """ 337 338 if self.assignments is None: 339 if single_assignment: 340 self.assignments = 1 341 else: 342 self.assignments = AtLeast(1) 343 else: 344 if single_assignment: 345 self.assignments += 1 346 else: 347 self.assignments += AtLeast(1) 348 349 self.context_values.update(context_values) 350 351 def is_static_attribute(self): 352 353 """ 354 Return whether this attribute is defined on a fixed/static object such 355 as a class or a module. 356 """ 357 358 return isinstance(self.parent, (Class, Module)) 359 360 def defines_ambiguous_class(self): 361 362 "Return whether this attribute defines more than one class." 363 364 if self.assignments > 1: 365 have_class = 0 366 for obj in self.get_values(): 367 if isinstance(obj, Class): 368 if have_class: 369 return 1 370 have_class = 1 371 372 return 0 373 374 def defined_within_hierarchy(self): 375 376 """ 377 Return whether the parent and context of the attribute belong to the 378 same class hierarchy. 379 """ 380 381 # Must be defined within a class. 382 383 if isinstance(self.parent, Class): 384 385 # To be sure, all contexts must be classes and be the same as the 386 # parent, or be a superclass of the parent, or be a subclass of the 387 # parent. 388 389 for context in self.get_contexts(): 390 if not ( 391 isinstance(context, Class) and ( 392 context is self.parent or 393 context.has_subclass(self.parent) or 394 self.parent.has_subclass(context)) 395 ): 396 return 0 397 398 return 1 399 400 # Instance attributes are not defined within a hierarchy. 401 402 else: 403 return 0 404 405 def defined_outside_hierarchy(self): 406 407 """ 408 Return whether the parent and context of the attribute never belong to 409 the same class hierarchy. 410 """ 411 412 # Must be defined within a class. 413 414 if isinstance(self.parent, Class): 415 416 # To be sure, all contexts must be classes and be the same as the 417 # parent, or be a superclass of the parent, or be a subclass of the 418 # parent. 419 420 for context in self.get_contexts(): 421 if not ( 422 isinstance(context, Class) and not ( 423 context is self.parent or 424 context.has_subclass(self.parent) or 425 self.parent.has_subclass(context)) 426 ): 427 return 0 428 429 return 1 430 431 # Instance attributes are not defined within a hierarchy. 432 433 else: 434 return 0 435 436 def __repr__(self): 437 return "Attr(%r, %s, %r) # [%s], %r" % ( 438 self.position, shortrepr(self.parent), self.name, 439 self._context_values_str(), self.assignments 440 ) 441 442 def _context_values_str(self): 443 l = [] 444 for (c, v) in self.context_values: 445 l.append("(c=%s, v=%s)" % (shortrepr(c), shortrepr(v))) 446 return ", ".join(l) 447 448 # Instances are special in that they need to be wrapped together with context in 449 # a running program, but they are not generally constant. 450 451 class Instance: 452 453 "A placeholder indicating the involvement of an instance." 454 455 def __init__(self): 456 self.parent = None 457 458 # Image generation details. 459 460 self.location = None 461 462 def __repr__(self): 463 return "Instance()" 464 465 __shortrepr__ = __repr__ 466 467 class Constant: 468 469 "A superclass for all constant or context-free structures." 470 471 pass 472 473 # Data objects appearing in programs before run-time. 474 475 class Const(Constant, Instance): 476 477 "A constant object with no context." 478 479 def __init__(self, value): 480 Instance.__init__(self) 481 self.value = value 482 483 def get_value(self): 484 return self.value 485 486 def __repr__(self): 487 if self.location is not None: 488 return "Const(%r, location=%r)" % (self.value, self.location) 489 else: 490 return "Const(%r)" % self.value 491 492 __shortrepr__ = __repr__ 493 494 # Support constants as dictionary keys in order to build constant tables. 495 496 def __eq__(self, other): 497 return other is not None and self.value == other.value and self.value.__class__ is other.value.__class__ 498 499 def __hash__(self): 500 return hash(self.value) 501 502 def value_type_name(self): 503 return "__builtins__." + self.value.__class__.__name__ 504 505 class Class(NamespaceDict, Naming, Constant): 506 507 "An inspected class." 508 509 def __init__(self, name, parent, module=None, node=None): 510 511 """ 512 Initialise the class with the given 'name', 'parent' object, optional 513 'module' and optional AST 'node'. 514 """ 515 516 NamespaceDict.__init__(self, module) 517 self.name = name 518 self.parent = parent 519 self.astnode = node 520 521 # Superclasses, descendants and attributes. 522 523 self.bases = [] 524 self.descendants = set() 525 self.instattr = set() # instance attributes 526 self.relocated = set() # attributes which do not have the same 527 # position as those of the same name in 528 # some superclasses 529 530 # Caches. 531 532 self.all_instattr = None # cache for instance_attributes 533 self.all_instattr_names = None # from all_instattr 534 self.all_classattr = None # cache for all_class_attributes 535 self.all_classattr_names = None # from all_classattr 536 self.allattr = None # cache for all_attributes 537 self.allattr_names = None # from allattr 538 539 # Image generation details. 540 541 self.location = None 542 self.code_location = None 543 self.code_body_location = None # corresponds to the instantiator 544 545 self.instantiator = None 546 self.instance_template_location = None # for creating instances at run-time 547 548 # Program-related details. 549 550 self.blocks = None 551 self.temp_usage = 0 552 self.local_usage = 0 553 self.all_local_usage = 0 554 555 # Add this class to its attributes. 556 557 self.set("__class__", self) 558 559 def __repr__(self): 560 if self.location is not None: 561 return "Class(%r, %s, location=%r)" % (self.name, shortrepr(self.parent), self.location) 562 else: 563 return "Class(%r, %s)" % (self.name, shortrepr(self.parent)) 564 565 def __shortrepr__(self): 566 return "Class(%r, %s)" % (self.name, shortrepr(self.parent)) 567 568 def get_body_block(self): 569 return self.get_instantiator().blocks[0] 570 571 # Namespace-related methods. 572 573 def get_updated_context_values(self, context_values): 574 575 """ 576 Adapt the contexts found in the given 'context_values', returning a new 577 set. 578 See: docs/assignment.txt 579 """ 580 581 results = set() 582 583 for context, value in context_values: 584 585 # Change the ownership of functions. 586 587 if context is ReplaceableContext and value is not None and isinstance(value, Function): 588 results.add((self, value)) 589 else: 590 results.add((context, value)) 591 592 return NamespaceDict.get_updated_context_values(self, results) 593 594 def finalise_attributes(self): 595 596 "Make sure that all attributes are fully defined." 597 598 if self.finalised: 599 return 600 601 self.finalise_class_attributes() 602 self.finalise_instance_attributes() 603 self.finalised = 1 604 605 # Convenience methods for accessing functions and methods. 606 607 def get_instantiator(self): 608 609 "Return a function which can be used to instantiate the class." 610 611 if self.instantiator is None: 612 self.instantiator = self.get_init_method().as_instantiator() 613 return self.instantiator 614 615 def get_init_method(self): 616 return self.all_class_attributes()["__init__"].get_value() 617 618 # Class-specific methods. 619 620 def add_base(self, base): 621 self.bases.append(base) 622 base.add_descendant(self) 623 624 def add_instance_attribute(self, name): 625 self.instattr.add(name) 626 627 def add_descendant(self, cls): 628 self.descendants.add(cls) 629 for base in self.bases: 630 base.add_descendant(cls) 631 632 def has_subclass(self, other): 633 return other in self.descendants 634 635 def all_descendants(self): 636 d = {} 637 for cls in self.descendants: 638 d[cls.full_name()] = cls 639 return d 640 641 "Return the attribute names provided by this class only." 642 643 class_attribute_names = NamespaceDict.keys 644 645 def class_attributes(self): 646 647 "Return class attributes provided by this class only." 648 649 return dict(self) 650 651 def all_class_attribute_names(self): 652 653 "Return the attribute names provided by classes in this hierarchy." 654 655 if self.all_classattr_names is None: 656 self.all_class_attributes() 657 return self.all_classattr_names 658 659 def all_class_attributes(self): 660 661 "Return all class attributes, indicating the class which provides them." 662 663 self.finalise_class_attributes() 664 return self.all_classattr 665 666 def finalise_class_attributes(self): 667 668 "Make sure that the class attributes are fully defined." 669 670 if self.all_classattr is None: 671 self.all_classattr = {} 672 clsattr = {} 673 674 # Record provisional position information for attributes of this 675 # class. 676 677 for name in self.class_attributes().keys(): 678 clsattr[name] = set() # position not yet defined 679 680 reversed_bases = self.bases[:] 681 reversed_bases.reverse() 682 683 # For the bases in reverse order, acquire class attribute details. 684 685 for cls in reversed_bases: 686 for name, attr in cls.all_class_attributes().items(): 687 self.all_classattr[name] = attr 688 689 # Record previous attribute information. 690 691 if clsattr.has_key(name): 692 clsattr[name].add(attr.position) 693 694 # Record class attributes provided by this class and its bases, 695 # along with their positions. 696 697 self.all_classattr.update(self.class_attributes()) 698 699 if clsattr: 700 for i, name in enumerate(self._get_position_list(clsattr)): 701 self.all_classattr[name].position = i 702 703 return self.all_classattr 704 705 def instance_attribute_names(self): 706 707 "Return the instance attribute names provided by the class." 708 709 if self.all_instattr_names is None: 710 self.instance_attributes() 711 return self.all_instattr_names 712 713 def instance_attributes(self): 714 715 "Return instance-only attributes for instances of this class." 716 717 self.finalise_instance_attributes() 718 return self.all_instattr 719 720 def finalise_instance_attributes(self): 721 722 "Make sure that the instance attributes are fully defined." 723 724 # Cache the attributes by converting the positioned attributes into a 725 # dictionary. 726 727 if self.all_instattr is None: 728 self.all_instattr = self._get_attributes() 729 self.all_instattr_names = self.all_instattr.keys() 730 731 return self.all_instattr 732 733 def _get_attributes(self): 734 735 """ 736 Return a dictionary mapping names to Attr instances incorporating 737 information about their positions in the final instance structure. 738 """ 739 740 instattr = {} 741 742 # Record provisional position information for attributes of this 743 # instance. 744 745 for name in self.instattr: 746 instattr[name] = set() # position not yet defined 747 748 reversed_bases = self.bases[:] 749 reversed_bases.reverse() 750 751 # For the bases in reverse order, acquire instance attribute 752 # details. 753 754 for cls in reversed_bases: 755 for name, attr in cls.instance_attributes().items(): 756 757 # Record previous attribute information. 758 759 if instattr.has_key(name): 760 instattr[name].add(attr.position) 761 else: 762 instattr[name] = set([attr.position]) 763 764 # Build the dictionary of attributes using the existing positions known 765 # for each name. 766 767 d = {} 768 for i, name in enumerate(self._get_position_list(instattr)): 769 d[name] = Attr(i, Instance(), name) 770 return d 771 772 def _get_position_list(self, positions): 773 774 """ 775 Return a list of attribute names for the given 'positions' mapping from 776 names to positions, indicating the positions of the attributes in the 777 final instance structure. 778 """ 779 780 position_items = positions.items() 781 namearray = [None] * len(position_items) 782 783 # Get the positions in ascending order of list size, with lists 784 # of the same size ordered according to their smallest position 785 # value. 786 787 position_items.sort(self._cmp_positions) 788 789 # Get the names in position order. 790 791 held = [] 792 793 for name, pos in position_items: 794 pos = list(pos) 795 pos.sort() 796 if pos and pos[0] < len(namearray) and namearray[pos[0]] is None: 797 namearray[pos[0]] = name 798 else: 799 if pos: 800 self.relocated.add(name) 801 held.append((name, pos)) 802 803 for i, attr in enumerate(namearray): 804 if attr is None: 805 name, pos = held.pop() 806 namearray[i] = name 807 808 #print self.name, positions 809 #print "->", namearray 810 return namearray 811 812 def _cmp_positions(self, a, b): 813 814 "Compare name plus position list operands 'a' and 'b'." 815 816 name_a, list_a = a 817 name_b, list_b = b 818 if len(list_a) < len(list_b): 819 return -1 820 elif len(list_a) > len(list_b): 821 return 1 822 elif not list_a: 823 return 0 824 else: 825 return cmp(min(list_a), min(list_b)) 826 827 def all_attribute_names(self): 828 829 """ 830 Return the names of all attributes provided by instances of this class. 831 """ 832 833 self.allattr_names = self.allattr_names or self.all_attributes().keys() 834 return self.allattr_names 835 836 def all_attributes(self): 837 838 """ 839 Return all attributes for an instance, indicating either the class which 840 provides them or that the instance itself provides them. 841 """ 842 843 if self.allattr is None: 844 self.allattr = {} 845 self.allattr.update(self.all_class_attributes()) 846 for name, attr in self.instance_attributes().items(): 847 if self.allattr.has_key(name): 848 print "Instance attribute %r in %r overrides class attribute." % (name, self) 849 self.allattr[name] = attr 850 return self.allattr 851 852 class Function(NamespaceDict, Naming, Constant): 853 854 "An inspected function." 855 856 def __init__(self, name, parent, argnames, defaults, has_star, has_dstar, module=None, node=None): 857 858 """ 859 Initialise the function with the given 'name', 'parent', list of 860 'argnames', list of 'defaults', the 'has_star' flag (indicating the 861 presence of a * parameter), the 'has_dstar' flag (indicating the 862 presence of a ** parameter), optional 'module', and optional AST 'node'. 863 """ 864 865 NamespaceDict.__init__(self, module) 866 self.name = name 867 self.parent = parent 868 self.argnames = argnames 869 self.defaults = defaults 870 self.has_star = has_star 871 self.has_dstar = has_dstar 872 self.astnode = node 873 874 # For lambda functions with defaults, add a context argument. 875 876 if name is None and defaults: 877 self.argnames.insert(0, "<context>") 878 879 # Initialise the positional names. 880 881 self.positional_names = self.argnames[:] 882 if has_dstar: 883 self.dstar_name = self.positional_names[-1] 884 del self.positional_names[-1] 885 if has_star: 886 self.star_name = self.positional_names[-1] 887 del self.positional_names[-1] 888 889 # Initialise default storage. 890 # NOTE: This must be initialised separately due to the reliance on node 891 # NOTE: visiting. 892 893 self.default_attrs = [] 894 895 # Caches. 896 897 self.localnames = None # cache for locals 898 899 # Add parameters to the namespace. 900 901 self._add_parameters(argnames) 902 903 # Image generation details. 904 905 self.location = None 906 self.code_location = None 907 self.code_body_location = None 908 909 # Program-related details. 910 911 self.blocks = None 912 self.body_block = None 913 914 self.temp_usage = 0 915 self.local_usage = 0 916 self.all_local_usage = 0 917 918 def _add_parameters(self, argnames): 919 for name in argnames: 920 if isinstance(name, tuple): 921 self._add_parameters(name) 922 else: 923 self.set(name, None) 924 925 def __repr__(self): 926 if self.location is not None: 927 return "Function(%r, %s, %r, location=%r, code_location=%r)" % ( 928 self.name, shortrepr(self.parent), self.argnames, self.location, self.code_location 929 ) 930 else: 931 return "Function(%r, %s, %r)" % ( 932 self.name, shortrepr(self.parent), self.argnames 933 ) 934 935 def __shortrepr__(self): 936 return "Function(%r, %s)" % ( 937 self.name, shortrepr(self.parent) 938 ) 939 940 def get_body_block(self): 941 return self.body_block 942 943 # Namespace-related methods. 944 945 def store_default(self, value): 946 attr = Attr(None, self, None) 947 attr.update([self.get_context_and_value(value)], 1) 948 self.default_attrs.append(attr) 949 950 def make_global(self, name): 951 if name not in self.argnames and not self.has_key(name): 952 self.globals.add(name) 953 return 1 954 else: 955 return 0 956 957 def parameters(self): 958 959 """ 960 Return a dictionary mapping parameter names to their position in the 961 parameter list. 962 """ 963 964 parameters = {} 965 for i, name in enumerate(self.argnames): 966 parameters[name] = i 967 return parameters 968 969 def all_locals(self): 970 971 "Return a dictionary mapping names to local and parameter details." 972 973 return dict(self) 974 975 def locals(self): 976 977 "Return a dictionary mapping names to local details." 978 979 if self.localnames is None: 980 self.localnames = {} 981 self.localnames.update(self.all_locals()) 982 for name in self.argnames: 983 del self.localnames[name] 984 return self.localnames 985 986 def is_method(self): 987 988 """ 989 Return whether this function is a method explicitly defined in a class. 990 """ 991 992 return isinstance(self.parent, Class) 993 994 def is_relocated(self, name): 995 996 """ 997 Determine whether the given attribute 'name' is relocated for instances 998 having this function as a method. 999 """ 1000 1001 for cls in self.parent.descendants: 1002 if name in cls.relocated: 1003 return 1 1004 return 0 1005 1006 def finalise_attributes(self): 1007 1008 """ 1009 Make sure all attributes (locals) are fully defined. Note that locals 1010 are not attributes in the sense of class, module or instance attributes. 1011 Defaults are also finalised by this method. 1012 """ 1013 1014 if self.finalised: 1015 return 1016 1017 # Defaults. 1018 1019 for i, default in enumerate(self.default_attrs): 1020 default.position = i 1021 1022 # Locals. 1023 1024 i = None 1025 for i, name in enumerate(self.argnames): 1026 self[name].position = i 1027 1028 if i is not None: 1029 nparams = i + 1 1030 else: 1031 nparams = 0 1032 1033 i = None 1034 for i, attr in enumerate(self.locals().values()): 1035 attr.position = i + nparams 1036 1037 if i is not None: 1038 nothers = i + 1 1039 else: 1040 nothers = 0 1041 1042 self.local_usage = nothers 1043 self.all_local_usage = nparams + nothers 1044 self.finalised = 1 1045 1046 def as_instantiator(self): 1047 1048 "Make an instantiator function from a method, keeping all arguments." 1049 1050 function = Function(self.parent.name, self.parent.parent, self.argnames, self.defaults, 1051 self.has_star, self.has_dstar, self.module, self.astnode) 1052 function.default_attrs = self.default_attrs 1053 return function 1054 1055 class UnresolvedName(NamespaceDict, Constant): 1056 1057 "A module, class or function which was mentioned but could not be imported." 1058 1059 def __init__(self, name, parent_name, module=None): 1060 NamespaceDict.__init__(self, module) 1061 self.name = name 1062 self.parent_name = parent_name 1063 self.parent = None 1064 1065 self.descendants = set() 1066 1067 def add_descendant(self, cls): 1068 self.descendants.add(cls) 1069 1070 def all_class_attributes(self): 1071 return {} 1072 1073 def instance_attributes(self): 1074 return {} 1075 1076 def __repr__(self): 1077 return "UnresolvedName(%r, %r)" % (self.name, self.parent_name) 1078 1079 __shortrepr__ = __repr__ 1080 1081 def full_name(self): 1082 if self.name is not None: 1083 return self.parent_name + "." + self.name 1084 else: 1085 return self.parent_name 1086 1087 class Module(NamespaceDict, Constant): 1088 1089 "An inspected module's core details." 1090 1091 def __init__(self, name): 1092 NamespaceDict.__init__(self, self) 1093 self.name = name 1094 self.parent = None 1095 1096 # Original location details. 1097 1098 self.astnode = None 1099 1100 # Complete lists of classes and functions. 1101 1102 self.all_objects = set() 1103 1104 # Keyword records. 1105 1106 self.keyword_names = set() 1107 1108 # Image generation details. 1109 1110 self.location = None 1111 self.code_location = None 1112 1113 # Program-related details. 1114 1115 self.blocks = None 1116 self.temp_usage = 0 1117 self.local_usage = 0 1118 self.all_local_usage = 0 1119 1120 def full_name(self): 1121 return self.name 1122 1123 def __repr__(self): 1124 if self.location is not None: 1125 return "Module(%r, location=%r)" % (self.name, self.location) 1126 else: 1127 return "Module(%r)" % self.name 1128 1129 def __shortrepr__(self): 1130 return "Module(%r)" % self.name 1131 1132 # Attribute methods. 1133 1134 "Return the module attribute names provided by the module." 1135 1136 module_attribute_names = NamespaceDict.keys 1137 1138 def module_attributes(self): 1139 1140 "Return a dictionary mapping names to module attributes." 1141 1142 return dict(self) 1143 1144 # vim: tabstop=4 expandtab shiftwidth=4