"""Loadero file resource.
File resource is seperated into three parts
FileParams class describes file attributes
FileAPI class groups file related API calls
File class combines FileParams and FileAPI
Single File object coresponds to single file in Loadero.
"""
from __future__ import annotations
from datetime import datetime
from dateutil import parser
from .pagination import PagedResponse
from ..api_client import APIClient
from .resource import (
FilterKey,
LoaderoResourceParams,
LoaderoResource,
QueryParams,
)
from .classificator import FileType
[docs]
class FileFilterKey(FilterKey):
"""FileFilterKey is an enum of all filter keys for file read all API
operation."""
FILE_TYPE = "filter_file_type"
[docs]
class FileParams(LoaderoResourceParams):
"""FileParams describes single Loadero file resources attributes."""
def __init__(
self,
file_id: int or None = None,
file_type: FileType or None = None,
content: str or None = None,
password: str or None = None,
name: str or None = None,
):
"""Creates a new FileParams instance that will contain single file
resources attributes.
Args:
file_id (int, optional): Existing file resources ID.
Defaults to None.
file_type (FileType, optional): The file resources type.
Defaults to None.
content (str, optional): Content of file resource. Defaults to None.
password (str, optional): For SSL certificate files,
provides a password for file. Defaults to None.
name (str, optional): Name of the file resource. Defaults to None.
"""
super().__init__(
attribute_map={
"id": "file_id",
"created": "_created",
"updated": "_updated",
"file_type": "file_type",
"content": "content",
"name": "name",
"password": "password",
},
custom_deserializers={
"created": parser.parse,
"updated": parser.parse,
"file_type": FileType.from_dict,
},
body_attributes=[
"content",
"file_type",
"password",
"name",
],
required_body_attributes=[
"content",
"file_type",
"name",
],
)
self.file_id = file_id
self.file_type = file_type
self.content = content
self.password = password
self.name = name
self._created = None
self._updated = None
@property
def created(self) -> datetime:
"""Time when file was created.
Returns:
datetime: Time when resource was created.
"""
return self._created
@property
def updated(self) -> datetime:
"""Time when file was last updated.
Returns:
datetime: Time when file was last updated.
"""
return self._updated
[docs]
class File(LoaderoResource):
"""File allows to perform CRUD manipulatons on a single Loadero file
resource.
APIClient must be previously initialized with a valid Loadero access token.
The target Loadero file resource is determined by FileParams.
"""
def __init__(
self, file_id: int or None = None, params: FileParams or None = None
):
"""Creates a new instance of File that allows to perform CRUD operations
of a single Loadero file resource.
The resources attribute data is stored in params field that is an
instance of FileParams.
Args:
file_id (int, optional): Existing file resources ID.
Defaults to None.
params (FileParams, optional): Instance of FileParams that describes
the file resource. Defaults to None.
"""
self.params = params or FileParams()
if file_id is not None:
self.params.file_id = file_id
super().__init__(self.params)
[docs]
def create(self) -> File:
"""Creates a new file.
Required attributes of params field that need to be populated, otherwise
the method will raise an exception:
- content
- file_type
Raises:
APIException: If API call fails.
Returns:
File: Created file resource.
"""
FileAPI.create(self.params)
return self
[docs]
def read(self) -> File:
"""Reads information about an existing file.
Required attributes of params field that need to be populated, otherwise
the method will raise an exception:
- file_id
Raises:
ValueError: If resource params do not sufficiently identify
resource.
APIException: If API call fails.
Returns:
File: Read file resource.
"""
FileAPI.read(self.params)
return self
[docs]
def update(self) -> File:
"""Update information about an existing file.
Required attributes of params field that need to be populated, otherwise
the method will raise an exception:
- file_id
- content
- file_type
Raises:
ValueError: If resource params do not sufficiently identify
resource.
APIException: If API call fails.
Returns:
File: Updated file resource.
"""
FileAPI.update(self.params)
return self
[docs]
def delete(self) -> None:
"""Delete an existing file.
Required attributes of params field that need to be populated, otherwise
the method will raise an exception:
- file_id
Raises:
ValueError: If resource params do not sufficiently identify
resource.
APIException: If API call fails.
"""
FileAPI.delete(self.params)
[docs]
class FileAPI:
"""FileAPI defines Loadero API operations for file resources."""
[docs]
@staticmethod
def create(params: FileParams) -> FileParams:
"""Create a new file resource.
Args:
params (FileParams): Describes the file resource to create.
Raises:
APIException: If API call fails.
Returns:
FileParams: Created file resource params.
"""
return params.from_dict(
APIClient().post(FileAPI.route(), params.to_dict())
)
[docs]
@staticmethod
def read(params: FileParams) -> FileParams:
"""Read an existing file resource.
Args:
params (FileParams): Describes the file resource to read.
Raises:
Exception: FileParams.file_id was not defined.
APIException: If API call fails.
Returns:
FileParams: Read file resource params.
"""
FileAPI.__validate_identifiers(params)
return params.from_dict(
APIClient().get(FileAPI().route(params.file_id))
)
[docs]
@staticmethod
def update(params: FileParams) -> FileParams:
"""Update an existing file resource.
Args:
params (FileParams): Describes the file and the changes to apply.
Raises:
Exception: FileParams.file_id was not defined.
APIException: If API call fails.
Returns:
FileParams: Read file resource.
"""
FileAPI.__validate_identifiers(params)
return params.from_dict(
APIClient().put(FileAPI.route(params.file_id), params.to_dict())
)
[docs]
@staticmethod
def delete(params: FileParams) -> None:
"""Delete an existing file resource.
Args:
params (FileParams): Describes the file to delete.
Raises:
Exception: FileParams.file_id was not defined.
APIException: If API call fails.
Returns:
FileParams: Read file resource.
"""
FileAPI.__validate_identifiers(params)
APIClient().delete(FileAPI.route(params.file_id))
[docs]
@staticmethod
def read_all(query_params: QueryParams or None = None) -> PagedResponse:
"""Read all files in project.
Args:
query_params (QueryParams, optional): Describes query parameters.
Raises:
APIException: If API call fails.
Returns:
PagedResponse: Paged response of file resources.
"""
qp = None
if query_params is not None:
qp = query_params.parse()
return PagedResponse(FileParams).from_dict(
APIClient().get(FileAPI.route(), qp)
)
[docs]
@staticmethod
def route(file_id: int or None = None) -> str:
"""Build file resource url route.
Args:
file_id (int, optional): File resource id. Defaults to None. If
omitted the route will point to all file resources
Returns:
str: Route to file resource.
"""
r = APIClient().project_route + "files/"
if file_id is not None:
r += f"{file_id}/"
return r
@staticmethod
def __validate_identifiers(params: FileParams, single: bool = True):
"""Validate file resource identifiers.
Args:
params (FileParams): File params.
single (bool, optional): Indicates if the resource identifiers
should be validated as pointing to a single resource.
Defaults to True.
Raises:
ValueError: FileParams.file_id must be a valid int.
"""
if single and params.file_id is None:
raise ValueError("FileParams.file_id must be a valid int")