合并 agent-mvp 到 master #1
@@ -1,36 +0,0 @@
|
||||
from fastapi import APIRouter, Request, Query
|
||||
from typing import Any, List, Dict, Union
|
||||
from app.services.tjnetwork import Any, get_all_users, get_user, get_user_schema
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
###########################################################
|
||||
# user 39
|
||||
###########################################################
|
||||
|
||||
@router.get("/network-schemas/user", summary="获取用户模式", description="获取指定网络的用户模式定义")
|
||||
async def fastapi_get_user_schema(network: str = Query(..., description="管网名称(或数据库名称)")) -> dict[str, dict[Any, Any]]:
|
||||
"""
|
||||
获取用户模式定义
|
||||
|
||||
返回指定网络的用户模式结构定义
|
||||
"""
|
||||
return get_user_schema(network)
|
||||
|
||||
@router.get("/users/detail", summary="获取单个用户", description="获取指定网络中的单个用户信息")
|
||||
async def fastapi_get_user(network: str = Query(..., description="管网名称(或数据库名称)"), user_name: str = Query(..., description="用户名")) -> dict[Any, Any]:
|
||||
"""
|
||||
获取用户信息
|
||||
|
||||
返回指定网络中指定用户名的详细信息
|
||||
"""
|
||||
return get_user(network, user_name)
|
||||
|
||||
@router.get("/users", summary="获取所有用户", description="获取指定网络的所有用户列表")
|
||||
async def fastapi_get_all_users(network: str = Query(..., description="管网名称(或数据库名称)")) -> list[dict[Any, Any]]:
|
||||
"""
|
||||
获取所有用户列表
|
||||
|
||||
返回指定网络中所有用户的信息
|
||||
"""
|
||||
return get_all_users(network)
|
||||
@@ -22,7 +22,6 @@ from app.api.v1.endpoints import (
|
||||
sensor_placement,
|
||||
simulation,
|
||||
snapshots,
|
||||
users,
|
||||
web_search,
|
||||
)
|
||||
from app.api.v1.endpoints.components import (
|
||||
@@ -152,11 +151,6 @@ api_router.include_router(
|
||||
tags=["Snapshots"],
|
||||
dependencies=[simulation_access],
|
||||
)
|
||||
api_router.include_router(
|
||||
users.router,
|
||||
tags=["Users"],
|
||||
dependencies=[webgis_view_access],
|
||||
)
|
||||
api_router.include_router(
|
||||
schemes.router,
|
||||
tags=["Schemes"],
|
||||
|
||||
@@ -460,8 +460,6 @@ from .s36_wda_cal import (
|
||||
# -----------------------------------------------------------------------------
|
||||
from .s38_scada_info import get_scada_info_schema, get_scada_info, get_all_scada_info
|
||||
|
||||
from .s39_user import get_user_schema, get_user, get_all_users
|
||||
|
||||
from .s40_schema import get_scheme_schema, get_scheme, get_all_schemes
|
||||
|
||||
from .s41_pipe_risk_probability import (
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
from .database import *
|
||||
from .s0_base import *
|
||||
|
||||
class User(object):
|
||||
def __init__(self, input: dict[str, Any]) -> None:
|
||||
self.type = 'user'
|
||||
self.id = str(input['user_id'])
|
||||
self.name = str(input['username'])
|
||||
self.password = str(input['password'])
|
||||
|
||||
def as_dict(self) -> dict[str, Any]:
|
||||
return { 'type': self.type, 'id': self.id, 'name': self.name, 'password': self.password }
|
||||
|
||||
def as_id_dict(self) -> dict[str, Any]:
|
||||
return { 'type': self.type, 'id': self.id }
|
||||
|
||||
|
||||
def get_user_schema(name: str) -> dict[str, dict[Any, Any]]:
|
||||
return { 'id' : {'type': 'str' , 'optional': False , 'readonly': True },
|
||||
'name' : {'type': 'str' , 'optional': False , 'readonly': False},
|
||||
'password' : {'type': 'str' , 'optional': False , 'readonly': False} }
|
||||
|
||||
def get_user(name: str, user_name: str) -> dict[Any, Any]:
|
||||
t = try_read(name, f"select * from users where username = '{user_name}'")
|
||||
if t == None:
|
||||
return {}
|
||||
|
||||
d = {}
|
||||
d['id'] = str(t['user_id'])
|
||||
d['name'] = str(t['username'])
|
||||
# d['password'] = str(t['password'])
|
||||
|
||||
return d
|
||||
|
||||
def get_all_users(name: str) -> list[dict[Any, Any]]:
|
||||
return read_all(name, "select * from users")
|
||||
|
||||
@@ -11,53 +11,6 @@ from app.core.config import get_pgconn_string
|
||||
from app.services.time_api import parse_utc_time
|
||||
|
||||
|
||||
# 2025/03/23
|
||||
def create_user(name: str, username: str, password: str):
|
||||
"""
|
||||
创建用户
|
||||
:param name: 数据库名称
|
||||
:param username: 用户名
|
||||
:param password: 密码
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
# 动态替换数据库名称
|
||||
conn_string = get_pgconn_string(db_name=name)
|
||||
# 连接到 PostgreSQL 数据库(这里是数据库 "bb")
|
||||
with psycopg.connect(conn_string) as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
"INSERT INTO users (username, password) VALUES (%s, %s)",
|
||||
(username, password),
|
||||
)
|
||||
# 提交事务
|
||||
conn.commit()
|
||||
print("新用户创建成功!")
|
||||
except Exception as e:
|
||||
print(f"创建用户出错:{e}")
|
||||
|
||||
|
||||
# 2025/03/23
|
||||
def delete_user(name: str, username: str):
|
||||
"""
|
||||
删除用户
|
||||
:param name: 数据库名称
|
||||
:param username: 用户名
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
# 动态替换数据库名称
|
||||
conn_string = get_pgconn_string(db_name=name)
|
||||
# 连接到 PostgreSQL 数据库(这里是数据库 "bb")
|
||||
with psycopg.connect(conn_string) as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute("DELETE FROM users WHERE username = %s", (username,))
|
||||
conn.commit()
|
||||
print(f"用户 {username} 删除成功!")
|
||||
except Exception as e:
|
||||
print(f"删除用户出错:{e}")
|
||||
|
||||
|
||||
# 2025/03/23
|
||||
def scheme_name_exists(name: str, scheme_name: str) -> bool:
|
||||
"""
|
||||
@@ -98,8 +51,8 @@ def store_scheme_info(
|
||||
:param name: 数据库名称
|
||||
:param scheme_name: 方案名称
|
||||
:param scheme_type: 方案类型
|
||||
:param username: 用户名(需在 users 表中已存在)
|
||||
:param scheme_start_time: 方案起始时间(字符串)
|
||||
:param username: MetaDB 中的用户名快照
|
||||
:param scheme_start_time: 带时区的方案起始时间;写入前统一转换为 UTC
|
||||
:param scheme_detail: 方案详情(字典,会转换为 JSON)
|
||||
:return:
|
||||
"""
|
||||
|
||||
@@ -1290,19 +1290,6 @@ def get_scada_info(name: str, id: str) -> dict[str, Any]:
|
||||
def get_all_scada_info(name: str) -> list[dict[str, Any]]:
|
||||
return api.get_all_scada_info(name)
|
||||
|
||||
# DingZQ 2025-03-27
|
||||
############################################################
|
||||
# 39 users
|
||||
############################################################
|
||||
def get_user_schema(name: str) -> dict[str, dict[str, Any]]:
|
||||
return api.get_user_schema(name)
|
||||
|
||||
def get_user(name: str, user_name: str) -> dict[str, Any]:
|
||||
return api.get_user(name, user_name=user_name)
|
||||
|
||||
def get_all_users(name: str) -> list[dict[str, Any]]:
|
||||
return api.get_all_users(name)
|
||||
|
||||
############################################################
|
||||
# scheme 40
|
||||
############################################################
|
||||
|
||||
@@ -305,7 +305,6 @@ GET /getjson/
|
||||
app/api/v1/endpoints/snapshots.py
|
||||
app/api/v1/endpoints/cache.py
|
||||
app/api/v1/endpoints/audit.py
|
||||
app/api/v1/endpoints/users.py
|
||||
```
|
||||
|
||||
这些接口不纳入首批 Agent CLI。原因是它们更偏运维、审计或状态回滚,不属于 Agent 面向水务业务分析的核心调用范围。
|
||||
@@ -335,9 +334,6 @@ POST /clearallredis/
|
||||
GET /audit/logs
|
||||
GET /audit/logs/my
|
||||
GET /audit/logs/count
|
||||
GET /getuserschema/
|
||||
GET /getuser/
|
||||
GET /getallusers/
|
||||
```
|
||||
|
||||
## Help
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"contracts": {
|
||||
"server": {
|
||||
"file": "server-v1.openapi.json",
|
||||
"sha256": "d80a968d281fdb2953364a5979c2d61fda5151a1e1759c01cc96780b11a6d56c"
|
||||
"sha256": "3cb27b1a6f83ad0619e6b086b314303d15b4d23ce0c9ab318c9cbe720d974c40"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19425,108 +19425,6 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v1/network-schemas/user": {
|
||||
"get": {
|
||||
"description": "获取指定网络的用户模式定义",
|
||||
"operationId": "get_network_schemas_user",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "header",
|
||||
"name": "X-Project-Id",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"title": "X-Project-Id",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"additionalProperties": {
|
||||
"type": "object"
|
||||
},
|
||||
"title": "Response Get Network Schemas User",
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Successful Response"
|
||||
},
|
||||
"401": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ProblemDetails"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Authentication required"
|
||||
},
|
||||
"403": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ProblemDetails"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Insufficient permission"
|
||||
},
|
||||
"404": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ProblemDetails"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Resource not found"
|
||||
},
|
||||
"409": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ProblemDetails"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Resource conflict"
|
||||
},
|
||||
"422": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ProblemDetails"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Validation error"
|
||||
},
|
||||
"503": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ProblemDetails"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Dependency unavailable"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"OAuth2PasswordBearer": []
|
||||
}
|
||||
],
|
||||
"summary": "获取用户模式",
|
||||
"tags": [
|
||||
"Users"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v1/network-schemas/valve": {
|
||||
"get": {
|
||||
"description": "获取指定水网中所有阀门的架构和字段定义",
|
||||
@@ -47552,237 +47450,6 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v1/users": {
|
||||
"get": {
|
||||
"description": "获取指定网络的所有用户列表",
|
||||
"operationId": "get_users",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "query",
|
||||
"name": "limit",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"default": 100,
|
||||
"maximum": 1000,
|
||||
"minimum": 1,
|
||||
"title": "Limit",
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
{
|
||||
"in": "query",
|
||||
"name": "offset",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"default": 0,
|
||||
"minimum": 0,
|
||||
"title": "Offset",
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
{
|
||||
"in": "header",
|
||||
"name": "X-Project-Id",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"title": "X-Project-Id",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Page_dict_Any__Any__"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Successful Response"
|
||||
},
|
||||
"401": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ProblemDetails"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Authentication required"
|
||||
},
|
||||
"403": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ProblemDetails"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Insufficient permission"
|
||||
},
|
||||
"404": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ProblemDetails"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Resource not found"
|
||||
},
|
||||
"409": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ProblemDetails"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Resource conflict"
|
||||
},
|
||||
"422": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ProblemDetails"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Validation error"
|
||||
},
|
||||
"503": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ProblemDetails"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Dependency unavailable"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"OAuth2PasswordBearer": []
|
||||
}
|
||||
],
|
||||
"summary": "获取所有用户",
|
||||
"tags": [
|
||||
"Users"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v1/users/detail": {
|
||||
"get": {
|
||||
"description": "获取指定网络中的单个用户信息",
|
||||
"operationId": "get_users_detail",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "用户名",
|
||||
"in": "query",
|
||||
"name": "user_name",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"description": "用户名",
|
||||
"title": "User Name",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"in": "header",
|
||||
"name": "X-Project-Id",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"title": "X-Project-Id",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"title": "Response Get Users Detail",
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Successful Response"
|
||||
},
|
||||
"401": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ProblemDetails"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Authentication required"
|
||||
},
|
||||
"403": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ProblemDetails"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Insufficient permission"
|
||||
},
|
||||
"404": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ProblemDetails"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Resource not found"
|
||||
},
|
||||
"409": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ProblemDetails"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Resource conflict"
|
||||
},
|
||||
"422": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ProblemDetails"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Validation error"
|
||||
},
|
||||
"503": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ProblemDetails"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Dependency unavailable"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"OAuth2PasswordBearer": []
|
||||
}
|
||||
],
|
||||
"summary": "获取单个用户",
|
||||
"tags": [
|
||||
"Users"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v1/valve-closure-analyses": {
|
||||
"post": {
|
||||
"description": "高级版本的阀门关闭分析,支持同时关闭多个阀门,并在指定持续时间内进行模拟。返回纯文本格式的分析结果。",
|
||||
|
||||
@@ -138,7 +138,6 @@ from app.services.tjnetwork import (
|
||||
get_all_sensor_placements,
|
||||
get_all_service_areas,
|
||||
get_all_tanks,
|
||||
get_all_users,
|
||||
get_all_valves,
|
||||
get_all_vertex_links,
|
||||
get_all_vertices,
|
||||
@@ -238,8 +237,6 @@ from app.services.tjnetwork import (
|
||||
get_time_schema,
|
||||
get_title,
|
||||
get_title_schema,
|
||||
get_user,
|
||||
get_user_schema,
|
||||
get_valve,
|
||||
get_valve_schema,
|
||||
get_vertex,
|
||||
@@ -2910,24 +2907,6 @@ async def fastapi_get_all_scada_info(network: str) -> list[dict[str, float]]:
|
||||
return get_all_scada_info(network)
|
||||
|
||||
|
||||
###########################################################
|
||||
# user 39
|
||||
###########################################################
|
||||
@app.get("/getuserschema/")
|
||||
async def fastapi_get_user_schema(network: str) -> dict[str, dict[Any, Any]]:
|
||||
return get_user_schema(network)
|
||||
|
||||
|
||||
@app.get("/getuser/")
|
||||
async def fastapi_get_user(network: str, user_name: str) -> dict[Any, Any]:
|
||||
return get_user(network, user_name)
|
||||
|
||||
|
||||
@app.get("/getallusers/")
|
||||
async def fastapi_get_all_users(network: str) -> list[dict[Any, Any]]:
|
||||
return get_all_users(network)
|
||||
|
||||
|
||||
############################################################
|
||||
# scheme 40
|
||||
############################################################
|
||||
|
||||
@@ -327,9 +327,6 @@ Non-commented FastAPI routes defined in `scripts/main.py`.
|
||||
- `GET /getscadainfoschema/`
|
||||
- `GET /getscadainfo/`
|
||||
- `GET /getallscadainfo/`
|
||||
- `GET /getuserschema/`
|
||||
- `GET /getuser/`
|
||||
- `GET /getallusers/`
|
||||
- `GET /getschemeschema/`
|
||||
- `GET /getscheme/`
|
||||
- `GET /getallschemes/`
|
||||
|
||||
@@ -1145,53 +1145,6 @@ def submit_scada_info(name: str, coord_id: str) -> None:
|
||||
print(f"scada_info文件不存在。")
|
||||
|
||||
|
||||
# 2025/03/23
|
||||
def create_user(name: str, username: str, password: str):
|
||||
"""
|
||||
创建用户
|
||||
:param name: 数据库名称
|
||||
:param username: 用户名
|
||||
:param password: 密码
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
# 动态替换数据库名称
|
||||
conn_string = get_pgconn_string(db_name=name)
|
||||
# 连接到 PostgreSQL 数据库(这里是数据库 "bb")
|
||||
with psycopg.connect(conn_string) as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
"INSERT INTO users (username, password) VALUES (%s, %s)",
|
||||
(username, password),
|
||||
)
|
||||
# 提交事务
|
||||
conn.commit()
|
||||
print("新用户创建成功!")
|
||||
except Exception as e:
|
||||
print(f"创建用户出错:{e}")
|
||||
|
||||
|
||||
# 2025/03/23
|
||||
def delete_user(name: str, username: str):
|
||||
"""
|
||||
删除用户
|
||||
:param name: 数据库名称
|
||||
:param username: 用户名
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
# 动态替换数据库名称
|
||||
conn_string = get_pgconn_string(db_name=name)
|
||||
# 连接到 PostgreSQL 数据库(这里是数据库 "bb")
|
||||
with psycopg.connect(conn_string) as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute("DELETE FROM users WHERE username = %s", (username,))
|
||||
conn.commit()
|
||||
print(f"用户 {username} 删除成功!")
|
||||
except Exception as e:
|
||||
print(f"删除用户出错:{e}")
|
||||
|
||||
|
||||
# 2025/03/23
|
||||
def scheme_name_exists(name: str, scheme_name: str) -> bool:
|
||||
"""
|
||||
@@ -1572,12 +1525,6 @@ if __name__ == "__main__":
|
||||
# burst_analysis(name='bb', modify_pattern_start_time='2025-04-17T00:00:00+08:00',
|
||||
# burst_ID='GSD230112144241FA18292A84CB', burst_size=400, modify_total_duration=1800, scheme_name='GSD230112144241FA18292A84CB_400')
|
||||
|
||||
# 示例:create_user
|
||||
# create_user(name=project_info.name, username='tjwater dev', password='123456')
|
||||
|
||||
# # 示例:delete_user
|
||||
# delete_user(name=project_info.name, username='admin_test')
|
||||
|
||||
# # 示例:query_scheme_list
|
||||
# result = query_scheme_list(name=project_info.name)
|
||||
# print(result)
|
||||
|
||||
@@ -77,6 +77,20 @@ def test_handler_router_defines_only_the_public_rest_operations() -> None:
|
||||
assert ("GET", "/getpipeproperties/") not in source_operations
|
||||
|
||||
|
||||
def test_legacy_project_user_operations_are_not_exposed() -> None:
|
||||
source_paths = {
|
||||
route.path
|
||||
for route in source_api_router.routes
|
||||
if isinstance(route, APIRoute)
|
||||
}
|
||||
|
||||
assert {
|
||||
"/network-schemas/user",
|
||||
"/users",
|
||||
"/users/detail",
|
||||
}.isdisjoint(source_paths)
|
||||
|
||||
|
||||
def test_rest_openapi_satisfies_contract_invariants() -> None:
|
||||
from fastapi import FastAPI
|
||||
|
||||
|
||||
Reference in New Issue
Block a user