Skip to content

Commit 6bf15ab

Browse files
author
Nina Kahr
committed
PA-752: Handle errors during website creation. by Filip, Nina
1 parent e2fd80f commit 6bf15ab

File tree

3 files changed

+46
-70
lines changed

3 files changed

+46
-70
lines changed

pythonanywhere_core/exceptions.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,7 @@ class PythonAnywhereApiException(Exception):
1212

1313
class NoTokenError(PythonAnywhereApiException):
1414
pass
15+
16+
17+
class DomainAlreadyExistsException(PythonAnywhereApiException):
18+
pass

pythonanywhere_core/website.py

Lines changed: 8 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from textwrap import dedent
55

66
from pythonanywhere_core.base import call_api, get_api_endpoint
7-
from pythonanywhere_core.exceptions import SanityException, PythonAnywhereApiException
7+
from pythonanywhere_core.exceptions import DomainAlreadyExistsException, PythonAnywhereApiException
88

99

1010
class Website:
@@ -29,44 +29,14 @@ def __init__(self) -> None:
2929
self.websites_base_url = get_api_endpoint(username=getpass.getuser(), flavor="websites")
3030
self.domains_base_url = get_api_endpoint(username=getpass.getuser(), flavor="domains")
3131

32-
def sanity_check(self, domain_name: str, nuke: bool = False) -> None:
33-
"""Check that we have a token, and that we don't already have a webapp for this domain"""
34-
print(snakesay("Running API sanity checks"))
35-
token = os.environ.get("API_TOKEN")
36-
if not token:
37-
raise SanityException(
38-
dedent(
39-
"""
40-
Could not find your API token.
41-
You may need to create it on the Accounts page?
42-
You will also need to close this console and open a new one once you've done that.
43-
"""
44-
)
45-
)
46-
47-
if nuke:
48-
return
4932

50-
response = call_api(
51-
f"{self.websites_base_url}{domain_name}/",
52-
"get"
53-
)
54-
55-
if response.status_code == 200:
56-
raise SanityException(
57-
f"You already have a webapp for {domain_name}.\n\nUse the --nuke option if you want to replace it."
58-
)
59-
60-
61-
def create(self, domain_name: str, command: str, nuke: bool = False) -> dict:
33+
def create(self, domain_name: str, command: str) -> dict:
6234
"""Creates new website with ``domain_name`` and ``command``.
6335
6436
:param domain_name: domain name for new website
6537
:param command: command for new website
6638
:returns: dictionary with created website info"""
6739

68-
self.sanity_check(domain_name, nuke)
69-
7040
response = call_api(
7141
self.websites_base_url,
7242
"post",
@@ -76,6 +46,12 @@ def create(self, domain_name: str, command: str, nuke: bool = False) -> dict:
7646
"webapp": {"command": command}
7747
}
7848
)
49+
if response.status_code == 400 and "domain with this domain name already exists" in response.text:
50+
raise DomainAlreadyExistsException
51+
52+
if not response.ok:
53+
raise PythonAnywhereApiException(f"POST to create website failed with status code {response.status_code} and error message: {response.text}")
54+
7955
return response.json()
8056

8157
def get(self, domain_name: str) -> dict:

tests/test_website.py

Lines changed: 34 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@
66
from unittest.mock import patch
77

88
from pythonanywhere_core.base import get_api_endpoint
9-
from pythonanywhere_core.exceptions import PythonAnywhereApiException
9+
from pythonanywhere_core.exceptions import PythonAnywhereApiException, DomainAlreadyExistsException
1010
from pythonanywhere_core.website import Website
11-
from pythonanywhere_core.exceptions import SanityException, PythonAnywhereApiException
1211

1312

1413
pytestmark = pytest.mark.usefixtures("api_token")
@@ -77,6 +76,39 @@ def test_create_returns_json_with_created_website_info(
7776
)
7877

7978

79+
def test_create_raises_when_domain_name_already_exists(
80+
api_responses,
81+
websites_base_url,
82+
domain_name,
83+
command
84+
):
85+
with pytest.raises(DomainAlreadyExistsException):
86+
api_responses.add(
87+
responses.POST,
88+
url=websites_base_url,
89+
status=400,
90+
body=json.dumps({"domain_name":["domain with this domain name already exists."]})
91+
)
92+
Website().create(domain_name=domain_name, command=command)
93+
94+
def test_raises_with_api_error_message_for_any_other_error(
95+
api_responses,
96+
websites_base_url,
97+
domain_name,
98+
command
99+
):
100+
with pytest.raises(PythonAnywhereApiException) as e:
101+
api_responses.add(
102+
responses.POST,
103+
url=websites_base_url,
104+
status=400,
105+
body=json.dumps({"message":["Something went wrong."]})
106+
)
107+
Website().create(domain_name=domain_name, command=command)
108+
109+
assert "Something went wrong." in str(e)
110+
111+
80112
def test_get_returns_json_with_info_for_given_domain(
81113
api_responses, websites_base_url, website_info, domain_name
82114
):
@@ -161,39 +193,3 @@ def test_raises_if_ssl_info_does_not_return_200(api_responses, domain_name, doma
161193

162194
assert "GET SSL details via API failed, got" in str(e.value)
163195
assert "nope" in str(e.value)
164-
165-
166-
def test_website_sanity_check_domain_already_exists(api_responses, websites_base_url, website_info, domain_name):
167-
api_responses.add(
168-
responses.GET,
169-
url=f"{websites_base_url}{domain_name}/",
170-
status=200,
171-
body=json.dumps(website_info)
172-
)
173-
174-
with pytest.raises(SanityException) as e:
175-
Website().sanity_check(domain_name=domain_name, nuke=False)
176-
177-
178-
def test_website_sanity_check_can_be_bypassed_with_nuke_option(api_responses, websites_base_url, website_info, domain_name):
179-
# Test that the sanity check does not raise an exception
180-
Website().sanity_check(domain_name=domain_name, nuke=True)
181-
182-
183-
def test_website_sanity_check_tests_api_token_present(api_responses, websites_base_url, website_info, domain_name):
184-
import os
185-
del os.environ["API_TOKEN"]
186-
187-
# Test that the sanity check does not raise an exception
188-
with pytest.raises(SanityException) as e:
189-
Website().sanity_check(domain_name=domain_name, nuke=False)
190-
191-
assert "Could not find your API token" in str(e.value)
192-
193-
194-
@patch('pythonanywhere_core.website.Website.sanity_check')
195-
def test_create_website_calls_sanity_check(mock_sanity_check, api_responses, websites_base_url, website_info, domain_name, command):
196-
mock_sanity_check.side_effect = SanityException('Boom!')
197-
198-
with pytest.raises(SanityException):
199-
Website().create(domain_name=domain_name, command=command, nuke=False)

0 commit comments

Comments
 (0)