<commit_before># stdlib
from typing import Optional
from typing import Union
from datetime import datetime

# third party
from nacl.encoding import HexEncoder
from nacl.signing import SigningKey
from pydantic import BaseModel
from pydantic import EmailStr


class BaseUser(BaseModel):
    email: Optional[EmailStr]
    name: Optional[str]
    role: Union[Optional[int], Optional[str]]  # TODO: Should be int in SyftUser
    daa_pdf: Optional[bytes] = b""

    class Config:
        orm_mode = True


class UserCreate(BaseUser):
    email: EmailStr
    role: str = "Data Scientist"
    name: str
    password: str
    institution: Optional[str]
    website: Optional[str]


class ApplicantStatus(BaseModel):
    status: str


class UserUpdate(BaseUser):
    password: Optional[str]
    budget: Optional[float]


class UserCandidate(BaseUser):
    email: EmailStr
    status: str = "pending"
    name: str


class User(BaseUser):
    id: int
    role: Union[int, str]  # TODO: This should be int. Perhaps add role_name instead?
    budget_spent: Optional[float]
    allocated_budget: Optional[float]
    institution: Optional[str]
    website: Optional[str]
    added_by: Optional[str]
    created_at: Optional[str]


class UserPrivate(User):
    private_key: str
    created_at: Optional[datetime]


    def get_signing_key(self) -> SigningKey:
        return SigningKey(self.private_key.encode(), encoder=HexEncoder)


class UserSyft(User):
    hashed_password: str
    salt: str
    verify_key: str<commit_msg>Fix users model<commit_after># stdlib
from datetime import datetime
from typing import Optional
from typing import Union

# third party
from nacl.encoding import HexEncoder
from nacl.signing import SigningKey
from pydantic import BaseModel
from pydantic import EmailStr


class BaseUser(BaseModel):
    email: Optional[EmailStr]
    name: Optional[str]
    role: Union[Optional[int], Optional[str]]  # TODO: Should be int in SyftUser
    daa_pdf: Optional[bytes] = b""

    class Config:
        orm_mode = True


class UserCreate(BaseUser):
    email: EmailStr
    role: str = "Data Scientist"
    name: str
    password: str
    institution: Optional[str]
    website: Optional[str]


class ApplicantStatus(BaseModel):
    status: str


class UserUpdate(BaseUser):
    password: Optional[str]
    budget: Optional[float]


class UserCandidate(BaseUser):
    email: EmailStr
    status: str = "pending"
    name: str


class User(BaseUser):
    id: int
    role: Union[int, str]  # TODO: This should be int. Perhaps add role_name instead?
    budget_spent: Optional[float]
    allocated_budget: Optional[float]
    institution: Optional[str]
    website: Optional[str]
    added_by: Optional[str]
    created_at: Union[Optional[str], Optional[datetime]]


class UserPrivate(User):
    private_key: str

    def get_signing_key(self) -> SigningKey:
        return SigningKey(self.private_key.encode(), encoder=HexEncoder)


class UserSyft(User):
    hashed_password: str
    salt: str
    verify_key: str
{'fraction_non_alphanumeric': 0.08557213930348259, 'fraction_numerical': 0.0, 'mean_word_length': 3.856682769726248, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '245330', 'n_tokens_mistral': 936, 'n_tokens_neox': 916, 'n_words': 274}