コード例 #1
0
def _make_tests_node(data):
    """Create the final "tests" data that will be written to a package.py file.

    Important:
        This function technically doesn't create a "correct"
        parso dict. For the sake of simplicity, some corners were
        cut. For example, value data is converted into a raw
        :class:`parso.python.tree.String`. It's not technically
        "correct" but since this function is called just before writing
        the data into disk and not further modified, it's okay.

    Args:
        data (iter[str, :class:`parso.python.tree.PythonBaseNode`]):
            The key / value information that will be converted into a
            parso dict.

    Returns:
        :class:`parso.python.tree.PythonNode`:
            An atom PythonNode which has a full dictionary "tests"
            defined. This will later override an existing "tests"
            attribute in a package.py or be appended to the file as an
            assignment.

    """
    nodes = []

    for key, value in data:
        nodes.extend([
            tree.String(_escape(key), (0, 0), prefix="\n    "),
            tree.Operator(":", (0, 0)),
        ])

        if isinstance(value, collections.MutableMapping):
            nodes.append(_make_dict_nodes(sorted(value.items()),
                                          prefix="    "))
        elif hasattr(value, "get_code"):
            if hasattr(value, "prefix"):
                value.prefix = " "

            nodes.append(value)
        else:
            nodes.append(tree.String(_escape_all(value), (0, 0), prefix=" "))

        nodes.append(tree.Operator(",", (0, 0)))

    base = tree.PythonNode("dictorsetmaker", nodes)

    return tree.PythonNode(
        "atom",
        [
            tree.Operator("{", (0, 0)), base,
            tree.Operator("}", (0, 0), prefix="\n")
        ],
    )
コード例 #2
0
ファイル: syntax_tree.py プロジェクト: rrudakov/jedi
def _apply_decorators(context, node):
    """
    Returns the function, that should to be executed in the end.
    This is also the places where the decorators are processed.
    """
    if node.type == 'classdef':
        decoratee_context = ClassContext(context.evaluator,
                                         parent_context=context,
                                         tree_node=node)
    else:
        decoratee_context = FunctionContext.from_context(context, node)
    initial = values = ContextSet(decoratee_context)
    for dec in reversed(node.get_decorators()):
        debug.dbg('decorator: %s %s', dec, values)
        dec_values = context.eval_node(dec.children[1])
        trailer_nodes = dec.children[2:-1]
        if trailer_nodes:
            # Create a trailer and evaluate it.
            trailer = tree.PythonNode('trailer', trailer_nodes)
            trailer.parent = dec
            dec_values = eval_trailer(context, dec_values, trailer)

        if not len(dec_values):
            debug.warning('decorator not found: %s on %s', dec, node)
            return initial

        values = dec_values.execute(arguments.ValuesArguments([values]))
        if not len(values):
            debug.warning('not possible to resolve wrappers found %s', node)
            return initial

        debug.dbg('decorator end %s', values)
    return values
コード例 #3
0
def _make_new_list(requirements):
    """Make a flat Python list, using parso nodes.

    Args:
        requirements (iter[:class:`parso.python.tree.String`]):
            The Rez requirements that'll be used to generate the new
            list. No nodes related to punctuation should be used here.
            Just requirements.

    Returns:
        :class:`parso.python.tree.PythonNode`: The generated list.

    """
    nodes = []

    for requirement in requirements:
        nodes.append(requirement)
        nodes.append(tree.Operator(",", (0, 0)))

    prefix = "\n"

    if not nodes:
        prefix = ""

    return tree.PythonNode(
        "atom",
        [tree.Operator("[", (0, 0))] + nodes +
        [tree.Operator("]", (0, 0), prefix=prefix)],
    )
コード例 #4
0
def _make_dict_nodes(data, prefix=""):
    """Create a parso node that represents the inner key / value pairs of a Python dict.

    In terms of the work needed to generate a Rez "tests" attribute,
    this function is used mainly to create the "inner dict" that a
    "tests" attribute frequently defines.

    Args:
        data (iter[tuple[str, str or list or :class:`parso.python.tree.PythonBaseNode`]]):

    Returns:
        :class:`parso.python.tree.PythonNode`:
            A node that defines the inside of a parso dict. This node
            is not equivalent to an actual dict and still needs to be
            wrapped with another :class:`parso.python.tree.PythonNode`
            to be valid.

    """
    nodes = []

    for key, item in data:
        item = _escape_all(item)

        nodes.append(
            tree.String(_escape(key), (0, 0),
                        prefix="\n    {prefix}".format(prefix=prefix)))
        nodes.append(tree.Operator(":", (0, 0)))
        nodes.append(
            tree.PythonNode(
                "atom",
                [
                    tree.String(item, (0, 0), prefix=" "),
                    tree.Operator(",", (0, 0))
                ],
            ), )

    return tree.PythonNode(
        "atom",
        [
            tree.Operator("{", (0, 0), prefix=" "),
            tree.PythonNode("dictorsetmaker", nodes),
            tree.Operator("}", (0, 0), prefix="\n    "),
        ],
    )
コード例 #5
0
    def _make_import(namespace_parts, prefix="", alias=None):
        """Make a new from-import node and insert it into an existing parso graph.

        Args:
            namespace_parts (list[str]):
                The import that will be converted into a parso from-import node.
            prefix (str, optional):
                The leading whitespace (indentation) placed before the new import.

        Returns:
            :class:`parso.python.tree.ImportFrom`: A newly generated import statement.

        """
        base_names = namespace_parts[:-1]
        base_count = len(base_names)
        base_nodes = []

        if base_count > 1:
            for is_last, name in iterbot.iter_is_last(base_names):
                base_nodes.append(tree.Name(name, (0, 0)))

                if not is_last:
                    base_nodes.append(tree.Operator(".", (0, 0)))

            base_nodes[0].prefix = " "
            base = tree.PythonNode("dotted_name", base_nodes)
        else:
            base = tree.Name(base_names[0], (0, 0), prefix=" ")

        tail = tree.Name(namespace_parts[-1], (0, 0), prefix=" ")

        if alias:
            tail = tree.PythonNode(
                "import_as_name",
                [tail, tree.Keyword("as", (0, 0), prefix=" "), alias])

        return tree.ImportFrom([
            tree.Keyword("from", (0, 0), prefix=prefix),
            base,
            tree.Keyword("import", (0, 0), prefix=" "),
            tail,
        ])
コード例 #6
0
def _make_intersphinx_dict(pairs):
    """Create a parso literal that defines ``intersphinx_mapping``.

    Args:
        pairs (list[:class:`parso.python.tree.Node`]):
            The key / value dict pairs that will be added into a new
            ``intersphinx_mapping`` dict literal.

    Returns:
        :class:`parso.python.tree.PythonNode`: The generated dict.

    """
    return tree.PythonNode(
        "atom",
        [
            tree.Operator("{", (0, 0), prefix=" "),
            tree.PythonNode("dictorsetmaker", pairs),
            tree.Operator("}", (len(pairs), 0), prefix="\n"),
        ],
    )
コード例 #7
0
def insert_or_append_raw_node(node, graph, assignment, attribute):
    """Add a new `attribute` to `graph`, according to pre-existing data.

    Args:
        node (:class:`parso.python.tree.PythonNode`):
            The main data that will be added to `graph`.
        graph (:class:`parso.python.tree.PythonNode`):
            A Python module that may already contain an assignment for
            `attribute`. If it doesn't the attribute will be added,
            automatically.
        assignment (:class:`parso.python.tree.PythonNode` or NoneType):
            If `graph` has an existing node where `attribute` is
            defined, this node will represent that position. If this
            parameter is None, a new position for `attribute` will be
            automatically found and used.
        attribute (str):
            The name of the Rez-related object to use.

    Returns:
        :class:`parso.python.tree.PythonNode`: The main module with a modified `attribute`.

    """
    if assignment:
        index = _find_nearest_node_index(graph.children, attribute)
        del graph.children[index]
        graph.children.insert(index, tree.PythonNode("assignment", [node]))

        return graph

    index = _find_nearest_node_index(graph.children, attribute)

    if index == -1:
        graph.children.append(tree.PythonNode("assignment", [node]))

        return graph

    prefix_node = node_seek.get_node_with_first_prefix(node)
    prefix_node.prefix = "\n\n"
    graph.children.insert(index, tree.PythonNode("assignment", [node]))

    return graph
コード例 #8
0
ファイル: syntax_tree.py プロジェクト: myhololens/jedi
def _apply_decorators(context, node):
    """
    Returns the function, that should to be executed in the end.
    This is also the places where the decorators are processed.
    """
    if node.type == 'classdef':
        decoratee_value = ClassValue(
            context.inference_state,
            parent_context=context,
            tree_node=node
        )
    else:
        decoratee_value = FunctionValue.from_context(context, node)
    initial = values = ValueSet([decoratee_value])

    if is_big_annoying_library(context):
        return values

    for dec in reversed(node.get_decorators()):
        debug.dbg('decorator: %s %s', dec, values, color="MAGENTA")
        with debug.increase_indent_cm():
            dec_values = context.infer_node(dec.children[1])
            trailer_nodes = dec.children[2:-1]
            if trailer_nodes:
                # Create a trailer and infer it.
                trailer = tree.PythonNode('trailer', trailer_nodes)
                trailer.parent = dec
                dec_values = infer_trailer(context, dec_values, trailer)

            if not len(dec_values):
                code = dec.get_code(include_prefix=False)
                # For the short future, we don't want to hear about the runtime
                # decorator in typing that was intentionally omitted. This is not
                # "correct", but helps with debugging.
                if code != '@runtime\n':
                    debug.warning('decorator not found: %s on %s', dec, node)
                return initial

            values = dec_values.execute(arguments.ValuesArguments([values]))
            if not len(values):
                debug.warning('not possible to resolve wrappers found %s', node)
                return initial

        debug.dbg('decorator end %s', values, color="MAGENTA")
    if values != initial:
        return ValueSet([Decoratee(c, decoratee_value) for c in values])
    return values
コード例 #9
0
    def _get_entries(assignment):
        """Find every help key + value entry from some "help" attribute.

        If `assignment` is invalid, this function may return an empty list.

        Args:
            assignment (:class:`parso.python.tree.ExprStmt`):
                The node that assigns the "help" attribute, which will
                be modified.

        Returns:
            list[:class:`parso.python.tree.PythonNode`]:
                The list node that is a parso "list of list of strs".

        """
        root = _get_list_root(assignment)

        if root:
            return _get_inner_list_entries(root)

        string_root = _get_str_root(assignment)

        if not string_root:
            return []

        if string_root.get_code().strip() in ("''", '""'):
            return []

        node = tree.PythonNode(
            "testlist_comp",
            [
                tree.String(
                    '"{rez_configuration.DEFAULT_HELP_LABEL}"'.format(
                        rez_configuration=rez_configuration),
                    (0, 0),
                ),
                tree.Operator(",", (0, 0)),
                string_root,
            ],
        )

        for child in node.children:
            child.parent = node

        return [node]
コード例 #10
0
ファイル: fake.py プロジェクト: 18636800170/movieApi
def _get_faked(grammar, module, obj, name=None):
    result, fake_module = _faked(grammar, module, obj, name)
    if result is None:
        # We're not interested in classes. What we want is functions.
        raise FakeDoesNotExist
    elif result.type == 'classdef':
        return result, fake_module
    else:
        # Set the docstr which was previously not set (faked modules don't
        # contain it).
        assert result.type == 'funcdef'
        doc = '"""%s"""' % obj.__doc__  # TODO need escapes.
        suite = result.children[-1]
        string = tree.String(doc, (0, 0), '')
        new_line = tree.Newline('\n', (0, 0))
        docstr_node = tree.PythonNode('simple_stmt', [string, new_line])
        suite.children.insert(1, docstr_node)
        return result, fake_module
コード例 #11
0
def insert_or_append(node, graph, assignment, attribute):
    """Add a new `attribute` to `graph`, according to pre-existing data.

    Args:
        node (:class:`parso.python.tree.PythonNode`):
            The main data that will be added to `graph`.
        graph (:class:`parso.python.tree.PythonNode`):
            A Python module that may already contain an assignment for
            `attribute`. If it doesn't the attribute will be added,
            automatically.
        assignment (:class:`parso.python.tree.PythonNode` or NoneType):
            If `graph` has an existing node where `attribute` is
            defined, this node will represent that position. If this
            parameter is None, a new position for `attribute` will be
            automatically found and used.
        attribute (str):
            The name of the Rez-related object to use.

    Returns:
        :class:`parso.python.tree.PythonNode`: The main module with a modified `attribute`.

    """
    if assignment:
        if hasattr(node, "children"):
            node.children[0].prefix = " "

        assignment.children[-1] = node

        return graph

    index = _find_nearest_node_index(graph.children, attribute)

    if index == -1:
        graph.children.append(
            tree.PythonNode(
                "assignment",
                [
                    tree.String(
                        "{attribute} = ".format(attribute=attribute),
                        (0, 0),
                        prefix="\n\n",
                    )
                ] + [node],
            ))

        return graph

    _kill_suffix(graph.children[index - 1])

    graph.children.insert(
        index,
        tree.PythonNode(
            "assignment",
            [
                tree.String("{attribute} = ".format(attribute=attribute),
                            (0, 0),
                            prefix="\n\n")
            ] + [node],
        ),
    )
    _adjust_prefix(graph.children, index)

    return graph
コード例 #12
0
    def modify_with_existing(  # pylint: disable=arguments-differ
            cls, graph, data, append=False):
        """Add `data` to a parso node `graph`.

        Reference:
            https://github.com/nerdvegas/rez/wiki/Package-Definition-Guide#help

        Args:
            graph (:class:`parso.python.Tree.PythonBaseNode`):
                Some node that may assignment an attribute called
                "tests". If "tests" assignment exists, it gets
                overwritten. If no assignment exists then a new
                assignment is appended to the end of the file.
            data (list[list[str]] or str or :class:`parso.python.tree.PythonNode`):
                Any values that'd typically define a Rez "tests"
                attribute. Basically anything is allowed, as long the
                Rez package schema considers it valid.
            append (bool, optional):
                If False, anything in `data` will override the objects
                in `graph` if there are any conflicts between the two.
                If True, the conflicts are ignored and `data` is just
                added to `graph` is if no conflict exists. Default is False.

        Returns:
            str:
                The modified Python source code. It should resemble the
                source code of `graph` plus any serialized `data`.

        """
        assignments = parso_utility.find_assignment_nodes(
            "help", graph) or parso_utility.find_definition_root_nodes(
                "help", graph)

        try:
            assignment = assignments[-1]
        except IndexError:
            assignment = None

        if isinstance(data, tree.BaseNode):
            graph = convention.insert_or_append_raw_node(
                data, graph, assignment, "help")

            return graph.get_code()

        help_data = parso.parse(json.dumps(
            data, cls=encoder.BuiltinEncoder)).children[0]

        if (assignment and not _get_list_root(assignment)
                and isinstance(help_data, tree.String)):
            help_data.prefix = " "
            graph = convention.insert_or_append(help_data, graph, assignment,
                                                "help")

            return graph.get_code()

        if _get_list_root(assignment) and isinstance(help_data, tree.String):
            raise ValueError(
                'You may not add string "{help_data}" '
                'because assignment "{assignment}" is a list.'.format(
                    help_data=help_data.get_code(),
                    assignment=assignment.get_code()))

        help_data = _get_inner_list_entries(help_data)

        entries = []

        if assignment:
            entries = cls._get_entries(assignment)

        if not append:
            entries = cls._resolve_entries(entries, help_data)
        else:
            entries.extend(help_data)

        entries = [
            tree.PythonNode("atom", [
                tree.Operator("[", (0, 0)), entry,
                tree.Operator("]", (0, 0))
            ]) for entry in entries
        ]
        entries = _separate_with_commas(entries)

        node = tree.PythonNode(
            "atom",
            [tree.Operator("[", (0, 0))] + entries +
            [tree.Operator(",", (0, 0)),
             tree.Operator("]", (0, 0))],
        )

        node = _apply_formatting(node)

        graph = convention.insert_or_append(node, graph, assignment, "help")

        return graph.get_code()