#!/usr/bin/env python
# coding: utf-8
# Copyright (c) 2026 Huawei Technologies Co., Ltd.
# openUBMC is licensed under Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#         http://license.coscl.org.cn/MulanPSL2
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.

import re
import html
from collections import defaultdict
from typing import Optional, Tuple, Dict, Union, List

from .base import BaseValidator


class ServiceValidator(BaseValidator):
    """Redfish Service 服务验证器"""

    @property
    def name(self) -> str:
        return "service"

    @property
    def package_name(self) -> str:
        """包名 - Service validator 使用完整包名"""
        return "redfish_service_validator"

    @property
    def supported_formats(self) -> list:
        """支持的解析格式：html"""
        return ["html"]

    def _print_txt_summary(self, lines: list, result_counter: dict):
        """
        美化输出TXT摘要信息到shell
        :param lines: TXT文件行列表
        :param result_counter: 结果统计计数器
        """
        # 提取关键信息
        target_uri = ""
        redfish_version = ""
        service_description = ""

        for line in lines:
            if "Target URI:" in line:
                target_uri = line.split("Target URI:")[-1].strip()
            elif "Redfish Version of Service:" in line:
                redfish_version = line.split("Redfish Version of Service:")[-1].strip()
            elif "Description of service:" in line:
                service_description = line.split("Description of service:")[-1].strip()

        # 输出美化的摘要
        print("\n" + "=" * 60)
        print(" " * 12 + "Redfish Service 校验结果报告")
        print("=" * 60)

        if target_uri:
            print(f"\n目标 URI: {target_uri}")
        if service_description:
            print(f"服务描述: {service_description}")
        if redfish_version:
            print(f"Redfish 版本: {redfish_version}")

        print(f"\n测试统计:")
        print(f"   [PASS] 通过: {result_counter.get('pass', 0)}")
        print(f"   [FAIL] 失败: {result_counter.get('fail', 0)}")
        print(f"   [WARN] 警告: {result_counter.get('warn', 0)}")

        total = sum([result_counter.get(k, 0) for k in ['pass', 'fail', 'warn']])
        if total > 0:
            pass_rate = (result_counter.get('pass', 0) / total) * 100
            print(f"\n通过率: {pass_rate:.1f}%")

        print("=" * 60 + "\n")

    def _filter_error_warning_blocks(self, block: str, ignore_types: list) -> str:
        """
        过滤 URI 块中的 error 或 warning 块
        :param block: URI 块内容
        :param ignore_types: 忽略类型列表，支持 ["error"]、["warning"]、["not_tested"] 或组合
        :return: 过滤后的块

        说明：
        - error/warning: 过滤对应块 + 移除标题栏计数显示
        - not_tested: 仅移除标题栏计数显示，不过滤块
        """
        filtered_block = block

        if "error" in ignore_types:
            # 过滤 error 块：<tr><td class="fail log">...</td></tr>
            pattern = r'<tr>\s*<td class="fail log">.*?</td>\s*</tr>'
            filtered_block = re.sub(pattern, '', filtered_block, flags=re.DOTALL)

        if "warning" in ignore_types:
            # 过滤 warning 块：<tr><td class="warn log">.*?</td>\s*</tr>
            pattern = r'<tr>\s*<td class="warn log">.*?</td>\s*</tr>'
            filtered_block = re.sub(pattern, '', filtered_block, flags=re.DOTALL)

        # 过滤标题栏中的 error/warning/not_tested 计数显示
        # not_tested 格式：<div><b>not_tested:</b>5</div>
        if "error" in ignore_types or "warning" in ignore_types or "not_tested" in ignore_types:
            def remove_count_divs(match):
                td_content = match.group(0)
                # 移除 <div class="fail">...</div> (error 相关)
                if "error" in ignore_types:
                    td_content = re.sub(r'<div class="fail">.*?</div>', '', td_content, flags=re.DOTALL)
                # 移除 <div class="warn">...</div> (warning 相关)
                if "warning" in ignore_types:
                    td_content = re.sub(r'<div class="warn">.*?</div>', '', td_content, flags=re.DOTALL)
                # 移除 <div><b>not_tested:</b>5</div>
                if "not_tested" in ignore_types:
                    td_content = re.sub(r'<div><b>not_tested:\s*</b>\s*\d+\s*</div>', '', td_content)
                # 如果 td 内容为空，返回空的 td
                if re.match(r'<td[^>]*>\s*</td>', td_content):
                    return '<td></td>'
                return td_content

            # 匹配包含 error/warning/not_tested 计数的 td
            pattern = r'<td[^>]*>(<div class="fail">.*?</div>|<div[^>]*><b>pass:.*?</div>|<div class="warn">.*?</div>|<div><b>not_tested:.*?</div>)+</td>'
            filtered_block = re.sub(pattern, remove_count_divs, filtered_block, flags=re.DOTALL)

        return filtered_block

    def _find_uri_block_end(self, html_str: str, start: int) -> int:
        """找到 URI 块的结束位置"""
        # URI 块从 <th class="titlerow bluebg"> 开始
        # 到下一个 <th class="titlerow bluebg"> 或 </body></html> 结束
        next_uri = html_str.find('<th class="titlerow bluebg">', start + 1)
        body_end = html_str.find('</body>', start)
        table_end = html_str.find('</table></body>', start)

        candidates = []
        if next_uri != -1:
            candidates.append(next_uri)
        if body_end != -1:
            candidates.append(body_end)
        if table_end != -1:
            candidates.append(table_end)

        return min(candidates) if candidates else len(html_str)

    def _filter_properties(self, uri_block: str, excluded_names: list, result_counter: dict) -> str:
        """
        过滤 URI 块中的特定属性检查
        :param uri_block: URI 块内容
        :param excluded_names: 要排除的属性名列表
        :param result_counter: 结果计数器
        :return: 过滤后的 URI 块
        """

        excluded_names_lower = [name.lower() for name in excluded_names]
        excluded_count = 0

        # 属性检查格式: <tr><td>Name</td><td>Value</td><td>Type</td><td>Exists</td><td class="pass center">PASS</td></tr>
        # 使用正则表达式找到所有属性检查行
        row_pattern = r'<tr>(<td>[^<]+</td><td[^>]*>.*?</td><td[^>]*>.*?</td><td[^>]*>.*?</td><td class="(pass|fail|warn|log)\s*center"[^>]*>.*?</td></tr>)'

        def replace_row(match):
            nonlocal excluded_count
            row_content = match.group(1)
            result_type = match.group(2)
            # 提取属性名
            name_match = re.search(r'<td>([^<]+)</td>', row_content)
            if name_match:
                name = name_match.group(1).strip()
                if name.lower() in excluded_names_lower:
                    excluded_count += 1
                    return ''  # 删除这一行
                else:
                    result_counter[result_type] += 1
                    return match.group(0)
            return match.group(0)

        filtered_block = re.sub(row_pattern, replace_row, uri_block, flags=re.DOTALL)

        # 统计剩余结果
        for result_type in ['pass', 'fail', 'warn', 'log']:
            pattern = f'<td class="{result_type}\\s*center"'
            result_counter[result_type] += len(re.findall(pattern, filtered_block))

        return filtered_block

    def _count_results_in_string(self, text: str, result_counter: dict):
        """统计字符串中的结果"""

        # 统计属性检查结果
        for result_type in ['pass', 'fail', 'warn', 'log']:
            pattern = f'<td class="{result_type}\\s*center"'
            result_counter[result_type] += len(re.findall(pattern, text))

        # 统计错误/通过/警告汇总
        summary_pattern = r'<div class="(pass|fail|warn)"><b>(?:error|pass|warn)?:\s*</b>\s*(\d+)'
        for match in re.finditer(summary_pattern, text):
            result_type = match.group(1)
            count = int(match.group(2))
            result_counter[result_type] += count

    def parse_tsv_excluded(self, file_path: str, white_list: Optional[dict] = None):
        raise NotImplementedError("Service validator TSV 解析尚未实现")

    def parse_html_excluded(self, file_path: str, white_list: Optional[Dict[str, Union[List, Dict]]] = None) -> Tuple[str, dict]:
        """
        解析HTML文件并返回过滤后的内容和统计结果
        :param file_path: HTML文件路径
        :param white_list: 白名单字典，格式：
                          {URI: [Name列表]} - 精确过滤对应行
                          {URI: {"Ignore": ["error", "warning", "not_tested"]}} - 过滤
                          {URI: {"Ignore": [...], "Names": [...]}} - 同时过滤
                          URI 支持正则表达式（包含 .*()[]{}$+?|\\\\ 等特殊字符时自动识别）
        :return: (过滤后的HTML内容, 统计结果字典)

        白名单规则：
        1. 仅配置 URI：过滤掉整个块（支持正则表达式）
        2. 配置 URI 和 Name 列表：精确过滤对应行（URI 支持正则表达式）
        3. 配置 URI 和 Ignore：
           - error/warning: 过滤对应块 + 移除标题栏计数显示
           - not_tested: 仅移除标题栏计数显示，不过滤块
        4. 配置 URI、Name 和 Ignore：先过滤 error/warning 块，再过滤匹配的 Name 行
        """
        if white_list is None:
            white_list = {}

        result_counter = defaultdict(int)
        filtered_uri_count = 0
        filtered_name_count = 0
        filtered_error_count = 0
        filtered_warning_count = 0
        filtered_not_tested_count = 0

        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                html_content = f.read()

            # 构建过滤规则
            # uri_only_rules: 只有 URI 的规则，过滤整个 URI 测试结果（精确匹配）
            # uri_only_patterns: URI 正则表达式模式，过滤整个 URI 测试结果
            # uri_combined_rules: URI 对应的规则，包含 names 和 ignore（精确匹配）
            # uri_combined_patterns: URI 正则表达式对应的规则，包含 names 和 ignore
            uri_only_rules = []
            uri_only_patterns = []
            uri_combined_rules = {}
            uri_combined_patterns = []

            for uri, rule in white_list.items():
                # 检查是否是正则表达式（包含特殊字符）
                is_regex = any(c in uri for c in ['.*', '(', ')', '[', ']', '{', '}', '^', '$', '+', '?', '|', '\\'])

                if isinstance(rule, dict) and "Ignore" in rule:
                    # 字典格式，可能包含 Ignore 和 Names
                    ignore = [item.lower() for item in rule["Ignore"]]
                    names = rule.get("Names", [])
                    rule_data = {"pattern": uri, "names": names, "ignore": ignore}

                    if is_regex:
                        uri_combined_patterns.append(rule_data)
                    else:
                        uri_combined_rules[uri] = {"names": names, "ignore": ignore}
                elif isinstance(rule, list):
                    # 列表格式，只包含 Name
                    rule_data = {"pattern": uri, "names": rule, "ignore": []}

                    if is_regex:
                        uri_combined_patterns.append(rule_data)
                    else:
                        uri_combined_rules[uri] = {"names": rule, "ignore": []}
                else:
                    # 只有 URI，过滤整个块
                    if is_regex:
                        uri_only_patterns.append(uri)
                    else:
                        uri_only_rules.append(uri)

            # HTML 是单行格式，需要用字符串处理
            # 找到所有 URI 块的起始位置
            # URI 标题格式（有 response time）:
            #   <th class="titlerow bluebg"><b>URI (response time ...)</b></th>
            #   <th class="titlerow bluebg"><b>URI (response time ...)Extra</b></th>
            #   <th class="titlerow bluebg">URI (response time ...)Extra</th>
            # URI 标题格式（无 response time）:
            #   <th class="titlerow bluebg"><b>URI</b></th>
            #   <th class="titlerow bluebg">URI</th>
            uri_pattern = r'<th class="titlerow bluebg"><b>([^<]+?)\s*(?:\(response time[^)]*\))?</b></th>|<th class="titlerow bluebg">(.*?)\s*(?:\([^)]*\))?(?:&ensp;[^<]*)?</th>'

            # 找到所有匹配的 URI 块
            filtered_parts = []
            last_end = 0

            for match in re.finditer(uri_pattern, html_content):
                # 添加前面的内容
                filtered_parts.append(html_content[last_end:match.start()])

                # 从两个可能的捕获组中提取 URI
                uri = match.group(1) if match.group(1) else match.group(2)
                if uri is None:
                    continue
                uri = uri.strip()
                # 清理 URI 中的 HTML 实体
                uri = uri.replace('&ensp;', ' ').replace('&nbsp;', ' ')
                uri = uri.strip()
                # 移除 response time 和额外文本
                uri = re.sub(r'\s*\(response time[^)]*\).*', '', uri).strip()

                block_start = match.start()
                block_end = self._find_uri_block_end(html_content, block_start)

                uri_block = html_content[block_start:block_end]

                # 检查 URI 是否匹配任何规则
                matched_rule = None
                matched_by_regex = False

                # 1. 检查精确匹配的 URI 过滤规则
                if uri in uri_only_rules:
                    filtered_uri_count += 1
                    last_end = block_end
                    continue  # 跳过此 URI 块
                # 2. 检查精确匹配的 URI 组合规则
                elif uri in uri_combined_rules:
                    matched_rule = uri_combined_rules[uri]
                # 3. 检查正则表达式匹配的 URI 过滤规则
                else:
                    for pattern in uri_only_patterns:
                        if re.search(pattern, uri):
                            filtered_uri_count += 1
                            matched_by_regex = True
                            break
                    if matched_by_regex:
                        last_end = block_end
                        continue  # 跳过此 URI 块
                    # 4. 检查正则表达式匹配的 URI 组合规则
                    if not matched_rule:
                        for rule_data in uri_combined_patterns:
                            if re.search(rule_data["pattern"], uri):
                                matched_rule = rule_data
                                matched_by_regex = True
                                break

                # 应用组合规则
                if matched_rule:
                    ignore_types = matched_rule.get("ignore", [])
                    matching_names = matched_rule.get("names", [])

                    # 如果 names 和 ignore 都为空，过滤整个 URI 块
                    if not ignore_types and not matching_names:
                        filtered_uri_count += 1
                        last_end = block_end
                        continue

                    # 先过滤 error/warning 块
                    if ignore_types:
                        uri_block = self._filter_error_warning_blocks(uri_block, ignore_types)
                        if "error" in ignore_types:
                            filtered_error_count += 1
                        if "warning" in ignore_types:
                            filtered_warning_count += 1
                        if "not_tested" in ignore_types:
                            filtered_not_tested_count += 1

                    # 再过滤匹配的 Name 行
                    # Service 属性检查格式:
                    # - <tr><td>Name</td><td>Value</td><td>Type</td><td>Exists</td><td class="pass center">PASS</td></tr>
                    # - <tr><td>Name</td><td>Value</td><td>Type</td><td>Exists</td><td class="center">OK</td></tr>
                    if matching_names:
                        row_pattern = r'(<tr>(<td>[^<]+</td>)<td[^>]*>.*?</td><td[^>]*>.*?</td><td[^>]*>.*?</td><td class="(?:pass|fail|warn|log)?\s*center"[^>]*>.*?</td></tr>)'

                        def filter_row(row_match):
                            nonlocal filtered_name_count
                            full_row = row_match.group(1)
                            name_cell = row_match.group(2)
                            # 提取属性名，并解码 HTML 实体（支持 # / 等特殊字符）
                            name_match = re.search(r'<td>([^<]+)</td>', name_cell)
                            if name_match:
                                match_name = html.unescape(name_match.group(1).strip())
                                if match_name in matching_names:
                                    filtered_name_count += 1
                                    return ""
                            return full_row

                        uri_block = re.sub(row_pattern, filter_row, uri_block, flags=re.DOTALL)
                        if filtered_name_count > 0:
                            print(f"    URI {uri}: 过滤了 {filtered_name_count} 个属性")

                    filtered_parts.append(uri_block)
                else:
                    # 不过滤，直接保留
                    filtered_parts.append(uri_block)

                last_end = block_end

            # 添加剩余内容
            filtered_parts.append(html_content[last_end:])

            filtered_html = ''.join(filtered_parts)

            # 统计结果：遍历所有剩余的 URI 块，累加每个块中的 pass/fail/warning 计数
            # 先找到所有 URI 块
            uri_header_pattern = r'<th class="titlerow bluebg">(?:<b>)?([^<]+?)(?:</b>)?.*?</th>'
            uri_headers = list(re.finditer(uri_header_pattern, filtered_html))

            for uri_match in uri_headers:
                uri_start = uri_match.end()
                # 找到 URI 块的结束位置
                next_uri = filtered_html.find('<th class="titlerow bluebg">', uri_start)
                if next_uri == -1:
                    next_uri = len(filtered_html)
                uri_block = filtered_html[uri_start:next_uri]

                # 在该 URI 块中查找 pass/fail/warning 计数
                # 支持多种格式：
                # - <div class="pass"><b>pass: </b>8</div>
                # - <div><b>pass: </b>8</div>
                # - <td class="pass center">PASS</td>
                pass_match = re.search(r'<b>pass:\s*</b>\s*(\d+)', uri_block, re.IGNORECASE)
                if pass_match:
                    result_counter["pass"] += int(pass_match.group(1))

                error_match = re.search(r'<b>error:\s*</b>\s*(\d+)', uri_block, re.IGNORECASE)
                if error_match:
                    result_counter["error"] += int(error_match.group(1))

                warning_match = re.search(r'<b>warning?:\s*</b>\s*(\d+)', uri_block, re.IGNORECASE)
                if warning_match:
                    result_counter["warning"] += int(warning_match.group(1))

                # 统计属性检查结果（如果没有找到计数 div）
                if not pass_match and not error_match and not warning_match:
                    # 统计 <td class="pass center">、<td class="fail center"> 等
                    result_counter["pass"] += len(re.findall(r'<td class="pass center"', uri_block))
                    result_counter["fail"] += len(re.findall(r'<td class="fail center"', uri_block))
                    result_counter["warn"] += len(re.findall(r'<td class="warn center"', uri_block))

            # fail 值等于 error 值
            result_counter["fail"] = result_counter.get("error", 0)
            # warn 值等于 warning 值
            result_counter["warn"] = result_counter.get("warning", 0)

            # fail 值等于 error 值
            result_counter["fail"] = result_counter.get("error", 0)
            # warn 值等于 warning 值
            result_counter["warn"] = result_counter.get("warning", 0)

            # 更新 Results Summary
            summary_pattern = r'<div><b>Results Summary</b></div><div>Pass:\s*(\d+),\s*Fail:\s*(\d+),\s*Warning:\s*(\d+)</div>'
            summary_match = re.search(summary_pattern, filtered_html)
            if summary_match:
                pass_count = result_counter.get("pass", 0)
                fail_count = result_counter.get("fail", 0)
                warning_count = result_counter.get("warn", 0)

                new_summary = f'<div><b>Results Summary</b></div><div>Pass: {pass_count}, Fail: {fail_count}, Warning: {warning_count}</div>'
                filtered_html = filtered_html[:summary_match.start()] + new_summary + filtered_html[summary_match.end():]
                print(f"  更新 Results Summary: Pass={pass_count}, Fail={fail_count}, Warning={warning_count}")

            filter_msg = f"  过滤掉 {filtered_uri_count} 个 URI，{filtered_name_count} 个匹配行"
            if filtered_error_count > 0:
                filter_msg += f"，{filtered_error_count} 个 error 块"
            if filtered_warning_count > 0:
                filter_msg += f"，{filtered_warning_count} 个 warning 块"
            if filtered_not_tested_count > 0:
                filter_msg += f"，{filtered_not_tested_count} 个 not_tested 计数"
            print(filter_msg)

            return filtered_html, dict(result_counter)

        except FileNotFoundError:
            print(f"错误：找不到文件 {file_path}")
            return '', dict(result_counter)
        except Exception as e:
            print(f"解析HTML文件时出错：{str(e)}")
            import traceback
            traceback.print_exc()
            return '', dict(result_counter)

    def get_mapped_args(self) -> dict:
        """返回参数映射字典，将通用参数映射到 service 特定参数"""
        return {
            "user": "--username",
            "rhost": "--ip"
        }

    def process_txt_files(self, input_dir: str, output_dir: str, result_counter: dict):
        """
        处理并美化TXT格式文件（Service 特有）
        :param input_dir: 输入目录
        :param output_dir: 输出目录
        :param result_counter: 结果统计计数器
        """
        import os

        txt_files = [os.path.join(input_dir, f) for f in os.listdir(input_dir) if f.startswith('ConformanceLog') and f.endswith('.txt')]

        if not txt_files:
            return

        print(f"\n找到 {len(txt_files)} 个TXT文件")

        for txt_file in txt_files:
            filename = os.path.basename(txt_file)
            print(f"正在处理: {filename}")

            try:
                with open(txt_file, 'r', encoding='utf-8') as f:
                    lines = f.readlines()

                # 更新统计值
                updated_lines = []
                for line in lines:
                    # 查找并更新 Results Summary 行
                    if 'Pass:' in line and 'Fail:' in line and 'Warning:' in line:
                        pass_count = result_counter.get("pass", 0)
                        fail_count = result_counter.get("fail", 0)
                        warning_count = result_counter.get("warn", 0)

                        # 保留前缀（如 "INFO - "）
                        prefix_match = re.match(r'^(INFO -\s*)', line)
                        prefix = prefix_match.group(1) if prefix_match else ''

                        updated_line = f'{prefix}Pass: {pass_count}, Fail: {fail_count}, Warning: {warning_count}\n'
                        updated_lines.append(updated_line)
                    else:
                        updated_lines.append(line)

                # 写入输出文件
                output_txt_path = os.path.join(output_dir, filename)
                with open(output_txt_path, 'w', encoding='utf-8') as f:
                    f.writelines(updated_lines)
                print(f"  已保存到 {output_txt_path}")

                # 美化输出到 shell
                self._print_txt_summary(updated_lines, result_counter)

            except Exception as e:
                print(f"  处理TXT文件时出错：{str(e)}")

    def build_run_args(self, args) -> list:
        """
        构建 service 校验器特有的运行参数
        :param args: 参数对象
        :return: 参数列表
        """
        cmd_args = []
        if hasattr(args, 'verbose') and args.verbose:
            cmd_args.extend(["-" + "v" * args.verbose])
        if hasattr(args, 'config') and args.config:
            cmd_args.extend(["--config", args.config])
        if hasattr(args, 'description') and args.description:
            cmd_args.extend(["--description", args.description])
        if hasattr(args, 'forceauth') and args.forceauth:
            cmd_args.append("--forceauth")
        if hasattr(args, 'authtype') and args.authtype:
            cmd_args.extend(["--authtype", args.authtype])
        if hasattr(args, 'token') and args.token:
            cmd_args.extend(["--token", args.token])
        if hasattr(args, 'ext_http_proxy') and args.ext_http_proxy:
            cmd_args.extend(["--ext_http_proxy", args.ext_http_proxy])
        if hasattr(args, 'ext_https_proxy') and args.ext_https_proxy:
            cmd_args.extend(["--ext_https_proxy", args.ext_https_proxy])
        if hasattr(args, 'serv_http_proxy') and args.serv_http_proxy:
            cmd_args.extend(["--serv_http_proxy", args.serv_http_proxy])
        if hasattr(args, 'serv_https_proxy') and args.serv_https_proxy:
            cmd_args.extend(["--serv_https_proxy", args.serv_https_proxy])
        if hasattr(args, 'payload') and args.payload:
            for p in args.payload:
                if isinstance(p, list):
                    cmd_args.extend(["--payload"] + p)
                else:
                    cmd_args.extend(["--payload", p])
        if hasattr(args, 'logdir') and args.logdir:
            cmd_args.extend(["--logdir", args.logdir])
        if hasattr(args, 'nooemcheck') and args.nooemcheck:
            cmd_args.append("--nooemcheck")
        if hasattr(args, 'debugging') and args.debugging:
            cmd_args.append("--debugging")
        if hasattr(args, 'uricheck') and args.uricheck:
            cmd_args.append("--uricheck")
        if hasattr(args, 'schema_directory') and args.schema_directory:
            cmd_args.extend(["--schema_directory", args.schema_directory])
        if hasattr(args, 'mockup') and args.mockup:
            cmd_args.extend(["--mockup", args.mockup])
        if hasattr(args, 'collectionlimit') and args.collectionlimit:
            cmd_args.extend(["--collectionlimit"] + list(args.collectionlimit))
        if hasattr(args, 'requesttimeout') and args.requesttimeout:
            cmd_args.extend(["--requesttimeout", str(args.requesttimeout)])
        if hasattr(args, 'requestattempts') and args.requestattempts:
            cmd_args.extend(["--requestattempts", str(args.requestattempts)])
        return cmd_args
