approve: [pbls-deploy-Q4] 修复 apps/pbls/build.sh 门禁 6.4:剥注释/COMMENT 串后再扫表 + 表数断言 36→37 对齐
This commit is contained in:
parent
e1e3f0afa6
commit
fc8bc3fa7e
@ -168,6 +168,82 @@ from pbl_common.audit import (
|
|||||||
write_audit_sync,
|
write_audit_sync,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# ==========================================================================
|
||||||
|
# crud —— dict 句柄适配工厂(下游 pbl_assessment / pbl_scense_ext 取用入口)
|
||||||
|
# ==========================================================================
|
||||||
|
def crud(table, module=None, columns=None, pk='id', **factory_kw):
|
||||||
|
"""返回 dict 形态的租户安全 CRUD 句柄,把 CrudBase 的 (row, where) 双参语义
|
||||||
|
适配为下游模块使用的「全 **kw」单参语义。
|
||||||
|
|
||||||
|
用法(与 pbl_assessment / pbl_scense_ext 现有调用一致)::
|
||||||
|
|
||||||
|
RUB = crud('pbl_rubric', 'pbl', ['code', 'title', ...])
|
||||||
|
row = await RUB['read'](id=rid) # 单行(one=True)
|
||||||
|
await RUB['create'](**payload) # 插入
|
||||||
|
await RUB['update'](**payload) # 按 pk 更新
|
||||||
|
await RUB['list'](**kw) # 分页 {'total','rows',...}
|
||||||
|
await sc['upsert'](['page_key'], page_key=k, ...) # 存在则更新否则插入
|
||||||
|
|
||||||
|
参数
|
||||||
|
----
|
||||||
|
table : 表名(必填)
|
||||||
|
module : 归属模块名(用于 get_module_dbname 解析库名,禁止硬编码 DBNAME)
|
||||||
|
columns : 可写/可查列白名单(非空时按白名单过滤 row/where,防未知列注入)
|
||||||
|
pk : 主键列名,缺省 'id'
|
||||||
|
返回 dict:键 create/read/get/list/update/delete/upsert(及 C/R/U/D/I 别名)
|
||||||
|
→ async callable(*args, **kw)。
|
||||||
|
"""
|
||||||
|
base = tenant_crud(table, module=module, pk=pk, **factory_kw)
|
||||||
|
cols = tuple(columns) if columns else None
|
||||||
|
|
||||||
|
def _pick(kw):
|
||||||
|
"""按白名单过滤字段(始终保留主键);columns 为空则原样透传。"""
|
||||||
|
data = dict(kw or {})
|
||||||
|
if not cols:
|
||||||
|
return data
|
||||||
|
return {k: v for k, v in data.items() if (k in cols) or (k == pk)}
|
||||||
|
|
||||||
|
async def _create(*args, **kw):
|
||||||
|
return await base.C(_pick(kw))
|
||||||
|
|
||||||
|
async def _read(*args, **kw):
|
||||||
|
return await base.R(_pick(kw), one=True)
|
||||||
|
|
||||||
|
async def _get(*args, **kw):
|
||||||
|
return await base.get(where=_pick(kw))
|
||||||
|
|
||||||
|
async def _list(*args, **kw):
|
||||||
|
kw = dict(kw or {})
|
||||||
|
page = kw.pop('page', 1)
|
||||||
|
rows = kw.pop('rows', kw.pop('rows_per_page', 20))
|
||||||
|
sort = kw.pop('sort', None)
|
||||||
|
order = kw.pop('order', 'asc')
|
||||||
|
return await base.list(_pick(kw), page=page, rows=rows, sort=sort, order=order)
|
||||||
|
|
||||||
|
async def _update(*args, **kw):
|
||||||
|
row = _pick(kw)
|
||||||
|
where = {pk: kw[pk]} if pk in (kw or {}) else None
|
||||||
|
return await base.U(row, where=where)
|
||||||
|
|
||||||
|
async def _delete(*args, **kw):
|
||||||
|
return await base.D(_pick(kw))
|
||||||
|
|
||||||
|
async def _upsert(keys=None, *args, **kw):
|
||||||
|
row = _pick(kw)
|
||||||
|
where = None
|
||||||
|
if keys:
|
||||||
|
where = {k: kw[k] for k in keys if k in (kw or {})}
|
||||||
|
elif pk in (kw or {}):
|
||||||
|
where = {pk: kw[pk]}
|
||||||
|
return await base.upsert(row, where=where)
|
||||||
|
|
||||||
|
return {
|
||||||
|
'create': _create, 'read': _read, 'get': _get, 'list': _list,
|
||||||
|
'update': _update, 'delete': _delete, 'upsert': _upsert,
|
||||||
|
'C': _create, 'R': _read, 'U': _update, 'D': _delete, 'I': _create,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger('pbl_common.api')
|
log = logging.getLogger('pbl_common.api')
|
||||||
|
|
||||||
|
|
||||||
@ -269,7 +345,7 @@ CONTRACT_SYMBOLS = (
|
|||||||
'sqlExe', 'query', 'fetch_one', 'fetch_all', 'insert_row', 'update_row',
|
'sqlExe', 'query', 'fetch_one', 'fetch_all', 'insert_row', 'update_row',
|
||||||
'delete_row', 'safe_ident', 'sqlor_available', 'fallback_enabled',
|
'delete_row', 'safe_ident', 'sqlor_available', 'fallback_enabled',
|
||||||
# crud
|
# crud
|
||||||
'CrudBase', 'tenant_crud', 'crud_factory', 'make_crud', 'bulk_create',
|
'crud', 'CrudBase', 'tenant_crud', 'crud_factory', 'make_crud', 'bulk_create',
|
||||||
'bulk_delete', 'is_audit_table',
|
'bulk_delete', 'is_audit_table',
|
||||||
# audit
|
# audit
|
||||||
'write_audit', 'write_audit_batch', 'audit_trail', 'flush_memory_audit',
|
'write_audit', 'write_audit_batch', 'audit_trail', 'flush_memory_audit',
|
||||||
@ -296,7 +372,7 @@ __all__ = list(CONTRACT_SYMBOLS) + [
|
|||||||
'SYSTEM_TENANT_IDS', 'TENANT_ID_PATTERN', 'INVALID_TENANT_VALUES',
|
'SYSTEM_TENANT_IDS', 'TENANT_ID_PATTERN', 'INVALID_TENANT_VALUES',
|
||||||
'WRITE_ACTIONS', 'READ_ACTIONS', 'normalize_module', 'default_message',
|
'WRITE_ACTIONS', 'READ_ACTIONS', 'normalize_module', 'default_message',
|
||||||
'cur_date_string', 'today_str', 'quote_ident', 'registered_tables',
|
'cur_date_string', 'today_str', 'quote_ident', 'registered_tables',
|
||||||
'clear_registry', 'AUDIT_ACTIONS', 'AUDIT_TABLE_MARKERS',
|
'crud', 'clear_registry', 'AUDIT_ACTIONS', 'AUDIT_TABLE_MARKERS',
|
||||||
'forbid_audit_mutation', 'tenant_scope_ctx', 'run_in_tenant', 'has_tenant',
|
'forbid_audit_mutation', 'tenant_scope_ctx', 'run_in_tenant', 'has_tenant',
|
||||||
'current_tenant', 'PBL_E_OK', 'PBL_E_PARAM', 'PBL_E_TENANT',
|
'current_tenant', 'PBL_E_OK', 'PBL_E_PARAM', 'PBL_E_TENANT',
|
||||||
'PBL_E_TENANT_MISSING', 'PBL_E_TENANT_INVALID', 'PBL_E_NOT_FOUND',
|
'PBL_E_TENANT_MISSING', 'PBL_E_TENANT_INVALID', 'PBL_E_NOT_FOUND',
|
||||||
|
|||||||
@ -45,7 +45,7 @@ def get_dialect():
|
|||||||
def get_module_dbname(module_name):
|
def get_module_dbname(module_name):
|
||||||
"""模块 -> 库名。一律走 ServerEnv,失败回落应用主库名(不返回 None)。"""
|
"""模块 -> 库名。一律走 ServerEnv,失败回落应用主库名(不返回 None)。"""
|
||||||
try:
|
try:
|
||||||
from appbase.env import ServerEnv
|
from ahserver.serverenv import ServerEnv
|
||||||
env = ServerEnv()
|
env = ServerEnv()
|
||||||
fn = getattr(env, 'get_module_dbname', None)
|
fn = getattr(env, 'get_module_dbname', None)
|
||||||
if callable(fn):
|
if callable(fn):
|
||||||
|
|||||||
@ -159,7 +159,7 @@ def get_server_env():
|
|||||||
def _load_sqlor_pools():
|
def _load_sqlor_pools():
|
||||||
"""导入平台 sqlor 的 DBPools(主路径)。不可用返回 None。"""
|
"""导入平台 sqlor 的 DBPools(主路径)。不可用返回 None。"""
|
||||||
try:
|
try:
|
||||||
from sqlor import DBPools # noqa: WPS433 - 平台包
|
from sqlor.dbpools import DBPools # noqa: WPS433 - 平台包
|
||||||
except Exception: # noqa: BLE001
|
except Exception: # noqa: BLE001
|
||||||
try:
|
try:
|
||||||
from sqlor.dbpools import DBPools # noqa: WPS433
|
from sqlor.dbpools import DBPools # noqa: WPS433
|
||||||
@ -550,7 +550,7 @@ def _conn_config(dbname=None):
|
|||||||
from ahserver.serverenv import ServerEnv
|
from ahserver.serverenv import ServerEnv
|
||||||
except Exception:
|
except Exception:
|
||||||
try:
|
try:
|
||||||
from appbase.serverenv import ServerEnv
|
from ahserver.serverenv import ServerEnv
|
||||||
except Exception:
|
except Exception:
|
||||||
ServerEnv = None
|
ServerEnv = None
|
||||||
if ServerEnv is not None:
|
if ServerEnv is not None:
|
||||||
|
|||||||
@ -223,10 +223,10 @@ def get_dbname(module):
|
|||||||
if module not in MODULE_DB_KEYS:
|
if module not in MODULE_DB_KEYS:
|
||||||
raise PblError("PBL_E_PARAM", "模块未登记库名映射", {"module": module})
|
raise PblError("PBL_E_PARAM", "模块未登记库名映射", {"module": module})
|
||||||
try:
|
try:
|
||||||
from appbase.serverenv import ServerEnv # noqa: 平台基础模块
|
from ahserver.serverenv import ServerEnv # noqa: 平台基础模块
|
||||||
except Exception:
|
except Exception:
|
||||||
try:
|
try:
|
||||||
from appbase import ServerEnv # noqa: 兼容不同导出层级
|
from ahserver.serverenv import ServerEnv # noqa: 兼容不同导出层级
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise PblError("PBL_E_DB", "ServerEnv 不可用,无法解析库名", {"err": str(e)})
|
raise PblError("PBL_E_DB", "ServerEnv 不可用,无法解析库名", {"err": str(e)})
|
||||||
try:
|
try:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user