# -*- coding: utf-8 -*- import logging import re from typing import Dict, Any, Tuple import json logger = logging.getLogger(__name__) def is_camel_case(s: str) -> bool: """ 检查字符串是否为小驼峰式命名 (lowerCamelCase)。 小驼峰式命名要求: 1. 以小写字母开头。 2. 后续可以跟字母或数字。 3. 不能包含下划线或短横线。 """ if not s or not isinstance(s, str): return False # 检查是否以小写字母开头,并且不包含下划线或中划线 return re.match(r'^[a-z]+([A-Z0-9][a-z0-9]*)*$', s) is not None def extract_json_from_response(response: Any) -> Tuple[Any, str]: """ 从API响应中安全地提取JSON数据。 这个响应可以是一个 requests.Response 对象,也可以是一个字典(模拟的响应)。 """ if hasattr(response, 'json'): # 类似 requests.Response 对象 try: return response.json(), "" except json.JSONDecodeError as e: return None, f"JSON解析失败: {e}" except Exception as e: return None, f"从响应中提取JSON时发生未知错误: {e}" elif isinstance(response, dict): # 模拟的响应字典 return response, "" elif isinstance(response, str): try: return json.loads(response), "" except json.JSONDecodeError as e: return None, f"JSON字符串解析失败: {e}" return None, "不支持的响应类型" def format_url_with_path_params(path_template: str, path_params: Dict[str, Any]) -> str: """ 使用提供的路径参数格式化URL路径模板。 例如, path_template='/users/{userId}/items/{itemId}' path_params={'userId': 123, 'itemId': 'abc'} -> '/users/123/items/abc' Args: path_template: 包含占位符的URL路径,例如 /resource/{id}。 path_params: 包含占位符名称及其值的字典。 Returns: 格式化后的URL路径。 """ url = path_template try: # 优先使用 .format(**path_params) 如果所有占位符都能匹配 # 这要求 path_params 中的键与模板中的占位符完全对应 # url = path_template.format(**path_params) # 更简洁,但如果参数不完全匹配会报错 # 使用正则表达式逐个替换更安全,可以处理部分参数或额外参数的情况 for param_name, param_value in path_params.items(): placeholder = f"{{{param_name}}}" if placeholder in url: url = url.replace(placeholder, str(param_value)) else: # Log if a path param was provided but not found in template. Could be optional. logger.debug(f"Path parameter '{param_name}' provided but placeholder '{placeholder}' not found in template '{path_template}'.") # 检查是否还有未替换的占位符 (可选,但推荐) remaining_placeholders = re.findall(r"({[^{}]+?})", url) if remaining_placeholders: logger.warning(f"URL '{url}' 中仍有未替换的路径参数占位符: {remaining_placeholders}。原始模板: '{path_template}', 提供参数: {path_params}") except KeyError as e: logger.error(f"格式化URL路径 '{path_template}' 失败:路径参数 '{e}' 未在提供的 path_params 中找到。可用参数: {list(path_params.keys())}") # 根据需要,这里可以选择是返回原始模板还是抛出异常 # return path_template raise ValueError(f"Missing path parameter {e} for URL template {path_template}") from e except Exception as e: logger.error(f"格式化URL路径 '{path_template}' 时发生未知错误: {e}") raise # 或者返回原始模板 return url