making a whole bunch of changes preparing for documentation autoupdating
Some checks failed
Pylint / Pylint (3.12) (push) Failing after 37s

This commit is contained in:
SeaswimmerTheFsh 2023-12-20 17:53:00 -05:00
parent 1cbe895c3e
commit b774ecdc0a
Signed by: cswimr
GPG key ID: 1EBC234EEDA901AE
9 changed files with 204 additions and 172 deletions

View file

@ -1,9 +1,3 @@
class KwargConflict(Exception):
"""
Raised when the keyword arguments passed to a function conflict.
"""
pass
class HTTPFailure(Exception):
"""
Raised when an HTTP request fails.
@ -15,3 +9,9 @@ class PyZiplineError(Exception):
Raised when an error occurs in the PyZipline library.
"""
pass
class FeatureDisabledError(Exception):
"""
Raised when a feature is disabled on the Zipline instance.
"""
pass

View file

@ -13,10 +13,11 @@ class Embed:
):
"""Embed object used for checking embeds
:param color: String of the embed's color
:param title: String of the embed's title
:param siteName: String of the embed's site name
:param description: String of the embed's description
Args:
color (str): String of the embed's color
title (str): String of the embed's title
siteName (str): String of the embed's site name
description (str): String of the embed's description
"""
self.color = color
@ -46,19 +47,20 @@ class File:
):
"""File object used for uploading files to Zipline
:param createdAt: Datetime object of when the file was created
:param id: Integer ID of the file
:param mimetype: String of the file's mimetype
:param views: Integer of the number of views the file has
:param name: String of the file's name
:param size: Integer of the file's size in bytes
:param favorite: Boolean of whether the file is favorited
:param originalName: (optional) String of the file's original name
:param url: (optional) String of the file's URL
:param maxViews: (optional) Integer of the file's maximum number of views
:param expiredAt: (optional) Datetime object of when the file will expire
:param thumbnail: (optional) String of the file's thumbnail URL
:param folderId: (optional) Integer of the file's folder ID
Args:
createdAt (datetime.datetime): Datetime object of when the file was created
id (int): ID of the file
mimetype (str): String of the file's mimetype
views (int): Integer of the number of views the file has
name (str): String of the file's name
size (int): Integer of the file's size in bytes
favorite (bool): Boolean of whether the file is favorited
originalName (str = None): (optional) String of the file's original name
url (str = None): (optional) String of the file's URL
maxViews (int = None): (optional) Integer of the file's maximum number of views
expiredAt (datetime.datetime = None): (optional) Datetime object of when the file will expire
thumbnail (str = None): (optional) String of the file's thumbnail URL
folderId (int = None): (optional) Integer of the file's folder ID
"""
self.createdAt = createdAt
@ -78,19 +80,18 @@ class File:
class Result:
def __init__(self, status_code: int, message: str = '', data: List[Dict] = None):
def __init__(self, success: bool, status_code: int, message: str = '', data: List[Dict] = None):
"""Result returned from low-level RestAdapter
:param status_code: Standard HTTP Status code
:type status_code: int
:param message: Human readable result
:type message: str
:param data: Python List of Dictionaries (or maybe just a single Dictionary on error)
:type data: Union[List[Dict], Dict]
Args:
success (bool): Boolean of whether the request was successful
status_code (int): Standard HTTP Status code
message (str = ''): Human readable result
data (List[Dict] = None): Python List of Dictionaries (or maybe just a single Dictionary on error)
"""
self.status_code = int(status_code)
self.message = str(message)
self.success = success
self.status_code = status_code
self.message = message
self.data = data if data else []
@ -107,20 +108,14 @@ class Invite:
):
"""Invite object used for managing invites
:param id: Integer ID of the invite
:type id: int
:param code: String of the invite's code
:type code: str
:param createdAt: Datetime object of when the invite was created
:type createdAt: datetime
:param expiredAt: Datetime object of when the invite will expire
:type expiredAt: datetime
:param used: Boolean of whether the invite has been used
:type used: bool
:param createdById: Integer ID of the user who created the invite
:type createdById: int
Args:
id (int): Integer ID of the invite
code (str): String of the invite's code
createdAt (datetime): Datetime object of when the invite was created
expiredAt (datetime): Datetime object of when the invite will expire
used (bool): Boolean of whether the invite has been used
createdById (int): Integer ID of the user who created the invite
"""
self.id = id
self.code = code
self.createdAt = createdAt
@ -144,22 +139,15 @@ class OAuth:
):
"""OAuth object used for managing OAuth
:param id: Integer ID of the OAuth
:type id: int
:param provider: String of the OAuth's provider, one of 'DISCORD', 'GITHUB', 'GOOGLE'
:type provider: str
:param userId: Integer ID of the user who owns the OAuth
:type userId: int
:param providerId: String of the OAuth's provider ID
:type providerId: str
:param username: String of the OAuth's connected account's username
:type username: str
:param token: String of the OAuth's access token
:type token: str
:param refresh: String of the OAuth's refresh token
:type refresh: str
Args:
id (int): Integer ID of the OAuth
provider (str): String of the OAuth's provider, one of 'DISCORD', 'GITHUB', 'GOOGLE'
userId (int): Integer ID of the user who owns the OAuth
providerId (str): String of the OAuth's provider ID
username (str): String of the OAuth's connected account's username
token (str): String of the OAuth's access token
refresh (str): String of the OAuth's refresh token
"""
self.id = id
self.provider = provider
self.userId = userId
@ -190,34 +178,21 @@ class User:
):
"""User object used for managing users
:param id: Integer ID of the user
:type id: int
:param uuid: String of the user's UUID
:type uuid: str
:param username: String of the user's username
:type username: str
:param avatar: String of the user's avatar, base64 encoded
:type avatar: str
:param token: String of the user's token
:type token: str
:param administrator: Boolean of whether the user is an administrator
:type administrator: bool
:param superAdmin: Boolean of whether the user is a super administrator
:type superAdmin: bool
:param systemTheme: String of the user's system theme
:type systemTheme: str
:param embed: Embed object of the user's embed
:type embed: Embed
:param totpSecret: String of the user's TOTP secret
:type totpSecret: str
:param domains: List of Strings of the user's domains
:type domains: List[str]
:param oauth: (optional) List of OAuth objects
:type oauth: Union[List[OAuth], None]
:param ratelimit: (optional) Datetime object of when the user's ratelimit expires
:type ratelimit: Union[datetime, None]
Args:
id (int): Integer ID of the user
uuid (str): String of the user's UUID
username (str): String of the user's username
avatar (str): String of the user's avatar, base64 encoded
token (str): String of the user's token
administrator (bool): Boolean of whether the user is an administrator
superAdmin (bool): Boolean of whether the user is a super administrator
systemTheme (str): String of the user's system theme
embed (Embed): Embed object of the user's embed
totpSecret (str): String of the user's TOTP secret
domains (List[str]): List of Strings of the user's domains
oauth (List[OAuth] = None): (optional) List of OAuth objects
ratelimit (datetime = None): (optional) Datetime object of when the user's ratelimit expires
"""
self.id = id
self.uuid = uuid
self.username = username

View file

@ -12,17 +12,15 @@ class RestAdapter:
def __init__(self, hostname: str, token: str = '', ssl: bool = True, enforced_signing: bool = True, logger: logging.Logger = None):
"""Constructor for RestAdapter
:param hostname: The hostname of your Zipline instance, WITHOUT https or http.
:type hostname: str
:param token: (optional) String used for authentication when making requests.
:param token: str
:param ssl: (optional) Normally set to True, but if your Zipline instance doesn't use SSL/TLS, set this to False.
:type ssl: bool
:param enforced_signing: (optional) Normally set to True, but if having SSL/TLS cert validation issues, can turn off with False.
:type enforced_signing: bool
:param logger: (optional) If your app has a logger, pass it in here.
:type logger: logging.Logger
:raise KwargConflict: Raised when the keyword arguments passed to a function conflict.
Args:
hostname (str): The hostname of your Zipline instance, WITHOUT https or http.
token (str = None): String used for authentication when making requests.
ssl (bool = True): Normally set to True, but if your Zipline instance doesn't use SSL/TLS, set this to False.
enforced_signing (bool = True): Normally set to True, but if having SSL/TLS cert validation issues, can turn off with False.
logger (logging.Logger = None) If your app has a logger, pass it in here.
Raises:
ValueError: Raised when the keyword arguments passed to the class constructor conflict.
"""
self._url = f"http{'s' if ssl else ''}://{hostname}/api/"
self._token = token
@ -31,7 +29,7 @@ class RestAdapter:
self._logger = logger or logging.getLogger(__name__)
if ssl is False and enforced_signing is True:
raise KwargConflict("Cannot enforce signing without SSL")
raise ValueError("Cannot enforce signing without SSL")
if not ssl and not enforced_signing:
disable_warnings()
@ -39,18 +37,19 @@ class RestAdapter:
def _do(self, http_method: str, endpoint: str, params: Dict = None, data: Dict = None) -> Result:
"""Internal method to make a request to the Zipline server. You shouldn't use this directly.
:param http_method: The HTTP method to use (GET, POST, DELETE)
:type http_method: str
:param endpoint: The endpoint to make the request to.
:type endpoint: str
:param params: (optional) Python dictionary of query parameters to send with the request.
:type params: Dict
:param data: (optional) Python dictionary of data to send with the request.
:type data: Dict
:raise HTTPFailure: Raised when an HTTP request fails.
:raise PyZiplineError: Raised when an error occurs in the PyZipline library.
:return: Result object
:rtype: Result"""
Args:
http_method (str): The HTTP method to use (GET, POST, DELETE)
endpoint (str): The endpoint to make the request to.
params (Dict = None): Python dictionary of query parameters to send with the request.
data (Dict = None): Python dictionary of data to send with the request.
Returns:
Result: A Result object containing the status code, message, and data from the request.
Raises:
HTTPError: Raised when an HTTP request fails.
PyZiplineError: Raised when an error occurs in the PyZipline library.
"""
full_url = self._url + endpoint
headers = {'Authorization': self._token}
@ -71,51 +70,46 @@ class RestAdapter:
self._logger.error(msg=log_line_post.format(False, None, e))
raise PyZiplineError("Could not decode response from Zipline server") from e
# If status_code in 200-299 range, return success Result with data, otherwise raise exception
# If status_code in 200-299 range, return success Result with data, otherwise return failed Result with message
is_success = 299 >= response.status_code >= 200
log_line = log_line_post.format(is_success, response.status_code, response.reason)
if is_success:
self._logger.debug(msg=log_line_post.format(is_success, response.status_code, response.reason))
return Result(status_code=response.status_code, message=response.reason, data=data_out)
self._logger.error(msg=log_line)
raise PyZiplineError(f"{response.status_code}: {response.reason}")
self._logger.debug(msg=log_line_post.format(is_success, response.status_code, response.reason))
return Result(success=is_success, status_code=response.status_code, message=response.reason, data=data_out)
def get(self, endpoint: str, params: Dict = None) -> Result:
"""Make a GET request to the Zipline server. You should almost never have to use this directly.
:param endpoint: The endpoint to make the request to.
:type endpoint: str
:param params: (optional) Python dictionary of query parameters to send with the request.
:type params: Dict
:return: Result object
:rtype: Result"""
Args:
endpoint (str): The endpoint to make the request to.
params (Dict = None): Python dictionary of query parameters to send with the request.
Returns:
Result: A Result object containing the status code, message, and data from the request.
"""
return self._do(http_method='GET', endpoint=endpoint, params=params)
def post(self, endpoint: str, params: Dict = None, data: Dict = None) -> Result:
"""Make a POST request to the Zipline server. You should almost never have to use this directly.
:param endpoint: The endpoint to make the request to.
:type endpoint: str
:param params: (optional) Python dictionary of query parameters to send with the request.
:type params: Dict
:param data: (optional) Python dictionary of data to send with the request.
:type data: Dict
:return: Result object
:rtype: Result"""
Args:
endpoint (str): The endpoint to make the request to.
params (Dict = None): Python dictionary of query parameters to send with the request.
data (Dict = None): Python dictionary of data to send with the request.
Returns:
Result: A Result object containing the status code, message, and data from the request.
"""
return self._do(http_method='POST', endpoint=endpoint, params=params, data=data)
def delete(self, endpoint: str, params: Dict = None, data: Dict = None) -> Result:
"""Make a DELETE request to the Zipline server. You should almost never have to use this directly.
:param endpoint: The endpoint to make the request to.
:type endpoint: str
:param params: (optional) Python dictionary of query parameters to send with the request.
:type params: Dict
:param data: (optional) Python dictionary of data to send with the request.
:type data: Dict
:return: Result object
:rtype: Result"""
Args:
endpoint (str): The endpoint to make the request to.
params (Dict = None): Python dictionary of query parameters to send with the request.
data (Dict = None): Python dictionary of data to send with the request.
Returns:
Result: A Result object containing the status code, message, and data from the request.
"""
return self._do(http_method='DELETE', endpoint=endpoint, params=params, data=data)

View file

@ -3,9 +3,10 @@ from datetime import datetime
def convert_str_to_datetime(date_string: str) -> datetime:
"""Converts a string to a datetime object
:param date_string: String to convert
:type date_string: str
:return: Datetime object
:rtype: datetime
Args:
date_string (str): String to convert
Returns:
datetime.datetime: Datetime object
"""
return datetime.strptime(date_string, '%Y-%m-%dT%H:%M:%S.%fZ')

View file

@ -1,9 +1,20 @@
import logging
from pyzipline.rest_adapter import RestAdapter
from pyzipline.errors import PyZiplineError
from pyzipline.errors import PyZiplineError, FeatureDisabledError
from pyzipline.models import *
class ZiplineApi:
"""Represents an instance of the Zipline API.
All API requests should be made through this class.
Args:
hostname (str): The hostname of your Zipline instance, WITHOUT https or http.
token (str = None): String used for authentication when making requests.
ssl (bool = True): Normally set to True, but if your Zipline instance doesn't use SSL/TLS, set this to False.
enforced_signing (bool = True): Normally set to True, but if having SSL/TLS cert validation issues, can turn off with False.
logger (logging.Logger = None): If your app has a logger, pass it in here.
"""
def __init__(
self,
hostname: str,
@ -12,25 +23,16 @@ class ZiplineApi:
enforced_signing: bool = True,
logger: logging.Logger = None
):
"""Constructor for ZiplineApi.
All API requests should be made through this class.
Args:
hostname (str): The hostname of your Zipline instance, WITHOUT https or http.
token (str = None): String used for authentication when making requests.
ssl (bool = True): Normally set to True, but if your Zipline instance doesn't use SSL/TLS, set this to False.
enforced_signing (bool = True): Normally set to True, but if having SSL/TLS cert validation issues, can turn off with False.
logger (logging.Logger = None): If your app has a logger, pass it in here.
"""
self._rest_adapter = RestAdapter(hostname=hostname, token=token, ssl=ssl, enforced_signing=enforced_signing, logger=logger)
def get_user(self, user_id: int) -> User:
"""Get a user by ID
user_id (int): Integer ID of the user to retrieve
:return: The :class:`pyzipline.models.User` object matching the ID
:rtype: :class:`pyzipline.models.User`
Args:
user_id (int): Integer ID of the user to retrieve
Returns:
:class:`pyzipline.models.User`: The user with the given ID
"""
result = self._rest_adapter.get(endpoint=f"user/{user_id}")
return User(**result.data)
@ -38,8 +40,35 @@ class ZiplineApi:
def get_self(self) -> User:
"""Get the currently authenticated user
:return: `pyzipline.models.User`object matching the authenticated user
:rtype: `pyzipline.models.User`
Returns:
:class:`pyzipline.models.User`: The currently authenticated user
"""
result = self._rest_adapter.get(endpoint=f"user")
return User(**result.data)
def check_user_exists(self, username: str, invite: str = None) -> bool:
"""Check if a user exists by username
Args:
username (str): Username to check
invite (str = None): Invite code to use, only required if registration without invites is disabled
Raises:
FeatureDisabledError: Raised when registration or invites are disabled on the Zipline instance
PyZiplineError: Raised
Returns:
bool: True if user exists, False if not
"""
params = {'username': username} if invite is None else {'username': username, 'code': invite}
result: Result = self._rest_adapter.get(endpoint=f"user/check", params=params)
if result.status_code == 200:
return bool(result.data['success'])
elif result.message == 'user resistration is disabled' or result.message == 'invites are disabled':
raise FeatureDisabledError(result.message)
elif result.message == 'username already exists':
return True
elif result.message == 'invalid invite code':
raise ValueError(result.message)
else:
raise PyZiplineError(result.message)