Пример #1
0
    def analyze_file(self, pyfile, use_cache=False):
        # don't analyze the file again if we've already done it and it hasn't
        # changed.  If `use_cache` is True then lookup/record in global cache.
        mtime = os.path.getmtime(pyfile)
        if pyfile in self.fileinfo:
            if mtime <= self.fileinfo[pyfile][1]:
                return self.fileinfo[pyfile][0]

        if use_cache:
            info = _FileInfoCache.lookup(pyfile)
            if info is not None and mtime <= info[1]:
                self.fileinfo[pyfile] = info
                return info[0]

        logger.info("analyzing %s", pyfile)

        myvisitor = PythonSourceFileAnalyser(pyfile, self)
        self.modinfo[get_module_path(pyfile)] = myvisitor
        self.fileinfo[myvisitor.fname] = (myvisitor, os.path.getmtime(myvisitor.fname))
        self.files_count += 1

        if use_cache:
            _FileInfoCache.record(pyfile, (myvisitor, os.path.getmtime(myvisitor.fname)))

        return myvisitor
Пример #2
0
    def analyze_file(self, pyfile, use_cache=False):
        # don't analyze the file again if we've already done it and it hasn't
        # changed.  If `use_cache` is True then lookup/record in global cache.
        mtime = os.path.getmtime(pyfile)
        if pyfile in self.fileinfo:
            if mtime <= self.fileinfo[pyfile][1]:
                return self.fileinfo[pyfile][0]

        if use_cache:
            info = _FileInfoCache.lookup(pyfile)
            if info is not None and mtime <= info[1]:
                self.fileinfo[pyfile] = info
                return info[0]

        logger.info("analyzing %s", pyfile)

        myvisitor = PythonSourceFileAnalyser(pyfile, self)
        self.modinfo[get_module_path(pyfile)] = myvisitor
        self.fileinfo[myvisitor.fname] = (myvisitor,
                                          os.path.getmtime(myvisitor.fname))
        self.files_count += 1

        if use_cache:
            _FileInfoCache.record(
                pyfile, (myvisitor, os.path.getmtime(myvisitor.fname)))

        return myvisitor
Пример #3
0
    def __init__(self, fname, tree_analyser):
        ast.NodeVisitor.__init__(self)
        self.fname = os.path.abspath(os.path.expanduser(fname))
        self.modpath = get_module_path(fname)
        self.classes = {}
        self.localnames = {}  # map of local names to package names
        self.starimports = []
        self.unresolved_classes = set()
        self.tree_analyser = tree_analyser

        # in order to get this to work with the 'ast' lib, I have
        # to read using universal newlines and append a newline
        # to the string I read for some files.  The 'compiler' lib
        # didn't have this problem. :(
        f = open(self.fname, "Ur")
        try:
            contents = f.read()
            if len(contents) > 0 and contents[-1] != "\n":
                contents += "\n"
            for node in ast.walk(ast.parse(contents, self.fname)):
                self.visit(node)
        finally:
            f.close()

        self.update_graph(self.tree_analyser.graph)
        self.update_ifaces(self.tree_analyser.graph)

        self.tree_analyser = None
Пример #4
0
    def __init__(self, fname, tree_analyser):
        ast.NodeVisitor.__init__(self)
        self.fname = os.path.abspath(os.path.expanduser(fname))
        self.modpath = get_module_path(fname)
        self.classes = {}
        self.localnames = {}  # map of local names to package names
        self.starimports = []
        self.unresolved_classes = set()
        self.tree_analyser = tree_analyser

        # in order to get this to work with the 'ast' lib, I have
        # to read using universal newlines and append a newline
        # to the string I read for some files.  The 'compiler' lib
        # didn't have this problem. :(
        f = open(self.fname, 'Ur')
        try:
            contents = f.read()
            if len(contents) > 0 and contents[-1] != '\n':
                contents += '\n'
            for node in ast.walk(ast.parse(contents, self.fname)):
                self.visit(node)
        finally:
            f.close()

        self.update_graph(self.tree_analyser.graph)
        self.update_ifaces(self.tree_analyser.graph)

        self.tree_analyser = None
Пример #5
0
 def __init__(self, fpath):
     self.fpath = fpath
     self.modpath = get_module_path(fpath)
     self.modtime = os.path.getmtime(fpath)
     __import__(self.modpath)
     module = sys.modules[self.modpath]
     self.version = getattr(module, '__version__', None)
     self._update_class_info()
Пример #6
0
 def __init__(self, fpath):
     self.fpath = fpath
     self.modpath = get_module_path(fpath)
     self.modtime = os.path.getmtime(fpath)
     __import__(self.modpath)
     module = sys.modules[self.modpath]
     self.version = getattr(module, '__version__', None)
     self._update_class_info()
Пример #7
0
    def update(self, added, changed, removed):
        """File may have changed on disk, update information and return
        sets of added, removed and (possibly) changed classes.
        """
        self.modpath = get_module_path(self.fpath)
        startset = set(self.classes.keys())

        self._reload()

        keys = set(self.classes.keys())
        added.update(keys - startset)
        changed.update(startset & keys)
        removed.update(startset - keys)
Пример #8
0
    def update(self, added, changed, removed):
        """File may have changed on disk, update information and return
        sets of added, removed and (possibly) changed classes.
        """
        self.modpath = get_module_path(self.fpath)
        startset = set(self.classes.keys())

        self._reload()

        keys = set(self.classes.keys())
        added.update(keys - startset)
        changed.update(startset & keys)
        removed.update(startset - keys)
Пример #9
0
    def execfile(self, fname, digest=None):
        # first, make sure file has been imported
        __import__(get_module_path(fname))
        newdigest = file_md5(fname)
        if digest and digest != newdigest:
            logger.warning("file '%s' has been modified since the last time"
                           " it was exec'd" % fname)
        with open(fname) as f:
            contents = f.read()
        node = add_init_monitors(parse(contents, fname, mode='exec'))
        exec compile(node, fname, 'exec') in self._model_globals

        # make the recorded execfile command use the current md5 hash
        self._cmds_to_save.append("execfile('%s', '%s')" % (fname, newdigest))
Пример #10
0
    def analyze_file(self, pyfile):
        # don't analyze the file again if we've already done it and it hasn't changed
        if pyfile in self.fileinfo:
            if os.path.getmtime(pyfile) <= self.fileinfo[pyfile][1]:
                return self.fileinfo[pyfile][0]

        myvisitor = PythonSourceFileAnalyser(pyfile, self)
        self.modinfo[get_module_path(pyfile)] = myvisitor
        self.fileinfo[myvisitor.fname] = (myvisitor,
                                          os.path.getmtime(myvisitor.fname))

        self.files_count += 1

        return myvisitor
Пример #11
0
 def remove_file(self, fname):
     fvisitor = self.fileinfo[fname][0]
     del self.fileinfo[fname]
     del self.modinfo[fvisitor.modpath]
     nodes = []
     for klass, cinfo in self.class_map.items():
         if isinstance(cinfo, ClassInfo):
             if cinfo.fname == fname:
                 nodes.append(klass)
         else:
             modname = get_module_path(fname) + '.'
             if klass.startswith(modname) or cinfo.startswith(modname):
                 nodes.append(klass)
     self.graph.remove_nodes_from(nodes)
     for klass in nodes:
         del self.class_map[klass]
Пример #12
0
 def remove_file(self, fname):
     fvisitor = self.fileinfo[fname][0]
     del self.fileinfo[fname]
     del self.modinfo[fvisitor.modpath]
     nodes = []
     for klass, cinfo in self.class_map.items():
         if isinstance(cinfo, ClassInfo):
             if cinfo.fname == fname:
                 nodes.append(klass)
         else:
             modname = get_module_path(fname) + "."
             if klass.startswith(modname) or cinfo.startswith(modname):
                 nodes.append(klass)
     self.graph.remove_nodes_from(nodes)
     for klass in nodes:
         del self.class_map[klass]
Пример #13
0
 def _analyze(self):
     """Gather import and class inheritance information from
     the source trees under the specified set of starting 
     directories.
     """
     fileinfo = {}
     
     # gather python files from the specified starting directories
     # and parse them, extracting class and import information
     for pyfile in find_files(self.startdirs, "*.py", self.exclude):
         myvisitor = PythonSourceFileAnalyser(pyfile)
         # in order to get this to work with the 'ast' lib, I have
         # to read using universal newlines and append a newline
         # to the string I read for some files.  The 'compiler' lib
         # didn't have this problem. :(
         f = open(pyfile, 'Ur')
         try:
             for node in ast.walk(ast.parse(f.read()+'\n', pyfile)):
                 myvisitor.visit(node)
         finally:
             f.close()
         fileinfo[get_module_path(pyfile)] = myvisitor
         
     # now translate any indirect imports into absolute module pathnames
     # NOTE: only indirect imports within the set of specified source
     #       trees will be fully resolved, i.e., if a file in your set
     #       of source trees imports
     #       openmdao.main.api but you don't include openmdao.main in your
     #       list of source trees, any imports within openmdao.main.api
     #       won't be included in the translation.  This means that
     #       openmdao.main.api.Component will not be translated to
     #       openmdao.main.component.Component like it should.
     for visitor in fileinfo.values():
         visitor.translate(fileinfo)
 
     # build the inheritance/interface graph
     for visitor in fileinfo.values():
         for classname, classinfo in visitor.classes.items():
             for base in classinfo.bases:
                 self.graph.add_edge(classname, base)
             for impl in classinfo.impls:
                 self.ifaces.add(impl)
                 self.graph.add_edge(classname, impl)
 
     # flip orientation of inheritance graph so we can find all classes
     # that inherit from a particular base more easily
     self.graph = self.graph.reverse(copy=False)
Пример #14
0
    def _analyze(self):
        """Gather import and class inheritance information from
        the source trees under the specified set of starting 
        directories.
        """
        fileinfo = {}

        # gather python files from the specified starting directories
        # and parse them, extracting class and import information
        for pyfile in find_files(self.startdirs, "*.py", self.exclude):
            myvisitor = PythonSourceFileAnalyser(pyfile)
            # in order to get this to work with the 'ast' lib, I have
            # to read using universal newlines and append a newline
            # to the string I read for some files.  The 'compiler' lib
            # didn't have this problem. :(
            f = open(pyfile, 'Ur')
            try:
                for node in ast.walk(ast.parse(f.read() + '\n', pyfile)):
                    myvisitor.visit(node)
            finally:
                f.close()
            fileinfo[get_module_path(pyfile)] = myvisitor

        # now translate any indirect imports into absolute module pathnames
        # NOTE: only indirect imports within the set of specified source
        #       trees will be fully resolved, i.e., if a file in your set
        #       of source trees imports
        #       openmdao.main.api but you don't include openmdao.main in your
        #       list of source trees, any imports within openmdao.main.api
        #       won't be included in the translation.  This means that
        #       openmdao.main.api.Component will not be translated to
        #       openmdao.main.component.Component like it should.
        for visitor in fileinfo.values():
            visitor.translate(fileinfo)

        # build the inheritance/interface graph
        for visitor in fileinfo.values():
            for classname, classinfo in visitor.classes.items():
                for base in classinfo.bases:
                    self.graph.add_edge(classname, base)
                for impl in classinfo.impls:
                    self.ifaces.add(impl)
                    self.graph.add_edge(classname, impl)

        # flip orientation of inheritance graph so we can find all classes
        # that inherit from a particular base more easily
        self.graph = self.graph.reverse(copy=False)
Пример #15
0
    def on_modified(self, fpath, added_set, changed_set, deleted_set):
        if os.path.isdir(fpath):
            return

        with self._lock:
            imported = False
            if fpath in self.analyzer.fileinfo:  # file has been previously scanned
                visitor = self.analyzer.fileinfo[fpath][0]
                pre_set = set(visitor.classes.keys())

                if fpath in self.imported:  # we imported it earlier
                    imported = True
                    sys.path = [os.path.dirname(fpath)
                                ] + sys.path  # add fpath location to sys.path
                    try:
                        reload(self.imported[fpath][0])
                    except ImportError as err:
                        return None
                    finally:
                        sys.path = sys.path[1:]  # restore original sys.path
                    #self.imported[fpath] = (m, self.imported[fpath][1])
                elif os.path.getmtime(
                        fpath) > self.analyzer.fileinfo[fpath][1]:
                    modpath = get_module_path(fpath)
                    if modpath in sys.modules:
                        reload(sys.modules[modpath])
                self.on_deleted(fpath, set())  # clean up old refs
            else:  # it's a new file
                pre_set = set()

            visitor = self.analyzer.analyze_file(fpath)
            post_set = set(visitor.classes.keys())

            deleted_set.update(pre_set - post_set)
            added_set.update(post_set - pre_set)
            if imported:
                changed_set.update(pre_set.intersection(post_set))
Пример #16
0
 def __init__(self, fname, stop_classes=None):
     ast.NodeVisitor.__init__(self)
     self.fname = os.path.abspath(fname)
     self.modpath = get_module_path(fname)
     self.classes = {}
     self.localnames = {}  # map of local names to package names
Пример #17
0
 def __init__(self, fname, stop_classes=None):
     ast.NodeVisitor.__init__(self)
     self.fname = os.path.abspath(fname)
     self.modpath = get_module_path(fname)
     self.classes = {}
     self.localnames = {}  # map of local names to package names
Пример #18
0
 def tearDown(self):
     for pyfile in find_files(self.tdir, "*.py"):
         modpath = get_module_path(pyfile)
         if modpath in sys.modules:
             del sys.modules[modpath]
     shutil.rmtree(self.tdir, onerror=onerror)