簡體   English   中英

從 argparse CLI 生成 json 模式

[英]Generate json schema from argparse CLI

我有一個用argparse編寫的 CLI,我想知道是否有辦法從ArgumentParser生成 JSON 架構? 這背后的想法是將 JSON 模式分發給與應用程序接口的擴展,從而消除了每個擴展編寫和維護自己的模式的需要。

我的想法是

  1. argparse.ArgumentParser轉換為 Python 字典或 JSON 文件
  2. 然后將其傳遞給 JSON 模式生成器

例子

import argparse
from genson import SchemaBuilder

parser = argparse.ArgumentParser(
    description="Some description", prog="myprog", usage="myprog [options]"
)
parser.add_argument(
    "-v",
    "--version",
    action="store_true",
    help="Print server version number and exit",
)
parser.add_argument(
    "-c",
    "--config",
    type=str,
    default=".fortls",
    help="Configuration options file (default file name: %(default)s)",
)
args = vars(parser.parse_args(""))
# Generate schema
builder = SchemaBuilder()
builder.add_schema({"type": "object", "properties": {}})
for k, v in args.items():
    builder.add_object({k: v})
print(builder.to_json(indent=2))

Output

{
  "$schema": "http://json-schema.org/schema#",
  "type": "object",
  "properties": {
    "version": {
      "type": "boolean"
    },
    "config": {
      "type": "string"
    }
  }
}

但是,我很快意識到調用vars(parser().parse_args(""))將 CLI 轉換為字典會導致大量信息丟失,例如描述和必需信息。

還有另一種方法嗎? 如果可以更輕松地生成模式,我願意將argparse與其他一些 CLI 交換。

額外資源

從 JSON 數據生成 JSON 模式的工具

我想出的解決方案是從ArgumentParser訪問私有變量_actions並使用pydantic將其轉換為模式。 在我的具體情況下,這很容易做到,因為argparse中的所有 arguments 都是可選的。 如果不是,則在使用pydantic創建 model 時必須多加考慮

from __future__ import annotations
from pydantic import Field, create_model
import argparse

parser = argparse.ArgumentParser(
    description="Some description", prog="myprog", usage="myprog [options]"
)
parser.add_argument(
    "-v",
    "--version",
    action="store_true",
    help="Print server version number and exit",
)
parser.add_argument(
    "-c",
    "--config",
    type=str,
    default=".fortls",
    help="Configuration options file (default file name: %(default)s)",
)

schema_vals = {}
for arg in parser._actions:
    # if condition for arguments to exclude:
    #     continue
    val = arg.default
    desc: str = arg.help.replace("%(default)s", str(val))  # type: ignore
    schema_vals[arg.dest] = Field(val, description=desc)  # type: ignore

m = create_model("MySchema", **schema_vals)
m.__doc__ = "Some description"

with open("schema.json", "w") as f:
    print(m.schema_json(indent=2), file=f)

Output

{
  "title": "MySchema",
  "description": "Some description",
  "type": "object",
  "properties": {
    "help": {
      "title": "Help",
      "description": "show this help message and exit",
      "default": "==SUPPRESS==",
      "type": "string"
    },
    "version": {
      "title": "Version",
      "description": "Print server version number and exit",
      "default": false,
      "type": "boolean"
    },
    "config": {
      "title": "Config",
      "description": "Configuration options file (default file name: .fortls)",
      "default": ".fortls",
      "type": "string"
    }
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM