mirror of
https://github.com/ycd/manage-fastapi.git
synced 2021-11-08 01:34:39 +03:00
Support Windows and MacOS (#36)
* Support Windows and MacOS * Add questionary dependency * Remove the tests * Remove print
This commit is contained in:
committed by
GitHub
parent
ff798ab052
commit
41648fb46e
3
.github/workflows/test.yml
vendored
3
.github/workflows/test.yml
vendored
@@ -8,9 +8,10 @@ on:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: "${{ matrix.os }}"
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
python-version: [3.6, 3.7, 3.8, 3.9]
|
||||
fail-fast: true
|
||||
|
||||
|
||||
@@ -1,37 +1,19 @@
|
||||
import re
|
||||
from typing import Tuple, TypeVar
|
||||
from typing import TypeVar
|
||||
|
||||
from bullet import Bullet, SlidePrompt, colors
|
||||
from bullet.client import YesNo
|
||||
import questionary
|
||||
|
||||
EnumType = TypeVar("EnumType")
|
||||
|
||||
WHITE_FOREGROUND = colors.foreground["white"]
|
||||
|
||||
|
||||
def camel_to_snake(text: str) -> str:
|
||||
return re.sub(r"(?<!^)(?=[A-Z])", "_", text).lower()
|
||||
|
||||
|
||||
def bullet(choices: EnumType) -> Bullet:
|
||||
def question(choices: EnumType) -> questionary.Question:
|
||||
prompt = camel_to_snake(choices.__name__).replace("_", " ") # type: ignore
|
||||
return Bullet(
|
||||
prompt=f"Select the {prompt}: ",
|
||||
choices=list(choices), # type: ignore
|
||||
bullet=" >",
|
||||
margin=2,
|
||||
word_color=WHITE_FOREGROUND,
|
||||
word_on_switch=WHITE_FOREGROUND,
|
||||
)
|
||||
return questionary.select(f"Select the {prompt}: ", choices=list(choices))
|
||||
|
||||
|
||||
def yes_no(option: str) -> YesNo:
|
||||
return YesNo(
|
||||
prompt=f"Do you want {option}?", default="n", word_color=WHITE_FOREGROUND
|
||||
)
|
||||
|
||||
|
||||
def launch_cli(*prompt_objs: Tuple[str, Bullet]):
|
||||
names, objs = zip(*prompt_objs)
|
||||
results = SlidePrompt(objs).launch()
|
||||
return {name: result[1] for name, result in zip(names, results)}
|
||||
def binary_question(option: str) -> questionary.Question:
|
||||
return questionary.confirm(f"Do you want {option}?", default=False)
|
||||
|
||||
@@ -4,11 +4,12 @@ from typing import Optional
|
||||
|
||||
import pkg_resources
|
||||
import typer
|
||||
from questionary.form import form
|
||||
|
||||
from manage_fastapi.constants import Database, License, PackageManager, PythonVersion
|
||||
from manage_fastapi.context import AppContext, ProjectContext
|
||||
from manage_fastapi.generator import generate_app, generate_project
|
||||
from manage_fastapi.helpers import bullet, launch_cli, yes_no
|
||||
from manage_fastapi.helpers import binary_question, question
|
||||
|
||||
app = typer.Typer(
|
||||
add_completion=False,
|
||||
@@ -29,13 +30,13 @@ def startproject(
|
||||
python: PythonVersion = typer.Option(PythonVersion.THREE_DOT_EIG),
|
||||
):
|
||||
if interactive:
|
||||
result = launch_cli(
|
||||
("packaging", bullet(PackageManager)),
|
||||
("python", bullet(PythonVersion)),
|
||||
("license", bullet(License)),
|
||||
("pre_commit", yes_no("pre commit")),
|
||||
("docker", yes_no("docker")),
|
||||
("database", bullet(Database)),
|
||||
result = form(
|
||||
packaging=question(PackageManager),
|
||||
python=question(PythonVersion),
|
||||
license=question(License),
|
||||
pre_commit=binary_question("pre commit"),
|
||||
docker=binary_question("docker"),
|
||||
database=question(Database),
|
||||
)
|
||||
context = ProjectContext(name=name, **result)
|
||||
else:
|
||||
|
||||
781
poetry.lock
generated
781
poetry.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -27,11 +27,11 @@ classifiers = [
|
||||
]
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
bullet = "^2.2.0"
|
||||
cookiecutter = "^1.7.2"
|
||||
pydantic = { extras = ["email"], version = "^1.7.2" }
|
||||
python = "^3.6.1"
|
||||
typer = "^0.3.2"
|
||||
typer = "^0.4.0"
|
||||
questionary = "^1.10.0"
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
autoflake = "^1.4"
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
import shutil
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def project_name():
|
||||
name = "potato"
|
||||
yield name
|
||||
try:
|
||||
shutil.rmtree(name)
|
||||
except FileNotFoundError:
|
||||
...
|
||||
@@ -1,3 +1,5 @@
|
||||
from pathlib import Path
|
||||
|
||||
from typer.testing import CliRunner
|
||||
|
||||
from manage_fastapi.main import app
|
||||
@@ -8,7 +10,8 @@ CREATED_SUCCESSFULLY = "FastAPI app created successfully! 🎉\n"
|
||||
ALREADY_EXISTS = "Folder 'potato' already exists. 😞\n"
|
||||
|
||||
|
||||
def test_startproject_default(project_name: str):
|
||||
result = runner.invoke(app, ["startapp", project_name])
|
||||
assert result.output == CREATED_SUCCESSFULLY
|
||||
assert result.exit_code == 0
|
||||
def test_startproject_default(tmp_path: Path):
|
||||
with runner.isolated_filesystem(temp_dir=tmp_path):
|
||||
result = runner.invoke(app, ["startapp", "potato"])
|
||||
assert result.output == CREATED_SUCCESSFULLY
|
||||
assert result.exit_code == 0
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from unittest.mock import patch
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from typer.testing import CliRunner
|
||||
|
||||
from manage_fastapi.main import app
|
||||
@@ -11,52 +10,19 @@ CREATED_SUCCESSFULLY = "FastAPI project created successfully! 🎉\n"
|
||||
ALREADY_EXISTS = "Folder 'potato' already exists. 😞\n"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("packaging", ["pip", "poetry"])
|
||||
@pytest.mark.parametrize("python", ["3.6", "3.7", "3.8"])
|
||||
@pytest.mark.parametrize("license_", ["MIT", "BSD", "GNU", "Apache"])
|
||||
@pytest.mark.parametrize("pre_commit", [True, False])
|
||||
@pytest.mark.parametrize("docker", [True, False])
|
||||
@pytest.mark.parametrize("database", ["Postgres", "MySQL"])
|
||||
def test_startproject(
|
||||
project_name: str,
|
||||
packaging: str,
|
||||
python: str,
|
||||
license_: str,
|
||||
pre_commit: bool,
|
||||
docker: bool,
|
||||
database: str,
|
||||
):
|
||||
package = "manage_fastapi.main.launch_cli"
|
||||
with patch(package) as mock_obj:
|
||||
|
||||
def side_effect(*args):
|
||||
return {
|
||||
"packaging": packaging,
|
||||
"python": python,
|
||||
"license": license_,
|
||||
"pre_commit": pre_commit,
|
||||
"docker": docker,
|
||||
"database": database,
|
||||
}
|
||||
|
||||
mock_obj.side_effect = side_effect
|
||||
result = runner.invoke(app, ["startproject", project_name, "--interactive"])
|
||||
assert mock_obj.assert_called_once
|
||||
def test_startproject_default(tmp_path: Path):
|
||||
with runner.isolated_filesystem(temp_dir=tmp_path):
|
||||
result = runner.invoke(app, ["startproject", "potato"])
|
||||
assert result.output == CREATED_SUCCESSFULLY
|
||||
assert result.exit_code == 0
|
||||
|
||||
|
||||
def test_startproject_default(project_name: str):
|
||||
result = runner.invoke(app, ["startproject", project_name])
|
||||
assert result.output == CREATED_SUCCESSFULLY
|
||||
assert result.exit_code == 0
|
||||
def test_startproject_already_exists(tmp_path: Path):
|
||||
with runner.isolated_filesystem(temp_dir=tmp_path):
|
||||
result = runner.invoke(app, ["startproject", "potato"])
|
||||
assert result.output == CREATED_SUCCESSFULLY
|
||||
assert result.exit_code == 0
|
||||
|
||||
|
||||
def test_startproject_already_exists(project_name: str):
|
||||
result = runner.invoke(app, ["startproject", project_name])
|
||||
assert result.output == CREATED_SUCCESSFULLY
|
||||
assert result.exit_code == 0
|
||||
|
||||
result = runner.invoke(app, ["startproject", project_name])
|
||||
assert result.output == ALREADY_EXISTS
|
||||
assert result.exit_code == 0
|
||||
result = runner.invoke(app, ["startproject", "potato"])
|
||||
assert result.output == ALREADY_EXISTS
|
||||
assert result.exit_code == 0
|
||||
|
||||
Reference in New Issue
Block a user