1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
|
""" A Python namespace. """
# Standard library imports.
import os, sys
# Enthought library imports.
from enthought.traits.api import Dict, HasTraits
class Namespace(HasTraits):
""" A Python namespace. """
#### 'Namespace' interface ################################################
# All of the names defined within the module.
locals = Dict
# All of the names imported into the module.
imports = Dict
# fixme: This is a dict from name -> bool indicating whether a name in
# locals is a trait or not. Should locals be a dict containing a tuple?
_is_trait = Dict
###########################################################################
# 'Namespace' interface.
###########################################################################
def is_trait(self, name):
""" Attempt to resolve a name to see if it is a trait. """
# fixme: We might want to be a bit cleverer than this ;^)
return True
# Try the namespace's locals first.
if name in self.locals:
# These are the definitive traits markers!
if name in ['TraitFactory', 'Trait', 'Instance']:
is_trait = True
# The name won't be in the '_is_trait' dictionary if it was not
# defined by an assignment i.e., it is a class or function!
elif not self._is_trait.get(name, False):
is_trait = False
else:
next = self.locals[name]
if len(next.source) > 0:
is_trait = self.is_trait(next.source)
else:
is_trait = False
# Is the name imported?
elif self.is_imported(name):
module_name = self.get_next_module_name(name)
module = self.get_next_module(module_name)
if module is not None:
components = name.split('.')
is_trait = module.is_trait(components[-1])
else:
is_trait = False
# If we have a parent namespace then try that.
elif self.namespace is not None:
is_trait = self.namespace.is_trait(name)
# Otherwise give up!
else:
is_trait = False
return is_trait
def is_imported(self, name):
""" Returns TRUE if a name is imported. """
components = name.split('.')
return components[0] in self.imports
def get_next_module_name(self, symbol):
""" Returns the name of the module that a symbol was imported from. """
components = symbol.split('.')
if len(components) == 1:
module_name = self.imports[symbol]
else:
path = []
# The first component MUST have been imported.
#
# An empty string means 'import' as opposed to 'from' used.
value = self.imports[components[0]]
if len(value) > 0:
path.append(value)
module_name = '.'.join(path)
return module_name
path.append(components[0])
for component in components[1:-1]:
path.append(component)
module_name = '.'.join(path)
return module_name
def get_next_module(self, module_name):
""" Returns a parsed module with the specified name.
Returns None if the module cannot be found or is 'ignored'. We ignore
all modules in the Python core, extension modules etc.
"""
# fixme: Circular imports!
from enclbr import find_module, read_file
# Try to find the module that the symbol came from.
dirname = os.path.dirname(self.filename)
filename = find_module(module_name, [dirname] + sys.path)
if filename is not None:
# If the filename refers to a directory then it must be a
# package.
if os.path.isdir(filename):
filename = os.path.join(filename, '__init__.py')
# fixme: We should probably put in some more formal filter
# mechanism here!
#
# Ignore extension modules.
if filename.endswith('.pyd') or filename.endswith('.so'):
module = None
# Ignore standard modules.
elif filename.startswith(sys.prefix):
module = None
# Parse it!
else:
module = read_file(filename)
else:
module = None
return module
#### EOF ######################################################################
|