1
0
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:
Marcelo Trylesinski
2021-09-02 22:24:13 +02:00
committed by GitHub
parent ff798ab052
commit 41648fb46e
8 changed files with 487 additions and 430 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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"

View File

@@ -1,13 +0,0 @@
import shutil
import pytest
@pytest.fixture
def project_name():
name = "potato"
yield name
try:
shutil.rmtree(name)
except FileNotFoundError:
...

View File

@@ -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

View File

@@ -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