commit e0f4d9a855707947d507d72b055d70029db1b602 Author: sanspie Date: Thu Jan 16 20:15:15 2025 +0300 initial commit diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..3fc2da4 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,10 @@ +FROM python:3.11-slim + +WORKDIR /app + +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +COPY . . + +CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"] \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..19643c0 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,13 @@ +version: '3.8' + +services: + web: + build: . + ports: + - "8000:8000" + volumes: + - ./media:/app/media + - ./static:/app/static + - ./templates:/app/templates + environment: + - TZ=UTC \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..d1553f0 --- /dev/null +++ b/main.py @@ -0,0 +1,73 @@ +from fastapi import FastAPI, Request +from fastapi.responses import HTMLResponse +from fastapi.staticfiles import StaticFiles +from fastapi.templating import Jinja2Templates +from datetime import datetime +import asyncio + +app = FastAPI() + +# Mount static and media folders +app.mount("/static", StaticFiles(directory="static"), name="static") +app.mount("/media", StaticFiles(directory="media"), name="media") + +# Templates folder +templates = Jinja2Templates(directory="templates") + +# Python's official birth date +PYTHON_BIRTH = datetime(1991, 2, 20) + + +class SharedState: + """ Tracks Python's current age in decimal years, updated asynchronously. """ + def __init__(self): + self.current_age = 0.0 + self.running = False + + async def update_age(self): + """ Continuously update Python's age in decimal years. """ + while self.running: + now = datetime.now() + delta = now - PYTHON_BIRTH + # Convert time delta to decimal years + self.current_age = delta.days / 365.25 + (delta.seconds / (86400 * 365.25)) + await asyncio.sleep(0.1) # Update about 10 times per second + + +state = SharedState() + +@app.on_event("startup") +async def on_startup(): + state.running = True + asyncio.create_task(state.update_age()) + +@app.on_event("shutdown") +async def on_shutdown(): + state.running = False + +@app.get("/", response_class=HTMLResponse) +async def home(request: Request): + """ + Main page with an that loads /stream. + """ + return templates.TemplateResponse( + "index.html", + { + "request": request, + "now": datetime.now() + } + ) + +@app.get("/stream", response_class=HTMLResponse) +async def stream_time(request: Request): + """ + Returns a tiny HTML snippet that self-refreshes every 0.1 seconds. + No leftover lines, no JS. The page is simply reloaded repeatedly. + """ + return templates.TemplateResponse( + "counter.html", + { + "request": request, + "current_age": f"{state.current_age:.10f}" + } + ) diff --git a/media/meme1.jpg b/media/meme1.jpg new file mode 100644 index 0000000..ec554d5 Binary files /dev/null and b/media/meme1.jpg differ diff --git a/media/meme2.png b/media/meme2.png new file mode 100644 index 0000000..7e80d47 Binary files /dev/null and b/media/meme2.png differ diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..3d7cfdb --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +fastapi==0.109.1 +uvicorn==0.27.0 +jinja2==3.1.3 +python-multipart==0.0.7 +aiofiles==23.2.1 \ No newline at end of file diff --git a/static/python.svg b/static/python.svg new file mode 100644 index 0000000..e771ee2 --- /dev/null +++ b/static/python.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/templates/counter.html b/templates/counter.html new file mode 100644 index 0000000..ba7d402 --- /dev/null +++ b/templates/counter.html @@ -0,0 +1,24 @@ + + + + + + + + + ПИТОН ПОБЕДА УЖЕ {{ current_age }} ЛЕТ + + \ No newline at end of file diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..a4d6239 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,146 @@ + + + + + + ПИТОН ПОБЕДА + + + +

{{ now.year }} - ГОД ОЧЕРЕДНОЙ ПИТОН ПОБЕДЫ 🐍

+ + + +
+
+ +
+ +
+

Почему 2025 это год Питона?

+
💻 Python программисты пишут код быстрее, чем JavaScript его интерпретирует
+
🐍 У нас есть настоящие лямбды, а не эти ваши "=>"
+
⚡️ Мутируемые дефолтные аргументы? Это не баг, а фича!
+
+
+ +
+ Python Meme 1 +
+ +
+ Работает на FastAPI - Без JavaScript! 🚀 +
+ + + \ No newline at end of file