pycupra 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pycupra/__init__.py +7 -0
- pycupra/__version__.py +6 -0
- pycupra/connection.py +1617 -0
- pycupra/const.py +180 -0
- pycupra/dashboard.py +1258 -0
- pycupra/exceptions.py +87 -0
- pycupra/utilities.py +116 -0
- pycupra/vehicle.py +2556 -0
- pycupra-0.0.1.dist-info/METADATA +57 -0
- pycupra-0.0.1.dist-info/RECORD +13 -0
- pycupra-0.0.1.dist-info/WHEEL +5 -0
- pycupra-0.0.1.dist-info/licenses/LICENSE +201 -0
- pycupra-0.0.1.dist-info/top_level.txt +1 -0
pycupra/exceptions.py
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
class SeatConfigException(Exception):
|
2
|
+
"""Raised when Seat Connect API client is configured incorrectly"""
|
3
|
+
|
4
|
+
def __init__(self, status):
|
5
|
+
"""Initialize exception"""
|
6
|
+
super(SeatConfigException, self).__init__(status)
|
7
|
+
self.status = status
|
8
|
+
|
9
|
+
class SeatAuthenticationException(Exception):
|
10
|
+
"""Raised when credentials are invalid during authentication"""
|
11
|
+
|
12
|
+
def __init__(self, status):
|
13
|
+
"""Initialize exception"""
|
14
|
+
super(SeatAuthenticationException, self).__init__(status)
|
15
|
+
self.status = status
|
16
|
+
|
17
|
+
class SeatAccountLockedException(Exception):
|
18
|
+
"""Raised when account is locked from too many login attempts"""
|
19
|
+
|
20
|
+
def __init__(self, status):
|
21
|
+
"""Initialize exception"""
|
22
|
+
super(SeatAccountLockedException, self).__init__(status)
|
23
|
+
self.status = status
|
24
|
+
|
25
|
+
class SeatTokenExpiredException(Exception):
|
26
|
+
"""Raised when server reports that the access token has expired"""
|
27
|
+
|
28
|
+
def __init__(self, status):
|
29
|
+
"""Initialize exception"""
|
30
|
+
super(SeatTokenExpiredException, self).__init__(status)
|
31
|
+
self.status = status
|
32
|
+
|
33
|
+
class SeatException(Exception):
|
34
|
+
"""Raised when an unknown error occurs during API interaction"""
|
35
|
+
|
36
|
+
def __init__(self, status):
|
37
|
+
"""Initialize exception"""
|
38
|
+
super(SeatException, self).__init__(status)
|
39
|
+
self.status = status
|
40
|
+
|
41
|
+
class SeatThrottledException(Exception):
|
42
|
+
"""Raised when the API throttles the connection"""
|
43
|
+
|
44
|
+
def __init__(self, status):
|
45
|
+
"""Initialize exception"""
|
46
|
+
super(SeatThrottledException, self).__init__(status)
|
47
|
+
self.status = status
|
48
|
+
|
49
|
+
class SeatEULAException(Exception):
|
50
|
+
"""Raised when EULA must be accepted before login"""
|
51
|
+
|
52
|
+
def __init__(self, status):
|
53
|
+
"""Initialize exception"""
|
54
|
+
super(SeatEULAException, self).__init__(status)
|
55
|
+
self.status = status
|
56
|
+
|
57
|
+
class SeatLoginFailedException(Exception):
|
58
|
+
"""Raised when login fails for an unknown reason"""
|
59
|
+
|
60
|
+
def __init__(self, status):
|
61
|
+
"""Initialize exception"""
|
62
|
+
super(SeatLoginFailedException, self).__init__(status)
|
63
|
+
self.status = status
|
64
|
+
|
65
|
+
class SeatInvalidRequestException(Exception):
|
66
|
+
"""Raised when an unsupported request is made"""
|
67
|
+
|
68
|
+
def __init__(self, status):
|
69
|
+
"""Initialize exception"""
|
70
|
+
super(SeatInvalidRequestException, self).__init__(status)
|
71
|
+
self.status = status
|
72
|
+
|
73
|
+
class SeatRequestInProgressException(Exception):
|
74
|
+
"""Raised when a request fails because another request is already in progress"""
|
75
|
+
|
76
|
+
def __init__(self, status):
|
77
|
+
"""Initialize exception"""
|
78
|
+
super(SeatRequestInProgressException, self).__init__(status)
|
79
|
+
self.status = status
|
80
|
+
|
81
|
+
class SeatServiceUnavailable(Exception):
|
82
|
+
"""Raised when a API is unavailable"""
|
83
|
+
|
84
|
+
def __init__(self, status):
|
85
|
+
"""Initialize exception"""
|
86
|
+
super(SeatServiceUnavailable, self).__init__(status)
|
87
|
+
self.status = status
|
pycupra/utilities.py
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
from datetime import date, datetime
|
2
|
+
from base64 import b64encode
|
3
|
+
from string import ascii_letters as letters, digits
|
4
|
+
from sys import argv
|
5
|
+
from os import environ as env
|
6
|
+
from os.path import join, dirname, expanduser
|
7
|
+
from itertools import product
|
8
|
+
import json
|
9
|
+
import logging
|
10
|
+
import re
|
11
|
+
|
12
|
+
_LOGGER = logging.getLogger(__name__)
|
13
|
+
|
14
|
+
|
15
|
+
def read_config():
|
16
|
+
"""Read config from file."""
|
17
|
+
for directory, filename in product(
|
18
|
+
[
|
19
|
+
dirname(argv[0]),
|
20
|
+
expanduser("~"),
|
21
|
+
env.get("XDG_CONFIG_HOME", join(expanduser("~"), ".config")),
|
22
|
+
],
|
23
|
+
["seat.conf", ".seat.conf"],
|
24
|
+
):
|
25
|
+
try:
|
26
|
+
config = join(directory, filename)
|
27
|
+
_LOGGER.debug("checking for config file %s", config)
|
28
|
+
with open(config) as config:
|
29
|
+
return dict(
|
30
|
+
x.split(": ")
|
31
|
+
for x in config.read().strip().splitlines()
|
32
|
+
if not x.startswith("#")
|
33
|
+
)
|
34
|
+
except (IOError, OSError):
|
35
|
+
continue
|
36
|
+
return {}
|
37
|
+
|
38
|
+
|
39
|
+
def json_loads(s):
|
40
|
+
return json.loads(s, object_hook=obj_parser)
|
41
|
+
|
42
|
+
|
43
|
+
def obj_parser(obj):
|
44
|
+
"""Parse datetime."""
|
45
|
+
for key, val in obj.items():
|
46
|
+
try:
|
47
|
+
obj[key] = datetime.strptime(val, "%Y-%m-%dT%H:%M:%S%z")
|
48
|
+
except (TypeError, ValueError):
|
49
|
+
pass
|
50
|
+
return obj
|
51
|
+
|
52
|
+
|
53
|
+
def find_path(src, path):
|
54
|
+
"""Simple navigation of a hierarchical dict structure using XPATH-like syntax.
|
55
|
+
|
56
|
+
>>> find_path(dict(a=1), 'a')
|
57
|
+
1
|
58
|
+
|
59
|
+
>>> find_path(dict(a=1), '')
|
60
|
+
{'a': 1}
|
61
|
+
|
62
|
+
>>> find_path(dict(a=None), 'a')
|
63
|
+
|
64
|
+
|
65
|
+
>>> find_path(dict(a=1), 'b')
|
66
|
+
Traceback (most recent call last):
|
67
|
+
...
|
68
|
+
KeyError: 'b'
|
69
|
+
|
70
|
+
>>> find_path(dict(a=dict(b=1)), 'a.b')
|
71
|
+
1
|
72
|
+
|
73
|
+
>>> find_path(dict(a=dict(b=1)), 'a')
|
74
|
+
{'b': 1}
|
75
|
+
|
76
|
+
>>> find_path(dict(a=dict(b=1)), 'a.c')
|
77
|
+
Traceback (most recent call last):
|
78
|
+
...
|
79
|
+
KeyError: 'c'
|
80
|
+
|
81
|
+
"""
|
82
|
+
if not path:
|
83
|
+
return src
|
84
|
+
if isinstance(path, str):
|
85
|
+
path = path.split(".")
|
86
|
+
return find_path(src[path[0]], path[1:])
|
87
|
+
|
88
|
+
|
89
|
+
def is_valid_path(src, path):
|
90
|
+
"""
|
91
|
+
>>> is_valid_path(dict(a=1), 'a')
|
92
|
+
True
|
93
|
+
|
94
|
+
>>> is_valid_path(dict(a=1), '')
|
95
|
+
True
|
96
|
+
|
97
|
+
>>> is_valid_path(dict(a=1), None)
|
98
|
+
True
|
99
|
+
|
100
|
+
>>> is_valid_path(dict(a=1), 'b')
|
101
|
+
False
|
102
|
+
"""
|
103
|
+
try:
|
104
|
+
find_path(src, path)
|
105
|
+
return True
|
106
|
+
except KeyError:
|
107
|
+
return False
|
108
|
+
|
109
|
+
|
110
|
+
def camel2slug(s):
|
111
|
+
"""Convert camelCase to camel_case.
|
112
|
+
|
113
|
+
>>> camel2slug('fooBar')
|
114
|
+
'foo_bar'
|
115
|
+
"""
|
116
|
+
return re.sub("([A-Z])", "_\\1", s).lower().lstrip("_")
|