-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathutils.py
More file actions
125 lines (102 loc) · 4.03 KB
/
utils.py
File metadata and controls
125 lines (102 loc) · 4.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
from flask import jsonify
from typing import get_origin, get_args, Any, Union, Literal
from datetime import datetime, timezone
def dict_to_xml(data: dict) -> str:
"""딕셔너리를 XML 문자열로 변환합니다.
Args:
data: 변환할 딕셔너리
Returns:
str: XML 형식의 문자열
"""
xml_parts = []
for key, value in data.items():
if isinstance(value, datetime):
# Ensure UTC and ISO format
text = value.astimezone(timezone.utc).isoformat()
else:
text = str(value)
xml_parts.append(f'<{key}>{text}</{key}>')
return ''.join(xml_parts)
def is_valid_type(value, expected_type):
origin = get_origin(expected_type)
args = get_args(expected_type)
if origin is Union:
# Union 타입 처리: 여러 타입 중 하나라도 만족하면 True
return any(is_valid_type(value, arg) for arg in args)
elif origin is Literal:
# Literal 타입: 고정된 값 중 하나여야 함
return value in args
elif origin is list:
if not isinstance(value, list):
return False
if args: # e.g. list[str]
return all(is_valid_type(item, args[0]) for item in value)
return True
elif origin is dict:
if not isinstance(value, dict):
return False
if args: # e.g. dict[str, int]
key_type, value_type = args
return all(is_valid_type(k, key_type) and is_valid_type(v, value_type)
for k, v in value.items())
return True
elif origin is tuple:
if not isinstance(value, tuple):
return False
if args:
return all(is_valid_type(v, t) for v, t in zip(value, args))
return True
elif isinstance(expected_type, type):
return isinstance(value, expected_type)
return False
def confirm_request(data: dict, required: dict[str, Any]):
if not data:
return jsonify({"error": "Please provide JSON request body."}), 400
for key, expected_type in required.items():
if key not in data:
return jsonify({"error": f"Please provide '{key}' field in the JSON request body."}), 400
if not is_valid_type(data[key], expected_type):
return jsonify({
"error": f"Field '{key}' has invalid datatype or value. "
f"Expected {expected_type}, got {data[key]!r} ({type(data[key]).__name__})"
}), 400
return None
def compare_dicts_sorted(
dict1: dict[str, list[int]],
dict2: dict[str, list[int]]
) -> bool:
"""두 개의 딕셔너리를 비교해서 원소가 완벽히 동일하면 참을, 그렇지 않으면 거짓을 반환하는 함수."""
# 두 딕셔너리의 키 집합이 동일한지 확인
if set(dict1.keys()) != set(dict2.keys()):
return False
# 각 키별로 정렬된 리스트를 비교 (중복을 고려)
for key in dict1:
if sorted(dict1[key]) != sorted(dict2[key]):
return False
return True
import requests
def request_api(**request_kwargs):
"""간단한 API 요청 함수."""
if request_kwargs.get('method') == "GET":
return requests.get(request_kwargs.get('url'), params=request_kwargs['params'])
elif request_kwargs.get('method') == "POST":
return requests.post(request_kwargs.get('url'), json=request_kwargs['data'])
else:
return requests.models.Response()
class ApiResponse:
def __init__(self, response):
self.status_code = response.status_code
try:
self.data = response.json()
except Exception as e:
self.data = response.reason
def __repr__(self):
string = f"status: {self.status_code}\nresponse:"
if isinstance(self.data, dict):
for key, value in self.data.items():
string += f"\n\t{key}: {value}"
else:
string += f"\t{self.data}"
return string
def api_test(**request_kwargs):
return ApiResponse(request_api(**request_kwargs))