Skip to content

Commit ad99a1a

Browse files
committed
Core: Updated exceptions
1 parent 158e910 commit ad99a1a

File tree

8 files changed

+114
-59
lines changed

8 files changed

+114
-59
lines changed

shellhub/__init__.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,22 @@
11
# Increment versions here according to SemVer
22
__version__ = "0.0.1"
33

4-
# Import here what you want to be able to import from this package and place it in __all__
5-
from shellhub.models.device import ShellHubDevice, ShellHubDeviceInfo
6-
from shellhub.models.base import ShellHub
7-
from shellhub.exceptions import ShellHubApiError
4+
from .models.device import ShellHubDevice, ShellHubDeviceInfo
5+
from .models.base import ShellHub
6+
from .exceptions import (
7+
ShellHubApiError,
8+
ShellHubAuthenticationError,
9+
DeviceNotFoundError,
10+
ShellHubBaseException,
11+
)
12+
813

914
__all__ = [
1015
"ShellHub",
1116
"ShellHubDevice",
1217
"ShellHubDeviceInfo",
1318
"ShellHubApiError",
19+
"ShellHubAuthenticationError",
20+
"DeviceNotFoundError",
21+
"ShellHubBaseException",
1422
]

shellhub/exceptions.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,14 @@
1-
class ShellHubApiError(Exception):
1+
class ShellHubBaseException(Exception):
2+
pass
3+
4+
5+
class ShellHubApiError(ShellHubBaseException):
6+
pass
7+
8+
9+
class ShellHubAuthenticationError(ShellHubBaseException):
10+
pass
11+
12+
13+
class DeviceNotFoundError(ShellHubApiError):
214
pass

shellhub/models/base.py

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66
import requests
77

88
import shellhub.models.device
9+
from shellhub.exceptions import DeviceNotFoundError
910
from shellhub.exceptions import ShellHubApiError
11+
from shellhub.exceptions import ShellHubAuthenticationError
12+
from shellhub.exceptions import ShellHubBaseException
1013

1114

1215
class ShellHub:
@@ -39,13 +42,17 @@ def _login(self) -> None:
3942
},
4043
)
4144
except requests.exceptions.ConnectionError:
42-
raise ValueError("Incorrect endpoint. Is the server up and running ?")
45+
raise ShellHubBaseException("Incorrect endpoint. Is the server up and running ?")
4346

4447
if response.status_code == 401:
45-
raise ShellHubApiError("Incorrect username or password")
48+
raise ShellHubAuthenticationError("Incorrect username or password")
4649
elif response.status_code != 200:
47-
response.raise_for_status()
48-
self._access_token = response.json()["token"]
50+
try:
51+
response.raise_for_status()
52+
except requests.exceptions.HTTPError as e:
53+
raise ShellHubApiError(e)
54+
else:
55+
self._access_token = response.json()["token"]
4956

5057
def make_request(
5158
self,
@@ -79,7 +86,7 @@ def make_request(
7986
json=json,
8087
)
8188
if response.status_code == 401:
82-
raise ShellHubApiError("Couldn't fix request with a token refresh")
89+
raise ShellHubApiError(f"Couldn't fix request with a token refresh: {response.text}")
8390

8491
return response
8592

@@ -88,7 +95,10 @@ def _get_devices(
8895
) -> "List[shellhub.models.device.ShellHubDevice]":
8996
response = self.make_request(endpoint="/api/devices", method="GET", query_params=query_params)
9097

91-
response.raise_for_status()
98+
try:
99+
response.raise_for_status()
100+
except requests.exceptions.HTTPError as e:
101+
raise ShellHubApiError(e)
92102

93103
devices = []
94104
for device in response.json():
@@ -120,7 +130,11 @@ def get_all_devices(
120130
def get_device(self, uid: str) -> "shellhub.models.device.ShellHubDevice":
121131
response = self.make_request(endpoint=f"/api/devices/{uid}", method="GET")
122132
if response.status_code == 404:
123-
raise ShellHubApiError(f"Device {uid} not found.")
124-
elif response.status_code != 200:
125-
response.raise_for_status()
126-
return shellhub.models.device.ShellHubDevice(self, response.json())
133+
raise DeviceNotFoundError(f"Device {uid} not found.")
134+
else:
135+
try:
136+
response.raise_for_status()
137+
except requests.exceptions.HTTPError as e:
138+
raise ShellHubApiError(e)
139+
else:
140+
return shellhub.models.device.ShellHubDevice(self, response.json())

shellhub/models/device.py

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
from typing import List
33
from typing import Optional
44

5+
import requests
6+
57
import shellhub.models.base
8+
from shellhub.exceptions import DeviceNotFoundError
69
from shellhub.exceptions import ShellHubApiError
710

811

@@ -56,14 +59,11 @@ def __init__(self, api_object: shellhub.models.base.ShellHub, device_json): # t
5659
self.info = ShellHubDeviceInfo(device_json["info"])
5760
self.public_key = device_json["public_key"]
5861
self.tenant_id = device_json["tenant_id"]
59-
# TODO: Convert to datetime object
6062
self.last_seen = device_json["last_seen"]
6163
self.online = device_json["online"]
6264
self.namespace = device_json["namespace"]
6365
self.status = device_json["status"]
64-
# TODO: Convert to datetime object
6566
self.status_updated_at = device_json["status_updated_at"]
66-
# TODO: Convert to datetime object
6767
self.created_at = device_json["created_at"]
6868
self.remote_addr = device_json["remote_addr"]
6969
self.tags = device_json["tags"]
@@ -74,10 +74,14 @@ def delete(self) -> bool:
7474
if response.status_code == 200:
7575
return True
7676
elif response.status_code == 404:
77-
raise ShellHubApiError(f"Device {self.uid} not found.")
77+
raise DeviceNotFoundError(f"Device {self.uid} not found.")
7878
else:
79-
response.raise_for_status()
80-
return False
79+
try:
80+
response.raise_for_status()
81+
except requests.exceptions.HTTPError as e:
82+
raise ShellHubApiError(e)
83+
else:
84+
return False
8185

8286
def rename(self, name: Optional[str] = None) -> bool:
8387
"""
@@ -90,12 +94,16 @@ def rename(self, name: Optional[str] = None) -> bool:
9094
self.name = name
9195
return True
9296
elif response.status_code == 404:
93-
raise ShellHubApiError(f"Device {self.uid} not found.")
97+
raise DeviceNotFoundError(f"Device {self.uid} not found.")
9498
elif response.status_code == 409:
9599
raise ShellHubApiError(f"Device with name {name} already exists.")
96100
else:
97-
response.raise_for_status()
98-
return False
101+
try:
102+
response.raise_for_status()
103+
except requests.exceptions.HTTPError as e:
104+
raise ShellHubApiError(e)
105+
else:
106+
return False
99107

100108
def accept(self) -> bool:
101109
if not self.acceptable:
@@ -106,18 +114,26 @@ def accept(self) -> bool:
106114
self.refresh()
107115
return True
108116
elif response.status_code == 404:
109-
raise ShellHubApiError(f"Device {self.uid} not found.")
117+
raise DeviceNotFoundError(f"Device {self.uid} not found.")
110118
else:
111-
response.raise_for_status()
112-
return False
119+
try:
120+
response.raise_for_status()
121+
except requests.exceptions.HTTPError as e:
122+
raise ShellHubApiError(e)
123+
else:
124+
return False
113125

114126
def refresh(self) -> None:
115127
response = self._api.make_request(endpoint=f"/api/devices/{self.uid}", method="GET")
116128
if response.status_code == 404:
117-
raise ShellHubApiError(f"Device {self.uid} not found.")
118-
elif response.status_code != 200:
119-
response.raise_for_status()
120-
self.__init__(self._api, response.json()) # type: ignore
129+
raise DeviceNotFoundError(f"Device {self.uid} not found.")
130+
elif response.status_code == 200:
131+
self.__init__(self._api, response.json()) # type: ignore
132+
else:
133+
try:
134+
response.raise_for_status()
135+
except requests.exceptions.HTTPError as e:
136+
raise ShellHubApiError(e)
121137

122138
def __repr__(self) -> str:
123139
return (

tests/conftest.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,21 @@
22
import requests_mock as r_mock
33

44
from shellhub import ShellHub
5+
from tests.utils import MOCKED_DOMAIN_URL
56

67

78
@pytest.fixture(scope="function")
89
def shellhub():
910
with r_mock.Mocker() as m:
1011
# Mock the login URL
11-
login_url = "http://localhost.shellhub/api/login"
12+
login_url = f"{MOCKED_DOMAIN_URL}/api/login"
1213
mock_response = {
1314
"token": "jwt_token",
1415
}
1516
m.post(login_url, json=mock_response)
1617

1718
# Create an instance of ShellHub with mocked login
18-
shellhub_instance = ShellHub(username="john.doe", password="dolphin", endpoint="http://localhost.shellhub")
19+
shellhub_instance = ShellHub(username="john.doe", password="dolphin", endpoint=MOCKED_DOMAIN_URL)
1920

2021
yield shellhub_instance
2122

@@ -51,5 +52,5 @@ def shellhub_device(shellhub, requests_mock):
5152
"acceptable": False,
5253
}
5354
]
54-
requests_mock.get("http://localhost.shellhub/api/devices", json=mock_response)
55+
requests_mock.get(f"{MOCKED_DOMAIN_URL}/api/devices", json=mock_response)
5556
return shellhub.get_all_devices()[0]

tests/test_base.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,38 @@
11
import pytest
22

33
from shellhub import ShellHub
4-
from shellhub import ShellHubApiError
4+
from shellhub import ShellHubAuthenticationError
5+
from shellhub import ShellHubBaseException
6+
from tests.utils import MOCKED_DOMAIN_URL
57

68

79
def test_login(requests_mock):
8-
login_url = "http://localhost.shellhub/api/login"
10+
login_url = f"{MOCKED_DOMAIN_URL}/api/login"
911
mock_response = {
1012
"token": "jwt_token",
1113
}
1214
requests_mock.post(login_url, json=mock_response)
13-
shellhub = ShellHub(username="john.doe", password="dolphin", endpoint="http://localhost.shellhub")
15+
shellhub = ShellHub(username="john.doe", password="dolphin", endpoint=MOCKED_DOMAIN_URL)
1416
assert shellhub._access_token == mock_response["token"]
1517

1618

1719
def test_incorrect_endpoint():
18-
with pytest.raises(ValueError):
19-
ShellHub(username="john.doe", password="dolphin", endpoint="http://localhost.shellhub")
20+
with pytest.raises(ShellHubBaseException):
21+
ShellHub(username="john.doe", password="dolphin", endpoint=MOCKED_DOMAIN_URL)
2022

2123

2224
def test_incorrect_username_password(requests_mock):
23-
login_url = "http://localhost.shellhub/api/login"
25+
login_url = f"{MOCKED_DOMAIN_URL}/api/login"
2426
mock_response = {
2527
"detail": "Incorrect username or password",
2628
}
2729
requests_mock.post(login_url, json=mock_response, status_code=401)
28-
with pytest.raises(ShellHubApiError):
29-
ShellHub(username="john.doe", password="dolphin", endpoint="http://localhost.shellhub")
30+
with pytest.raises(ShellHubAuthenticationError):
31+
ShellHub(username="john.doe", password="dolphin", endpoint=MOCKED_DOMAIN_URL)
3032

3133

3234
def test_repr(shellhub):
33-
assert repr(shellhub) == "<ShellHub username=john.doe endpoint=http://localhost.shellhub>"
35+
assert repr(shellhub) == f"<ShellHub username=john.doe endpoint={MOCKED_DOMAIN_URL}>"
3436

3537

3638
def test_str(shellhub):

0 commit comments

Comments
 (0)