首页 > 其他分享 >devtool.py -- 一个FastAPI的开发环境便捷脚本

devtool.py -- 一个FastAPI的开发环境便捷脚本

时间:2022-11-22 23:13:41浏览次数:66  
标签:cmd run args -- FastAPI py version str def

 

用惯了Django的manage.py所以在FastAPI的项目里,也写了一个类似的脚步:

#!/usr/bin/env python
import subprocess
import sys
from pathlib import Path
from typing import List, Tuple


def get_part(s: str) -> str:
    """根据输入的选项,返回对应的命令参数

    Usage::
        >>> get_part('1')
        'patch'
        >>> get_part('patch')
        'patch'
    """
    choices = {"1": "patch", "2": "minor", "3": "major"}
    choices.update({v: v for v in choices.values()})
    try:
        return choices[s]
    except KeyError:
        print(f"Invalid part: {s!r}")
        sys.exit(1)


def run_and_echo(cmd: str) -> int:
    """先打印出SHELL命令,然后执行它"""
    print("-->", cmd)
    return subprocess.run(cmd, shell=True).returncode


def get_current_version() -> str:
    """获取pyproject.toml文件里的版本号"""
    r = subprocess.run(["poetry", "version", "-s"], capture_output=True)
    return r.stdout.decode().strip()


def exit_if_run_failed(cmd: str) -> None:
    """打印和执行SHELL命令,并在执行失败时退出脚本"""
    if rc := run_and_echo(cmd):
        sys.exit(rc)


def bump():
    """根据输入的选项,执行bumpversion命令去升级版本和打标签"""
    version = get_current_version()
    print(f"Current version: {version}")
    if sys.argv[1:]:
        part = get_part(sys.argv[1])
    else:
        tip = (
            "Choices:\n1. patch\n2. minor\n3. major\n\n"
            "Which one to bump?(Leave blank to use `patch`) "
        )
        if a := input(tip).strip():
            part = get_part(a)
        else:
            part = "patch"
    parse = '"(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)"'  # NOQA
    cmd = (
        f"bumpversion --commit --parse {parse}"
        f" --current-version {version} {part} pyproject.toml"
    )
    if part != "patch":
        cmd + " --tag"
    exit_if_run_failed(cmd)
    exit_if_run_failed("git push && git push --tags && git log -1")


class UpgradeDependencies:
    """升级依赖到最新版本
    (直接用poetry update的话,只会升级小版本,不会升级大版本)
    """

    @staticmethod
    def parse_extras(version_info: str, extras_tip: str) -> str:
        extras_info = version_info.split(extras_tip)[-1]
        return extras_info.split("[", 1)[-1].split("]")[0].replace('"', "")

    @classmethod
    def build_args(cls, package_lines: List[str], extras_tip: str) -> List[str]:
        args: List[str] = []
        for m in package_lines:
            package, version_info = m.split("=", 1)
            if (package := package.strip()).lower() == "python":
                continue
            if extras_tip in version_info:
                package += "[" + cls.parse_extras(version_info, extras_tip) + "]"
                args.append(f'"{package}@latest"')
            else:
                args.append(f"{package}@latest")
        return args

    @classmethod
    def get_args(cls) -> Tuple[List[str], List[str]]:
        main_title = "[tool.poetry.dependencies]"
        dev_title = "[tool.poetry.dev-dependencies]"
        toml_file = Path(__file__).parent.resolve().parent / "pyproject.toml"
        text = toml_file.read_text("utf8").split(main_title)[-1]
        main, dev = text.split(dev_title)
        devs = dev.split("[tool.")[0].strip().splitlines()
        mains = main.strip().splitlines()
        extras_tip = "extras"
        return cls.build_args(mains, extras_tip), cls.build_args(devs, extras_tip)


def update():
    """升级所有依赖包到最新版"""
    main_args, dev_args = UpgradeDependencies.get_args()
    command = "poetry add"
    upgrade = "{0} {1} && {0} --dev {2}".format(
        command, " ".join(main_args), " ".join(dev_args)
    )
    exit_if_run_failed(upgrade)


def lint(remove=None):
    """格式化加静态检查"""
    remove_imports = "autoflake --in-place --remove-all-unused-imports"
    cmd = ""
    paths = "."
    if args := sys.argv[1:]:
        if (flag := "-r") in args:
            if remove is None:
                remove = True
            args = [i for i in args if i != flag]
        paths = " ".join(args)
        if remove and all(Path(i).is_file() for i in args):
            cmd = f"{remove_imports} {paths} && " + cmd
    lint_them = "{0} {2} {1} && {0} {3} {1} && {0} {4} {1} && {0} {5} {1}"
    tools = ("isort", "black", "pflake8", "mypy")
    cmd += lint_them.format("poetry run", paths, *tools)
    exit_if_run_failed(cmd)


def dev():
    """启动服务:相当于django的runserver"""
    cmd = "poetry run python main.py"
    if args := sys.argv[1:]:
        cmd += " " + " ".join(args)
    exit_if_run_failed(cmd)


def makemigrations():
    """生成数据库迁移文件,类似Django的./manage.py makemigrations"""
    exit_if_run_failed("aerich migrate")


def migrate():
    """更新数据库表结构:相当于django的./manage.py migrate"""
    exit_if_run_failed("aerich upgrade")

标签:cmd,run,args,--,FastAPI,py,version,str,def
From: https://www.cnblogs.com/waketzheng/p/16916834.html

相关文章

  • Grid 布局
    flex布局是解决一维的布局问题,grid布局是解决二维的布局问题博文推荐GridMDN讲解    Grid基本用法讲解Auto-fillvsauto-fit......
  • 马尔科夫不等式与切比雪夫不等式
    马尔科夫不等式(Markovinequality)任取非负随机变量$X$,则$\foralla>0$有$P(X\gea)\le\frac{E(X)}a$证明:任取\(a>0\),设\(Y_a=\begin{cases}0&(X<a)\\a&......
  • kubesphere环境安装
    安装步骤选择4核8G(master)、8核16G(node1)、8核16G(node2)三台机器,按量付费进行实验,CentOS7.9安装Docker安装Kubernetes安装KubeSphere前置环境安装KubeSphere1、安装D......
  • Linux笔记03: Linux常用命令_3.1命令的基本格式
    3.1命令的基本格式 3.1.1命令提示符[root@localhost~]#这就是Linux系统的命令提示符。各部分含义如下:●[]:这是提示符的分隔符号,没有特殊含义。●ro......
  • DP 专训
    因为一些原因前面部分先咕着stringCounting题意\(~~~~\)有\(26\)种不同的字符,第\(i\)种有\(c_i\)个。构造一个长为\(n\)的字符串,使得字符串上不存在长度为奇......
  • TypeScript & Type Challenges All In One
    TypeScript&TypeChallengesAllInOneCollectionofTypeScripttypechallengeswithonlinejudgehttps://tsch.js.org/https://github.com/type-challenges/typ......
  • 随机打乱数组--java实现
    参考链接听说过java.utils.Random随机数是伪随机,但是Math库还没学,所以下面代码中还是用的Randompublicstaticint[]shuffle(int[]arr){Randomr=newRandom(......
  • webpack基础
    webpackwebpack是代码编译工具,有入口、出口、loader和插件。webpack是一个用于现代[JavaScript](https://baike.baidu.com/item/JavaScript/321142?fromModule=lem......
  • 前端项目中:需要注意的点
    (1)数组的拷贝浅拷贝:当数据为一维数组时,可以很好的开辟一块新的内存空间当数据为高维数组时,有协同修改的风险深拷贝:完全的开辟一块新的内存空间https://ww......
  • Java 用Lambda实现一个通用的制造者工具
    在我们日常开发中,虽然是用了lombok在实体类中已经帮我们省了get、set方法,但是在公司的项目中,还是经常会出现new一个对象然后一个个的给它set值的情况,太丑了,如下图List<St......