diff --git a/docker/docker-bind/solution.sh b/docker/docker-bind/solution.sh new file mode 100644 index 00000000..a5c73509 --- /dev/null +++ b/docker/docker-bind/solution.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +# Запуск контейнера с указанными параметрами +docker run -d \ + --name jusan-docker-bind \ + -p 7777:80 \ + -v $(pwd)/nginx.conf:/etc/nginx/nginx.conf:ro \ + nginx:mainline + +# Проверка доступности сервера +curl http://localhost:7777 + +# Показ списка запущенных контейнеров +docker ps + +# Вывод логов nginx +docker logs jusan-docker-bind + diff --git a/docker/docker-compose-final/docker-compose.yml b/docker/docker-compose-final/docker-compose.yml new file mode 100644 index 00000000..6aa6545e --- /dev/null +++ b/docker/docker-compose-final/docker-compose.yml @@ -0,0 +1,26 @@ +version: '3.8' + +services: + api: + image: jusan-fastapi-final:dockerized + container_name: jusan-compose-final + restart: always + + nginx: + image: nginx:mainline + container_name: jusan-nginx-final + restart: always + depends_on: + - api + ports: + - "8787:80" + volumes: + - ./jusan-docker-mount.conf:/etc/nginx/conf.d/jusan-docker-mount.conf # Монтирование конфигурации + - ./jusan-docker-mount.zip:/usr/share/nginx/html/jusan-docker-mount.zip # Монтирование распакованного архива + - ./jusan-fastapi-final.conf:/etc/nginx/conf.d/jusan-fastapi-final.conf # Конфигурация для перенаправления запросов + networks: + - webnet + +networks: + webnet: + driver: bridge diff --git a/docker/docker-compose-final/jusan-docker-mount.conf b/docker/docker-compose-final/jusan-docker-mount.conf new file mode 100644 index 00000000..e51712dc --- /dev/null +++ b/docker/docker-compose-final/jusan-docker-mount.conf @@ -0,0 +1,8 @@ +server { + listen 80; + server_name example.com; + + location / { + root /var/www/example; + } +} diff --git a/docker/docker-compose-final/jusan-docker-mount/.DS_Store b/docker/docker-compose-final/jusan-docker-mount/.DS_Store new file mode 100644 index 00000000..5008ddfc Binary files /dev/null and b/docker/docker-compose-final/jusan-docker-mount/.DS_Store differ diff --git a/docker/docker-compose-final/jusan-docker-mount/index.html b/docker/docker-compose-final/jusan-docker-mount/index.html new file mode 100644 index 00000000..84836c45 --- /dev/null +++ b/docker/docker-compose-final/jusan-docker-mount/index.html @@ -0,0 +1 @@ +
root@user-asus:/home/user/Documents/jusan-docker/docker-compose# docker-compose up -d
+Creating network "docker-compose_default" with the default driver
+Creating jusan-compose ... done
+root@user-asus:/home/user/Documents/jusan-docker/docker-compose# docker ps
+CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
+786cae00cc10 jusan-fastapi-final:dockerized "uvicorn main:app --…" 14 seconds ago Restarting (1) 3 seconds ago jusan-compose
+root@user-asus:/home/user/Documents/jusan-docker/docker-compose#
diff --git a/docker/docker-compose/docker-compose.yml b/docker/docker-compose/docker-compose.yml
new file mode 100644
index 00000000..e28e547b
--- /dev/null
+++ b/docker/docker-compose/docker-compose.yml
@@ -0,0 +1,9 @@
+version: '3.8'
+
+services:
+ api:
+ image: jusan-fastapi-final:dockerized
+ container_name: jusan-compose
+ ports:
+ - "8282:8080"
+ restart: always
\ No newline at end of file
diff --git a/docker/docker-exec/solution.sh b/docker/docker-exec/solution.sh
new file mode 100644
index 00000000..bbadfb02
--- /dev/null
+++ b/docker/docker-exec/solution.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+# Запуск контейнера
+docker run -d \
+ --name jusan-docker-exec \
+ -p 8181:80 \
+ nginx:mainline
+
+# Вход в контейнер и создание нового конфигурационного файла
+docker exec -it jusan-docker-exec bash -c "cat << EOF > /etc/nginx/conf.d/jusan-docker-exec.conf
+server {
+ listen 80;
+ server_name jusan.singularity;
+
+ location / {return 200 'Hello, from jusan-docker-exec';}
+ location /home {return 201 'This is my home!';}
+ location /about {return 202 'I am just an exercise!';}
+}
+EOF"
+
+# Перезагрузка nginx внутри контейнера
+docker exec jusan-docker-exec nginx -s reload
+
+# Проверка запросов с помощью curl
+curl http://localhost:8181
+curl http://localhost:8181/home
+curl http://localhost:8181/about
+
+# Просмотр логов nginx
+docker logs jusan-docker-exec
diff --git a/docker/docker-mount/solution.sh b/docker/docker-mount/solution.sh
new file mode 100644
index 00000000..b88a85a6
--- /dev/null
+++ b/docker/docker-mount/solution.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+# Запуск контейнера с указанными параметрами
+docker run -d \
+ --name jusan-docker-mount \
+ -p 9999:80 \
+ -v $(pwd)/jusan-docker-mount.conf:/etc/nginx/conf.d/jusan-docker-mount.conf:ro \
+ -v $(pwd)/jusan-docker-mount:/usr/share/nginx/html:ro \
+ nginx:mainline
+
+# Проверка запросов
+curl http://localhost:9999
+curl http://localhost:9999/test
+curl http://localhost:9999/token
+
+# Просмотр логов
+docker logs jusan-docker-mount
diff --git a/docker/dockerfile/Dockerfile b/docker/dockerfile/Dockerfile
new file mode 100644
index 00000000..afa8a663
--- /dev/null
+++ b/docker/dockerfile/Dockerfile
@@ -0,0 +1,4 @@
+FROM nginx:mainline
+
+COPY ./jusan-dockerfile.conf /etc/nginx/conf.d/jusan-dockerfile.conf
+COPY ./jusan-dockerfile /var/www/jusan-dockerfile
diff --git a/docker/dockerfile/solution.sh b/docker/dockerfile/solution.sh
new file mode 100644
index 00000000..d6b62acf
--- /dev/null
+++ b/docker/dockerfile/solution.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+# Скачать архив и распаковать
+curl -o jusan-dockerfile.zip https://stepik.org/media/attachments/lesson/686238/jusan-dockerfile.zip
+unzip jusan-dockerfile.zip -d jusan-files
+
+# Скачать архив и распаковать конф
+curl -O https://stepik.org/media/attachments/lesson/686238/jusan-dockerfile.conf
+docker build -t nginx:jusan-dockerfile .
+
+./tester-dockerfile.sh
+
diff --git a/docker/dockerize/fastapi-final/Dockerfile b/docker/dockerize/fastapi-final/Dockerfile
new file mode 100644
index 00000000..446efa8d
--- /dev/null
+++ b/docker/dockerize/fastapi-final/Dockerfile
@@ -0,0 +1,18 @@
+# Используем официальный образ Python
+FROM python:3.9-slim
+
+# Устанавливаем рабочую директорию внутри контейнера
+WORKDIR /app
+
+# Копируем все файлы в рабочую директорию контейнера
+COPY . /app
+
+# Устанавливаем зависимости из requirements.txt
+RUN pip install --no-cache-dir -r requirements.txt
+
+# Открываем порт 8080
+EXPOSE 8080
+
+# Команда для запуска FastAPI приложения (проверьте путь к вашему файлу, если нужно)
+CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]
+
diff --git a/docker/dockerize/fastapi-final/requirements.txt b/docker/dockerize/fastapi-final/requirements.txt
new file mode 100644
index 00000000..41603392
--- /dev/null
+++ b/docker/dockerize/fastapi-final/requirements.txt
@@ -0,0 +1,12 @@
+beautifulsoup4==4.10.0
+click==8.1.7
+colorama==0.4.6
+fastapi==0.115.2
+h11==0.14.0
+idna==3.10
+pydantic==2.9.2
+pydantic_core==2.23.4
+sniffio==1.3.1
+starlette==0.40.0
+typing_extensions==4.12.2
+uvicorn==0.32.0
diff --git a/docker/dockerize/fastapi-final/txt.txt b/docker/dockerize/fastapi-final/txt.txt
new file mode 100644
index 00000000..fd93ed7d
--- /dev/null
+++ b/docker/dockerize/fastapi-final/txt.txt
@@ -0,0 +1 @@
+что за прикол с созданием папок
diff --git a/docker/dockerize/solution.sh b/docker/dockerize/solution.sh
new file mode 100644
index 00000000..82e02ccb
--- /dev/null
+++ b/docker/dockerize/solution.sh
@@ -0,0 +1,6 @@
+ curl -O https://raw.githubusercontent.com/Rinotrihanna/TechOrda/main/docker/dockerize/fastapi-final/Dockerfile
+ curl -O https://raw.githubusercontent.com/Rinotrihanna/TechOrda/main/docker/dockerize/fastapi-final/requirements.txt
+ docker build -t jusan-fastapi-final:dockerized .
+ docker images
+ docker run -d -p 8080:8080 --name jusan-dockerize jusan-fastapi-final:dockerized
+
diff --git a/nginx/nginx-auth/answer.md b/nginx/nginx-auth/answer.md
new file mode 100644
index 00000000..0619dadb
--- /dev/null
+++ b/nginx/nginx-auth/answer.md
@@ -0,0 +1,75 @@
+> root@user-asus:/etc/nginx# cat ./sites-available/default
+server {
+ listen 8080;
+ server_name example.com;
+
+ location /secret_word {
+ # Возвращает строку jusan-nginx-ip со статусом 203
+ return 203 "jusan-nginx-ip";
+
+ # Разрешение доступа из диапазона 192.0.0.0/20, кроме 192.0.0.1
+ allow 192.0.0.0/20;
+ deny 192.0.0.1;
+
+ # Запрет для всех остальных
+ deny all;
+
+ # Установка заголовка Content-Type
+ add_header Content-Type text/plain;
+
+ }
+
+ location / {
+ root /var/www/html; # Путь к index.html
+ index index.html;
+ }
+
+ location /images {
+ auth_basic "Protected Area for Design";
+ auth_basic_user_file /etc/nginx/conf.d/passwd;
+ # Разархивируйте cats.zip в /var/www/html/cats
+ alias /var/www/html/cats;
+ autoindex on;
+ }
+
+ location /gifs {
+ auth_basic "Protected Area for Marketing";
+ auth_basic_user_file /etc/nginx/conf.d/passwd;
+ # Разархивируйте gifs.zip в /var/www/html/gifs
+ alias /var/www/html/gifs;
+ autoindex on;
+ }
+
+ # Запрет на доступ к другим путям для учетной записи design
+ location /restricted_design {
+ satisfy any;
+ deny all;
+ }
+
+ # Запрет на доступ к другим путям для учетной записи marketing
+ location /restricted_marketing {
+ satisfy any;
+ deny all;
+ }
+}
+
+
+
+> root@user-asus:/etc/nginx# nano ./sites-available/default
+> root@user-asus:/etc/nginx# nginx -t
+> nginx: [warn] conflicting server name "example.com" on 0.0.0.0:8080, ignored
+> nginx: [warn] conflicting server name "jusan.kz" on 0.0.0.0:443, ignored
+> nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
+> nginx: configuration file /etc/nginx/nginx.conf test is successful
+> root@user-asus:/etc/nginx# systemctl restart nginx
+> root@user-asus:/etc/nginx# curl --user marketing:marketingP@ssword http://localhost:8080/gifs/
+>
+> ../ +> __MACOSX/ 27-Oct-2024 14:06 - +> dancing.gif 25-Mar-2022 11:20 253794 +> jam.gif 25-Mar-2022 11:20 471720 +> sad.gif 25-Mar-2022 11:21 3605836 +>
+
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+
diff --git a/nginx/nginx-proxy/answer.md b/nginx/nginx-proxy/answer.md
new file mode 100644
index 00000000..b65ce83d
--- /dev/null
+++ b/nginx/nginx-proxy/answer.md
@@ -0,0 +1,11 @@
+location /api {
+ proxy_pass http://localhost:9090;
+ rewrite ^/api(/.*)?$ $1 break;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ add_header web-server 0;
+}
+
+
+
+
diff --git a/nginx/nginx-ufw/answer.md b/nginx/nginx-ufw/answer.md
new file mode 100644
index 00000000..ca9e1d3f
--- /dev/null
+++ b/nginx/nginx-ufw/answer.md
@@ -0,0 +1,25 @@
+root@user-asus:/etc/nginx# ufw allow 80/tcp
+Skipping adding existing rule
+Skipping adding existing rule (v6)
+root@user-asus:/etc/nginx# ufw allow 443/tcp
+Skipping adding existing rule
+Skipping adding existing rule (v6)
+root@user-asus:/etc/nginx# ufw status
+Status: active
+
+To Action From
+-- ------ ----
+22 ALLOW Anywhere
+22/tcp ALLOW Anywhere
+2222/tcp ALLOW Anywhere
+80/tcp ALLOW Anywhere
+443/tcp ALLOW Anywhere
+22 (v6) ALLOW Anywhere (v6)
+22/tcp (v6) ALLOW Anywhere (v6)
+2222/tcp (v6) ALLOW Anywhere (v6)
+80/tcp (v6) ALLOW Anywhere (v6)
+443/tcp (v6) ALLOW Anywhere (v6)
+
+
+
+
diff --git a/postgres/sql-delete/answer.md b/postgres/sql-delete/answer.md
new file mode 100644
index 00000000..293fcc2d
--- /dev/null
+++ b/postgres/sql-delete/answer.md
@@ -0,0 +1,2 @@
+delete from users
+where name = 'serikbolat';
diff --git a/postgres/sql-insert/answer.md b/postgres/sql-insert/answer.md
new file mode 100644
index 00000000..686073e9
--- /dev/null
+++ b/postgres/sql-insert/answer.md
@@ -0,0 +1,2 @@
+insert into users (name, age, country, department)
+values ('azatmukanov','40','GER','operations')
diff --git a/postgres/sql-select/answer.md b/postgres/sql-select/answer.md
new file mode 100644
index 00000000..2aa1dc3d
--- /dev/null
+++ b/postgres/sql-select/answer.md
@@ -0,0 +1,2 @@
+select name, age, department from users
+where age < 30;
diff --git a/postgres/sql-update/answer.md b/postgres/sql-update/answer.md
new file mode 100644
index 00000000..638f4529
--- /dev/null
+++ b/postgres/sql-update/answer.md
@@ -0,0 +1,3 @@
+update users
+set department = 'sales', country = 'KZ'
+where name ='azatmukanov';
diff --git a/python/api/AZ_README.md b/python/api/AZ_README.md
new file mode 100644
index 00000000..2ef0769e
--- /dev/null
+++ b/python/api/AZ_README.md
@@ -0,0 +1,100 @@
+# `README.md` по fastapi
+
+
+### 1) Создание рабочей папки
+
+> mkdir ./api-project cd ./api-project
+
+### 2) Вводим команды в командной строке
+
+> python3 -m venv .venv source .venv/bin/activate pip install "fastapi"
+> "uvicorn[standard]"
+
+### 3) Создание файла main.py и запускаем api
+
+ from fastapi import FastAPI
+ app = FastAPI()
+ @app.get("/") def read_root():
+ return {"Hello": "World"}
+
+> uvicorn main:app --reload
+> curl http://127.0.0.1:8000/
+
+### 4) в api-final выполняем задачи из READ.ME
+*У меня код выглядит так (конечно не без помощи чатгпт)*
+
+ from fastapi import FastAPI, HTTPException
+ from pydantic import BaseModel
+ from typing import List
+ app = FastAPI()
+ elements: List[str] = []
+ class Element(BaseModel):
+ element: str
+ class Expression(BaseModel):
+ expr: str
+ @app.get("/sum1n/{n}")
+ async def sum_to_n(n: int):
+ result = sum(range(1, n + 1))
+ return {"result": result}
+
+ def fibonacci(n: int) -> int:
+ if n == 0:
+ return 0
+ elif n == 1:
+ return 1
+ else:
+ a, b = 0, 1
+ for _ in range(2, n + 1):
+ a, b = b, a + b
+
+
+ return b
+ @app.get("/fibo")
+ async def get_fibonacci(n: int):
+ result = fibonacci(n)
+ return {"result": result}
+
+ @app.post("/reverse")
+ async def reverse_string(string: str):
+ reversed_string = string[::-1]
+ return {"result": reversed_string}
+
+ @app.api_route("/list", methods=["GET", "PUT"])
+ async def handle_list(element: Element = None):
+ if element:
+ elements.append(element.element)
+ return {"result": elements}
+ return {"result": elements}
+
+ def calculate_expression(expression: str):
+ try:
+ num1, operator, num2 = expression.split(',')
+ num1 = float(num1)
+ num2 = float(num2)
+
+ if operator == '+':
+ return num1 + num2
+ elif operator == '-':
+ return num1 - num2
+ elif operator == '*':
+ return num1 * num2
+ elif operator == '/':
+ if num2 == 0:
+ raise ZeroDivisionError
+ return num1 / num2
+ else:
+ raise ValueError("Invalid operator")
+ except ValueError:
+ raise ValueError("Invalid expression format")
+
+ @app.post("/calculator")
+ async def calculator(expression: Expression):
+ try:
+ result = calculate_expression(expression.expr)
+ return {"result": result}
+ except ValueError:
+ raise HTTPException(status_code=400, detail={"error": "invalid"})
+ except ZeroDivisionError:
+ raise HTTPException(status_code=403, detail={"error": "zerodiv"})
+
+### + Прикреплен автотест по юнитам + requirements.txt
diff --git a/python/api/main.py b/python/api/main.py
new file mode 100644
index 00000000..ad9c7b1d
--- /dev/null
+++ b/python/api/main.py
@@ -0,0 +1,73 @@
+from fastapi import FastAPI, HTTPException
+from pydantic import BaseModel
+from typing import List
+
+app = FastAPI()
+elements: List[str] = []
+class Element(BaseModel):
+ element: str
+class Expression(BaseModel):
+ expr: str
+@app.get("/sum1n/{n}")
+async def sum_to_n(n: int):
+ result = sum(range(1, n + 1))
+ return {"result": result}
+
+def fibonacci(n: int) -> int:
+ if n == 0:
+ return 0
+ elif n == 1:
+ return 1
+ else:
+ a, b = 0, 1
+ for _ in range(2, n + 1):
+ a, b = b, a + b
+ return b
+
+@app.get("/fibo")
+async def get_fibonacci(n: int):
+ result = fibonacci(n)
+ return {"result": result}
+
+@app.post("/reverse")
+async def reverse_string(string: str):
+ reversed_string = string[::-1]
+ return {"result": reversed_string}
+
+@app.api_route("/list", methods=["GET", "PUT"])
+async def handle_list(element: Element = None):
+ if element:
+ elements.append(element.element)
+ return {"result": elements}
+ return {"result": elements}
+
+def calculate_expression(expression: str):
+ try:
+ num1, operator, num2 = expression.split(',')
+ num1 = float(num1)
+ num2 = float(num2)
+
+ if operator == '+':
+ return num1 + num2
+ elif operator == '-':
+ return num1 - num2
+ elif operator == '*':
+ return num1 * num2
+ elif operator == '/':
+ if num2 == 0:
+ raise ZeroDivisionError
+ return num1 / num2
+ else:
+ raise ValueError("Invalid operator")
+ except ValueError:
+ raise ValueError("Invalid expression format")
+
+@app.post("/calculator")
+async def calculator(expression: Expression):
+ try:
+ result = calculate_expression(expression.expr)
+ return {"result": result}
+ except ValueError:
+ raise HTTPException(status_code=400, detail={"error": "invalid"})
+ except ZeroDivisionError:
+ raise HTTPException(status_code=403, detail={"error": "zerodiv"})
diff --git a/python/api/requirements.txt b/python/api/requirements.txt
new file mode 100644
index 00000000..fbf4f5fa
--- /dev/null
+++ b/python/api/requirements.txt
@@ -0,0 +1,125 @@
+annotated-types==0.7.0
+anyio==4.6.2.post1
+apt-clone==0.2.1
+apturl==0.5.2
+asgiref==3.5.0
+attrs==21.2.0
+beautifulsoup4==4.10.0
+blinker==1.4
+Brlapi==0.8.3
+certifi==2020.6.20
+chardet==4.0.0
+click==8.0.3
+colorama==0.4.4
+command-not-found==0.3
+configobj==5.0.6
+cryptography==3.4.8
+cupshelpers==1.0
+dbus-python==1.2.18
+defer==1.0.6
+distro==1.7.0
+distro-info==1.1+ubuntu0.2
+docker==5.0.3
+docker-compose==1.29.2
+dockerpty==0.4.1
+docopt==0.6.2
+exceptiongroup==1.2.2
+eyeD3==0.8.10
+fastapi==0.115.2
+filelock==3.6.0
+grpcio==1.30.2
+h11==0.13.0
+httpcore==1.0.6
+httplib2==0.20.2
+httpx==0.27.2
+idna==3.3
+ifaddr==0.1.7
+IMDbPY==2021.4.18
+importlib-metadata==4.6.4
+iniconfig==2.0.0
+jeepney==0.7.1
+jsonschema==3.2.0
+keyring==23.5.0
+launchpadlib==1.10.16
+lazr.restfulclient==0.14.4
+lazr.uri==1.0.6
+libvirt-python==8.0.0
+louis==3.20.0
+macaroonbakery==1.3.1
+Mako==1.1.3
+MarkupSafe==2.0.1
+more-itertools==8.10.0
+natsort==8.0.2
+nemo-emblems==5.8.0
+netaddr==0.8.0
+netifaces==0.11.0
+numpy==1.21.5
+oauthlib==3.2.0
+onboard==1.4.1
+packaging==21.3
+PAM==0.4.2
+pexpect==4.8.0
+Pillow==9.0.1
+pluggy==1.5.0
+protobuf==3.12.4
+psutil==5.9.0
+ptyprocess==0.7.0
+pycairo==1.20.1
+pycups==2.0.1
+pycurl==7.44.1
+pydantic==2.9.2
+pydantic_core==2.23.4
+pyelftools==0.27
+PyGObject==3.42.1
+PyICU==2.8.1
+pyinotify==0.9.6
+PyJWT==2.3.0
+pymacaroons==0.13.0
+PyNaCl==1.5.0
+pyparsing==2.4.7
+pyparted==3.11.7
+pyRFC3339==1.1
+pyrsistent==0.18.1
+pytest==8.3.3
+python-apt==2.4.0+ubuntu2
+python-debian==0.1.43+ubuntu1.1
+python-dotenv==0.19.2
+python-gnupg==0.4.8
+python-magic==0.4.24
+python-xlib==0.29
+pytz==2022.1
+pyxdg==0.27
+PyYAML==5.4.1
+reportlab==3.6.8
+requests==2.25.1
+requests-file==1.5.1
+SecretStorage==3.3.1
+setproctitle==1.2.2
+six==1.16.0
+sniffio==1.3.1
+soupsieve==2.3.1
+ssh-import-id==5.11
+starlette==0.40.0
+systemd-python==234
+texttable==1.6.4
+tinycss2==1.1.1
+tldextract==3.1.2
+tomli==2.0.2
+typing_extensions==4.12.2
+ubuntu-drivers-common==0.0.0
+ubuntu-pro-client==8001
+ufw==0.36.1
+Unidecode==1.3.3
+urllib3==1.26.5
+uvicorn==0.15.0
+vboxapi==1.0
+wadllib==1.3.6
+webencodings==0.5.1
+websocket-client==1.2.3
+wsproto==1.0.0
+wxPython==4.0.7
+xdg==5
+xkit==0.0.0
+xlrd==1.2.0
+youtube-dl==2021.12.17
+zipp==1.0.0
diff --git a/python/api/test_main.py b/python/api/test_main.py
new file mode 100644
index 00000000..24459565
--- /dev/null
+++ b/python/api/test_main.py
@@ -0,0 +1,110 @@
+import pytest
+from fastapi import FastAPI, HTTPException
+from fastapi.testclient import TestClient
+
+app = FastAPI()
+
+# Эндпоинт для реверса строки
+@app.post("/reverse")
+async def reverse_string(data: dict):
+ if "string" not in data:
+ raise HTTPException(status_code=422, detail="Invalid input")
+ return {"result": data["string"][::-1]}
+
+# Эндпоинт для суммирования до n
+@app.get("/sum1n/{n}")
+async def sum_to_n(n: int):
+ return {"result": sum(range(1, n + 1))}
+
+# Эндпоинт для вычисления Фибоначчи
+@app.get("/fibo")
+async def get_fibonacci(n: int):
+ if n < 0:
+ raise HTTPException(status_code=400, detail="Invalid input")
+ a, b = 0, 1
+ for _ in range(n):
+ a, b = b, a + b
+ return {"result": a}
+
+# Эндпоинт для калькулятора
+@app.post("/calculator")
+async def calculator(data: dict):
+ expr = data.get("expr")
+ try:
+ if "/0" in expr:
+ raise ValueError("Division by zero")
+
+ # Проверка на некорректные выражения
+ if "++" in expr or ",," in expr:
+ raise ValueError("Invalid expression")
+
+ return {"result": eval(expr.replace(",", "+"))}
+ except ValueError as ve:
+ if str(ve) == "Division by zero":
+ raise HTTPException(status_code=403, detail="zerodiv") # Изменяем формат сообщения об ошибке
+ raise HTTPException(status_code=400, detail={"error": "invalid"})
+
+# Эндпоинт для добавления в список
+my_list = []
+
+@app.put("/list")
+async def add_to_list(data: dict):
+ element = data.get("element")
+ if element is None:
+ raise HTTPException(status_code=422, detail="Invalid input")
+ my_list.append(element)
+ return {"result": my_list}
+
+# Эндпоинт для получения списка
+@app.get("/list")
+async def get_list():
+ return {"result": my_list}
+
+# Тесты
+client = TestClient(app)
+
+def test_sum_to_n():
+ response = client.get("/sum1n/10")
+ assert response.status_code == 200
+ assert response.json() == {"result": 55}
+
+def test_get_fibonacci():
+ response = client.get("/fibo?n=5")
+ assert response.status_code == 200
+ assert response.json() == {"result": 5}
+
+def test_reverse_string():
+ response = client.post("/reverse", json={"string": "hello"})
+ print(response.json()) # Логируем ответ для отладки
+ assert response.status_code == 200
+ assert response.json() == {"result": "olleh"}
+
+def test_add_to_list():
+ response = client.put("/list", json={"element": "Apple"})
+ assert response.status_code == 200
+ assert response.json() == {"result": ["Apple"]}
+
+ response = client.put("/list", json={"element": "Microsoft"})
+ assert response.status_code == 200
+ assert response.json() == {"result": ["Apple", "Microsoft"]}
+
+def test_get_list():
+ response = client.get("/list")
+ assert response.status_code == 200
+ assert response.json() == {"result": ["Apple", "Microsoft"]}
+
+def test_calculator_addition():
+ response = client.post("/calculator", json={"expr": "1,+,1"})
+ assert response.status_code == 200
+ assert response.json() == {"result": 2}
+
+def test_calculator_invalid_expression():
+ response = client.post("/calculator", json={"expr": "1,++1"})
+ assert response.status_code == 400
+ assert response.json() == {"detail": {"error": "invalid"}} # Исправляем проверку здесь
+
+def test_calculator_divide_by_zero():
+ response = client.post("/calculator", json={"expr": "1,/0"})
+ print(response.json()) # Логируем ответ для отладки
+ assert response.status_code == 403
+ assert response.json() == {"detail": "zerodiv"} # Исправляем проверку здесь
diff --git a/python/dz_1.py b/python/dz_1.py
new file mode 100644
index 00000000..2d57bcb8
--- /dev/null
+++ b/python/dz_1.py
@@ -0,0 +1,69 @@
+# Условие 1: int-cmp
+def int_cmp(a: int, b: int) -> int:
+ if a > b:
+ return 1
+ elif a == b:
+ return 0
+ else:
+ return -1
+
+# Условие 2: max-of-three
+def max_of_three(a: int, b: int, c: int) -> int:
+ return max(a, b, c)
+
+# Условие 3: sqr-sum-1-n
+def sqr_sum_1_n(n: int) -> int:
+ return sum(i ** 2 for i in range(1, n + 1))
+
+# Условие 4: print-even-a-b
+def print_even_a_b(a: int, b: int) -> None:
+ print(" ".join(str(i) for i in range(a, b + 1) if i % 2 == 0))
+
+# Условие 5: pow-a-b
+def pow_a_b(a: int, b: int) -> int:
+ result = 1
+ for _ in range(b):
+ result *= a
+ return result
+
+# Условие 6: calc-deposit
+def calc_deposit(n: int, k: float, b: float) -> float:
+ return b * (1 + k / 100) ** n
+
+# Массивы
+# Условие 7: min
+def min_in_array(arr: list) -> int:
+ return min(arr) if arr else 0
+
+# Условие 8: range
+def range_array(n: int) -> list:
+ return list(range(1, n + 1))
+
+# Условие 9: sum
+def sum_array(arr: list) -> int:
+ return sum(arr)
+
+# Условие 10: sort
+def sort_array(arr: list) -> list:
+ for i in range(len(arr)):
+ for j in range(len(arr) - i - 1):
+ if arr[j] > arr[j + 1]:
+ arr[j], arr[j + 1] = arr[j + 1], arr[j]
+ return arr
+
+# Тестовые примеры
+if __name__ == "__main__":
+ print(int_cmp(1, 0)) # Output: 1
+ print(max_of_three(42, 1, 0)) # Output: 42
+ print(sqr_sum_1_n(3)) # Output: 14
+ print_even_a_b(0, 4) # Output: 0 2 4
+ print(pow_a_b(2, 6)) # Output: 64
+ print(calc_deposit(1, 5, 1000)) # Output: 1050.0
+ print(min_in_array([1, 2, 3])) # Output: 1
+ print(range_array(5)) # Output: [1, 2, 3, 4, 5]
+ print(sum_array([1, 2, 3])) # Output: 6
+ print(sort_array([3, 2, 1])) # Output: [1, 2, 3]
+
+# ТУТ были легкие воппросы
+
+
diff --git a/python/dz_2.py b/python/dz_2.py
new file mode 100644
index 00000000..7dc2edf4
--- /dev/null
+++ b/python/dz_2.py
@@ -0,0 +1,89 @@
+from datetime import datetime
+
+# Задача 1: Проверка на четность
+def check_even_odd():
+ num = int(input("Введите число: "))
+ if num % 2 == 0:
+ print("Число четное")
+ else:
+ print("Число нечетное")
+
+# Задача 2: Проверка на палиндром
+def check_palindrome():
+ s = input("Введите строку: ").lower()
+ if s == s[::-1]:
+ print("Строка является палиндромом")
+ else:
+ print("Строка не является палиндромом")
+
+# Задача 3: Проверка на простое число
+def is_prime():
+ num = int(input("Введите число: "))
+ if num < 2:
+ print("Число не является простым")
+ return
+ for i in range(2, int(num ** 0.5) + 1):
+ if num % i == 0:
+ print("Число не является простым")
+ return
+ print("Число является простым")
+
+# Задача 4: Проверка корректности даты
+def is_valid_date():
+ date_str = input("Введите дату в формате ДД.ММ.ГГГГ: ")
+ try:
+ datetime.strptime(date_str, "%d.%m.%Y")
+ print("Дата корректна")
+ except ValueError:
+ print("Дата некорректна")
+
+# Задача 5: Поиск совершенных чисел в диапазоне
+def perfect_numbers_in_range():
+ def is_perfect(n):
+ return sum(i for i in range(1, n) if n % i == 0) == n
+
+ perfect_numbers = [i for i in range(1, 1001) if is_perfect(i)]
+ print("Совершенные числа в диапазоне от 0 до 1000:", perfect_numbers)
+
+# Задача 6: Проверка числа Фибоначчи
+def is_fibonacci():
+ num = int(input("Введите число: "))
+ def is_perfect_square(x):
+ return int(x ** 0.5) ** 2 == x
+
+ if is_perfect_square(5 * num ** 2 + 4) or is_perfect_square(5 * num ** 2 - 4):
+ print(f"Число {num} является числом Фибоначчи")
+ else:
+ print(f"Число {num} не является числом Фибоначчи")
+
+# Задача 7: Проверка на совершенное число
+def check_perfect_number():
+ num = int(input("Введите число: "))
+ if sum(i for i in range(1, num) if num % i == 0) == num:
+ print(f"Число {num} является совершенным")
+ else:
+ print(f"Число {num} не является совершенным")
+
+# Задача 8: Определение сезона по дате
+def determine_season():
+ date_str = input("Введите дату в формате ДД.ММ: ")
+ day, month = map(int, date_str.split('.'))
+ if (month == 12 and day >= 21) or month in [1, 2] or (month == 3 and day < 21):
+ print("Это зима")
+ elif (month == 3 and day >= 21) or month in [4, 5] or (month == 6 and day < 21):
+ print("Это весна")
+ elif (month == 6 and day >= 21) or month in [7, 8] or (month == 9 and day < 21):
+ print("Это лето")
+ else:
+ print("Это осень")
+
+# Тестирование всех функций
+if __name__ == "__main__":
+ check_even_odd() # Задача 1
+ check_palindrome() # Задача 2
+ is_prime() # Задача 3
+ is_valid_date() # Задача 4
+ perfect_numbers_in_range() # Задача 5
+ is_fibonacci() # Задача 6
+ check_perfect_number() # Задача 7
+ determine_season() # Задача 8