Skip to content

Commit ebc4358

Browse files
authored
HW10 init (#8)
1 parent c6e7866 commit ebc4358

File tree

6 files changed

+722
-14
lines changed

6 files changed

+722
-14
lines changed

.pre-commit-config.yaml

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,21 +38,20 @@ repos:
3838
- id: mypy
3939
exclude: 'tests'
4040

41-
4241
# run local pylint in venv
43-
- repo: local
44-
hooks:
45-
- id: pylint
46-
name: pylint
47-
entry: pylint
48-
language: system
49-
types: [python]
50-
require_serial: true
51-
args:
52-
- --max-line-length=120
53-
- --ignore-imports=yes
54-
- -d duplicate-code
55-
- -d C0111,W0621,R0913,R1705,W0201,R0903,W0613,C0415,C0103
42+
#- repo: local
43+
# hooks:
44+
# - id: pylint
45+
# name: pylint
46+
# entry: pylint
47+
# language: system
48+
# types: [python]
49+
# require_serial: true
50+
# args:
51+
# - --max-line-length=120
52+
# - --ignore-imports=yes
53+
# - -d duplicate-code
54+
# - -d C0111,W0621,R0913,R1705,W0201,R0903,W0613,C0415,C0103
5655

5756

5857
- repo: https://github.com/asottile/pyupgrade

homework_10/README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Задание
2+
3+
В этом домашнем задании предлагается реализовать REST API, занимающегося инференсом некой модели машинного обучения, т.е. поступает набор признаков объекта, на выходе возвращается предсказание модели. В качестве основы проекта предлагается фреймворк FastAPI
4+
5+
# Запуск
6+
7+
```bash
8+
poetry install --no-root
9+
poetry run uvicorn app.app:app --host 127.0.0.1 --port 8000
10+
```
11+
12+
# Реализация
13+
14+
По GET запросу вида `localhost:8000/analysis/<some_text>` делается анализ текста: считается относительное количество гласных английских букв в строке и отдается в формате JSON:
15+
```
16+
{"result": <float>}
17+
```

homework_10/app/__init__.py

Whitespace-only changes.

homework_10/app/app.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
from typing import Optional
2+
3+
import jwt # type: ignore[import-error]
4+
from fastapi import Depends, FastAPI, HTTPException, status
5+
from fastapi.security import OAuth2PasswordBearer
6+
from passlib.context import CryptContext
7+
from pydantic import BaseModel
8+
9+
# auth secrets
10+
SECRET_KEY = "secret_key"
11+
ALGORITHM = "HS256"
12+
ACCESS_TOKEN_EXPIRE_MINUTES = 1
13+
14+
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
15+
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
16+
17+
# fake db
18+
users_db = {
19+
"john_smith": {
20+
"username": "john_smith",
21+
"hashed_password": pwd_context.hash("john_smith"),
22+
"age": 25,
23+
"group": "users",
24+
},
25+
"admin1": {
26+
"username": "admin1",
27+
"hashed_password": pwd_context.hash("john_smith"),
28+
"age": 25,
29+
"group": "admin",
30+
},
31+
}
32+
33+
app = FastAPI()
34+
35+
36+
class User(BaseModel):
37+
username: str
38+
email: str
39+
age: int
40+
role: str
41+
42+
43+
class TokenData(BaseModel):
44+
username: Optional[str] = None
45+
46+
47+
class ModelInferenceOutput(BaseModel):
48+
result: float
49+
50+
51+
async def get_current_user(token: str = Depends(oauth2_scheme)):
52+
credentials_exception = HTTPException(
53+
status_code=status.HTTP_401_UNAUTHORIZED,
54+
detail="Could not validate credentials",
55+
headers={"WWW-Authenticate": "Bearer"},
56+
)
57+
try:
58+
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
59+
username: str = payload.get("sub")
60+
if username is None:
61+
raise credentials_exception
62+
token_data = TokenData(username=username)
63+
except jwt.PyJWTError:
64+
raise credentials_exception
65+
user = users_db.get(token_data.username, None) # type: ignore[arg-type]
66+
if user is None:
67+
raise credentials_exception
68+
return user
69+
70+
71+
@app.get("/")
72+
def index():
73+
return {"text": "ML model inference"}
74+
75+
76+
@app.get("/analysis/{data}", response_model=ModelInferenceOutput)
77+
def run_model_analysis(data: str, user: User = Depends(get_current_user)):
78+
if user.role != "admin":
79+
raise HTTPException(status_code=403, detail="Operation not permitted.")
80+
result = sum(map(data.lower().count, "aeiuyo")) / len(data)
81+
return {"result": result}

0 commit comments

Comments
 (0)