Skip to content

Commit 5e74045

Browse files
authored
New Command : type-fastapi standard (#4)
* add standard structure support * added tests for standard
1 parent 40ae861 commit 5e74045

File tree

9 files changed

+222
-24
lines changed

9 files changed

+222
-24
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,6 @@ build
55
dist
66

77
# Files
8+
9+
# virtual environment
10+
venv

poetry.lock

Lines changed: 83 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "type-fastapi"
3-
version = "0.1.1"
3+
version = "0.1.2"
44
description = ""
55
authors = ["KevinRawal <[email protected]>"]
66
readme = "README.md"
@@ -16,6 +16,7 @@ pytest = "^8.3.3"
1616

1717
[tool.poetry.group.dev.dependencies]
1818
pytest-cov = "^6.0.0"
19+
black = "^24.10.0"
1920

2021
[build-system]
2122
requires = ["poetry-core"]

tests/test_main.py

Lines changed: 0 additions & 14 deletions
This file was deleted.
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import os
2+
import tempfile
3+
from typer.testing import CliRunner
4+
from type_fastapi.main import app
5+
6+
def test_type_fastapi_standard():
7+
"""
8+
Test the `standard` subcommand creates the expected files and directories.
9+
"""
10+
# Create a temporary directory
11+
with tempfile.TemporaryDirectory() as temp_dir:
12+
# Change the current working directory to the temporary directory
13+
current_dir = os.getcwd()
14+
os.chdir(temp_dir)
15+
16+
try:
17+
# Run the CLI command
18+
runner = CliRunner()
19+
result = runner.invoke(app, ["standard"])
20+
assert result.exit_code == 0
21+
22+
# Check if all files and directories are created
23+
expected_paths = [
24+
"app/__init__.py",
25+
"app/main.py",
26+
"app/routers/__init__.py",
27+
"app/services/__init__.py",
28+
"app/schemas/__init__.py",
29+
"app/models/__init__.py",
30+
"app/external_services/__init__.py",
31+
"app/config/__init__.py",
32+
"app/config/database.py",
33+
"app/utils/__init__.py",
34+
"tests/__init__.py",
35+
".gitignore",
36+
"requirements.txt",
37+
"README.md",
38+
]
39+
40+
for path in expected_paths:
41+
assert os.path.exists(path), f"File {path} was not created."
42+
43+
finally:
44+
# Clean up: Restore the original working directory
45+
os.chdir(current_dir)
46+
47+
if __name__ == "__main__":
48+
test_type_fastapi_standard()

type_fastapi/commands/__init__.py

Whitespace-only changes.

type_fastapi/commands/standard.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import typer
2+
import os
3+
4+
from type_fastapi.utils import create_structure
5+
6+
7+
def standard():
8+
"""
9+
Create a standard FastAPI setup
10+
"""
11+
base_dir = os.getcwd() # Current working directory
12+
structure = [
13+
{
14+
"app": [
15+
"__init__.py",
16+
"main.py",
17+
{"routers": ["__init__.py"]},
18+
{"services": ["__init__.py"]},
19+
{"schemas": ["__init__.py"]},
20+
{"models": ["__init__.py"]},
21+
{"external_services": ["__init__.py"]},
22+
{"config": ["__init__.py", "database.py"]},
23+
{"utils": ["__init__.py"]},
24+
]
25+
},
26+
{"tests": ["__init__.py"]},
27+
".gitignore",
28+
"requirements.txt",
29+
"README.md",
30+
]
31+
32+
create_structure(base_dir, structure)
33+
typer.echo("FastAPI project structure has been created successfully.")

type_fastapi/main.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import typer
2-
2+
from type_fastapi.commands.standard import standard
33

44
app = typer.Typer()
55

6+
app.command(name="standard")(standard)
7+
68

79
@app.callback()
810
def callback():
@@ -11,10 +13,5 @@ def callback():
1113
"""
1214

1315

14-
@app.command()
15-
def create_simple():
16-
"""
17-
Create a simple FastAPI app
18-
"""
19-
print("Create a simple FastAPI app")
20-
pass
16+
if __name__ == "__main__":
17+
app()

type_fastapi/utils.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import os
2+
import typer
3+
4+
5+
def create_structure(base, items):
6+
"""
7+
Recursively create files and directories based on the given items.
8+
9+
Args:
10+
base (str): The base directory to create the files and directories in.
11+
items (list[Union[str, dict]]): The list of items to create. If an item is a
12+
string, it is created as a file with the name being the value of the
13+
string. If an item is a dictionary, it is created as a directory with
14+
the key being the name of the directory and the value being the list of
15+
subitems to create inside the directory.
16+
17+
Returns:
18+
None
19+
"""
20+
for item in items:
21+
if isinstance(item, str):
22+
# Create files
23+
file_path = os.path.join(base, item)
24+
if os.path.exists(file_path):
25+
typer.secho(
26+
f"Warning: File already exists: {file_path}", fg=typer.colors.YELLOW
27+
)
28+
else:
29+
with open(file_path, "w", encoding="utf-8") as f:
30+
if item == "README.md":
31+
f.write("# FastAPI Project\n\nThis is a FastAPI project.")
32+
elif item == "requirements.txt":
33+
f.write("fastapi\nuvicorn\n") # Example dependencies
34+
elif item == ".gitignore":
35+
f.write("*.pyc\n__pycache__/\n.env\n")
36+
37+
elif isinstance(item, dict):
38+
# Create directories recursively
39+
for folder, subitems in item.items():
40+
folder_path = os.path.join(base, folder)
41+
if not os.path.exists(folder_path):
42+
os.makedirs(folder_path, exist_ok=True)
43+
create_structure(folder_path, subitems)
44+
else:
45+
typer.secho(
46+
f"Warning: Directory already exists: {folder_path}",
47+
fg=typer.colors.YELLOW,
48+
)

0 commit comments

Comments
 (0)