def merge()

in src/aaz_dev/command/controller/workspace_cfg_editor.py [0:0]


    def merge(self, plus_cfg_editor):
        """
        create conditions according to the path
        expand all http-operations with merged path in the main cfg using condition for switching
        """
        if not self._can_merge(plus_cfg_editor):
            return None

        plus_operations_by_method = {}
        plus_ops_required_args = {}
        plus_resources_arg_groups = []
        for method in ['get', 'put', 'post', 'delete', 'patch']:
            for _, command in plus_cfg_editor.iter_commands_by_operations(method):
                if command.subresource_selector:
                    continue
                if method not in plus_operations_by_method:
                    plus_operations_by_method[method] = {}
                for operation in command.operations:
                    if isinstance(operation, CMDHttpOperation) and operation.http.request.method.lower() == method:
                        plus_operations_by_method[method][operation.operation_id] = operation
                plus_op_required_args, plus_op_optional_args = self._parse_command_http_op_url_args(command)
                plus_ops_required_args.update(plus_op_required_args)
                if not plus_resources_arg_groups:
                    # merge args
                    new_args = set()
                    for args in plus_op_required_args.values():
                        new_args.update(args)
                    for args in plus_op_optional_args.values():
                        new_args.update(args)
                    for arg_group in command.arg_groups:
                        arg_group = plus_cfg_editor._filter_args_in_arg_group(arg_group, new_args, copy=True)
                        if arg_group:
                            plus_resources_arg_groups.append(arg_group)
            if method in plus_operations_by_method:
                assert len(plus_operations_by_method[method]) == len(plus_cfg_editor.resources)

        main_editor = WorkspaceCfgEditor(self.cfg.__class__(self.cfg.to_primitive()))  # generate a copy of main cfg
        for _, main_command in main_editor.iter_commands():
            # create plus http operations by replace the path and query args
            merged_operations = []
            plus_operations = []
            plus_op_required_args = {}
            for operation in main_command.operations:
                if not isinstance(operation, CMDHttpOperation):
                    if plus_operations:
                        merged_operations.extend(plus_operations)
                        plus_operations = []
                    merged_operations.append(operation)
                    continue
                if plus_operations and operation.http.request.method.lower() == plus_operations[0].http.request.method.lower():
                    merged_operations.append(operation)
                    continue
                if plus_operations:
                    merged_operations.extend(plus_operations)
                    plus_operations = []
                merged_operations.append(operation)
                for operation_id, plus_operation in plus_operations_by_method[operation.http.request.method.lower()].items():
                    plus_operation = plus_operation.__class__(plus_operation.to_primitive())
                    plus_operation.http.request.header = operation.http.request.header
                    plus_operation.http.request.body = operation.http.request.body
                    plus_operation.http.responses = operation.http.responses
                    if plus_operation.http.request.method.lower() == 'get' and plus_operation.http.request.query.params:
                        # the get method in generate update command will ignore the optional query params if it's not exist in the put or patch operations.
                        # here we need to exclude them if those query params has args in the main command
                        params = []
                        for param in plus_operation.http.request.query.params:
                            arg, _ = main_editor.find_arg_in_command_by_var(main_command, arg_var=param.arg)
                            if not param.required and not arg:
                                continue
                            params.append(param)
                        plus_operation.http.request.query.params = params
                    plus_operation = plus_operation.__class__(plus_operation.to_primitive())
                    plus_operations.append(plus_operation)
                    if operation_id not in plus_op_required_args:
                        plus_op_required_args[operation_id] = plus_ops_required_args[operation_id]
            if plus_operations:
                merged_operations.extend(plus_operations)
                plus_operations = []

            # merge args
            for arg_group in plus_resources_arg_groups:
                try:
                    main_editor._command_merge_arg_group(main_command, arg_group)
                except exceptions.InvalidAPIUsage as ex:
                    logger.error(ex)
                    return None

            # create conditions
            main_op_required_args, _ = main_editor._parse_command_http_op_url_args(main_command)

            op_required_args = {**plus_op_required_args, **main_op_required_args}
            merged_required_args, merged_optional_args, main_command.conditions, main_command.operations = main_editor._merge_command_operations(
                op_required_args,
                *merged_operations
            )

            # update arg required of command
            for arg_group in main_command.arg_groups:
                for arg in arg_group.args:
                    if arg.var in merged_required_args:
                        arg.required = True
                    elif arg.var in merged_optional_args:
                        arg.required = False

            for resource in plus_cfg_editor.resources:
                resource = resource.__class__(resource.to_primitive())
                resource.subresource = main_command.resources[0].subresource # follow the main command's subresource
                main_command.resources.append(resource)

            # relink main_command
            main_command.link()

        for resource in plus_cfg_editor.resources:
            main_editor.cfg.resources.append(
                resource.__class__(resource.to_primitive())
            )

        main_editor.reformat()
        return main_editor