first commit

This commit is contained in:
2023-05-01 20:00:32 +09:00
commit 819c4a6a07
39 changed files with 1866 additions and 0 deletions

View File

@ -0,0 +1,16 @@
from mdrsclient.models.error import DRFStandardizedErrors
from mdrsclient.models.file import File
from mdrsclient.models.folder import Folder, FolderSimple
from mdrsclient.models.laboratory import Laboratories, Laboratory
from mdrsclient.models.user import Token, User
__all__ = [
"DRFStandardizedErrors",
"File",
"Folder",
"FolderSimple",
"Laboratories",
"Laboratory",
"Token",
"User",
]

View File

@ -0,0 +1,14 @@
from pydantic.dataclasses import dataclass
@dataclass(frozen=True)
class DRFStandardizedError:
code: str
detail: str
attr: str | None
@dataclass(frozen=True)
class DRFStandardizedErrors:
type: str
errors: list[DRFStandardizedError]

25
mdrsclient/models/file.py Normal file
View File

@ -0,0 +1,25 @@
from pydantic.dataclasses import dataclass
from mdrsclient.models.utils import iso8601_to_user_friendly
@dataclass(frozen=True)
class File:
id: str
name: str
type: str
size: int
thumbnail: str | None
description: str
metadata: dict
download_url: str
created_at: str
updated_at: str
@property
def created_at_name(self) -> str:
return iso8601_to_user_friendly(self.created_at)
@property
def updated_at_name(self) -> str:
return iso8601_to_user_friendly(self.updated_at)

View File

@ -0,0 +1,58 @@
from typing import Final
from pydantic.dataclasses import dataclass
from mdrsclient.models import File
from mdrsclient.models.utils import iso8601_to_user_friendly
ACCESS_LEVEL_NAMES: Final[dict[int, str]] = {
-1: "Storage",
0: "Private",
1: "CBS Open",
2: "PW Open",
3: "Public",
}
@dataclass(frozen=True)
class FolderSimple:
id: str
pid: str | None
name: str
access_level: int
lock: bool
lab_id: int
description: str
created_at: str
updated_at: str
restrict_opened_at: str | None
@property
def access_level_name(self) -> str:
return ACCESS_LEVEL_NAMES[self.access_level]
@property
def lock_name(self) -> str:
return "locked" if self.lock else "unlocked"
@property
def created_at_name(self) -> str:
return iso8601_to_user_friendly(self.created_at)
@property
def updated_at_name(self) -> str:
return iso8601_to_user_friendly(self.updated_at)
@dataclass(frozen=True)
class Folder(FolderSimple):
metadata: list[dict]
sub_folders: list[FolderSimple]
files: list[File]
path: str
def find_sub_folder(self, name: str) -> FolderSimple | None:
return next((x for x in self.sub_folders if x.name == name), None)
def find_file(self, name: str) -> File | None:
return next((x for x in self.files if x.name == name), None)

View File

@ -0,0 +1,34 @@
from typing import Generator
from pydantic.dataclasses import dataclass
@dataclass(frozen=True)
class Laboratory:
id: int
name: str
pi_name: str
full_name: str
@dataclass(frozen=True)
class Laboratories:
items: list[Laboratory]
def __iter__(self) -> Generator[Laboratory, None, None]:
yield from self.items
def empty(self) -> bool:
return len(self.items) == 0
def clear(self) -> None:
self.items.clear()
def append(self, item: Laboratory) -> None:
self.items.append(item)
def find_by_id(self, id: int) -> Laboratory | None:
return next((x for x in self.items if x.id == id), None)
def find_by_name(self, name: str) -> Laboratory | None:
return next((x for x in self.items if x.name == name), None)

50
mdrsclient/models/user.py Normal file
View File

@ -0,0 +1,50 @@
import time
import jwt
from pydantic import parse_obj_as
from pydantic.dataclasses import dataclass
@dataclass(frozen=True)
class DecodedJWT:
token_type: str
exp: int
iat: int
jti: str
user_id: int
@dataclass(frozen=True)
class Token:
access: str
refresh: str
@property
def user_id(self) -> int:
access_decoded = self.__decode(self.access)
return access_decoded.user_id
@property
def is_expired(self) -> bool:
now = int(time.time()) + 10
refresh_decoded = self.__decode(self.refresh)
return now > refresh_decoded.exp
@property
def is_refresh_required(self) -> bool:
now = int(time.time()) + 10
access_decoded = self.__decode(self.access)
refresh_decoded = self.__decode(self.refresh)
return now > access_decoded.exp and now < refresh_decoded.exp
def __decode(self, token: str) -> DecodedJWT:
data = jwt.decode(token, options={"verify_signature": False})
return parse_obj_as(DecodedJWT, data)
@dataclass(frozen=True)
class User:
id: int
username: str
laboratory_id: int
laboratory: str

View File

@ -0,0 +1,5 @@
import datetime
def iso8601_to_user_friendly(text: str) -> str:
return datetime.datetime.fromisoformat(text).strftime("%Y/%m/%d %H:%M:%S")