# -*- coding: utf-8 -*- """ github3.decorators ================== This module provides decorators to the rest of the library """ from functools import wraps from requests.models import Response import os try: # (No coverage) # python2 from StringIO import StringIO # (No coverage) except ImportError: # (No coverage) # python3 from io import BytesIO as StringIO class RequestsStringIO(StringIO): def read(self, n=-1, *args, **kwargs): # StringIO is an old-style class, so can't use super return StringIO.read(self, n) def requires_auth(func): """Decorator to note which object methods require authorization.""" @wraps(func) def auth_wrapper(self, *args, **kwargs): auth = False if hasattr(self, '_session'): auth = (self._session.auth or self._session.headers.get('Authorization')) if auth: return func(self, *args, **kwargs) else: from .models import GitHubError # Mock a 401 response r = generate_fake_error_response( '{"message": "Requires authentication"}' ) raise GitHubError(r) return auth_wrapper def requires_basic_auth(func): """Specific (basic) authentication decorator. This is used to note which object methods require username/password authorization and won't work with token based authorization. """ @wraps(func) def auth_wrapper(self, *args, **kwargs): if hasattr(self, '_session') and self._session.auth: return func(self, *args, **kwargs) else: from .models import GitHubError # Mock a 401 response r = generate_fake_error_response( '{"message": "Requires username/password authentication"}' ) raise GitHubError(r) return auth_wrapper def requires_app_credentials(func): """Require client_id and client_secret to be associated. This is used to note and enforce which methods require a client_id and client_secret to be used. """ @wraps(func) def auth_wrapper(self, *args, **kwargs): client_id, client_secret = self._session.retrieve_client_credentials() if client_id and client_secret: return func(self, *args, **kwargs) else: from .models import GitHubError # Mock a 401 response r = generate_fake_error_response( '{"message": "Requires username/password authentication"}' ) raise GitHubError(r) return auth_wrapper def generate_fake_error_response(msg, status_code=401, encoding='utf-8'): r = Response() r.status_code = status_code r.encoding = encoding r.raw = RequestsStringIO(msg.encode()) r._content_consumed = True r._content = r.raw.read() return r # Use mock decorators when generating documentation, so all functino signatures # are displayed correctly if os.getenv('GENERATING_DOCUMENTATION', None) == 'github3': requires_auth = requires_basic_auth = lambda x: x # noqa # (No coverage)