doc first implementation
This commit is contained in:
@@ -1,7 +1,14 @@
|
|||||||
from fastmcp import FastMCP
|
from fastmcp import FastMCP
|
||||||
|
|
||||||
from personal_mcp.catalog.server import catalog_server
|
from personal_mcp.catalog.server import catalog_server
|
||||||
|
from personal_mcp.skills.fastapi_async_sqlalchemy_modernization.server import (
|
||||||
|
fastapi_async_sqlalchemy_modernization_server,
|
||||||
|
)
|
||||||
from personal_mcp.skills.fastapi_uv_docker.server import fastapi_uv_docker_server
|
from personal_mcp.skills.fastapi_uv_docker.server import fastapi_uv_docker_server
|
||||||
|
from personal_mcp.skills.nicegui.server import nicegui_server
|
||||||
|
from personal_mcp.skills.nicegui_ui_customization.server import (
|
||||||
|
nicegui_ui_customization_server,
|
||||||
|
)
|
||||||
from personal_mcp.skills.pytest_scaffolding.server import pytest_scaffolding_server
|
from personal_mcp.skills.pytest_scaffolding.server import pytest_scaffolding_server
|
||||||
from personal_mcp.skills.python_logging_dictconfig.server import (
|
from personal_mcp.skills.python_logging_dictconfig.server import (
|
||||||
python_logging_dictconfig_server,
|
python_logging_dictconfig_server,
|
||||||
@@ -10,6 +17,12 @@ from personal_mcp.skills.python_logging_dictconfig.server import (
|
|||||||
mcp = FastMCP("personal-mcp")
|
mcp = FastMCP("personal-mcp")
|
||||||
|
|
||||||
mcp.mount(catalog_server, namespace="catalog")
|
mcp.mount(catalog_server, namespace="catalog")
|
||||||
|
mcp.mount(
|
||||||
|
fastapi_async_sqlalchemy_modernization_server,
|
||||||
|
namespace="fastapi_async_sqlalchemy_modernization",
|
||||||
|
)
|
||||||
|
mcp.mount(nicegui_server, namespace="nicegui")
|
||||||
|
mcp.mount(nicegui_ui_customization_server, namespace="nicegui_ui_customization")
|
||||||
mcp.mount(pytest_scaffolding_server, namespace="pytest_scaffolding")
|
mcp.mount(pytest_scaffolding_server, namespace="pytest_scaffolding")
|
||||||
mcp.mount(python_logging_dictconfig_server, namespace="python_logging_dictconfig")
|
mcp.mount(python_logging_dictconfig_server, namespace="python_logging_dictconfig")
|
||||||
mcp.mount(fastapi_uv_docker_server, namespace="fastapi_uv_docker")
|
mcp.mount(fastapi_uv_docker_server, namespace="fastapi_uv_docker")
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def _repo_root() -> Path:
|
||||||
|
return Path(__file__).resolve().parents[3]
|
||||||
|
|
||||||
|
|
||||||
|
def load_skill_document(*, skill_id: str, skill_slug: str) -> dict[str, str]:
|
||||||
|
"""Load the canonical skill markdown document for an MCP skill."""
|
||||||
|
document_path = _repo_root() / "skills" / skill_slug / "SKILL.md"
|
||||||
|
if not document_path.exists():
|
||||||
|
raise FileNotFoundError(
|
||||||
|
f"Missing skill document for '{skill_id}': {document_path}"
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"id": skill_id,
|
||||||
|
"uri": f"resource://skills/{skill_id}/document",
|
||||||
|
"format": "markdown",
|
||||||
|
"source_path": str(document_path),
|
||||||
|
"content": document_path.read_text(encoding="utf-8"),
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
"""FastAPI async SQLAlchemy modernization skill server."""
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
id: fastapi-async-sqlalchemy-modernization
|
||||||
|
name: FastAPI Async SQLAlchemy Modernization
|
||||||
|
version: 1.0.0
|
||||||
|
description: Create a step-by-step modernization plan for an existing FastAPI app using SQLAlchemy async patterns.
|
||||||
|
tags:
|
||||||
|
- fastapi
|
||||||
|
- sqlalchemy
|
||||||
|
- async
|
||||||
|
- modernization
|
||||||
|
capabilities:
|
||||||
|
- resource://skills/fastapi-async-sqlalchemy-modernization/document
|
||||||
|
depends_on: []
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
from fastmcp import FastMCP
|
||||||
|
|
||||||
|
from personal_mcp.skills.document_loader import load_skill_document
|
||||||
|
|
||||||
|
fastapi_async_sqlalchemy_modernization_server = FastMCP(
|
||||||
|
"fastapi-async-sqlalchemy-modernization"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@fastapi_async_sqlalchemy_modernization_server.resource(
|
||||||
|
"resource://skills/fastapi-async-sqlalchemy-modernization/document"
|
||||||
|
)
|
||||||
|
def skill_document() -> dict[str, str]:
|
||||||
|
"""Return the canonical Markdown document for this skill."""
|
||||||
|
return load_skill_document(
|
||||||
|
skill_id="fastapi-async-sqlalchemy-modernization",
|
||||||
|
skill_slug="fastapi-async-sqlalchemy-modernization",
|
||||||
|
)
|
||||||
@@ -7,8 +7,5 @@ tags:
|
|||||||
- uv
|
- uv
|
||||||
- docker
|
- docker
|
||||||
capabilities:
|
capabilities:
|
||||||
- resource://skills/fastapi_uv_docker/overview
|
- resource://skills/fastapi-uv-docker/document
|
||||||
- resource://skills/fastapi_uv_docker/rules
|
|
||||||
- resource://skills/fastapi_uv_docker/checklist
|
|
||||||
- resource://skills/fastapi_uv_docker/references
|
|
||||||
depends_on: []
|
depends_on: []
|
||||||
|
|||||||
@@ -1,88 +1,14 @@
|
|||||||
from pathlib import Path
|
|
||||||
|
|
||||||
from fastmcp import FastMCP
|
from fastmcp import FastMCP
|
||||||
|
|
||||||
|
from personal_mcp.skills.document_loader import load_skill_document
|
||||||
|
|
||||||
fastapi_uv_docker_server = FastMCP("fastapi-uv-docker")
|
fastapi_uv_docker_server = FastMCP("fastapi-uv-docker")
|
||||||
|
|
||||||
_REFERENCE_DIR = (
|
|
||||||
Path(__file__).resolve().parents[4]
|
|
||||||
/ "skills"
|
|
||||||
/ "fastapi-uv-docker"
|
|
||||||
/ "references"
|
|
||||||
)
|
|
||||||
_REFERENCE_FILES = {
|
|
||||||
"fastapi_best_practices": _REFERENCE_DIR / "fastapi-best-practices.md",
|
|
||||||
"uv_project_layout": _REFERENCE_DIR / "uv-project-layout.md",
|
|
||||||
"uvicorn_settings": _REFERENCE_DIR / "uvicorn-settings.md",
|
|
||||||
"docker_cloud_native": _REFERENCE_DIR / "docker-cloud-native.md",
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@fastapi_uv_docker_server.resource("resource://skills/fastapi-uv-docker/document")
|
||||||
def _load_reference_bundle() -> dict[str, str]:
|
def skill_document() -> dict[str, str]:
|
||||||
bundle: dict[str, str] = {}
|
"""Return the canonical Markdown document for this skill."""
|
||||||
for key, path in _REFERENCE_FILES.items():
|
return load_skill_document(
|
||||||
bundle[key] = path.read_text(encoding="utf-8")
|
skill_id="fastapi-uv-docker",
|
||||||
return bundle
|
skill_slug="fastapi-uv-docker",
|
||||||
|
)
|
||||||
|
|
||||||
@fastapi_uv_docker_server.resource("resource://skills/fastapi_uv_docker/overview")
|
|
||||||
def fastapi_overview() -> dict:
|
|
||||||
"""Return high-level intent for FastAPI plus uv plus Docker migration."""
|
|
||||||
return {
|
|
||||||
"id": "fastapi-uv-docker",
|
|
||||||
"intent": "Migrate projects toward cloud-native FastAPI architecture managed by uv.",
|
|
||||||
"focus": [
|
|
||||||
"src package layout",
|
|
||||||
"uv-based dependency and lock management",
|
|
||||||
"container-ready runtime conventions",
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@fastapi_uv_docker_server.resource("resource://skills/fastapi_uv_docker/rules")
|
|
||||||
def fastapi_rules() -> dict:
|
|
||||||
"""Return migration rules for stable FastAPI service architecture."""
|
|
||||||
return {
|
|
||||||
"rules": [
|
|
||||||
"Prefer src layout and installable package boundaries.",
|
|
||||||
"Use app factory and lifespan hooks for startup/shutdown ownership.",
|
|
||||||
"Keep runtime configuration in environment-backed settings.",
|
|
||||||
"Use uv lockfile and avoid drift between local and container environments.",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@fastapi_uv_docker_server.resource("resource://skills/fastapi_uv_docker/checklist")
|
|
||||||
def fastapi_checklist() -> dict:
|
|
||||||
"""Return a compact migration checklist for FastAPI plus uv plus Docker."""
|
|
||||||
return {
|
|
||||||
"checklist": [
|
|
||||||
"Audit current project manager, layout, and runtime settings.",
|
|
||||||
"Establish uv project metadata and lockfile ownership.",
|
|
||||||
"Implement app factory, lifespan, and health endpoints.",
|
|
||||||
"Create multi-stage Docker image with non-root runtime user.",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@fastapi_uv_docker_server.resource("resource://skills/fastapi_uv_docker/references")
|
|
||||||
def fastapi_references() -> dict:
|
|
||||||
"""Return bundled references for detailed implementation guidance."""
|
|
||||||
return {
|
|
||||||
"sources": {key: str(path) for key, path in _REFERENCE_FILES.items()},
|
|
||||||
"format": "markdown",
|
|
||||||
"content": _load_reference_bundle(),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@fastapi_uv_docker_server.tool()
|
|
||||||
def fastapi_uv_docker_mvp_checklist(current_state: str = "bare python project") -> list[str]:
|
|
||||||
"""Return a compact migration checklist for FastAPI + uv + Docker."""
|
|
||||||
return [
|
|
||||||
f"Current state: {current_state}",
|
|
||||||
"Create src/ package layout for the FastAPI app.",
|
|
||||||
"Manage dependencies with uv and keep uv.lock committed.",
|
|
||||||
"Use an app factory and lifespan hooks.",
|
|
||||||
"Add /healthz endpoint for operational checks.",
|
|
||||||
"Build with a multi-stage Dockerfile and run as non-root user.",
|
|
||||||
]
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
"""NiceGUI architecture skill server."""
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
id: nicegui
|
||||||
|
name: NiceGUI
|
||||||
|
version: 1.0.0
|
||||||
|
description: Design and scaffold a production-ready NiceGUI plus FastAPI application architecture.
|
||||||
|
tags:
|
||||||
|
- nicegui
|
||||||
|
- fastapi
|
||||||
|
- ui
|
||||||
|
- architecture
|
||||||
|
capabilities:
|
||||||
|
- resource://skills/nicegui/document
|
||||||
|
depends_on: []
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
from fastmcp import FastMCP
|
||||||
|
|
||||||
|
from personal_mcp.skills.document_loader import load_skill_document
|
||||||
|
|
||||||
|
nicegui_server = FastMCP("nicegui")
|
||||||
|
|
||||||
|
|
||||||
|
@nicegui_server.resource("resource://skills/nicegui/document")
|
||||||
|
def skill_document() -> dict[str, str]:
|
||||||
|
"""Return the canonical Markdown document for this skill."""
|
||||||
|
return load_skill_document(skill_id="nicegui", skill_slug="nicegui")
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
"""NiceGUI UI customization skill server."""
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
id: nicegui-ui-customization
|
||||||
|
name: NiceGUI UI Customization
|
||||||
|
version: 1.0.0
|
||||||
|
description: Design and implement production NiceGUI interfaces with reusable components and event-driven interactions.
|
||||||
|
tags:
|
||||||
|
- nicegui
|
||||||
|
- ui
|
||||||
|
- customization
|
||||||
|
- frontend
|
||||||
|
capabilities:
|
||||||
|
- resource://skills/nicegui-ui-customization/document
|
||||||
|
depends_on: []
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
from fastmcp import FastMCP
|
||||||
|
|
||||||
|
from personal_mcp.skills.document_loader import load_skill_document
|
||||||
|
|
||||||
|
nicegui_ui_customization_server = FastMCP("nicegui-ui-customization")
|
||||||
|
|
||||||
|
|
||||||
|
@nicegui_ui_customization_server.resource(
|
||||||
|
"resource://skills/nicegui-ui-customization/document"
|
||||||
|
)
|
||||||
|
def skill_document() -> dict[str, str]:
|
||||||
|
"""Return the canonical Markdown document for this skill."""
|
||||||
|
return load_skill_document(
|
||||||
|
skill_id="nicegui-ui-customization",
|
||||||
|
skill_slug="nicegui-ui-customization",
|
||||||
|
)
|
||||||
@@ -7,8 +7,5 @@ tags:
|
|||||||
- testing
|
- testing
|
||||||
- python
|
- python
|
||||||
capabilities:
|
capabilities:
|
||||||
- resource://skills/pytest_scaffolding/overview
|
- resource://skills/pytest-scaffolding/document
|
||||||
- resource://skills/pytest_scaffolding/rules
|
|
||||||
- resource://skills/pytest_scaffolding/checklist
|
|
||||||
- resource://skills/pytest_scaffolding/references
|
|
||||||
depends_on: []
|
depends_on: []
|
||||||
|
|||||||
@@ -1,90 +1,14 @@
|
|||||||
from pathlib import Path
|
|
||||||
|
|
||||||
from fastmcp import FastMCP
|
from fastmcp import FastMCP
|
||||||
|
|
||||||
|
from personal_mcp.skills.document_loader import load_skill_document
|
||||||
|
|
||||||
pytest_scaffolding_server = FastMCP("pytest-scaffolding")
|
pytest_scaffolding_server = FastMCP("pytest-scaffolding")
|
||||||
|
|
||||||
_REFERENCE_PATH = (
|
|
||||||
Path(__file__).resolve().parents[4]
|
|
||||||
/ "skills"
|
|
||||||
/ "pytest-scaffolding"
|
|
||||||
/ "references"
|
|
||||||
/ "pytest-docs.md"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
@pytest_scaffolding_server.resource("resource://skills/pytest-scaffolding/document")
|
||||||
def _load_reference_text() -> str:
|
def skill_document() -> dict[str, str]:
|
||||||
return _REFERENCE_PATH.read_text(encoding="utf-8")
|
"""Return the canonical Markdown document for this skill."""
|
||||||
|
return load_skill_document(
|
||||||
|
skill_id="pytest-scaffolding",
|
||||||
@pytest_scaffolding_server.resource("resource://skills/pytest_scaffolding/overview")
|
skill_slug="pytest-scaffolding",
|
||||||
def pytest_overview() -> dict:
|
|
||||||
"""Return the high-level intent and boundaries of this pattern module."""
|
|
||||||
return {
|
|
||||||
"id": "pytest-scaffolding",
|
|
||||||
"intent": "Design maintainable pytest structure before deep test implementation.",
|
|
||||||
"focus": [
|
|
||||||
"hierarchical test layout",
|
|
||||||
"dependency-aware fixture boundaries",
|
|
||||||
"fast local feedback loops",
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@pytest_scaffolding_server.resource("resource://skills/pytest_scaffolding/rules")
|
|
||||||
def pytest_rules() -> dict:
|
|
||||||
"""Return method rules to keep test architecture consistent."""
|
|
||||||
return {
|
|
||||||
"rules": [
|
|
||||||
"Mirror major source package boundaries under tests/.",
|
|
||||||
"Use explicit markers for integration, smoke, and external tests.",
|
|
||||||
"Keep global fixtures lightweight; place expensive fixtures in subtree conftest files.",
|
|
||||||
"Prefer deterministic unit tests and isolate slow or external dependencies.",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@pytest_scaffolding_server.resource("resource://skills/pytest_scaffolding/checklist")
|
|
||||||
def pytest_checklist() -> dict:
|
|
||||||
"""Return an execution checklist for first-pass test scaffolding."""
|
|
||||||
return {
|
|
||||||
"checklist": [
|
|
||||||
"Map source modules to initial test modules.",
|
|
||||||
"Classify each module as unit, integration, or smoke.",
|
|
||||||
"Create baseline fixtures in tests/conftest.py.",
|
|
||||||
"Register markers in pyproject.toml.",
|
|
||||||
"Validate collection and run fast path first.",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@pytest_scaffolding_server.resource("resource://skills/pytest_scaffolding/references")
|
|
||||||
def pytest_references() -> dict:
|
|
||||||
"""Return canonical reference material for this pattern module."""
|
|
||||||
return {
|
|
||||||
"source": str(_REFERENCE_PATH),
|
|
||||||
"format": "markdown",
|
|
||||||
"content": _load_reference_text(),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@pytest_scaffolding_server.prompt()
|
|
||||||
def scaffold_pytest_prompt(target_scope: str = "src/") -> str:
|
|
||||||
"""Prompt template for planning pytest scaffolding for a target scope."""
|
|
||||||
return (
|
|
||||||
"Create a minimal pytest scaffold plan. "
|
|
||||||
f"Target scope: {target_scope}. "
|
|
||||||
"Return directory mapping, marker suggestions, and the first three tests to write."
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest_scaffolding_server.tool()
|
|
||||||
def propose_pytest_mvp_tree(target_scope: str = "src/") -> str:
|
|
||||||
"""Return a minimal test scaffold plan for a target scope."""
|
|
||||||
return (
|
|
||||||
f"MVP pytest scaffold for {target_scope}:\n"
|
|
||||||
"1. Mirror the source subtree under tests/.\n"
|
|
||||||
"2. Add one happy-path test and one edge-case test per core module.\n"
|
|
||||||
"3. Keep fast tests isolated from integration/external dependencies.\n"
|
|
||||||
"4. Use uv run pytest as the canonical runner."
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -7,8 +7,5 @@ tags:
|
|||||||
- python
|
- python
|
||||||
- observability
|
- observability
|
||||||
capabilities:
|
capabilities:
|
||||||
- resource://skills/python_logging_dictconfig/overview
|
- resource://skills/python-logging-dictconfig/document
|
||||||
- resource://skills/python_logging_dictconfig/rules
|
|
||||||
- resource://skills/python_logging_dictconfig/checklist
|
|
||||||
- resource://skills/python_logging_dictconfig/references
|
|
||||||
depends_on: []
|
depends_on: []
|
||||||
|
|||||||
@@ -1,94 +1,16 @@
|
|||||||
from pathlib import Path
|
|
||||||
|
|
||||||
from fastmcp import FastMCP
|
from fastmcp import FastMCP
|
||||||
|
|
||||||
|
from personal_mcp.skills.document_loader import load_skill_document
|
||||||
|
|
||||||
python_logging_dictconfig_server = FastMCP("python-logging-dictconfig")
|
python_logging_dictconfig_server = FastMCP("python-logging-dictconfig")
|
||||||
|
|
||||||
_REFERENCE_PATH = (
|
|
||||||
Path(__file__).resolve().parents[4]
|
@python_logging_dictconfig_server.resource(
|
||||||
/ "skills"
|
"resource://skills/python-logging-dictconfig/document"
|
||||||
/ "python-logging-dictconfig"
|
|
||||||
/ "references"
|
|
||||||
/ "python-logging-docs.md"
|
|
||||||
)
|
)
|
||||||
|
def skill_document() -> dict[str, str]:
|
||||||
|
"""Return the canonical Markdown document for this skill."""
|
||||||
def _load_reference_text() -> str:
|
return load_skill_document(
|
||||||
return _REFERENCE_PATH.read_text(encoding="utf-8")
|
skill_id="python-logging-dictconfig",
|
||||||
|
skill_slug="python-logging-dictconfig",
|
||||||
|
)
|
||||||
@python_logging_dictconfig_server.resource("resource://skills/python_logging_dictconfig/overview")
|
|
||||||
def logging_overview() -> dict:
|
|
||||||
"""Return high-level purpose and intended outcomes for logging configuration."""
|
|
||||||
return {
|
|
||||||
"id": "python-logging-dictconfig",
|
|
||||||
"intent": "Centralize Python logging setup with dictConfig during application startup.",
|
|
||||||
"focus": [
|
|
||||||
"single startup configuration",
|
|
||||||
"consistent formatting and level policy",
|
|
||||||
"named module loggers without local configuration",
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@python_logging_dictconfig_server.resource("resource://skills/python_logging_dictconfig/rules")
|
|
||||||
def logging_rules() -> dict:
|
|
||||||
"""Return implementation rules for predictable logging behavior."""
|
|
||||||
return {
|
|
||||||
"rules": [
|
|
||||||
"Call dictConfig once at startup, not in leaf modules.",
|
|
||||||
"Use logging.getLogger(__name__) in all modules.",
|
|
||||||
"Avoid basicConfig in application packages.",
|
|
||||||
"Set disable_existing_loggers to False unless intentional suppression is required.",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@python_logging_dictconfig_server.resource("resource://skills/python_logging_dictconfig/checklist")
|
|
||||||
def logging_checklist() -> dict:
|
|
||||||
"""Return a startup checklist for logging configuration rollout."""
|
|
||||||
return {
|
|
||||||
"checklist": [
|
|
||||||
"Define formatter, handlers, and root logger in one LOGGING dict.",
|
|
||||||
"Wire configure_logging() in startup path only once.",
|
|
||||||
"Verify expected output at DEBUG/INFO/WARNING/ERROR levels.",
|
|
||||||
"Tune noisy third-party loggers intentionally.",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@python_logging_dictconfig_server.resource("resource://skills/python_logging_dictconfig/references")
|
|
||||||
def logging_references() -> dict:
|
|
||||||
"""Return canonical reference material for dictConfig-based logging."""
|
|
||||||
return {
|
|
||||||
"source": str(_REFERENCE_PATH),
|
|
||||||
"format": "markdown",
|
|
||||||
"content": _load_reference_text(),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@python_logging_dictconfig_server.tool()
|
|
||||||
def logging_dictconfig_template(level: str = "INFO") -> dict:
|
|
||||||
"""Return a minimal dictConfig template for application startup."""
|
|
||||||
normalized = level.upper()
|
|
||||||
return {
|
|
||||||
"version": 1,
|
|
||||||
"disable_existing_loggers": False,
|
|
||||||
"formatters": {
|
|
||||||
"standard": {
|
|
||||||
"format": "%(asctime)s %(levelname)s %(name)s: %(message)s",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"handlers": {
|
|
||||||
"console": {
|
|
||||||
"class": "logging.StreamHandler",
|
|
||||||
"level": normalized,
|
|
||||||
"formatter": "standard",
|
|
||||||
"stream": "ext://sys.stdout",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": {
|
|
||||||
"level": normalized,
|
|
||||||
"handlers": ["console"],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user