Skip to content

Commit e690027

Browse files
Merge pull request #37 from Mr-Sunglasses/release/2
Release/2
2 parents 2b69f39 + f8d4d01 commit e690027

File tree

8 files changed

+122
-42
lines changed

8 files changed

+122
-42
lines changed

.github/workflows/mypy.yml

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name: mypy paste.py 🐍
2+
3+
on:
4+
pull_request:
5+
branches: [main]
6+
7+
jobs:
8+
build:
9+
runs-on: ubuntu-latest
10+
11+
steps:
12+
- uses: actions/checkout@v3
13+
- name: Setup PDM
14+
uses: pdm-project/setup-pdm@v3
15+
with:
16+
python-version: 3.11
17+
cache: true
18+
cache-dependency-path: "**/pdm.lock"
19+
- name: Install dependencies
20+
run: pdm install
21+
- name: Run mypy
22+
run: pdm mypy

mypy.ini

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[mypy]
2+
ignore_missing_imports = True
3+
disallow_untyped_defs = True

pdm.lock

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

pyproject.toml

+8
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ license = {text = "MIT"}
2020
[tool.pdm.scripts]
2121
start = "uvicorn src.paste.main:app --host 0.0.0.0 --port 8080 --workers 4"
2222
test = "pytest"
23+
mypy = "mypy src/paste"
2324

2425
[tool.pdm.dev-dependencies]
2526
test = [
@@ -33,3 +34,10 @@ lint = [
3334
hooks = [
3435
"pre-commit>=3.6.0",
3536
]
37+
typing = [
38+
"mypy>=1.8.0",
39+
]
40+
41+
[tool.ruff]
42+
line-length = 160
43+
exclude = ["data/*", ".git"]

src/paste/main.py

+37-25
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,24 @@
1-
from fastapi import File, UploadFile, HTTPException, status, Request, Form, FastAPI, Header
2-
from fastapi.responses import PlainTextResponse, HTMLResponse, RedirectResponse, JSONResponse
1+
from fastapi import (
2+
File,
3+
UploadFile,
4+
HTTPException,
5+
status,
6+
Request,
7+
Form,
8+
FastAPI,
9+
Header,
10+
Response,
11+
)
12+
from fastapi.responses import (
13+
PlainTextResponse,
14+
HTMLResponse,
15+
RedirectResponse,
16+
JSONResponse,
17+
)
318
import shutil
419
import os
520
import json
621
from pathlib import Path
7-
from fastapi import FastAPI
822
from fastapi.templating import Jinja2Templates
923
from fastapi.middleware.cors import CORSMiddleware
1024
from slowapi.errors import RateLimitExceeded
@@ -16,7 +30,7 @@
1630
from pygments.lexers import get_lexer_by_name, guess_lexer
1731
from pygments.formatters import HtmlFormatter
1832
from pygments.util import ClassNotFound
19-
from typing import List, Optional, Any
33+
from typing import List, Optional
2034

2135
limiter = Limiter(key_func=get_remote_address)
2236
app: FastAPI = FastAPI(title="paste.py 🐍")
@@ -41,29 +55,31 @@
4155

4256
BASE_DIR: Path = Path(__file__).resolve().parent
4357

44-
templates: Jinja2Templates = Jinja2Templates(
45-
directory=str(Path(BASE_DIR, "templates")))
58+
templates: Jinja2Templates = Jinja2Templates(directory=str(Path(BASE_DIR, "templates")))
4659

4760

4861
@app.post("/file")
4962
@limiter.limit("100/minute")
50-
async def post_as_a_file(request: Request, file: UploadFile = File(...)) -> PlainTextResponse:
63+
async def post_as_a_file(
64+
request: Request, file: UploadFile = File(...)
65+
) -> PlainTextResponse:
5166
try:
5267
uuid: str = generate_uuid()
5368
if uuid in large_uuid_storage:
5469
uuid = generate_uuid()
5570
# Extract file extension from the filename
5671
try:
57-
file_extension: str = Path(file.filename).suffix[1:]
58-
path: str = f"data/{uuid}.{file_extension}"
72+
file_extension: Optional[str] = None
73+
if file.filename is not None:
74+
file_extension = Path(file.filename).suffix[1:]
75+
path: str = f"data/{uuid}{file_extension}"
5976
except Exception:
6077
path = f"data/{uuid}"
6178
finally:
6279
val: str = "/".join(path.split("/")[1:])
6380
with open(path, "wb") as f:
6481
shutil.copyfileobj(file.file, f)
6582
large_uuid_storage.append(uuid)
66-
print(large_uuid_storage)
6783
except Exception:
6884
raise HTTPException(
6985
detail="There was an error uploading the file",
@@ -75,7 +91,9 @@ async def post_as_a_file(request: Request, file: UploadFile = File(...)) -> Plai
7591

7692

7793
@app.get("/paste/{uuid}")
78-
async def get_paste_data(uuid: str, user_agent: Optional[str] = Header(None)) -> Any:
94+
async def get_paste_data(
95+
uuid: str, user_agent: Optional[str] = Header(None)
96+
) -> Response:
7997
path: str = f"data/{uuid}"
8098
try:
8199
with open(path, "rb") as f:
@@ -97,13 +115,11 @@ async def get_paste_data(uuid: str, user_agent: Optional[str] = Header(None)) ->
97115
try:
98116
lexer = get_lexer_by_name(file_extension, stripall=True)
99117
except ClassNotFound:
100-
lexer = get_lexer_by_name(
101-
"text", stripall=True) # Default lexer
118+
lexer = get_lexer_by_name("text", stripall=True) # Default lexer
102119
formatter = HtmlFormatter(
103-
style="colorful", full=True, linenos="inline", cssclass='code')
120+
style="colorful", full=True, linenos="inline", cssclass="code"
121+
)
104122
highlighted_code: str = highlight(content, lexer, formatter)
105-
106-
print(highlighted_code)
107123
custom_style = """
108124
.code pre span.linenos {
109125
color: #999;
@@ -154,19 +170,16 @@ async def get_paste_data(uuid: str, user_agent: Optional[str] = Header(None)) ->
154170
</body>
155171
</html>
156172
"""
157-
return HTMLResponse(
158-
content=response_content
159-
)
160-
except Exception as e:
161-
print(e)
173+
return HTMLResponse(content=response_content)
174+
except Exception:
162175
raise HTTPException(
163176
detail="404: The Requested Resource is not found",
164177
status_code=status.HTTP_404_NOT_FOUND,
165178
)
166179

167180

168181
@app.get("/", response_class=HTMLResponse)
169-
async def indexpage(request: Request) -> HTMLResponse:
182+
async def indexpage(request: Request) -> Response:
170183
return templates.TemplateResponse("index.html", {"request": request})
171184

172185

@@ -187,7 +200,7 @@ async def delete_paste(uuid: str) -> PlainTextResponse:
187200

188201

189202
@app.get("/web", response_class=HTMLResponse)
190-
async def web(request: Request) -> HTMLResponse:
203+
async def web(request: Request) -> Response:
191204
return templates.TemplateResponse("web.html", {"request": request})
192205

193206

@@ -209,8 +222,7 @@ async def web_post(
209222
with open(path, "wb") as f:
210223
f.write(file_content)
211224
large_uuid_storage.append(uuid_)
212-
except Exception as e:
213-
print(e)
225+
except Exception:
214226
raise HTTPException(
215227
detail="There was an error uploading the file",
216228
status_code=status.HTTP_403_FORBIDDEN,

src/paste/templates/index.html

+13-10
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
<!DOCTYPE html>
22
<html lang="en">
33
<head>
4-
<title>paste.py 🐍</title>
5-
<meta charset="UTF-8"/>
6-
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
7-
<meta name="og:title" content="paste.py 🐍"/>
8-
<meta name="og:site_name" content="paste.py"/>
9-
<meta name="og:description" content="A simple pastebin powered by FastAPI."/>
10-
<meta name="og:type" content="website"/>
11-
<meta name="og:url" content="https://paste.fosscu.org"/>
12-
<meta name="og:locale" content="en_US"/>
4+
<title>paste.py 🐍</title>
5+
<meta charset="UTF-8" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<meta name="og:title" content="paste.py 🐍" />
8+
<meta name="og:site_name" content="paste.py" />
9+
<meta
10+
name="og:description"
11+
content="A simple pastebin powered by FastAPI."
12+
/>
13+
<meta name="og:type" content="website" />
14+
<meta name="og:url" content="https://paste.fosscu.org" />
15+
<meta name="og:locale" content="en_US" />
1316
<style>
1417
body {
1518
font-family: sans-serif;
@@ -109,7 +112,7 @@ <h3>EXAMPLES</h3>
109112
A shell function that can be added to <strong>.bashrc</strong> or <strong>.bash_profle</strong> or <strong>.zshrc</strong> for
110113
quick pasting from the command line. The command takes a filename or reads
111114
from stdin if none was supplied and outputs the URL of the paste to
112-
stdout: <pre>paste file.txt</pre> or <pre>echo "hi" | paste</pre></p>
115+
stdout: <pre>paste file.txt</pre> <!-- or <pre>echo "hi" | paste</pre></p> -->
113116

114117

115118
</pre>

src/paste/utils.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
import random
22
import string
33
import os
4+
from pathlib import Path
45

56

6-
def generate_uuid():
7+
def generate_uuid() -> str:
78
# Combine uppercase letters, lowercase letters, and digits
8-
characters = string.ascii_letters + string.digits
9+
characters: str = string.ascii_letters + string.digits
910

1011
# Generate a random 4-character code
11-
random_code = ''.join(random.choice(characters) for _ in range(4))
12+
random_code: str = "".join(random.choice(characters) for _ in range(4))
1213

1314
return random_code
1415

1516

16-
def extract_extension(file_name):
17+
def extract_extension(file_name: Path) -> str:
1718
_, extension = os.path.splitext(file_name)
1819
return extension

tests/test_api.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
from fastapi.testclient import TestClient
22
from src.paste.main import app
3+
from typing import Optional
34
import os
45

56
client: TestClient = TestClient(app)
67

7-
file: str = None
8+
file: Optional[str] = None
89

910

1011
def test_get_health_route() -> None:

0 commit comments

Comments
 (0)