127 lines
3.4 KiB
Python
127 lines
3.4 KiB
Python
"""工厂模式:构造测试用模拟对象。"""
|
|
import json
|
|
|
|
from common.utils.helpers import parse_id_list
|
|
|
|
|
|
class DictItem(dict):
|
|
"""带 to_dict 的伪模型对象。"""
|
|
|
|
def to_dict(self):
|
|
return dict(self)
|
|
|
|
|
|
class FakeHandler:
|
|
"""模拟 Tornado handler(支持 get_query_argument / request.body / finish)。"""
|
|
|
|
def __init__(self, query=None, body=None):
|
|
self._query = query or {}
|
|
self.request = type("Request", (), {
|
|
"body": json.dumps(body).encode("utf-8") if body is not None else b"{}",
|
|
"path": "/api/v1/test",
|
|
"method": "POST",
|
|
})()
|
|
self.result = None
|
|
|
|
def get_query_argument(self, name, default=None):
|
|
return self._query.get(name, default)
|
|
|
|
def finish(self, result):
|
|
self.result = result
|
|
return self.result
|
|
|
|
|
|
class FakeQuery:
|
|
"""内存查询对象:支持 filter/order_by/count/all(不做真实过滤)。"""
|
|
|
|
def __init__(self, items):
|
|
self.items = list(items)
|
|
|
|
def filter(self, *criterion):
|
|
return self
|
|
|
|
def order_by(self, *cols):
|
|
return self
|
|
|
|
def all(self):
|
|
return self.items
|
|
|
|
def count(self):
|
|
return len(self.items)
|
|
|
|
|
|
class FakeRepository:
|
|
"""内存版仓储,支持 BaseService 模板方法所需原语。"""
|
|
|
|
def __init__(self, items=None):
|
|
self.items = items if items is not None else []
|
|
self._deleted = []
|
|
|
|
# ---------- 数据清洗 ----------
|
|
def _clean_model_data(self, data: dict) -> dict:
|
|
"""模拟 BaseRepository._clean_model_data:透传数据。"""
|
|
return data if data else {}
|
|
|
|
# ---------- 查询 ----------
|
|
def filter(self, *criterion):
|
|
return FakeQuery(self.items)
|
|
|
|
def filter_by(self, **kwargs):
|
|
return FakeQuery(self.items)
|
|
|
|
def get_by_id(self, pk, soft_delete=True):
|
|
try:
|
|
pk = int(pk)
|
|
except (TypeError, ValueError):
|
|
return None
|
|
for item in self.items:
|
|
if getattr(item, "id", None) == pk:
|
|
return item
|
|
return None
|
|
|
|
def get_by_ids(self, ids, soft_delete=True):
|
|
valid = [i for i in ids if isinstance(i, int) and i > 0]
|
|
return [item for item in self.items if getattr(item, "id", None) in valid]
|
|
|
|
def exists(self, obj_id=None, soft_delete=True, **filters):
|
|
if obj_id is not None:
|
|
return self.get_by_id(obj_id) is not None
|
|
return any(self.items)
|
|
|
|
def exists_by_field(self, field, value, exclude_id=None, soft_delete=True):
|
|
for item in self.items:
|
|
if getattr(item, field, None) == value and getattr(item, "id", None) != exclude_id:
|
|
return True
|
|
return False
|
|
|
|
def paginate(self, query, page=1, limit=10):
|
|
items = list(query.items)
|
|
total = len(items)
|
|
start = (page - 1) * limit
|
|
return items[start:start + limit], total
|
|
|
|
def all(self, soft_delete=True):
|
|
return list(self.items)
|
|
|
|
# ---------- 写操作 ----------
|
|
def create(self, obj):
|
|
self.items.append(obj)
|
|
return obj
|
|
|
|
def update(self, pk, data):
|
|
return True
|
|
|
|
def soft_delete(self, ids):
|
|
self._deleted.extend(ids)
|
|
return len(ids)
|
|
|
|
def batch_delete(self, ids_str):
|
|
id_list = parse_id_list(str(ids_str))
|
|
if not id_list:
|
|
return 0
|
|
self._deleted.extend(id_list)
|
|
return len(id_list)
|
|
|
|
def close(self):
|
|
pass
|