Beispiel #1
0
    def _extract_decorator_node(self, model_name: str, model: ModelDefinition,
                                node: ast.Call):
        decorator_name = next(iter_name(node.func, reverse=True), None)

        if decorator_name not in FIELD_DECORATORS and decorator_name != "returns":
            return

        if (decorator_name == "returns" and len(node.args) >= 1
                and is_string_node(node.args[0])):
            model_name = get_string_node_value(node.args[0])
            if model_name != "self":
                yield _model_ref(
                    model.addon,
                    model.path,
                    ASTNodePosition.from_node(node.args[0]).start_pos_col_1,
                    model_name,
                )
                return

        for arg in node.args:
            if not is_string_node(arg):
                continue
            field_name = get_string_node_value(arg).split(".")[0]
            if field_name:
                yield ExternalIDReference(
                    model.addon,
                    UNKNOWN,
                    _field_record_id(model.addon.odoo_version, model_name,
                                     field_name),
                    "ir.model.fields",
                    Location(model.path,
                             ASTNodePosition.from_node(arg).start_pos_col_1),
                )
Beispiel #2
0
 def from_collection(node: typing.Union[ast.List, ast.Tuple]):
     for key, position in _iter_selection_keys(node):
         yield ExternalID(
             field.model.addon,
             field.model.addon.name,
             _selection_key_id(model_name, field.name, key),
             "ir.model.fields.selection",
             Location(field.model.path, position),
         )
Beispiel #3
0
 def on_addon(self, addon: Addon):
     # This is a special case, automatically created for all addons:
     # https://git.io/JeqKX.
     yield ExternalID(
         addon,
         "base",
         f"module_{addon.name}",
         "ir.module.module",
         Location(addon.path),
     )
Beispiel #4
0
    def on_csv_row(self, csv_row: CSVRow):
        model = csv_row.path.stem
        addon, path, row = csv_row.addon, csv_row.path, csv_row.row

        yield ExternalIDReference(addon, UNKNOWN, _model_record_id(model),
                                  "ir.model", Location(path))

        if path not in self._csv_external_id_fields:
            for field_name in row:
                if (field_name.split(":")[-1] == "id"
                        or field_name.split("/")[-1] == "id"):
                    self._csv_external_id_fields[path].add(field_name)

                # Add references to fields from the CSV file header.
                field_external_id = _field_record_id(
                    addon.odoo_version,
                    model,
                    (field_name[:-3] if field_name.endswith(
                        (":id", "/id")) else field_name),
                )
                yield ExternalIDReference(
                    addon,
                    UNKNOWN,
                    field_external_id,
                    "ir.model.fields",
                    Location(path, Position(1)),
                )

        for field_name in self._csv_external_id_fields[path]:
            # TODO: Add support for KNOWN_FIELD_MODELS.
            for external_id in _csv_split_external_id(csv_row.row[field_name]):
                addon_name, record_id = split_external_id(external_id)
                cls_ = ExternalID if field_name == "id" else ExternalIDReference
                yield cls_(
                    csv_row.addon,
                    addon_name,
                    record_id,
                    model if field_name == "id" else UNKNOWN,
                    Location(csv_row.path, Position(csv_row.line_no)),
                )
Beispiel #5
0
def _ref_or_def(addon, filename, position: typing.Union[int,
                                                        Position], external_id,
                model) -> typing.Union[ExternalID, ExternalIDReference]:
    addon_name, record_id = split_external_id(external_id)
    cls_ = ExternalIDReference
    if not addon_name or addon_name == addon.name:
        cls_ = ExternalID
    return cls_(
        addon,
        addon_name,
        record_id,
        model,
        Location(
            filename,
            Position(position) if isinstance(position, int) else position),
    )
Beispiel #6
0
def _ref(
    addon,
    filename,
    position: typing.Union[int, Position],
    external_id,
    model,
    unknown_addon=False,
) -> ExternalIDReference:
    addon_name, record_id = split_external_id(external_id)
    return ExternalIDReference(
        addon,
        UNKNOWN if unknown_addon else addon_name,
        record_id,
        model,
        Location(
            filename,
            Position(position) if isinstance(position, int) else position),
    )
Beispiel #7
0
 def _extract_sql_constraint(self, model_name: str, model: ModelDefinition):
     for name, node in iter_model_params(model.node):
         if name != "_sql_constraints" or not isinstance(
                 node, SQL_CONSTRAINT_NODES):
             continue
         for constraint in node.elts:
             if (isinstance(constraint, SQL_CONSTRAINT_NODES)
                     and len(constraint.elts) == 3
                     and is_string_node(constraint.elts[0])):
                 constraint_name = get_string_node_value(constraint.elts[0])
                 position = ASTNodePosition.from_node(
                     constraint.elts[0]).start_pos_col_1
                 yield ExternalID(
                     model.addon,
                     model.addon.name,
                     _constraint_id(model_name, constraint_name),
                     "ir.model.constraint",
                     Location(model.path, position),
                 )
Beispiel #8
0
    def _extract_xml_record(self, addon, filename, tree):
        # <record> operation.
        for record in tree.xpath("//record"):
            record_model, record_id = record.attrib["model"], record.get("id")
            if record_model:
                yield _model_ref(addon, filename, record.sourceline,
                                 record_model)
            if record_id:
                yield _ref_or_def(addon, filename, record.sourceline,
                                  record_id, record_model)

            # <field> operation.
            for field in record.iterchildren(tag="field"):
                field_name = field.attrib["name"]

                field_external_id = _field_record_id(addon.odoo_version,
                                                     record_model, field_name)
                yield ExternalIDReference(
                    addon,
                    UNKNOWN,
                    field_external_id,
                    "ir.model.fields",
                    Location(filename, Position(field.sourceline)),
                )

                ref = field.get("ref")
                if ref:
                    ref_model = KNOWN_FIELD_MODELS.get(record_model, {}).get(
                        field_name, UNKNOWN)
                    yield _ref(addon, filename, field.sourceline, ref,
                               ref_model)

                for attr_name in ("eval", "search"):
                    yield from self._get_ref_from_eval(addon, filename,
                                                       field.sourceline,
                                                       field.get(attr_name))

            # View-specific tags.
            if record_model != "ir.ui.view":
                continue

            arch = _get_view_arch(record)
            if arch is None:
                continue

            for button in arch.xpath(".//button[@type='action' and @name]"):
                button_name = button.get("name")
                if button_name:
                    yield _ref(
                        addon,
                        filename,
                        button.sourceline,
                        remove_old_style_format(button_name),
                        # Find out if we can have a model here.
                        UNKNOWN,
                    )

            for el in arch.xpath(".//*[@groups]"):
                groups = el.get("groups")
                for group in split_groups(groups):
                    yield _ref(addon, filename, el.sourceline, group,
                               "res.groups")