From 41d84948d2dc262906578015d840ff5424244411 Mon Sep 17 00:00:00 2001 From: SantaSpeen Date: Thu, 17 Mar 2022 21:35:46 +0300 Subject: [PATCH] v0.11 --- gitflic/__version__.py | 2 +- gitflic/api.py | 61 +++++++++++++++++++++++++++++++++++------- gitflic/auth.py | 38 ++++++++++++++------------ gitflic/exceptions.py | 7 ++++- 4 files changed, 79 insertions(+), 29 deletions(-) diff --git a/gitflic/__version__.py b/gitflic/__version__.py index ddb13d4..c6bc7d5 100644 --- a/gitflic/__version__.py +++ b/gitflic/__version__.py @@ -1,5 +1,5 @@ __title__ = "gitflic" -__version__ = "0.10" +__version__ = "0.11" __description__ = "GitflicApi wrapper" __author__ = "SantaSpeen" __author_email__ = "dir@sssr.dev" diff --git a/gitflic/api.py b/gitflic/api.py index 193ffeb..43dc2fe 100644 --- a/gitflic/api.py +++ b/gitflic/api.py @@ -1,18 +1,30 @@ """ Main Gitflic API wrapper. """ - -from enum import Enum - from .auth import GitflicAuth from .exceptions import ( - NotFound, NoRights, GitflicExceptions + NotFound, AccessDenied, GitflicExceptions ) API_URL = 'https://api.gitflic.ru' +def _fix_none(obj): + if isinstance(obj, tuple) or isinstance(obj, list): + obj = list(obj) + for index, item in enumerate(obj): + if item is None: + obj[index] = '' + + elif isinstance(obj, dict): + for k, v in obj.items(): + if v is None: + obj[k] = '' + + return obj + + class Gitflic: """ Gitflic API wrapper. @@ -38,11 +50,11 @@ class Gitflic: url = response.url if code == 403: - raise NoRights(f"Access denied for '{url}'") + raise AccessDenied(f"Access denied for '{url}'") elif code == 404: raise NotFound(f"Location '{url}' not found") - raise GitflicExceptions(f"Gitflic sent unknown error with HTTP code: {code}. Response: {response.text}") + raise GitflicExceptions(f"Gitflic sent unknown error with HTTP code: {code}. Url: {url}. Response: {response.text}") def call(self, method: str, *args, **kwargs): """ @@ -53,9 +65,38 @@ class Gitflic: response = self.session.get(API_URL + method, *args, **kwargs) return self._response_handler(response) - def reg_call(self, method: str): + def __reg_call_handler(self, *args, end=None, **kwargs): + if end is None: + end = "" + args: list = _fix_none(args) + kwargs: dict = _fix_none(kwargs) + disable_formatting: bool = kwargs.pop("disable_formatting", False) + method: str = kwargs['__gitflic_method_name__'] - l = lambda add_to_method="", *_args, **_kwargs: self.call(method+add_to_method, *_args, **_kwargs) - l.__name__ = method.replace("/", "_") + # If not need formatting + if not disable_formatting: + if len(args) > 0: + try: + if "%" in method: + method %= tuple(args) + else: + method = method.format(*args) - return l + except Exception as e: + raise GitflicExceptions(f"Formatting error: {e!r}; In call: '{method}; Args: {args}'") + elif len(kwargs) > 0: + if "%" in method: + method %= kwargs + else: + method = method.format_map(kwargs) + + method += end + + return self.call(method) + + def reg_call(self, method_string: str): + + func = lambda *args, **kwargs: self.__reg_call_handler(*args, **kwargs, __gitflic_method_name__=method_string) + func.__name__ = method_string + + return func diff --git a/gitflic/auth.py b/gitflic/auth.py index 3e9360b..7299549 100644 --- a/gitflic/auth.py +++ b/gitflic/auth.py @@ -1,7 +1,6 @@ """ Gitflic authentication wrapper. """ - from enum import Enum from typing import Union import logging @@ -9,7 +8,7 @@ import logging import requests from .exceptions import AuthError, GitflicExceptions - +from .__version__ import __version__ OAUTH_URL = "https://oauth.gitflic.ru/oauth/authorize?scope={}&clientId={}&redirectUrl={}&state={}" @@ -29,7 +28,7 @@ class GitflicAuth: """ Gitflic authentication wrapper. """ - + # noinspection PyTypeChecker def __init__(self, access_token: str = None, @@ -51,7 +50,12 @@ class GitflicAuth: # Requests. self.session: requests.Session = requests.Session() - # Auth. + # Set headers + self.session.headers = { + "User-Agent": f"gitflic-py/{__version__}", + 'Accept': "application/*", + 'Authorization': "token " + } # Token fields. self.access_token: str = access_token @@ -60,7 +64,7 @@ class GitflicAuth: self.scope: str = scope if not isinstance(scope, GitflicAuthScopes) else scope.value self.client_id: str = client_id self.redirect_url: str = redirect_url - self.state: str = state + self.state: str = state self.refresh_token: str = None self._try_login() @@ -77,21 +81,21 @@ class GitflicAuth: # OAUTH authorization. self._oauth_login() else: - if any(self.scope, self.client_id, self.redirect_url, self.state): + if any((self.scope, self.client_id, self.redirect_url, self.state)): raise GitflicExceptions( - "Not found one of params for OAUTH, you are required to send ALL params from ('scope', 'client_id', 'redirect_url', 'state')!" + "Not found one of params for OAUTH, you are required to send ALL params from ('scope', 'client_id', 'redirect_url', 'state')! " "See docs: https://gitflic.ru/help/api/access-token." ) raise GitflicExceptions( "Please pass 'token' param for raw auth or ('scope', 'client_id', 'redirect_url', 'state') params for OAUTH " "See docs: https://gitflic.ru/help/api/access-token." ) - + def _oauth_login(self): """ Tries to login user with OAUTH. """ - + self.log.debug("Trying to login with OAUTH...") # OAUTH authorization. @@ -109,16 +113,14 @@ class GitflicAuth: """ Tries to login user with given access token. """ - - self.log.debug("Trying to login with token...") - if self.access_token: - self.session.headers.update({ - "Authorization": "token " + self.access_token - }) + self.log.debug(f"Trying to login with token={self.access_token}...") + + assert isinstance(self.access_token, str) + self.session.headers['Authorization'] += self.access_token self.check_token() - + def check_token(self): """ Checks that current auth session token is valid or not (by making request to get current user). @@ -128,7 +130,9 @@ class GitflicAuth: r = self.session.get("https://api.gitflic.ru/user/me") if r.status_code == 403: - raise AuthError("Authentication failed. Invalid token?") + e = AuthError("Authentication failed. Invalid token?") + e.response = r + raise e else: r = r.json() self.log.debug(f"Successfully logged as {r.get('username')} {r.get('id')}") diff --git a/gitflic/exceptions.py b/gitflic/exceptions.py index 9cbd0f8..113b7bc 100644 --- a/gitflic/exceptions.py +++ b/gitflic/exceptions.py @@ -1,6 +1,8 @@ """ All exceptions that may be raised from Gitflic API wrapper. """ +from requests import Response + class GitflicExceptions(Exception): error_code: int = 1 @@ -12,15 +14,18 @@ class AuthError(GitflicExceptions): error_code = 403 reason = None reason_ru = None + response: Response = None -class NoRights(GitflicExceptions): +class AccessDenied(GitflicExceptions): error_code = 403 reason = "There are no access rights." reason_ru = "Нет прав для доступа." + response: Response = None class NotFound(GitflicExceptions): error_code = 404 reason = "No data was found for the query." reason_ru = "Данные по запросу не найдены." + response: Response = None