Beispiel #1
0
    def _db_func(self, data, filename, html_body, name, start_lineno, source,
                 typ):
        """
        Retrieve the Function object from the database if one exists, or create one.
        """
        def h(s):
            return hashlib.sha256(s.encode('utf8')).hexdigest()

        function_hash = h(filename + name + html_body + data +
                          str(start_lineno))

        Function = self.db.Function

        with self.db.session_scope() as session:
            db_func = one_or_none(
                session.query(Function).filter_by(
                    hash=function_hash))  # type: Optional[Function]
            if not db_func:
                db_func = Function(file=filename,
                                   name=name,
                                   type=typ,
                                   html_body=html_body,
                                   lineno=start_lineno,
                                   data=data,
                                   body_hash=h(source),
                                   hash=function_hash)
                session.add(db_func)
                session.commit()  # ensure .id exists
            assert isinstance(db_func.id, int)
            return db_func.id
Beispiel #2
0
    def _db_func(self, data, filename, html_body, name, start_lineno,
                 raw_body):
        """
        Retrieve the Function object from the database if one exists, or create one.
        """
        def h(s):
            return hashlib.sha256(s.encode('utf8')).hexdigest()

        function_hash = h(filename + name + html_body + data +
                          str(start_lineno))

        session = self.db.session
        Function = self.db.Function

        db_func = one_or_none(
            session.query(Function).filter_by(
                hash=function_hash))  # type: Optional[Function]
        if not db_func:
            db_func = Function(file=filename,
                               name=name,
                               html_body=html_body,
                               lineno=start_lineno,
                               data=data,
                               body_hash=h(raw_body),
                               hash=function_hash)
            session.add(db_func)
            session.commit()
        return db_func
Beispiel #3
0
    def _db_job(self, name):
        """
        Retrieve the Job object from database by name or create it
        """

        Job = self.db.Job

        with self.db.session_scope() as session:
            db_job = one_or_none(
                session.query(Job).filter_by(job_name=name)
            )  # type: Optional[Function]
            if not db_job:
                db_job = Job(
                    job_name=name,
                )
                session.add(db_job)
                session.commit()  # ensure .id exists
            assert isinstance(db_job.id, int)
            return db_job.id
Beispiel #4
0
    def __call__(self, func):
        if inspect.isclass(func):
            cls = func
            for name, meth in iteritems(cls.__dict__):
                if inspect.ismethod(meth) or inspect.isfunction(meth):
                    setattr(cls, name, self.__call__(meth))
            return cls

        new_func = super(BirdsEye, self).__call__(func)
        code_info = self._code_infos.get(new_func.__code__)
        if code_info:
            return new_func
        lines, start_lineno = inspect.getsourcelines(func)
        end_lineno = start_lineno + len(lines)
        name = safe_qualname(func)
        filename = os.path.abspath(inspect.getsourcefile(func))

        traced_file = new_func.traced_file
        traced_file.root._depth = 0
        for node in ast.walk(traced_file.root):
            for child in ast.iter_child_nodes(node):
                child._depth = node._depth + 1

        positions = []
        node_loops = {}
        for node in traced_file.nodes:
            if isinstance(node, ast.expr):
                node_type = 'expr'
                if not node._is_interesting_expression:
                    continue
            elif (isinstance(node, (ast.While, ast.For, ast.comprehension))
                  and not isinstance(node.parent, ast.GeneratorExp)):
                node_type = 'loop'
            elif isinstance(node, ast.stmt):
                node_type = 'stmt'
            else:
                continue
            assert isinstance(node, ast.AST)

            # In particular FormattedValue is missing this
            if not hasattr(node, 'first_token'):
                continue

            if not start_lineno <= node.first_token.start[0] <= end_lineno:
                continue

            start, end = traced_file.tokens.get_text_range(node)
            if start == end == 0:
                continue
            positions.append((start, 1, node._depth,
                              '<span data-index="%s" data-type="%s">' %
                              (node._tree_index, node_type)))
            positions.append((end, 0, node._depth, '</span>'))
            if node._loops:
                node_loops[node._tree_index] = [
                    n._tree_index for n in node._loops
                ]

        comprehensions = group_by_key_func([
            comp for comp in traced_file.nodes
            if isinstance(comp, ast.comprehension)
        ], lambda c: c.first_token.line)

        def get_start(n):
            return traced_file.tokens.get_text_range(n)[0]

        for comp_list in comprehensions.values():
            prev_start = None
            for comp in sorted(comp_list,
                               key=lambda c: c.first_token.startpos):
                if comp is comp.parent.generators[0]:
                    start = get_start(comp.parent)
                    if prev_start is not None and start < prev_start:
                        start = get_start(comp)
                else:
                    start = get_start(comp)
                if prev_start is not None:
                    positions.append((start, 1, 0, '\n '))
                    end_lineno += 1
                prev_start = start

        positions.append((len(traced_file.source), None, None, ''))
        positions.sort()

        html_body = []
        start = 0
        for pos, _, _, part in positions:
            html_body.append(html.escape(traced_file.source[start:pos]))
            html_body.append(part)
            start = pos
        html_body = ''.join(html_body)
        html_body = '\n'.join(
            html_body.split('\n')[start_lineno - 1:end_lineno - 1])

        db_args = dict(file=filename,
                       name=name,
                       html_body=html_body,
                       lineno=start_lineno,
                       data=json.dumps(
                           dict(node_loops=node_loops, ),
                           sort_keys=True,
                       ))

        db_func = one_or_none(session.query(Function).filter_by(**db_args))
        if not db_func:
            db_func = Function(**db_args)
            session.add(db_func)
            session.commit()
        self._code_infos[new_func.__code__] = CodeInfo(db_func, traced_file)

        return new_func