1.1 --- a/simplify/annotate.py Sat Jun 23 01:57:13 2007 +0200
1.2 +++ b/simplify/annotate.py Sat Jun 23 21:10:01 2007 +0200
1.3 @@ -24,25 +24,17 @@
1.4
1.5 --------
1.6
1.7 -To use this module, the easiest approach is to use the load function:
1.8 -
1.9 -load(filename, builtins)
1.10 -
1.11 -To control module importing, an importer should be constructed and employed.
1.12 -Here, the standard path for module searching is used:
1.13 +To use this module, the easiest approach is to use the annotate function which
1.14 +provides support for annotating modules already processed by simplify and
1.15 +fixnames:
1.16
1.17 -importer = Importer(sys.path)
1.18 -load(filename, builtins, importer)
1.19 +annotate(builtins, None, importer)
1.20 +annotate(module, builtins, importer)
1.21
1.22 -Underneath the load function, the annotate function provides support for
1.23 -annotating modules already processed by simplify and fixnames:
1.24 -
1.25 -annotate(module, builtins)
1.26 -
1.27 -And at the most basic level, the most intricate approach involves obtaining an
1.28 +At the most basic level, the most intricate approach involves obtaining an
1.29 Annotator object:
1.30
1.31 -annotator = Annotator()
1.32 +annotator = Annotator(importer)
1.33
1.34 Then, processing an existing module with it:
1.35
1.36 @@ -55,7 +47,6 @@
1.37 """
1.38
1.39 from simplify.simplified import *
1.40 -import simplify.ast, simplify.fixnames # for the load function
1.41 import compiler
1.42 import os
1.43
1.44 @@ -139,13 +130,13 @@
1.45 Try.
1.46 """
1.47
1.48 - def __init__(self, importer=None):
1.49 + def __init__(self, importer):
1.50
1.51 - "Initialise the visitor with an optional 'importer'."
1.52 + "Initialise the visitor with an 'importer'."
1.53
1.54 Visitor.__init__(self)
1.55 self.system = system
1.56 - self.importer = importer or Importer()
1.57 + self.importer = importer
1.58
1.59 # Satisfy visitor issues.
1.60
1.61 @@ -487,7 +478,7 @@
1.62 # exist for some combinations of classes in a hierarchy but not for
1.63 # others.
1.64
1.65 - if isinstance(attr.type, Class):
1.66 + if isinstance(attr.type, GeneralClass):
1.67 attributes = get_attributes(attr.type, "__init__")
1.68
1.69 # Deal with object invocations by using __call__ methods.
1.70 @@ -509,7 +500,7 @@
1.71 # If a class is involved, presume that it must create a new
1.72 # object.
1.73
1.74 - if isinstance(attr.type, Class):
1.75 + if isinstance(attr.type, GeneralClass):
1.76
1.77 # Instantiate the class.
1.78
1.79 @@ -534,7 +525,7 @@
1.80 if attribute.type not in invocations:
1.81 invocations.append(attribute.type)
1.82
1.83 - elif not isinstance(attr.type, Class):
1.84 + elif not isinstance(attr.type, GeneralClass):
1.85 print "Invocation type is None for", accessor
1.86
1.87 else:
1.88 @@ -547,7 +538,7 @@
1.89
1.90 # Special case: initialisation.
1.91
1.92 - if isinstance(attr.type, Class):
1.93 + if isinstance(attr.type, GeneralClass):
1.94
1.95 # Associate the instance with the result of this invocation.
1.96
1.97 @@ -811,7 +802,7 @@
1.98 raise_.dstar = None
1.99 types = set()
1.100 for attr in self.namespace.types:
1.101 - if isinstance(attr.type, Class):
1.102 + if isinstance(attr.type, GeneralClass):
1.103 self._visitInvoke(raise_, [attr], have_args=0)
1.104 types.update(self.namespace.types)
1.105 else:
1.106 @@ -1383,144 +1374,6 @@
1.107
1.108 # Namespace-related abstractions.
1.109
1.110 -class Importer:
1.111 -
1.112 - "An import machine, searching for and loading modules."
1.113 -
1.114 - def __init__(self, path=None):
1.115 -
1.116 - """
1.117 - Initialise the importer with the given search 'path' - a list of
1.118 - directories to search for Python modules.
1.119 - """
1.120 -
1.121 - self.path = path or [os.getcwd()]
1.122 - self.path.append(libdir)
1.123 - self.modules = {}
1.124 -
1.125 - def find_in_path(self, name):
1.126 -
1.127 - """
1.128 - Find the given module 'name' in the search path, returning None where no
1.129 - such module could be found, or a 2-tuple from the 'find' method
1.130 - otherwise.
1.131 - """
1.132 -
1.133 - for d in self.path:
1.134 - m = self.find(d, name)
1.135 - if m: return m
1.136 - return None
1.137 -
1.138 - def find(self, d, name):
1.139 -
1.140 - """
1.141 - In the directory 'd', find the given module 'name', where 'name' can
1.142 - either refer to a single file module or to a package. Return None if the
1.143 - 'name' cannot be associated with either a file or a package directory,
1.144 - or a 2-tuple from '_find_package' or '_find_module' otherwise.
1.145 - """
1.146 -
1.147 - m = self._find_package(d, name)
1.148 - if m: return m
1.149 - m = self._find_module(d, name)
1.150 - if m: return m
1.151 - return None
1.152 -
1.153 - def _find_module(self, d, name):
1.154 -
1.155 - """
1.156 - In the directory 'd', find the given module 'name', returning None where
1.157 - no suitable file exists in the directory, or a 2-tuple consisting of
1.158 - None (indicating that no package directory is involved) and a filename
1.159 - indicating the location of the module.
1.160 - """
1.161 -
1.162 - name_py = name + os.extsep + "py"
1.163 - filename = self._find_file(d, name_py)
1.164 - if filename:
1.165 - return None, filename
1.166 - return None
1.167 -
1.168 - def _find_package(self, d, name):
1.169 -
1.170 - """
1.171 - In the directory 'd', find the given package 'name', returning None
1.172 - where no suitable package directory exists, or a 2-tuple consisting of
1.173 - a directory (indicating the location of the package directory itself)
1.174 - and a filename indicating the location of the __init__.py module which
1.175 - declares the package's top-level contents.
1.176 - """
1.177 -
1.178 - filename = self._find_file(d, name)
1.179 - if filename:
1.180 - init_py = "__init__" + os.path.extsep + "py"
1.181 - init_py_filename = self._find_file(filename, init_py)
1.182 - if init_py_filename:
1.183 - return filename, init_py_filename
1.184 - return None
1.185 -
1.186 - def _find_file(self, d, filename):
1.187 -
1.188 - """
1.189 - Return the filename obtained when searching the directory 'd' for the
1.190 - given 'filename', or None if no actual file exists for the filename.
1.191 - """
1.192 -
1.193 - filename = os.path.join(d, filename)
1.194 - if os.path.exists(filename):
1.195 - return filename
1.196 - else:
1.197 - return None
1.198 -
1.199 - def load(self, name, builtins, alias=None):
1.200 -
1.201 - """
1.202 - Load the module or package with the given 'name' and using the specified
1.203 - 'builtins'. Return an Attribute object referencing the loaded module or
1.204 - package, or None if no such module or package exists.
1.205 - """
1.206 -
1.207 - if self.modules.has_key(name):
1.208 - return Attribute(None, self.modules[name])
1.209 -
1.210 - path = name.split(".")
1.211 - m = self.find_in_path(path[0])
1.212 - if not m:
1.213 - return None # NOTE: Import error.
1.214 - d, filename = m
1.215 -
1.216 - if self.modules.has_key(path[0]):
1.217 - top = module = self.modules[path[0]]
1.218 - else:
1.219 - top = module = self.modules[path[0]] = load(filename, builtins, path[0], self, no_annotate=1)
1.220 - annotate(module, builtins, self)
1.221 -
1.222 - if len(path) > 1:
1.223 - path_so_far = path[:1]
1.224 - for p in path[1:]:
1.225 - path_so_far.append(p)
1.226 - m = self.find(d, p)
1.227 - if not m:
1.228 - return None # NOTE: Import error.
1.229 - d, filename = m
1.230 - module_name = ".".join(path_so_far)
1.231 -
1.232 - if self.modules.has_key(module_name):
1.233 - submodule = self.modules[module_name]
1.234 - else:
1.235 - submodule = self.modules[module_name] = load(filename, builtins, module_name, self, no_annotate=1)
1.236 - annotate(submodule, builtins, self)
1.237 -
1.238 - # Store the submodule within its parent module.
1.239 -
1.240 - module.namespace[p] = [Attribute(None, submodule)]
1.241 - module = submodule
1.242 -
1.243 - if alias:
1.244 - return Attribute(None, module)
1.245 - else:
1.246 - return Attribute(None, top)
1.247 -
1.248 def combine(target, additions):
1.249
1.250 """
1.251 @@ -1566,7 +1419,7 @@
1.252
1.253 # Investigate any class's base classes.
1.254
1.255 - elif isinstance(structure, Class):
1.256 + elif isinstance(structure, GeneralClass):
1.257
1.258 # If no base classes exist, return an indicator that no attribute
1.259 # exists.
1.260 @@ -1609,7 +1462,7 @@
1.261
1.262 # Detect class attribute access via instances.
1.263
1.264 - if attribute is not None and isinstance(structure, Instance) and isinstance(accessor, Class):
1.265 + if attribute is not None and isinstance(structure, Instance) and isinstance(accessor, GeneralClass):
1.266 attribute = accessor.get_attribute_for_instance(attribute, structure)
1.267
1.268 # Produce an attribute with the appropriate context.
1.269 @@ -1640,26 +1493,11 @@
1.270
1.271 # Convenience functions.
1.272
1.273 -def load(name, builtins=None, module_name=None, importer=None, no_annotate=0):
1.274 +def annotate(module, builtins, importer):
1.275
1.276 """
1.277 - Load the module with the given 'name' (which may be a full module path),
1.278 - using the optional 'builtins' to resolve built-in names, and using the
1.279 - optional 'importer' to provide a means of finding and loading modules.
1.280 - """
1.281 -
1.282 - module = simplify.ast.simplify(name, builtins is None, module_name)
1.283 - simplify.fixnames.fix(module, builtins)
1.284 - if not no_annotate:
1.285 - annotate(module, builtins, importer)
1.286 - return module
1.287 -
1.288 -def annotate(module, builtins=None, importer=None):
1.289 -
1.290 - """
1.291 - Annotate the given 'module', also employing the optional 'builtins' module,
1.292 - if specified. If the optional 'importer' is given, use that to find and load
1.293 - modules.
1.294 + Annotate the given 'module', also employing the 'builtins' module which may
1.295 + be specified as None. Use the 'importer' to find and load modules.
1.296 """
1.297
1.298 annotator = Annotator(importer)