Пример #1
0
def check_param_or_command_type(ctxt: IDLCompatibilityContext,
                                old_type: Optional[Union[syntax.Enum, syntax.Struct, syntax.Type]],
                                new_type: Optional[Union[syntax.Enum, syntax.Struct, syntax.Type]],
                                cmd_name: str, old_idl_file: syntax.IDLParsedSpec,
                                new_idl_file: syntax.IDLParsedSpec, old_idl_file_path: str,
                                new_idl_file_path: str, param_name: Optional[str],
                                is_command_parameter: bool):
    """Check compatibility between old and new command parameter type or command type."""
    # pylint: disable=too-many-arguments,too-many-branches
    if old_type is None:
        ctxt.add_command_or_param_type_invalid_error(cmd_name, old_idl_file_path, param_name,
                                                     is_command_parameter)
        ctxt.errors.dump_errors()
        sys.exit(1)
    if new_type is None:
        ctxt.add_command_or_param_type_invalid_error(cmd_name, new_idl_file_path, param_name,
                                                     is_command_parameter)
        ctxt.errors.dump_errors()
        sys.exit(1)

    if isinstance(old_type, syntax.Type):
        if isinstance(new_type, syntax.Type):
            if "any" in old_type.bson_serialization_type:
                ctxt.add_old_command_or_param_type_bson_any_error(
                    cmd_name, old_type.name, old_idl_file_path, param_name, is_command_parameter)
            elif "any" in new_type.bson_serialization_type:
                ctxt.add_new_command_or_param_type_bson_any_error(
                    cmd_name, new_type.name, new_idl_file_path, param_name, is_command_parameter)

            else:
                check_superset(ctxt, cmd_name, new_type.name, new_type.bson_serialization_type,
                               old_type.bson_serialization_type, new_idl_file_path, param_name,
                               is_command_parameter)
        else:
            ctxt.add_new_command_or_param_type_enum_or_struct_error(
                cmd_name, new_type.name, old_type.name, new_idl_file_path, param_name,
                is_command_parameter)

    elif isinstance(old_type, syntax.Enum):
        if isinstance(new_type, syntax.Enum):
            check_superset(ctxt, cmd_name, new_type.name, new_type.values, old_type.values,
                           new_idl_file_path, param_name, is_command_parameter)
        else:
            ctxt.add_new_command_or_param_type_not_enum_error(cmd_name, new_type.name,
                                                              old_type.name, new_idl_file_path,
                                                              param_name, is_command_parameter)

    elif isinstance(old_type, syntax.Struct):
        if isinstance(new_type, syntax.Struct):
            check_command_params_or_type_struct_fields(
                ctxt, old_type, new_type, cmd_name, old_idl_file, new_idl_file, old_idl_file_path,
                new_idl_file_path, is_command_parameter)
        else:
            ctxt.add_new_command_or_param_type_not_struct_error(cmd_name, new_type.name,
                                                                old_type.name, new_idl_file_path,
                                                                param_name, is_command_parameter)
Пример #2
0
def check_param_or_command_type_recursive(
        ctxt: IDLCompatibilityContext, old_type: Optional[Union[syntax.Enum,
                                                                syntax.Struct,
                                                                syntax.Type]],
        new_type: Optional[Union[syntax.Enum, syntax.Struct,
                                 syntax.Type]], cmd_name: str,
        old_idl_file: syntax.IDLParsedSpec, new_idl_file: syntax.IDLParsedSpec,
        old_idl_file_path: str, new_idl_file_path: str,
        param_name: Optional[str], is_command_parameter: bool):
    # pylint: disable=too-many-arguments,too-many-branches
    """
    Check compatibility between old and new command or param type recursively.

    If the old type is a syntax.Type instance, check the compatibility between the old and new
    command type or parameter type recursively.
    """
    if not isinstance(new_type, syntax.Type):
        ctxt.add_new_command_or_param_type_enum_or_struct_error(
            cmd_name, new_type.name, old_type.name, new_idl_file_path,
            param_name, is_command_parameter)
        return

    # If bson_serialization_type switches from 'any' to non-any type.
    if "any" in old_type.bson_serialization_type and "any" not in new_type.bson_serialization_type:
        ctxt.add_old_command_or_param_type_bson_any_error(
            cmd_name, old_type.name, old_idl_file_path, param_name,
            is_command_parameter)
        return

    # If bson_serialization_type switches from non-any to 'any' type.
    if "any" not in old_type.bson_serialization_type and "any" in new_type.bson_serialization_type:
        ctxt.add_new_command_or_param_type_bson_any_error(
            cmd_name, new_type.name, new_idl_file_path, param_name,
            is_command_parameter)
        return

    allow_name: str = cmd_name + "-param-" + param_name if is_command_parameter else cmd_name

    if "any" in old_type.bson_serialization_type:
        # If 'any' is not explicitly allowed as the bson_serialization_type.
        if allow_name not in ALLOW_ANY_TYPE_LIST:
            ctxt.add_command_or_param_type_bson_any_not_allowed_error(
                cmd_name, old_type.name, old_idl_file_path, param_name,
                is_command_parameter)
            return

        if old_type.cpp_type != new_type.cpp_type:
            ctxt.add_command_or_param_cpp_type_not_equal_error(
                cmd_name, new_type.name, new_idl_file_path, param_name,
                is_command_parameter)

    if isinstance(old_type, syntax.VariantType):
        if not isinstance(new_type, syntax.VariantType):
            ctxt.add_new_command_or_param_type_not_variant_type_error(
                cmd_name, new_type.name, new_idl_file_path, param_name,
                is_command_parameter)
        else:
            new_variant_types = new_type.variant_types
            old_variant_types = old_type.variant_types

            # Check that new variant types are a superset of old variant types.
            for old_variant_type in old_variant_types:
                for new_variant_type in new_variant_types:
                    if old_variant_type.name == new_variant_type.name:
                        # Check that the old and new version of each variant type is also compatible.
                        check_param_or_command_type_recursive(
                            ctxt, old_variant_type, new_variant_type, cmd_name,
                            old_idl_file, new_idl_file, old_idl_file_path,
                            new_idl_file_path, param_name,
                            is_command_parameter)
                        break
                else:
                    # old_variant_type was not found in new_variant_types.
                    ctxt.add_new_command_or_param_variant_type_not_superset_error(
                        cmd_name, old_variant_type.name, new_idl_file_path,
                        param_name, is_command_parameter)

            # If old and new types both have a struct as a variant type, compare old and new variant_struct_type.
            # Since enums can't be part of variant types, we don't explicitly check for enums.
            if old_type.variant_struct_type is not None:
                if new_type.variant_struct_type is not None:
                    check_command_params_or_type_struct_fields(
                        ctxt, old_type.variant_struct_type,
                        new_type.variant_struct_type, cmd_name, old_idl_file,
                        new_idl_file, old_idl_file_path, new_idl_file_path,
                        is_command_parameter)

                # If old type has a variant struct type and new type does not have a variant struct type.
                else:
                    ctxt.add_new_command_or_param_variant_type_not_superset_error(
                        cmd_name, old_type.variant_struct_type.name,
                        new_idl_file_path, param_name, is_command_parameter)

    else:
        check_superset(ctxt, cmd_name, new_type.name,
                       new_type.bson_serialization_type,
                       old_type.bson_serialization_type, new_idl_file_path,
                       param_name, is_command_parameter)