Skip to content
This repository was archived by the owner on Feb 8, 2025. It is now read-only.

Commit 5b2d78f

Browse files
committed
reinit
1 parent 19354e6 commit 5b2d78f

18 files changed

+800
-332
lines changed

example/helloworld.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1+
import kasumi
12
from kasumi import Kasumi
23
from starlette.requests import Request
34
from starlette.responses import JSONResponse
45

56
app = Kasumi()
67

7-
@app.post("/")
8+
@app.get("/")
89
async def root(request: Request):
9-
return JSONResponse({"Hello": "World"})
10+
return JSONResponse({"Hello": "World"})
11+
12+
print(kasumi.__version__)

pdm.lock

+180-284
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

+16-25
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,43 @@
11
[project]
22
name = "Kasumi"
3-
description = "Starlette-based ASGI Web framework."
3+
description = "Another ASGI Web framework."
44
authors = [
55
{name = "AmaseCocoa", email = "[email protected]"},
66
]
77
dependencies = [
88
"starlette>=0.37.2",
9-
"cleo>=2.1.0",
10-
]
11-
classifiers = [
12-
"Programming Language :: Python :: 3.10",
13-
"Programming Language :: Python :: 3.11",
14-
"Programming Language :: Python :: 3.12",
9+
"typer>=0.12.3",
10+
"requests>=2.32.3",
11+
"tqdm>=4.66.4",
12+
"cowsay>=6.1",
1513
]
1614
requires-python = ">=3.10"
1715
readme = "README.md"
1816
license = {file = "LICENSE"}
1917
dynamic = ["version"]
2018

21-
[project.scripts]
22-
kasumi = "src.kasumi.cli.__main__:main"
23-
2419
[project.optional-dependencies]
2520
asgi_dev = [
2621
"uvicorn[standard]>=0.30.1",
2722
]
28-
lint = [
23+
test = [
24+
"pytest>=8.2.2",
2925
"ruff>=0.4.8",
3026
]
3127

28+
[project.scripts]
29+
kasumi = "kasumi.cli.__core:app"
30+
3231
[project.urls]
3332
# documentation = "https://kasumi.readthedocs.io/"
3433
repository = "https://github.com/AmaseCocoa/Kasumi/"
3534

36-
[build-system]
37-
requires = ["setuptools", "wheel", "setuptools_scm>=8.0"]
38-
build-backend = "setuptools.build_meta"
39-
40-
[tool.setuptools_scm]
41-
write_to = "src/kasumi/__version.py"
42-
version_scheme = "python-simplified-semver"
43-
local_scheme = "no-local-version"
35+
[tool.pdm.version]
36+
source = "scm"
4437

45-
[tool.setuptools]
46-
package-dir = {"" = "src"}
47-
48-
[tool.setuptools.dynamic]
49-
version = {attr = "kasumi.__version.__version__"}
38+
[build-system]
39+
requires = ["pdm-backend"]
40+
build-backend = "pdm.backend"
5041

5142
[tool.pdm]
52-
distribution = true
43+
distribution = true

requirements.txt

+319
Large diffs are not rendered by default.

src/kasumi/__init__.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
from importlib.metadata import version
2+
13
from starlette.requests import Request
24

35
from . import responses
4-
from .__version import __version__, __version_tuple__
5-
from .applications import Kasumi
6+
from .applications import Kasumi
7+
from .gear import Gear
8+
9+
__version__ = version("kasumi")

src/kasumi/__version.py

-16
This file was deleted.

src/kasumi/applications.py

+53-3
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,39 @@
11
import inspect
2+
from importlib import import_module
3+
import os
24
from http.client import responses
35

46
from starlette.requests import Request
57
from starlette.responses import PlainTextResponse
68

7-
from .exceptions import AlreadyRegistedError
8-
9+
from .exceptions import AlreadyRegistedError, GearException
10+
from .gear import Gear
911

1012
class Kasumi:
13+
1114
def __init__(self) -> None:
1215
self.__requests = {}
1316
self.__err = {}
1417

1518
async def __call__(self, scope, receive, send):
19+
"""
20+
This function handles incoming HTTP requests by routing them to the appropriate handler based on
21+
the request method and path.
22+
23+
:param scope: The `scope` parameter in the `__call__` method represents the metadata of the
24+
incoming request. It contains information such as the type of the request (e.g., 'http' for HTTP
25+
requests), the path of the request, and other details related to the communication channel. In
26+
the provided
27+
:param receive: The `receive` parameter in the `__call__` method is a callable that is used to
28+
receive messages from the client. It is typically an asynchronous function that receives
29+
messages from the client connection. In the context of an HTTP server, the `receive` function is
30+
used to receive incoming HTTP requests
31+
:param send: The `send` parameter in the `__call__` method is a coroutine function that is used
32+
to send messages to the client. It is typically used to send HTTP response messages back to the
33+
client. The `send` function takes a single argument, which is a dictionary representing the
34+
message to be
35+
"""
36+
1637
assert scope['type'] == 'http'
1738
request = Request(scope, receive)
1839
if self.__requests.get(scope['path']):
@@ -103,4 +124,33 @@ def decorator(func):
103124
raise AlreadyRegistedError(f'The function is already registered in the ErrorCode “{error_code}”.')
104125
self.__err[error_code] = func
105126
return func
106-
return decorator
127+
return decorator
128+
129+
def combine_route(self, route: dict, name: str, routeType: str="normal"):
130+
if routeType == "normal":
131+
self.__requests[name] = route
132+
elif routeType == "err":
133+
self.__err[name] = route
134+
135+
def include_gear(self, module: Gear):
136+
route = module._requests
137+
for k in route.keys():
138+
if self.__requests.get(k):
139+
for router in route[k].keys():
140+
if self.__requests[k].get(router):
141+
raise GearException(f"""The Route "{k}" registered in the gear has another function registered""")
142+
else:
143+
self.combine_route(
144+
route[k], k
145+
)
146+
del k
147+
err = module._err
148+
for k in err.keys():
149+
if self.__err.get(k):
150+
for error in err[k].keys():
151+
if self.__requests[k].get(error):
152+
raise GearException(f"""The Route "{k}" registered in the gear has another function registered""")
153+
else:
154+
self.combine_route(
155+
err[k], k
156+
)

src/kasumi/cli/__core.py

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import json
2+
import os
3+
import re
4+
import shutil
5+
import urllib.parse
6+
7+
import cowsay
8+
import requests
9+
import tqdm
10+
import typer
11+
from rich.console import Console
12+
from rich.table import Table
13+
14+
app = typer.Typer(
15+
name="Kasumi",
16+
no_args_is_help=True
17+
)
18+
console = Console()
19+
20+
@app.command(hidden=True, deprecated=True)
21+
def moo():
22+
print(cowsay.get_output_string('cow', 'Hello, World!') + "\n")
23+
table = Table("[bold dodger_blue2]Surprised?[/bold dodger_blue2]")
24+
table.add_row("This is a temporary addition due to Typer's specifications.")
25+
table.add_row("We plan to remove it in the future, so I suggest you enjoy Super Cow Powers while you can :)")
26+
table.add_row("")
27+
table.add_row("Love from the author❤")
28+
console.print(table)
29+
30+
@app.command()
31+
def init(dir: str=os.getcwd(), template: str=None, external_template: str=None):
32+
dir = r"C:\\Users\AmaseCocoa\Desktop\\test"
33+
if template is None:
34+
while True:
35+
table = Table("[bold dodger_blue2]Select Internal Template[/bold dodger_blue2]")
36+
table.add_column("ID", justify="right", style="cyan", no_wrap=True)
37+
table.add_column("Name", style="magenta")
38+
table.add_column("Theme's Description", justify="right", style="green")
39+
table.add_row("1", "default", "The most standard and smallest Kasumi template.")
40+
table.add_row("2", "with_gear", "Kasumi template using Gear")
41+
console.print(table)
42+
select = input("select: ")
43+
if select == "1":
44+
template = "default"
45+
break
46+
elif select == "2":
47+
template = "with_gear"
48+
break
49+
else:
50+
table = Table("[bold red]Error[/bold red]")
51+
table.add_row("The specified template does not exist.")
52+
console.print(table)
53+
if not external_template:
54+
template_dir = os.path.join(os.path.join(os.path.dirname(__file__), "__templates"), template)
55+
if os.path.isdir(template_dir):
56+
with open(os.path.join(template_dir, "manifest.json"), "r") as f:
57+
manifest = json.load(f)
58+
for file in manifest["files"]:
59+
if isinstance(file, dict):
60+
shutil.copytree(os.path.join(os.path.join(template_dir, file["dir"])), os.path.join(dir, file["dir"]))
61+
else:
62+
path = os.path.join(template_dir, file)
63+
shutil.copy(path, dir)
64+
else:
65+
table = Table("[bold red]Error[/bold red]")
66+
table.add_row("The specified template does not exist.")
67+
console.print(table)
68+
raise
69+
else:
70+
pattern = r"https?://[\w/:%#\$&\?\(\)~\.=\+\-]+"
71+
if re.match(pattern, external_template):
72+
if not external_template.endswith("manifest.json"):
73+
manifest = urllib.parse.urljoin(external_template, "manifest.json")
74+
else:
75+
raise ValueError
76+
manifest = requests.get(external_template)
77+
manifest_jsonized = manifest.json()
78+
for file in manifest_jsonized["files"]:
79+
with open(os.path.join(dir, file), 'wb') as fp:
80+
url = urllib.parse.urljoin(external_template, file)
81+
with requests.get(url, stream=True) as req:
82+
req.raise_for_status()
83+
total = int(req.headers.get('content-length', 0))
84+
with tqdm.tqdm(**{'desc': url,'total': total,'miniters': 1,'unit': 'B','unit_scale': True,'unit_divisor': 1024,}) as pb:
85+
for chunk in req.iter_content(chunk_size=8192):
86+
pb.update(len(chunk))
87+
fp.write(chunk)
88+
else:
89+
with open(os.path.join(external_template, "manifest.json"), "r") as f:
90+
manifest = json.load(f)
91+
for file in manifest["files"]:
92+
if isinstance(file, dict):
93+
os.mkdir(os.path.join(dir, file["dir"]))
94+
for filed in file["files"]:
95+
shutil.copy(os.path.join(os.path.join(os.path.join(external_template, file["dir"]), filed), os.path.join(dir, file["dir"])))
96+
else:
97+
shutil.copy(os.path.join(external_template, file), dir)
98+
console.print("[bold green]Project initialization succeeded![/bold green]")

src/kasumi/cli/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import kasumi
2+
from kasumi import Kasumi
3+
from starlette.requests import Request
4+
from starlette.responses import JSONResponse
5+
6+
app = Kasumi()
7+
8+
@app.get("/")
9+
async def root(request: Request):
10+
return JSONResponse({"Hello": "World"})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"files": ["main.py", "requirements.txt"],
3+
"zip_path": null
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
kasumi
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import kasumi
2+
from kasumi import Kasumi
3+
from starlette.requests import Request
4+
from starlette.responses import JSONResponse
5+
6+
from src.sub import router
7+
8+
app = Kasumi()
9+
app.include_gear(router)
10+
11+
@app.get("/")
12+
async def root(request: Request):
13+
return JSONResponse({"Hello": "World"})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"files": ["main.py", "requirements.txt", {"dir": "src", "files": ["sub.py"]}],
3+
"zip_path": null
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
kasumi
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import kasumi
2+
from kasumi import Gear
3+
from starlette.requests import Request
4+
from starlette.responses import JSONResponse
5+
6+
router = Gear(prefix="/")

src/kasumi/exceptions.py

+3
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
class AlreadyRegistedError(Exception):
2+
pass
3+
4+
class GearException(Exception):
25
pass

0 commit comments

Comments
 (0)