1 #!/usr/bin/env python 2 3 """ 4 Program data structures. There are two separate kinds of structures: those with 5 context, which are the values manipulated by programs, and those without 6 context, which are typically constant things which are stored alongside the 7 program but which are wrapped in context-dependent structures in the running 8 program. 9 10 Copyright (C) 2007, 2008, 2009, 2010 Paul Boddie <paul@boddie.org.uk> 11 12 This program is free software; you can redistribute it and/or modify it under 13 the terms of the GNU General Public License as published by the Free Software 14 Foundation; either version 3 of the License, or (at your option) any later 15 version. 16 17 This program is distributed in the hope that it will be useful, but WITHOUT 18 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 19 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 20 details. 21 22 You should have received a copy of the GNU General Public License along with 23 this program. If not, see <http://www.gnu.org/licenses/>. 24 25 -------- 26 27 The principal value structure class in this module is the Attr class which 28 represents attributes of objects and retains the context of each reference to an 29 attribute. This class models program behaviour at run-time. 30 31 The central data structure classes in this module are the following: 32 33 * Class 34 * Function 35 * Module 36 37 All of the above support the Naming interface either explicitly or through 38 general conformance, meaning that all can be asked to provide their 'full_name' 39 using the method of that name. 40 41 Additionally, all of the above also support a dictionary interface in order to 42 access names within their defined scopes. Specific methods also exist in order 43 to distinguish between certain kinds of attributes: 44 45 * Class: class_attributes, all_class_attributes, instance_attributes, all_attributes 46 * Function: parameters, locals, all_locals 47 * Module: module_attributes 48 49 These specific methods are useful in certain situations. 50 51 The above classes also provide an 'astnode' attribute, indicating the AST node 52 where each such object is defined. 53 """ 54 55 from micropython.program import DataObject, DataValue, ReplaceableContext, PlaceholderContext 56 from micropython.common import AtLeast, InspectError, \ 57 merge_set_dicts, update_set_dict, deepen_set_dict, combine_set_dicts 58 59 def shortrepr(obj): 60 if obj is None: 61 return repr(None) 62 else: 63 return obj.__shortrepr__() 64 65 lambda_index = 0 66 67 def new_lambda(): 68 69 "Return a new sequence number for a lambda definition." 70 71 global lambda_index 72 lambda_index += 1 73 return lambda_index 74 75 # Mix-ins and abstract classes. 76 77 class Naming: 78 79 "A mix-in providing naming conveniences." 80 81 def full_name(self): 82 if self.name is not None: 83 return self.parent.full_name() + "." + self.name 84 else: 85 return self.parent.full_name() 86 87 class NamespaceDict: 88 89 "A mix-in providing dictionary methods." 90 91 def __init__(self, module=None): 92 self.module = module 93 self.namespace = {} 94 self.globals = set() 95 self.lambdas = {} # only really useful for functions 96 self.finalised = 0 97 98 # Attributes accessed on objects, potentially narrowing their types. 99 # Specific namespaces should define known names during initialisation. 100 # For example, functions can define names belonging to parameters. 101 102 # Attribute users, defining names which use attributes. 103 104 self.attribute_users = [{}] # stack of assignments and branches 105 self.attribute_user_shelves = [] 106 107 # Suspended user details plus loop details. 108 109 self.suspended_broken_users = [] # stack of lists of user dicts 110 self.suspended_continuing_users = [] # stack of lists of user dicts 111 112 # Scope usage, indicating the origin of names. 113 114 self.scope_usage = [{}] # stack of scope usage 115 self.scope_shelves = [] 116 117 # Define attribute usage to identify active program sections. 118 # Attribute users are AST nodes defining names. 119 120 self.all_attribute_users = set() 121 122 # Attribute/name definition and access. 123 124 def __delitem__(self, name): 125 del self.namespace[name] 126 127 def has_key(self, name): 128 return self.namespace.has_key(name) 129 130 def keys(self): 131 return self.namespace.keys() 132 133 def values(self): 134 return self.namespace.values() 135 136 def items(self): 137 return self.namespace.items() 138 139 def __getitem__(self, name): 140 return self.namespace[name] 141 142 def get(self, name, default=None): 143 return self.namespace.get(name, default) 144 145 # Administrative methods. 146 147 def items_for_vacuum(self): 148 return self.items() + self.lambdas.items() 149 150 def vacuum_item(self, name): 151 if self.has_key(name): 152 del self[name] 153 154 def add_lambda(self, obj): 155 attr = Attr(None, self, obj.name) 156 attr.update([self.get_context_and_value(obj)], single_assignment=1) 157 self.lambdas[obj.name] = attr 158 159 # Specialised access methods. 160 161 def get_using_node(self, name, node): 162 163 """ 164 Access the given 'name' through this namespace, making use of the module 165 and builtins namespaces if necessary, annotating the given 'node' with 166 the scope involved. 167 """ 168 169 attr, scope, full_name = self._get_with_scope(name) 170 171 if scope is not None: 172 node._scope = scope 173 self.note_scope(name, scope) 174 175 if full_name is not None: 176 self.use_specific_attribute(full_name, name) 177 178 return attr 179 180 def _get_with_scope(self, name, external=0): 181 182 """ 183 Find the source of the given 'name', returning the attribute object, 184 scope (constant, local, global or builtins), and the full name of the 185 source namespace (or None for constants). 186 187 If the optional 'external' flag is set to a true value, only external 188 (non-local) namespaces will be involved in the search. 189 """ 190 191 module = self.module 192 builtins = module and module.builtins or None 193 importer = module and module.importer or None 194 195 # Constants. 196 197 if importer is not None and importer.predefined_constants.has_key(name): 198 return importer.get_predefined_constant(name), "constant", None 199 200 # Locals. 201 202 elif not external and self.has_key(name): 203 return self[name], "local", self.full_name() 204 205 # Globals. 206 207 elif module is not None and module is not self and module.has_key(name): 208 return module[name], "global", module.full_name() 209 210 # Builtins. 211 212 elif builtins is not None and builtins.has_key(name): 213 return builtins[name], "builtins", builtins.full_name() 214 215 # Unknown. 216 217 else: 218 return None, None, None 219 220 # Attribute definition methods. 221 222 def __setitem__(self, name, value): 223 self.set(name, value) 224 225 def set(self, name, value, single_assignment=1): 226 227 """ 228 A more powerful set operation, making 'name' refer to 'value' whilst 229 indicating whether a 'single_assignment' (true by default) occurs in 230 this operation (or whether the operation covers potentially many 231 assignments in the lifetime of a program). 232 """ 233 234 if name in self.globals: 235 self.module.set(name, value, 0) 236 else: 237 self._set(name, value, single_assignment) 238 self.define_scope(name, "local") 239 240 def set_module(self, name, value): 241 242 """ 243 A specialised set operation, making 'name' refer to 'value' in the 244 context of making a module reference available in association with 245 'name' as part of the import of that module or a submodule of that 246 module. 247 """ 248 249 self._set(name, value, 1) 250 251 def _set(self, name, attr_or_value, single_assignment=1): 252 253 """ 254 The underlying set operation associating 'name' with the given 255 'attr_or_value'. 256 See: docs/assignment.txt 257 """ 258 259 # Add and/or obtain the namespace entry. 260 261 if not self.namespace.has_key(name): 262 self.namespace[name] = Attr(None, self, name) 263 264 attr = self.namespace[name] 265 self._set_using_attr(attr, attr_or_value, single_assignment) 266 267 def _set_using_attr(self, attr, attr_or_value, single_assignment=1): 268 269 # Handle attribute assignment as well as assignment of basic objects. 270 # Attempt to fix the context if not explicitly defined. 271 272 if isinstance(attr_or_value, Attr): 273 context_values = self.get_updated_context_values(attr_or_value.context_values) 274 else: 275 context_values = self.get_updated_context_values([self.get_context_and_value(attr_or_value)]) 276 277 attr.update(context_values, single_assignment) 278 279 def get_context_and_value(self, value): 280 281 "Return a context, value tuple for the given 'value'." 282 283 # Functions have a replaceable context. 284 285 if isinstance(value, Function): 286 return (ReplaceableContext, value) 287 288 # Classes use placeholder contexts which cannot be replaced but which 289 # do not communicate useful contextual information. 290 291 elif isinstance(value, Class): 292 return (PlaceholderContext, value) 293 294 # Other values employ themselves as the context. 295 296 else: 297 return (value, value) 298 299 def get_updated_context_values(self, context_values): 300 301 """ 302 Adapt the contexts found in the given 'context_values', returning a new 303 set. 304 See: docs/assignment.txt 305 """ 306 307 results = set() 308 309 for context, value in context_values: 310 311 # Set the context of instances to themselves. 312 313 if isinstance(value, Instance): 314 results.add((value, value)) 315 else: 316 results.add((context, value)) 317 318 return results 319 320 def make_global(self, name): 321 322 "Declare 'name' as a global in the current namespace." 323 324 if not self.namespace.has_key(name): 325 self.globals.add(name) 326 self.define_scope(name, "global") 327 return 1 328 else: 329 return 0 330 331 # Attribute positioning. 332 333 def attributes_as_list(self): 334 335 "Return the attributes in a list." 336 337 self.finalise_attributes() 338 l = [None] * len(self.keys()) 339 for attr in self.values(): 340 l[attr.position] = attr 341 return l 342 343 def finalise_attributes(self): 344 345 "Make sure all attributes are fully defined." 346 347 if self.finalised: 348 return 349 350 # The default action is to assign attribute positions sequentially. 351 352 for i, attr in enumerate(self.values()): 353 attr.position = i 354 355 self.finalised = 1 356 357 def unfinalise_attributes(self): 358 359 "Open attribute definitions to editing and subsequent finalisation." 360 361 self.finalised = 0 362 363 # Attribute usage methods. 364 365 def finalise_attribute_usage(self): 366 367 "Propagate attribute usage for the namespace to the importer." 368 369 module = self.module 370 importer = module and module.importer 371 372 if importer is not None: 373 374 # Visit each user and examine the attribute usage for each name. 375 376 for user in self.all_attribute_users: 377 378 # First, visit the contributors and combine their attribute 379 # usage with the usage recorded directly on the user. 380 381 contributors, combined_usage = self.get_usage_from_contributors(user) 382 383 # Record the defining user on each contributor. 384 385 for contributor in contributors: 386 contributor._attrdefs.append(user) 387 388 # Then, tell the importer about the usage. 389 390 for name in user._attrnames.keys(): 391 392 # Only provide information about names defined by this user. 393 394 usage = combined_usage.get(name, []) 395 396 # Skip reporting where no actual usage occurs. 397 398 for attrnames in usage: 399 if attrnames: 400 break 401 else: 402 continue 403 404 # Eliminate non-usage. 405 406 importer.use_names(user, name, tuple([attrnames for attrnames in usage if attrnames]), self.full_name()) 407 408 def get_usage_from_contributors(self, node): 409 410 """ 411 Obtain usage information from the given 'node', combined with usage 412 details from its contributors, returning a tuple containing a set of all 413 contributors employed along with a dictionary mapping names to lists of 414 usage possibilities (each a collection of attribute names). 415 """ 416 417 if not hasattr(node, "_attrcombined"): 418 419 node._attrcontributors = set() 420 node._attrcombined = {} 421 422 contributor_usage = {} 423 all_contributors = set() 424 425 # Visit each contributor, gathering usage for each name. 426 427 for contributor in node._attrbranches: 428 429 # Get contributed usage for each contributor. 430 # This gathers usage for each name such as {(a, b), (c, d)} and 431 # {(a, b), (e, f)} into a single set {(a, b), (c, d), (e, f)}. 432 433 contributors, contributed_usage = self.get_usage_from_contributors(contributor) 434 update_set_dict(contributor_usage, [contributed_usage]) 435 436 # Record all contributors. 437 438 all_contributors.add(contributor) 439 all_contributors.update(contributors) 440 441 # Then get the resulting usage. 442 # Combine the current usage with the contributed usage. 443 # Thus, usage of {(f, g)} combined with {(a, b), (c, d)} would give 444 # {(f, g, a, b), (f, g, c, d)}. 445 446 usage = combine_set_dicts(deepen_set_dict(node._attrnames), contributor_usage) 447 448 node._attrcontributors = all_contributors 449 node._attrcombined = usage 450 451 return node._attrcontributors, node._attrcombined 452 453 def use_attribute(self, name, attrname): 454 455 "Declare the usage on 'name' of the given 'attrname'." 456 457 return self._use_attribute(name, attrname) 458 459 def use_specific_attribute(self, objname, attrname): 460 461 "Declare the usage on 'objname' of the given 'attrname'." 462 463 self._use_specific_attribute(objname, attrname) 464 465 # These shadow various methods in the InspectedModule class, and provide 466 # implementations generally. 467 468 def _use_specific_attribute(self, objname, attrname): 469 470 """ 471 Note attribute usage specifically on 'objname' - an object which is 472 known at inspection time - or in the current unit if 'objname' is None, 473 nominating a specific attribute 'attrname'. 474 475 This bypasses attribute user mechanisms. 476 """ 477 478 from_name = self.full_name() 479 objname = objname or from_name 480 module = self.module 481 importer = module and module.importer 482 483 if importer is not None: 484 importer.use_specific_name(objname, attrname, from_name) 485 486 def _use_attribute(self, name, attrname): 487 488 """ 489 Indicate the use of the given 'name' in this namespace of an attribute 490 with the given 'attrname'. 491 """ 492 493 users = self.attribute_users[-1] 494 495 # Add the usage to all current users. 496 497 if users.has_key(name): 498 for user in users[name]: 499 user._attrnames[name].add(attrname) 500 return users[name] 501 else: 502 return [] 503 504 def _define_attribute_user(self, node): 505 506 """ 507 Define 'node' as the user of attributes, indicating the point where the 508 user is defined. 509 """ 510 511 name = node.name 512 self._define_attribute_user_for_name(node, name) 513 514 def _define_attribute_user_for_name(self, node, name): 515 516 "Define 'node' as the user of attributes for the given 'name'." 517 518 users = self.attribute_users[-1] 519 520 # This node overrides previous definitions. 521 522 users[name] = set([node]) 523 524 # Record the attribute combinations for the name. 525 526 self._init_attribute_user_for_name(node, name) 527 528 # Remember this user. 529 530 self.all_attribute_users.add(node) 531 532 def _init_attribute_user_for_name(self, node, name): 533 534 "Make sure that 'node' is initialised for 'name'." 535 536 self._init_attribute_user(node) 537 node._attrnames[name] = set() 538 539 def _init_attribute_user(self, node): 540 541 # Attribute usage for names. 542 543 if not hasattr(node, "_attrnames"): 544 node._attrnames = {} 545 546 # Branches contributing usage to this node. 547 548 if not hasattr(node, "_attrbranches"): 549 node._attrbranches = [] 550 551 # Definitions receiving usage from this node. 552 553 if not hasattr(node, "_attrdefs"): 554 node._attrdefs = [] 555 556 # Eventual type information. 557 558 if not hasattr(node, "_attrtypes"): 559 node._attrtypes = {} 560 561 # Branch management methods. 562 563 def _new_branchpoint(self, loop_node=None): 564 565 """ 566 Establish a new branchpoint where several control-flow branches diverge 567 and subsequently converge. 568 """ 569 570 self.attribute_user_shelves.append([]) 571 self.scope_shelves.append([]) 572 573 if loop_node is not None: 574 self.suspended_broken_users.append([]) 575 self.suspended_continuing_users.append((loop_node, [])) 576 577 def _new_branch(self, node): 578 579 """ 580 Establish a new control-flow branch, transferring attribute usage to 581 the new branch so that it may be augmented for each name locally. 582 583 Add the given 'node' as an active user to be informed of attribute 584 usage. 585 """ 586 587 attribute_users = self.attribute_users[-1] 588 589 # Define this node as the active attribute user for all currently 590 # defined names. 591 592 new_users = {} 593 594 for name in attribute_users.keys(): 595 new_users[name] = [node] 596 self._init_attribute_user_for_name(node, name) 597 598 self._init_attribute_user(node) 599 self.attribute_users.append(new_users) 600 601 # Add this user as a contributor to the previously active users. 602 603 self._connect_users_to_branch(attribute_users, node) 604 605 # Retain a record of scope usage. 606 607 scope_usage = {} 608 scope_usage.update(self.scope_usage[-1]) 609 self.scope_usage.append(scope_usage) 610 611 def _connect_users_to_branch(self, attribute_users, node): 612 613 """ 614 Given the 'attribute_users' mapping, connect the users referenced in the 615 mapping to the given branch 'node'. 616 """ 617 618 all_users = set() 619 620 for users in attribute_users.values(): 621 all_users.update(users) 622 623 for user in all_users: 624 self._init_attribute_user(user) 625 user._attrbranches.append(node) 626 627 def _abandon_branch(self): 628 629 """ 630 Abandon scope usage, permitting locally different scopes for names, 631 provided these cannot "escape" from the branch. 632 """ 633 634 self.attribute_users[-1] = AbandonedBranchUsers() 635 self.scope_usage[-1] = AbandonedBranchScope() 636 637 def _suspend_broken_branch(self): 638 639 """ 640 Suspend a branch for resumption after the current loop. 641 """ 642 643 attribute_users = self.attribute_users[-1] 644 645 if not isinstance(attribute_users, AbandonedBranchUsers): 646 users = self.suspended_broken_users[-1] 647 users.append(attribute_users) 648 self._abandon_branch() 649 650 def _suspend_continuing_branch(self): 651 652 """ 653 Suspend a branch for resumption after the current iteration. 654 """ 655 656 attribute_users = self.attribute_users[-1] 657 658 if not isinstance(attribute_users, AbandonedBranchUsers): 659 loop_node, users = self.suspended_continuing_users[-1] 660 users.append(attribute_users) 661 self._abandon_branch() 662 663 def _shelve_branch(self): 664 665 """ 666 Shelve the current control-flow branch, recording the attribute usage 667 for subsequent merging. If this branch should be abandoned, the usage 668 observations are still recorded but will not contribute to subsequent 669 observations after a merge. 670 """ 671 672 users = self.attribute_users.pop() 673 self.attribute_user_shelves[-1].append(users) 674 675 scope_usage = self.scope_usage.pop() 676 self.scope_shelves[-1].append(scope_usage) 677 678 def _merge_branches(self): 679 680 """ 681 Merge control-flow branches. This should find the users active within 682 each branch, which have been "shelved", and update the active users 683 dictionary with these contributions. 684 """ 685 686 # Combine the attribute users. This ensures that a list of users 687 # affected by attribute usage is maintained for the current branch. 688 689 all_shelved_users = self.attribute_user_shelves.pop() 690 new_users = merge_set_dicts(all_shelved_users) 691 self.attribute_users[-1] = new_users 692 693 # Combine the scope usage. 694 695 scope_usage = self.scope_usage[-1] 696 new_scope_usage = {} 697 698 all_scope_usage = self.scope_shelves.pop() 699 all_scope_names = set() 700 701 # Find all the names for whom scope information has been defined. 702 703 for shelved_usage in all_scope_usage: 704 all_scope_names.update(shelved_usage.keys()) 705 706 for shelved_usage in all_scope_usage: 707 for name in all_scope_names: 708 709 # Find the recorded scope for the name. 710 711 if shelved_usage.has_key(name): 712 scope = shelved_usage[name] 713 elif scope_usage.has_key(name): 714 scope = scope_usage[name] 715 716 # For abandoned branches, no scope is asserted for a name. 717 718 elif isinstance(shelved_usage, AbandonedBranchScope): 719 scope = None 720 721 # If no scope is recorded, find a suitable external source. 722 723 else: 724 attr, scope, full_name = self._get_with_scope(name, external=1) 725 726 # Attempt to record the scope, testing for conflicts. 727 728 if scope: 729 if not new_scope_usage.has_key(name): 730 new_scope_usage[name] = scope 731 elif new_scope_usage[name] != scope: 732 new_scope_usage[name] = ScopeConflict(scope, new_scope_usage[name]) 733 734 self.scope_usage[-1] = new_scope_usage 735 736 def _resume_broken_branches(self): 737 738 """ 739 Incorporate users from suspended broken branches into the current set of 740 active users. 741 """ 742 743 suspended_users = self.suspended_broken_users.pop() 744 current_users = self.attribute_users[-1] 745 new_users = merge_set_dicts(suspended_users + [current_users]) 746 self.attribute_users[-1] = new_users 747 748 def _resume_continuing_branches(self): 749 750 """ 751 Incorporate users from suspended continuing branches into the current 752 set of active users, merging usage from the latter with the former. 753 """ 754 755 loop_node, suspended_users = self.suspended_continuing_users.pop() 756 current_users = self.attribute_users[-1] 757 758 # Connect the suspended users to the loop node. 759 760 for users in suspended_users: 761 self._connect_users_to_branch(users, loop_node) 762 763 # Merge suspended branches with the current branch. 764 765 new_users = merge_set_dicts(suspended_users + [current_users]) 766 self.attribute_users[-1] = new_users 767 768 # Scope usage methods. 769 770 def define_scope(self, name, scope): 771 772 """ 773 Define 'name' as being from the given 'scope' in the current namespace. 774 """ 775 776 self.scope_usage[-1][name] = scope 777 778 def note_scope(self, name, scope): 779 780 """ 781 Note usage of 'name' from the given 'scope' in the current namespace. 782 If a conflict has been recorded previously, raise an exception. 783 """ 784 785 scope_usage = self.scope_usage[-1] 786 787 if scope_usage.has_key(name): 788 found_scope = scope_usage[name] 789 if isinstance(found_scope, ScopeConflict): 790 raise InspectError("Scope conflict for %r: defined as both %s and %s." % ( 791 name, found_scope.old_scope, found_scope.new_scope)) 792 793 scope_usage[name] = scope 794 795 def used_in_scope(self, name, scope): 796 797 """ 798 Return whether 'name' is used from the given 'scope' in the current 799 namespace. 800 """ 801 802 scope_usage = self.scope_usage[-1] 803 return scope_usage.get(name) == scope 804 805 # Special helper classes for usage and scope resolution. 806 807 class EmptyDict: 808 809 "A class providing dictionaries which retain no information." 810 811 def has_key(self, name): 812 return 0 813 814 def __setitem__(self, name, value): 815 pass 816 817 def __getitem__(self, name): 818 raise KeyError, name 819 820 def get(self, name, default=None): 821 return default 822 823 def keys(self): 824 return [] 825 826 values = items = keys 827 828 class AbandonedBranchUsers(EmptyDict): 829 830 """ 831 A class providing a value or state for an abandoned branch distinct from an 832 empty usage dictionary. 833 """ 834 835 pass 836 837 class AbandonedBranchScope(EmptyDict): 838 839 """ 840 A class providing a value or state for an abandoned branch distinct from an 841 empty scope dictionary. 842 """ 843 844 pass 845 846 class ScopeConflict: 847 848 """ 849 A scope conflict caused when different code branches contribute different 850 sources of names. 851 """ 852 853 def __init__(self, old_scope, new_scope): 854 self.old_scope = old_scope 855 self.new_scope = new_scope 856 857 class NullBranch: 858 859 "A class representing an attribute user for a non-existent branch." 860 861 pass 862 863 # Program data structures. 864 865 class Attr: 866 867 "An attribute entry having a context." 868 869 def __init__(self, position, parent, name): 870 871 """ 872 Initialise the attribute with the given 'position' within the collection 873 of attributes of its 'parent', indicating its 'name'. 874 """ 875 876 self.position = position 877 self.parent = parent 878 self.name = name 879 880 # Possible values. 881 882 self.context_values = set() 883 884 # Number of assignments per name. 885 886 self.assignments = None 887 888 # Value-related methods. 889 890 def get_contexts(self): 891 return [c for (c, v) in self.context_values] 892 893 def get_values(self): 894 return [v for (c, v) in self.context_values] 895 896 def get_context(self): 897 if len(self.context_values) == 1: 898 return self.get_contexts()[0] 899 else: 900 return None 901 902 def get_value(self): 903 if len(self.context_values) == 1: 904 return self.get_values()[0] 905 else: 906 return None 907 908 def update(self, context_values, single_assignment): 909 910 """ 911 Update the attribute, adding the 'context_values' provided to the 912 known details associated with the attribute, changing the number of 913 assignments according to the 'single_assignment' status of the 914 operation, where a true value indicates that only one assignment is 915 associated with the update, and a false value indicates that potentially 916 many assignments may be involved. 917 """ 918 919 if self.assignments is None: 920 if single_assignment: 921 self.assignments = 1 922 else: 923 self.assignments = AtLeast(1) 924 else: 925 if single_assignment: 926 self.assignments += 1 927 else: 928 self.assignments += AtLeast(1) 929 930 self.context_values.update(context_values) 931 932 def is_constant(self): 933 934 """ 935 Return whether this attribute references something that can be regarded 936 as being constant within a particular scope. 937 """ 938 939 return self.assignments == 1 940 941 def is_strict_constant(self): 942 943 """ 944 Return whether this attribute references something that can be regarded 945 as being constant. 946 """ 947 948 value = self.get_value() 949 return not (value is None or isinstance(value, Instance)) 950 951 def is_static_attribute(self): 952 953 """ 954 Return whether this attribute is defined on a fixed/static object such 955 as a class or a module. 956 """ 957 958 return isinstance(self.parent, (Class, Module)) 959 960 def defines_ambiguous_class(self): 961 962 "Return whether this attribute defines more than one class." 963 964 if self.assignments > 1: 965 have_class = 0 966 for obj in self.get_values(): 967 if isinstance(obj, Class): 968 if have_class: 969 return 1 970 have_class = 1 971 972 return 0 973 974 def defined_within_hierarchy(self): 975 976 """ 977 Return whether the parent and context of the attribute belong to the 978 same class hierarchy. 979 """ 980 981 # Must be defined within a class. 982 983 if isinstance(self.parent, Class): 984 985 # To be sure, all contexts must be classes and be the same as the 986 # parent, or be a superclass of the parent, or be a subclass of the 987 # parent. 988 989 for context in self.get_contexts(): 990 if not ( 991 isinstance(context, Class) and ( 992 context is self.parent or 993 context.has_subclass(self.parent) or 994 self.parent.has_subclass(context)) 995 ): 996 return 0 997 998 return 1 999 1000 # Instance attributes are not defined within a hierarchy. 1001 1002 else: 1003 return 0 1004 1005 def defined_outside_hierarchy(self): 1006 1007 """ 1008 Return whether the parent and context of the attribute never belong to 1009 the same class hierarchy. 1010 """ 1011 1012 # Must be defined within a class. 1013 1014 if isinstance(self.parent, Class): 1015 1016 # To be sure, all contexts must be classes and be the same as the 1017 # parent, or be a superclass of the parent, or be a subclass of the 1018 # parent. 1019 1020 for context in self.get_contexts(): 1021 if not ( 1022 isinstance(context, Class) and not ( 1023 context is self.parent or 1024 context.has_subclass(self.parent) or 1025 self.parent.has_subclass(context)) 1026 ): 1027 return 0 1028 1029 return 1 1030 1031 # Instance attributes are not defined within a hierarchy. 1032 1033 else: 1034 return 0 1035 1036 def __repr__(self): 1037 return "Attr(%r, %s, %r) # {[%s] (%r)}" % ( 1038 self.position, shortrepr(self.parent), self.name, 1039 self._context_values_str(), self.assignments 1040 ) 1041 1042 def __shortrepr__(self): 1043 return "Attr(%r, %s, %r)" % ( 1044 self.position, shortrepr(self.parent), self.name 1045 ) 1046 1047 def _context_values_str(self): 1048 l = [] 1049 for (c, v) in self.context_values: 1050 l.append("(c=%s, v=%s)" % (shortrepr(c), shortrepr(v))) 1051 return ", ".join(l) 1052 1053 # Instances are special in that they need to be wrapped together with context in 1054 # a running program, but they are not generally constant. 1055 1056 class Instance: 1057 1058 "A placeholder indicating the involvement of an instance." 1059 1060 def __init__(self): 1061 self.parent = None 1062 1063 # Image generation details. 1064 1065 self.location = None 1066 1067 def __repr__(self): 1068 return "Instance()" 1069 1070 __shortrepr__ = __repr__ 1071 1072 class Constant: 1073 1074 "A superclass for all constant or context-free structures." 1075 1076 pass 1077 1078 # Data objects appearing in programs before run-time. 1079 1080 class Const(Constant, Instance): 1081 1082 "A constant object with no context." 1083 1084 def __init__(self, value): 1085 Instance.__init__(self) 1086 self.value = value 1087 1088 def get_value(self): 1089 return self.value 1090 1091 def __repr__(self): 1092 if self.location is not None: 1093 return "Const(%r, location=%r)" % (self.value, self.location) 1094 else: 1095 return "Const(%r)" % self.value 1096 1097 __shortrepr__ = __repr__ 1098 1099 # Support constants as dictionary keys in order to build constant tables. 1100 1101 def __eq__(self, other): 1102 return other is not None and self.value == other.value and self.value.__class__ is other.value.__class__ 1103 1104 def __hash__(self): 1105 return hash(self.value) 1106 1107 def value_type_name(self): 1108 return "__builtins__." + self.value.__class__.__name__ 1109 1110 class Class(NamespaceDict, Naming, Constant): 1111 1112 "An inspected class." 1113 1114 def __init__(self, name, parent, module=None, node=None): 1115 1116 """ 1117 Initialise the class with the given 'name', 'parent' object, optional 1118 'module' and optional AST 'node'. 1119 """ 1120 1121 NamespaceDict.__init__(self, module) 1122 self.name = name 1123 self.parent = parent 1124 self.astnode = node 1125 1126 # Superclasses, descendants and attributes. 1127 1128 self.bases = [] 1129 self.descendants = set() 1130 self.instattr = set() # instance attributes 1131 self.relocated = set() # attributes which do not have the same 1132 # position as those of the same name in 1133 # some superclasses 1134 1135 # Caches. 1136 1137 self.reset_caches() 1138 1139 # Image generation details. 1140 1141 self.location = None 1142 self.code_location = None 1143 self.code_body_location = None # corresponds to the instantiator 1144 1145 self.instantiator = None 1146 self.instance_template_location = None # for creating instances at run-time 1147 1148 # Program-related details. 1149 1150 self.blocks = None 1151 self.temp_usage = 0 1152 self.local_usage = 0 1153 self.all_local_usage = 0 1154 1155 # Add this class to its attributes. 1156 1157 self.set("__class__", self) 1158 1159 def reset_caches(self): 1160 1161 "Reset the caches." 1162 1163 self.all_instattr = None # cache for instance_attributes 1164 self.all_instattr_names = None # from all_instattr 1165 self.all_classattr = None # cache for all_class_attributes 1166 self.all_classattr_names = None # from all_classattr 1167 self.allattr = None # cache for all_attributes 1168 self.allattr_names = None # from allattr 1169 1170 def __repr__(self): 1171 if self.location is not None: 1172 return "Class(%r, %s, location=%r)" % (self.name, shortrepr(self.parent), self.location) 1173 else: 1174 return "Class(%r, %s)" % (self.name, shortrepr(self.parent)) 1175 1176 def __shortrepr__(self): 1177 return "Class(%r, %s)" % (self.name, shortrepr(self.parent)) 1178 1179 def get_body_block(self): 1180 return self.get_instantiator().blocks[0] 1181 1182 # Namespace-related methods. 1183 1184 def get_updated_context_values(self, context_values): 1185 1186 """ 1187 Adapt the contexts found in the given 'context_values', returning a new 1188 set. 1189 See: docs/assignment.txt 1190 """ 1191 1192 results = set() 1193 1194 for context, value in context_values: 1195 1196 # Change the ownership of functions. 1197 1198 if context is ReplaceableContext and value is not None and isinstance(value, Function): 1199 results.add((self, value)) 1200 else: 1201 results.add((context, value)) 1202 1203 return NamespaceDict.get_updated_context_values(self, results) 1204 1205 # Administrative methods. 1206 1207 def finalise_attributes(self): 1208 1209 "Make sure that all attributes are fully defined." 1210 1211 if self.finalised: 1212 return 1213 1214 self.finalise_class_attributes() 1215 self.finalise_instance_attributes() 1216 self.finalised = 1 1217 1218 def unfinalise_attributes(self): 1219 1220 "Open attribute definitions to editing and subsequent finalisation." 1221 1222 self.reset_caches() 1223 self.finalised = 0 1224 1225 # Convenience methods for accessing functions and methods. 1226 1227 def get_instantiator(self): 1228 1229 "Return a function which can be used to instantiate the class." 1230 1231 if self.instantiator is None: 1232 self.instantiator = self.get_init_method().as_instantiator() 1233 return self.instantiator 1234 1235 def get_init_method(self): 1236 return self.all_class_attributes()["__init__"].get_value() 1237 1238 # Class-specific methods. 1239 1240 def add_base(self, base): 1241 self.bases.append(base) 1242 base.add_descendant(self) 1243 1244 def add_instance_attribute(self, name): 1245 self.instattr.add(name) 1246 1247 def add_descendant(self, cls): 1248 self.descendants.add(cls) 1249 for base in self.bases: 1250 base.add_descendant(cls) 1251 1252 def has_subclass(self, other): 1253 return other in self.descendants 1254 1255 def all_descendants(self): 1256 d = {} 1257 for cls in self.descendants: 1258 d[cls.full_name()] = cls 1259 return d 1260 1261 "Return the attribute names provided by this class only." 1262 1263 class_attribute_names = NamespaceDict.keys 1264 1265 def class_attributes(self): 1266 1267 "Return class attributes provided by this class only." 1268 1269 return dict(self) 1270 1271 def all_class_attribute_names(self): 1272 1273 "Return the attribute names provided by classes in this hierarchy." 1274 1275 if self.all_classattr_names is None: 1276 self.all_class_attributes() 1277 self.all_classattr_names = self.all_classattr.keys() 1278 return self.all_classattr_names 1279 1280 def all_class_attributes(self): 1281 1282 "Return all class attributes, indicating the class which provides them." 1283 1284 self.finalise_class_attributes() 1285 return self.all_classattr 1286 1287 def finalise_class_attributes(self): 1288 1289 "Make sure that the class attributes are fully defined." 1290 1291 if self.all_classattr is None: 1292 self.all_classattr = {} 1293 clsattr = {} 1294 1295 # Record provisional position information for attributes of this 1296 # class. 1297 1298 for name in self.class_attributes().keys(): 1299 clsattr[name] = set() # position not yet defined 1300 1301 reversed_bases = self.bases[:] 1302 reversed_bases.reverse() 1303 1304 # For the bases in reverse order, acquire class attribute details. 1305 1306 for cls in reversed_bases: 1307 for name, attr in cls.all_class_attributes().items(): 1308 self.all_classattr[name] = attr 1309 1310 # Record previous attribute information. 1311 1312 if clsattr.has_key(name): 1313 clsattr[name].add(attr.position) 1314 1315 # Record class attributes provided by this class and its bases, 1316 # along with their positions. 1317 1318 self.all_classattr.update(self.class_attributes()) 1319 1320 if clsattr: 1321 for i, name in enumerate(self._get_position_list(clsattr)): 1322 self.all_classattr[name].position = i 1323 1324 return self.all_classattr 1325 1326 def instance_attribute_names(self): 1327 1328 "Return the instance attribute names provided by the class." 1329 1330 if self.all_instattr_names is None: 1331 self.instance_attributes() 1332 return self.all_instattr_names 1333 1334 def instance_attributes(self): 1335 1336 "Return instance-only attributes for instances of this class." 1337 1338 self.finalise_instance_attributes() 1339 return self.all_instattr 1340 1341 def finalise_instance_attributes(self): 1342 1343 "Make sure that the instance attributes are fully defined." 1344 1345 # Cache the attributes by converting the positioned attributes into a 1346 # dictionary. 1347 1348 if self.all_instattr is None: 1349 self.all_instattr = self._get_attributes() 1350 self.all_instattr_names = self.all_instattr.keys() 1351 1352 return self.all_instattr 1353 1354 def _get_attributes(self): 1355 1356 """ 1357 Return a dictionary mapping names to Attr instances incorporating 1358 information about their positions in the final instance structure. 1359 """ 1360 1361 instattr = {} 1362 1363 # Record provisional position information for attributes of this 1364 # instance. 1365 1366 for name in self.instattr: 1367 instattr[name] = set() # position not yet defined 1368 1369 reversed_bases = self.bases[:] 1370 reversed_bases.reverse() 1371 1372 # For the bases in reverse order, acquire instance attribute 1373 # details. 1374 1375 for cls in reversed_bases: 1376 for name, attr in cls.instance_attributes().items(): 1377 1378 # Record previous attribute information. 1379 1380 if instattr.has_key(name): 1381 instattr[name].add(attr.position) 1382 else: 1383 instattr[name] = set([attr.position]) 1384 1385 # Build the dictionary of attributes using the existing positions known 1386 # for each name. 1387 1388 d = {} 1389 for i, name in enumerate(self._get_position_list(instattr)): 1390 d[name] = Attr(i, Instance(), name) 1391 return d 1392 1393 def _get_position_list(self, positions): 1394 1395 """ 1396 Return a list of attribute names for the given 'positions' mapping from 1397 names to positions, indicating the positions of the attributes in the 1398 final instance structure. 1399 """ 1400 1401 position_items = positions.items() 1402 namearray = [None] * len(position_items) 1403 1404 # Get the positions in ascending order of list size, with lists 1405 # of the same size ordered according to their smallest position 1406 # value. 1407 1408 position_items.sort(self._cmp_positions) 1409 1410 # Get the names in position order. 1411 1412 held = [] 1413 1414 for name, pos in position_items: 1415 pos = list(pos) 1416 pos.sort() 1417 if pos and pos[0] < len(namearray) and namearray[pos[0]] is None: 1418 namearray[pos[0]] = name 1419 else: 1420 if pos: 1421 self.relocated.add(name) 1422 held.append((name, pos)) 1423 1424 for i, attr in enumerate(namearray): 1425 if attr is None: 1426 name, pos = held.pop() 1427 namearray[i] = name 1428 1429 return namearray 1430 1431 def _cmp_positions(self, a, b): 1432 1433 "Compare name plus position list operands 'a' and 'b'." 1434 1435 name_a, list_a = a 1436 name_b, list_b = b 1437 if len(list_a) < len(list_b): 1438 return -1 1439 elif len(list_a) > len(list_b): 1440 return 1 1441 elif not list_a: 1442 return 0 1443 else: 1444 return cmp(min(list_a), min(list_b)) 1445 1446 def all_attribute_names(self): 1447 1448 """ 1449 Return the names of all attributes provided by instances of this class. 1450 """ 1451 1452 self.allattr_names = self.allattr_names or self.all_attributes().keys() 1453 return self.allattr_names 1454 1455 def all_attributes(self): 1456 1457 """ 1458 Return all attributes for an instance, indicating either the class which 1459 provides them or that the instance itself provides them. 1460 """ 1461 1462 if self.allattr is None: 1463 self.allattr = {} 1464 self.allattr.update(self.all_class_attributes()) 1465 for name, attr in self.instance_attributes().items(): 1466 if self.allattr.has_key(name): 1467 print "Warning: instance attribute %r in %r overrides class attribute." % (name, self) 1468 self.allattr[name] = attr 1469 return self.allattr 1470 1471 class Function(NamespaceDict, Naming, Constant): 1472 1473 "An inspected function." 1474 1475 def __init__(self, name, parent, argnames, defaults, has_star, has_dstar, 1476 dynamic_def=0, module=None, node=None): 1477 1478 """ 1479 Initialise the function with the given 'name', 'parent', list of 1480 'argnames', list of 'defaults', the 'has_star' flag (indicating the 1481 presence of a * parameter), the 'has_dstar' flag (indicating the 1482 presence of a ** parameter), optional 'dynamic_def' (indicating that the 1483 function must be handled dynamically), optional 'module', and optional 1484 AST 'node'. 1485 """ 1486 1487 NamespaceDict.__init__(self, module) 1488 1489 if name is None: 1490 self.name = "lambda#%d" % new_lambda() 1491 self._is_lambda = 1 1492 else: 1493 self.name = name 1494 self._is_lambda = 0 1495 1496 self.parent = parent 1497 self.argnames = argnames 1498 self.defaults = defaults 1499 self.has_star = has_star 1500 self.has_dstar = has_dstar 1501 self.dynamic_def = dynamic_def 1502 self.astnode = node 1503 1504 # Initialise the positional names. 1505 1506 self.positional_names = self.argnames[:] 1507 if has_dstar: 1508 self.dstar_name = self.positional_names[-1] 1509 del self.positional_names[-1] 1510 if has_star: 1511 self.star_name = self.positional_names[-1] 1512 del self.positional_names[-1] 1513 1514 # Initialise default storage. 1515 # NOTE: This must be initialised separately due to the reliance on node 1516 # NOTE: visiting. 1517 1518 self.default_attrs = [] 1519 1520 # Initialise attribute usage. 1521 1522 if node is not None: 1523 for arg in argnames: 1524 1525 # Define attribute users. 1526 1527 self._define_attribute_user_for_name(node, arg) 1528 1529 # Caches. 1530 1531 self.localnames = None # cache for locals 1532 1533 # Add parameters to the namespace. 1534 1535 self._add_parameters(argnames) 1536 1537 # Image generation details. 1538 1539 self.dynamic = None 1540 self.location = None 1541 self.code_location = None 1542 self.code_body_location = None 1543 1544 # Program-related details. 1545 1546 self.blocks = None 1547 self.body_block = None 1548 1549 self.temp_usage = 0 1550 self.local_usage = 0 1551 self.all_local_usage = 0 1552 1553 def _add_parameters(self, argnames): 1554 1555 "Add 'argnames' to the namespace." 1556 1557 for name in argnames: 1558 self.set(name, Instance()) 1559 1560 for name, top_level in self._flattened_parameters(argnames): 1561 if not top_level: 1562 self.set(name, Instance()) 1563 1564 def _flattened_parameters(self, argnames, top_level=1): 1565 l = [] 1566 for name in argnames: 1567 if isinstance(name, tuple): 1568 l += self._flattened_parameters(name, 0) 1569 else: 1570 l.append((name, top_level)) 1571 return l 1572 1573 def __repr__(self): 1574 if self.location is not None: 1575 return "Function(%r, %s, %r, location=%r, code_location=%r)" % ( 1576 self.name, shortrepr(self.parent), self.argnames, self.location, self.code_location 1577 ) 1578 else: 1579 return "Function(%r, %s, %r)" % ( 1580 self.name, shortrepr(self.parent), self.argnames 1581 ) 1582 1583 def __shortrepr__(self): 1584 return "Function(%r, %s)" % ( 1585 self.name, shortrepr(self.parent) 1586 ) 1587 1588 def get_body_block(self): 1589 return self.body_block 1590 1591 def is_lambda(self): 1592 return self._is_lambda 1593 1594 # Defaults-related methods. 1595 1596 def store_default(self, attr_or_value): 1597 1598 """ 1599 Reserve space for defaults, set outside the function, potentially on a 1600 dynamic basis, using the 'attr_or_value'. 1601 """ 1602 1603 attr = Attr(None, self, None) 1604 self._set_using_attr(attr, attr_or_value) 1605 self.default_attrs.append(attr) 1606 1607 def make_dynamic(self): 1608 1609 "Return whether this function must be handled using a dynamic object." 1610 1611 if self.dynamic is None: 1612 for attr in self.default_attrs: 1613 if not attr.is_strict_constant() and self.dynamic_def: 1614 self.dynamic = 1 1615 self._make_dynamic() 1616 break 1617 else: 1618 self.dynamic = 0 1619 1620 return self.dynamic 1621 1622 is_dynamic = make_dynamic 1623 1624 def _make_dynamic(self): 1625 1626 "Where functions have dynamic defaults, add a context argument." 1627 1628 name = "<context>" 1629 self.argnames.insert(0, name) 1630 self.positional_names.insert(0, name) 1631 self.set(name, Instance()) 1632 1633 # Namespace-related methods. 1634 1635 def make_global(self, name): 1636 1637 "Declare 'name' as a global in the current namespace." 1638 1639 if name not in self.argnames and not self.has_key(name): 1640 self.globals.add(name) 1641 return 1 1642 else: 1643 return 0 1644 1645 def parameters(self): 1646 1647 """ 1648 Return a dictionary mapping parameter names to their position in the 1649 parameter list. 1650 """ 1651 1652 parameters = {} 1653 for i, name in enumerate(self.argnames): 1654 parameters[name] = i 1655 return parameters 1656 1657 def tuple_parameters(self, argnames=None): 1658 1659 """ 1660 Return a list of (position, parameter) entries corresponding to tuple 1661 parameters, where each parameter may either be a string or another such 1662 list of entries. 1663 """ 1664 1665 names = argnames or self.argnames 1666 1667 l = [] 1668 for i, name in enumerate(names): 1669 if isinstance(name, tuple): 1670 l.append((i, self.tuple_parameters(name))) 1671 elif argnames: 1672 l.append((i, name)) 1673 return l 1674 1675 def all_locals(self): 1676 1677 "Return a dictionary mapping names to local and parameter details." 1678 1679 return dict(self) 1680 1681 def locals(self): 1682 1683 "Return a dictionary mapping names to local details." 1684 1685 if self.localnames is None: 1686 self.localnames = {} 1687 self.localnames.update(self.all_locals()) 1688 for name in self.argnames: 1689 del self.localnames[name] 1690 return self.localnames 1691 1692 def is_method(self): 1693 1694 """ 1695 Return whether this function is a method explicitly defined in a class. 1696 """ 1697 1698 return isinstance(self.parent, Class) 1699 1700 def is_relocated(self, name): 1701 1702 """ 1703 Determine whether the given attribute 'name' is relocated for instances 1704 having this function as a method. 1705 """ 1706 1707 for cls in self.parent.descendants: 1708 if name in cls.relocated: 1709 return 1 1710 return 0 1711 1712 # Administrative methods. 1713 1714 def items_for_vacuum(self): 1715 return self.lambdas.items() 1716 1717 def vacuum_item(self, name): 1718 del self.lambdas[name] 1719 1720 def finalise_attributes(self): 1721 1722 """ 1723 Make sure all attributes (locals) are fully defined. Note that locals 1724 are not attributes in the sense of class, module or instance attributes. 1725 Defaults are also finalised by this method. 1726 """ 1727 1728 if self.finalised: 1729 return 1730 1731 # Defaults. 1732 1733 for i, default in enumerate(self.default_attrs): 1734 default.position = i 1735 1736 # Parameters. 1737 1738 i = self._finalise_parameters() 1739 1740 if i is not None: 1741 nparams = i + 1 1742 else: 1743 nparams = 0 1744 1745 # Locals (and tuple parameter names). 1746 1747 i = None 1748 for i, attr in enumerate(self.locals().values()): 1749 attr.position = i + nparams 1750 1751 if i is not None: 1752 nothers = i + 1 1753 else: 1754 nothers = 0 1755 1756 self.local_usage = nothers 1757 self.all_local_usage = nparams + nothers 1758 self.finalised = 1 1759 1760 def _finalise_parameters(self): 1761 if not self.argnames: 1762 return None 1763 1764 for i, name in enumerate(self.argnames): 1765 self[name].position = i 1766 1767 return i 1768 1769 def as_instantiator(self): 1770 1771 "Make an instantiator function from a method, keeping all arguments." 1772 1773 function = Function(self.parent.name, self.parent.parent, self.argnames, self.defaults, 1774 self.has_star, self.has_dstar, self.dynamic_def, self.module) 1775 function.default_attrs = self.default_attrs 1776 return function 1777 1778 class UnresolvedName(NamespaceDict, Constant): 1779 1780 "A module, class or function which was mentioned but could not be imported." 1781 1782 def __init__(self, name, parent_name, module=None): 1783 NamespaceDict.__init__(self, module) 1784 self.name = name 1785 self.parent_name = parent_name 1786 self.parent = None 1787 1788 self.descendants = set() 1789 1790 def add_descendant(self, cls): 1791 self.descendants.add(cls) 1792 1793 def all_attributes(self): 1794 return {} 1795 1796 def all_attribute_names(self): 1797 return [] 1798 1799 all_class_attributes = class_attributes = instance_attributes = all_attributes 1800 all_class_attribute_names = class_attribute_names = instance_attribute_names = all_attribute_names 1801 1802 def __repr__(self): 1803 return "UnresolvedName(%r, %r)" % (self.name, self.parent_name) 1804 1805 __shortrepr__ = __repr__ 1806 1807 def full_name(self): 1808 if self.name is not None: 1809 return self.parent_name + "." + self.name 1810 else: 1811 return self.parent_name 1812 1813 class Module(NamespaceDict, Constant): 1814 1815 "An inspected module's core details." 1816 1817 def __init__(self, name, importer): 1818 NamespaceDict.__init__(self, self) 1819 self.name = name 1820 self.importer = importer 1821 self.parent = None 1822 1823 # Original location details. 1824 1825 self.astnode = None 1826 1827 # Complete lists of classes and functions. 1828 1829 self.all_objects = set() 1830 1831 # Keyword records. 1832 1833 self.keyword_names = set() 1834 1835 # Image generation details. 1836 1837 self.location = None 1838 self.code_location = None 1839 1840 # Program-related details. 1841 1842 self.blocks = None 1843 self.temp_usage = 0 1844 self.local_usage = 0 1845 self.all_local_usage = 0 1846 1847 def full_name(self): 1848 return self.name 1849 1850 def __repr__(self): 1851 if self.location is not None: 1852 return "Module(%r, location=%r)" % (self.name, self.location) 1853 else: 1854 return "Module(%r)" % self.name 1855 1856 def __shortrepr__(self): 1857 return "Module(%r)" % self.name 1858 1859 # Attribute methods. 1860 1861 "Return the module attribute names provided by the module." 1862 1863 module_attribute_names = NamespaceDict.keys 1864 1865 def module_attributes(self): 1866 1867 "Return a dictionary mapping names to module attributes." 1868 1869 return dict(self) 1870 1871 # vim: tabstop=4 expandtab shiftwidth=4