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 @@ +

Hello, from jusan-docker-mount

\ No newline at end of file diff --git a/docker/docker-compose-final/jusan-docker-mount/test b/docker/docker-compose-final/jusan-docker-mount/test new file mode 100644 index 00000000..e1453b44 --- /dev/null +++ b/docker/docker-compose-final/jusan-docker-mount/test @@ -0,0 +1 @@ +Singularity \ No newline at end of file diff --git a/docker/docker-compose-final/jusan-docker-mount/token b/docker/docker-compose-final/jusan-docker-mount/token new file mode 100644 index 00000000..461e0831 --- /dev/null +++ b/docker/docker-compose-final/jusan-docker-mount/token @@ -0,0 +1 @@ +Jusan \ No newline at end of file diff --git a/docker/docker-compose-final/jusan-fastapi-final.conf b/docker/docker-compose-final/jusan-fastapi-final.conf new file mode 100644 index 00000000..2b6e7443 --- /dev/null +++ b/docker/docker-compose-final/jusan-fastapi-final.conf @@ -0,0 +1,12 @@ +server { + listen 80; + server_name jusan.docker-compose; + + location / { + proxy_pass http://jusan-compose-final:8080; # Перенаправление на API контейнер + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} diff --git a/docker/docker-compose-final/solution.sh b/docker/docker-compose-final/solution.sh new file mode 100644 index 00000000..5eeb4395 --- /dev/null +++ b/docker/docker-compose-final/solution.sh @@ -0,0 +1,6 @@ +curl -O https://stepik.org/media/attachments/lesson/686238/jusan-docker-mount.conf +curl -O https://stepik.org/media/attachments/lesson/686238/jusan-docker-mount.zip +unzip jusan-docker-mount.zip -d jusan-docker-mount +docker-compose up -d +docker-compose ps + diff --git a/docker/docker-compose/answer.md b/docker/docker-compose/answer.md new file mode 100644 index 00000000..8f06dada --- /dev/null +++ b/docker/docker-compose/answer.md @@ -0,0 +1,7 @@ +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/ +> +> Index of /gifs/ +> +>

Index of /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-cert/answer.md b/nginx/nginx-cert/answer.md new file mode 100644 index 00000000..b592beaa --- /dev/null +++ b/nginx/nginx-cert/answer.md @@ -0,0 +1,2 @@ +> root@user-asus:/etc/nginx# curl -H "Host: jusan.kz" -k https://localhost/secret_word +> jusan-nginx-certroot@user-asus:/etc/nginx# diff --git a/nginx/nginx-ip/answer.md b/nginx/nginx-ip/answer.md new file mode 100644 index 00000000..d34f8b11 --- /dev/null +++ b/nginx/nginx-ip/answer.md @@ -0,0 +1,9 @@ +> root@user-asus:/etc/nginx# curl -H "Host: example.com" -i http://localhost:8080/secret_word +> HTTP/1.1 203 +> Server: nginx/1.18.0 (Ubuntu) +> Date: Sun, 17 Nov 2024 10:57:48 GMT +> Content-Type: application/octet-stream +> Content-Length: 14 +> Connection: keep-alive + +> jusan-nginx-iproot@user-asus:/etc/nginx# diff --git a/nginx/nginx-locations/Screenshot from 2024-11-17 16-02-05.png b/nginx/nginx-locations/Screenshot from 2024-11-17 16-02-05.png new file mode 100644 index 00000000..ead7ce28 Binary files /dev/null and b/nginx/nginx-locations/Screenshot from 2024-11-17 16-02-05.png differ diff --git a/nginx/nginx-locations/answer.md b/nginx/nginx-locations/answer.md new file mode 100644 index 00000000..58feba16 --- /dev/null +++ b/nginx/nginx-locations/answer.md @@ -0,0 +1,38 @@ +jusan-nginx-iproot@user-asus:/etc/nginx# curl http://localhost:8080 + + + + + + + + Cats Page + + + +

+

Cat with Flower

+ flower +

+ +

+

Cat with Glasses

+ glasses +

+ +

+

Gray Cat

+ gray-animal +

+ +

+

Cats mafia

+ mafia +

+ +

+

Sleepy Cat

+ sleep +

+ + 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