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:
Seaswimmer 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,3 +1,3 @@
# API Reference
::: pyzipline.zipline
::: pyzipline.zipline.ZiplineApi

View file

@ -21,11 +21,14 @@ plugins:
- git-authors
- search
- social
# - mkdocstrings:
# default_handler: python
# handlers:
# python:
# paths: [pyzipline]
- mkdocstrings:
default_handler: python
handlers:
python:
paths: [pyzipline]
options:
docstring_options:
ignore_imit_summary: true
markdown_extensions:
- abbr

32
poetry.lock generated
View file

@ -598,6 +598,20 @@ gitdb = ">=4.0.1,<5"
[package.extras]
test = ["black", "coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock", "mypy", "pre-commit", "pytest", "pytest-cov", "pytest-instafail", "pytest-subtests", "pytest-sugar"]
[[package]]
name = "griffe"
version = "0.38.1"
description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API."
optional = false
python-versions = ">=3.8"
files = [
{file = "griffe-0.38.1-py3-none-any.whl", hash = "sha256:334c79d3b5964ade65c05dfcaf53518c576dedd387aaba5c9fd71212f34f1483"},
{file = "griffe-0.38.1.tar.gz", hash = "sha256:bd68d7da7f3d87bc57eb9962b250db123efd9bbcc06c11c1a91b6e583b2a9361"},
]
[package.dependencies]
colorama = ">=0.4"
[[package]]
name = "idna"
version = "3.6"
@ -882,6 +896,7 @@ Markdown = ">=3.3"
MarkupSafe = ">=1.1"
mkdocs = ">=1.4"
mkdocs-autorefs = ">=0.3.1"
mkdocstrings-python = {version = ">=0.5.2", optional = true, markers = "extra == \"python\""}
platformdirs = ">=2.2.0"
pymdown-extensions = ">=6.3"
@ -890,6 +905,21 @@ crystal = ["mkdocstrings-crystal (>=0.3.4)"]
python = ["mkdocstrings-python (>=0.5.2)"]
python-legacy = ["mkdocstrings-python-legacy (>=0.2.1)"]
[[package]]
name = "mkdocstrings-python"
version = "1.7.5"
description = "A Python handler for mkdocstrings."
optional = false
python-versions = ">=3.8"
files = [
{file = "mkdocstrings_python-1.7.5-py3-none-any.whl", hash = "sha256:5f6246026353f0c0785135db70c3fe9a5d9318990fc7ceb11d62097b8ffdd704"},
{file = "mkdocstrings_python-1.7.5.tar.gz", hash = "sha256:c7d143728257dbf1aa550446555a554b760dcd40a763f077189d298502b800be"},
]
[package.dependencies]
griffe = ">=0.37"
mkdocstrings = ">=0.20"
[[package]]
name = "multidict"
version = "6.0.4"
@ -1633,4 +1663,4 @@ multidict = ">=4.0"
[metadata]
lock-version = "2.0"
python-versions = "^3.10 || ^3.11 || ^3.12"
content-hash = "4a37211d89e134df27183ed799df55662694232bcc6aef27f99f47c131186940"
content-hash = "3f27e66de6ea095d7574340c1233c4c5ff13409f22d3dcb2a43829acd676be30"

View file

@ -23,7 +23,7 @@ optional = true
[tool.poetry.group.docs.dependencies]
mkdocs = "1.5.3"
mkdocstrings = "0.24.0"
mkdocstrings = {extras = ["python"], version = "0.24.0"}
mkdocs-git-authors-plugin = "0.7.2"
mkdocs-git-revision-date-localized-plugin = "1.2.2"
mkdocs-material = {extras = ["imaging"], version = "^9.5.2"}

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)