GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Issues (51)

besepa/api.py (21 issues)

1
import datetime
0 ignored issues
show
This module should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
2
import json
3
import logging
4
import os
5
import platform
6
import ssl
7
8
import requests
9
10
import besepa.util as util
11
from besepa import exceptions
12
from besepa.config import __endpoint_map__, __version__
13
14
log = logging.getLogger(__name__)
0 ignored issues
show
Coding Style Naming introduced by
The name log does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
15
16
17
class Api(object):
0 ignored issues
show
This class should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
18
    # User-Agent for HTTP request
19
    ssl_version = ssl.OPENSSL_VERSION
20
    library_details = "requests %s; python %s; %s" % (requests.__version__, platform.python_version(), ssl_version)
0 ignored issues
show
This line is too long as per the coding-style (115/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
21
    user_agent = "BesepaSDK/Besepa-Python-SDK %s (%s)" % (__version__, library_details)
22
23
    def __init__(self, options=None, **kwargs):
24
        """Create API object
25
26
        Usage::
27
28
            >>> import besepa
29
            >>> api = besepa.Api(mode="sandbox", api_key='API_KEY')
30
        """
31
        kwargs = util.merge_dict(options or {}, kwargs)
32
33
        self.mode = kwargs.get("mode", "sandbox")
34
35
        if self.mode not in ("live", "sandbox"):
36
            raise exceptions.InvalidConfig("Configuration Mode Invalid", "Received: %s" % self.mode,
37
                                           "Required: live or sandbox")
38
39
        self.endpoint = self.default_endpoint()
40
        # Mandatory parameter, so not using `dict.get`
41
        self.api_key = kwargs["api_key"]
42
        self.proxies = kwargs.get("proxies", None)
43
44
        self.options = kwargs
45
46
    def default_endpoint(self):
0 ignored issues
show
This method should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
47
        return __endpoint_map__.get(self.mode)
48
49
    def request(self, url, method, body=None, headers=None):
50
        """Make HTTP call, formats response and does error handling. Uses http_call method in API class.
0 ignored issues
show
This line is too long as per the coding-style (104/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
51
52
        Usage::
53
54
            >>> api.request("https://sandbox.besepa.com/api/1/customers", "GET", {})
55
            >>> api.request("https://sandbox.besepa.com/api/1/customers", "POST",
56
             "{'name': 'Ender Wiggin', 'taxid': '68571053A', 'reference: C1'}", {} )
57
        """
58
        http_headers = util.merge_dict(self.headers(), headers or {})
59
60
        try:
61
            return self.http_call(url, method, json=body, headers=http_headers)
62
        # Format Error message for bad request
63
        except exceptions.BadRequest as error:
64
            return {"error": json.loads(error.content)}
65
66
    def http_call(self, url, method, **kwargs):
67
        """Makes a http call. Logs response information.
68
        """
69
        log.info('Request[%s]: %s' % (method, url))
0 ignored issues
show
Coding Style Best Practice introduced by
Specify string format arguments as logging function parameters
Loading history...
70
71
        if self.mode.lower() != 'live':
72
            request_headers = kwargs.get("headers", {})
73
            request_body = kwargs.get("json", {})
74
            log.debug("Level: " + self.mode)
75
            log.debug('Request: \nHeaders: %s\nBody: %s' % (str(request_headers), str(request_body)))
0 ignored issues
show
This line is too long as per the coding-style (101/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
Coding Style Best Practice introduced by
Specify string format arguments as logging function parameters
Loading history...
76
        else:  # pragma: no cover
77
            log.info('Not logging full request/response headers and body in live mode for compliance')
0 ignored issues
show
This line is too long as per the coding-style (102/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
78
79
        start_time = datetime.datetime.now()
80
        response = requests.request(method, url, proxies=self.proxies, **kwargs)
81
        duration = datetime.datetime.now() - start_time
82
        log.info('Response[%d]: %s, Duration: %s.%ss.' % (
0 ignored issues
show
Coding Style Best Practice introduced by
Specify string format arguments as logging function parameters
Loading history...
83
            response.status_code, response.reason, duration.seconds, duration.microseconds))
84
85
        debug_id = response.headers.get('Besepa-Debug-Id')
86
        if debug_id:  # pragma: no cover
87
            log.debug('debug_id: %s' % debug_id)
0 ignored issues
show
Coding Style Best Practice introduced by
Specify string format arguments as logging function parameters
Loading history...
88
        if self.mode.lower() != 'live':  # pragma: no cover
89
            log.debug('Headers: %s\nBody: %s' % (str(response.headers), response.content.decode('utf-8')))
0 ignored issues
show
This line is too long as per the coding-style (106/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
Coding Style Best Practice introduced by
Specify string format arguments as logging function parameters
Loading history...
90
91
        return self.handle_response(response, response.content.decode('utf-8'))
92
93
    @staticmethod
94
    def handle_response(response, content):
95
        """Validate HTTP response
96
        """
97
        status = response.status_code
98
        if status in (301, 302, 303, 307):
99
            raise exceptions.Redirection(response, content)
100
        elif 200 <= status <= 299:
101
            return json.loads(content).get('response') if content else {}
102
        elif status == 400:
103
            raise exceptions.BadRequest(response, content)
104
        elif status == 401:
105
            raise exceptions.UnauthorizedAccess(response, content)
106
        elif status == 403:
107
            raise exceptions.ForbiddenAccess(response, content)
108
        elif status == 404:
109
            raise exceptions.ResourceNotFound(response, content)
110
        elif status == 405:
111
            raise exceptions.MethodNotAllowed(response, content)
112
        elif status == 409:
113
            raise exceptions.ResourceConflict(response, content)
114
        elif status == 410:
115
            raise exceptions.ResourceGone(response, content)
116
        elif status == 422:
117
            raise exceptions.ResourceInvalid(response, content)
118
        elif 401 <= status <= 499:
119
            raise exceptions.ClientError(response, content)
120
        elif 500 <= status <= 599:
121
            raise exceptions.ServerError(response, content)
122
        else:
123
            raise exceptions.ConnectionError(response, content, "Unknown response code: #{response.code}")
0 ignored issues
show
This line is too long as per the coding-style (106/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
124
125
    def headers(self):
126
        """Default HTTP headers
127
        """
128
        return {
129
            "Authorization": ("Bearer %s" % self.api_key),
130
            "Content-Type": "application/json",
131
            "Accept": "application/json",
132
            "User-Agent": self.user_agent
133
        }
134
135
    def get(self, action, headers=None):
136
        """Make GET request
137
138
        Usage::
139
140
            >>> api.get("api/1/customers")
141
            >>> api.get("api/1/customers/1")
142
        """
143
        return self.request(util.join_url(self.endpoint, action), 'GET', headers=headers or {})
144
145
    def post(self, action, params=None, headers=None):
146
        """Make POST request
147
148
        Usage::
149
150
            >>> api.post("api/1/customers", {'name': 'Ender Wiggin', 'taxid': '68571053A', 'reference: C1'})
0 ignored issues
show
This line is too long as per the coding-style (108/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
151
        """
152
        return self.request(util.join_url(self.endpoint, action), 'POST', body=params or {}, headers=headers or {})
0 ignored issues
show
This line is too long as per the coding-style (115/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
153
154
    def patch(self, action, params=None, headers=None):
155
        """Make PATCH request
156
157
        Usage::
158
159
            >>> api.patch("api/1/customers/1", {'name': 'Andrew Wiggins'})
160
        """
161
        return self.request(util.join_url(self.endpoint, action), 'PATCH', body=params or {}, headers=headers or {})
0 ignored issues
show
This line is too long as per the coding-style (116/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
162
163
    def delete(self, action, headers=None):
164
        """Make DELETE request
165
        """
166
        return self.request(util.join_url(self.endpoint, action), 'DELETE', headers=headers or {})
167
168
169
__api__ = None
170
171
172
def default():
173
    """Returns default api object and if not present creates a new one
174
    By default points to developer sandbox
175
    """
176
    global __api__
0 ignored issues
show
Usage of the global statement should be avoided.

Usage of global can make code hard to read and test, its usage is generally not recommended unless you are dealing with legacy code.

Loading history...
177
    if __api__ is None:
178
        try:
179
            api_key = os.environ["BESEPA_API_KEY"]
180
        except KeyError:
181
            raise exceptions.MissingConfig("Required BESEPA_API_KEY. \
182
                Refer http://docs.besepaen.apiary.io/#introduction/authorization")
183
184
        __api__ = Api(mode=os.environ.get("BESEPA_MODE", "sandbox"), api_key=api_key)
185
    return __api__
186
187
188
def set_config(options=None, **config):
189
    """Create new default api object with given configuration
190
    """
191
    global __api__
0 ignored issues
show
Usage of the global statement should be avoided.

Usage of global can make code hard to read and test, its usage is generally not recommended unless you are dealing with legacy code.

Loading history...
192
    __api__ = Api(options or {}, **config)
193
    return __api__
194
195
196
configure = set_config
0 ignored issues
show
Coding Style Naming introduced by
The name configure does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
197