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