Skip to content

Commit f0f851e

Browse files
authored
Merge pull request #17 from Pilifer/master
replacing flavor="webapps" default hack with nice {{flavor}}
2 parents 63986f0 + a747b31 commit f0f851e

File tree

2 files changed

+43
-41
lines changed

2 files changed

+43
-41
lines changed

pythonanywhere/api.py

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@
2222
class AuthenticationError(Exception):
2323
pass
2424

25+
2526
class NoTokenError(Exception):
2627
pass
2728

28-
def get_api_endpoint(flavor="webapps"):
29+
30+
def get_api_endpoint():
2931
domain = os.environ.get('PYTHONANYWHERE_DOMAIN', 'pythonanywhere.com')
30-
return 'https://www.{domain}/api/v0/user/{{username}}/{flavor}/'.format(domain=domain, flavor=flavor)
32+
return 'https://www.{domain}/api/v0/user/{{username}}/{{flavor}}/'.format(domain=domain)
3133

3234

3335
def call_api(url, method, **kwargs):
@@ -84,7 +86,7 @@ def sanity_checks(self, nuke):
8486
if nuke:
8587
return
8688

87-
url = get_api_endpoint().format(username=getpass.getuser()) + self.domain + '/'
89+
url = get_api_endpoint().format(username=getpass.getuser(), flavor="webapps") + self.domain + '/'
8890
response = call_api(url, 'get')
8991
if response.status_code == 200:
9092
raise SanityException(
@@ -98,9 +100,9 @@ def sanity_checks(self, nuke):
98100
def create(self, python_version, virtualenv_path, project_path, nuke):
99101
print(snakesay('Creating web app via API'))
100102
if nuke:
101-
webapp_url = get_api_endpoint().format(username=getpass.getuser()) + self.domain + '/'
103+
webapp_url = get_api_endpoint().format(username=getpass.getuser(), flavor="webapps") + self.domain + '/'
102104
call_api(webapp_url, 'delete')
103-
post_url = get_api_endpoint().format(username=getpass.getuser())
105+
post_url = get_api_endpoint().format(username=getpass.getuser(), flavor="webapps")
104106
patch_url = post_url + self.domain + '/'
105107
response = call_api(post_url, 'post', data={
106108
'domain_name': self.domain, 'python_version': PYTHON_VERSIONS[python_version]},
@@ -130,7 +132,7 @@ def create(self, python_version, virtualenv_path, project_path, nuke):
130132
def add_default_static_files_mappings(self, project_path):
131133
print(snakesay('Adding static files mappings for /static/ and /media/'))
132134

133-
url = get_api_endpoint().format(username=getpass.getuser()) + self.domain + '/static_files/'
135+
url = get_api_endpoint().format(username=getpass.getuser(), flavor="webapps") + self.domain + '/static_files/'
134136
call_api(url, 'post', json=dict(
135137
url='/static/', path=str(Path(project_path) / 'static'),
136138
))
@@ -142,7 +144,7 @@ def add_default_static_files_mappings(self, project_path):
142144

143145
def reload(self):
144146
print(snakesay('Reloading {domain} via API'.format(domain=self.domain)))
145-
url = get_api_endpoint().format(username=getpass.getuser()) + self.domain + '/reload/'
147+
url = get_api_endpoint().format(username=getpass.getuser(), flavor="webapps") + self.domain + '/reload/'
146148
response = call_api(url, 'post')
147149
if not response.ok:
148150
raise Exception(
@@ -155,7 +157,7 @@ def reload(self):
155157

156158
def set_ssl(self, certificate, private_key):
157159
print(snakesay('Setting up SSL for {domain} via API'.format(domain=self.domain)))
158-
url = get_api_endpoint().format(username=getpass.getuser()) + self.domain + '/ssl/'
160+
url = get_api_endpoint().format(username=getpass.getuser(), flavor="webapps") + self.domain + '/ssl/'
159161
response = call_api(
160162
url, 'post',
161163
json={'cert': certificate, 'private_key': private_key}
@@ -170,7 +172,7 @@ def set_ssl(self, certificate, private_key):
170172

171173

172174
def get_ssl_info(self):
173-
url = get_api_endpoint().format(username=getpass.getuser()) + self.domain + '/ssl/'
175+
url = get_api_endpoint().format(username=getpass.getuser(), flavor="webapps") + self.domain + '/ssl/'
174176
response = call_api(url, 'get')
175177
if not response.ok:
176178
raise Exception(
@@ -195,14 +197,14 @@ def delete_log(self, log_type, index=0):
195197
'Deleting current {type} log file for {domain} via API'.format(type=log_type, domain=self.domain)))
196198

197199
if index == 1:
198-
url = get_api_endpoint("files").format(username=getpass.getuser()) + "path/var/log/{domain}.{type}.log.1/".format(
200+
url = get_api_endpoint().format(username=getpass.getuser(), flavor="files") + "path/var/log/{domain}.{type}.log.1/".format(
199201
domain=self.domain, type=log_type)
200202
elif index > 1:
201-
url = get_api_endpoint("files").format(
202-
username=getpass.getuser()) + "path/var/log/{domain}.{type}.log.{index}.gz/".format(
203+
url = get_api_endpoint().format(
204+
username=getpass.getuser(), flavor="files") + "path/var/log/{domain}.{type}.log.{index}.gz/".format(
203205
domain=self.domain, type=log_type, index=index)
204206
else:
205-
url = get_api_endpoint("files").format(username=getpass.getuser()) + "path/var/log/{domain}.{type}.log/".format(
207+
url = get_api_endpoint().format(username=getpass.getuser(), flavor="files") + "path/var/log/{domain}.{type}.log/".format(
206208
domain=self.domain, type=log_type)
207209
response = call_api(url, "delete")
208210
if not response.ok:

tests/test_api.py

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
class TestGetAPIEndpoint:
2020

2121
def test_gets_domain_from_env_if_set(self, monkeypatch):
22-
assert get_api_endpoint() == 'https://www.pythonanywhere.com/api/v0/user/{username}/webapps/'
22+
assert get_api_endpoint() == 'https://www.pythonanywhere.com/api/v0/user/{username}/{flavor}/'
2323
monkeypatch.setenv('PYTHONANYWHERE_DOMAIN', 'foo.com')
24-
assert get_api_endpoint() == 'https://www.foo.com/api/v0/user/{username}/webapps/'
24+
assert get_api_endpoint() == 'https://www.foo.com/api/v0/user/{username}/{flavor}/'
2525

2626

2727
class TestCallAPI:
@@ -67,7 +67,7 @@ def test_compare_not_equal(self):
6767

6868
class TestWebappSanityChecks:
6969
domain = 'www.domain.com'
70-
expected_url = get_api_endpoint().format(username=getpass.getuser()) + domain + '/'
70+
expected_url = get_api_endpoint().format(username=getpass.getuser(), flavor="webapps") + domain + '/'
7171

7272
def test_does_not_complain_if_api_token_exists(self, api_token, api_responses):
7373
webapp = Webapp(self.domain)
@@ -115,8 +115,8 @@ def test_nuke_option_overrides_all_but_token_check(
115115
class TestCreateWebapp:
116116

117117
def test_does_post_to_create_webapp(self, api_responses, api_token):
118-
expected_post_url = get_api_endpoint().format(username=getpass.getuser())
119-
expected_patch_url = get_api_endpoint().format(username=getpass.getuser()) + 'mydomain.com/'
118+
expected_post_url = get_api_endpoint().format(username=getpass.getuser(), flavor="webapps")
119+
expected_patch_url = get_api_endpoint().format(username=getpass.getuser(), flavor="webapps") + 'mydomain.com/'
120120
api_responses.add(responses.POST, expected_post_url, status=201, body=json.dumps({'status': 'OK'}))
121121
api_responses.add(responses.PATCH, expected_patch_url, status=200)
122122

@@ -132,8 +132,8 @@ def test_does_post_to_create_webapp(self, api_responses, api_token):
132132

133133

134134
def test_does_patch_to_update_virtualenv_path_and_source_directory(self, api_responses, api_token):
135-
expected_post_url = get_api_endpoint().format(username=getpass.getuser())
136-
expected_patch_url = get_api_endpoint().format(username=getpass.getuser()) + 'mydomain.com/'
135+
expected_post_url = get_api_endpoint().format(username=getpass.getuser(), flavor="webapps")
136+
expected_patch_url = get_api_endpoint().format(username=getpass.getuser(), flavor="webapps") + 'mydomain.com/'
137137
api_responses.add(responses.POST, expected_post_url, status=201, body=json.dumps({'status': 'OK'}))
138138
api_responses.add(responses.PATCH, expected_patch_url, status=200)
139139

@@ -149,7 +149,7 @@ def test_does_patch_to_update_virtualenv_path_and_source_directory(self, api_res
149149

150150

151151
def test_raises_if_post_does_not_20x(self, api_responses, api_token):
152-
expected_post_url = get_api_endpoint().format(username=getpass.getuser())
152+
expected_post_url = get_api_endpoint().format(username=getpass.getuser(), flavor="webapps")
153153
api_responses.add(responses.POST, expected_post_url, status=500, body='an error')
154154

155155
with pytest.raises(Exception) as e:
@@ -160,7 +160,7 @@ def test_raises_if_post_does_not_20x(self, api_responses, api_token):
160160

161161

162162
def test_raises_if_post_returns_a_200_with_status_error(self, api_responses, api_token):
163-
expected_post_url = get_api_endpoint().format(username=getpass.getuser())
163+
expected_post_url = get_api_endpoint().format(username=getpass.getuser(), flavor="webapps")
164164
api_responses.add(responses.POST, expected_post_url, status=200, body=json.dumps({
165165
"status": "ERROR", "error_type": "bad", "error_message": "bad things happened"
166166
}))
@@ -173,8 +173,8 @@ def test_raises_if_post_returns_a_200_with_status_error(self, api_responses, api
173173

174174

175175
def test_raises_if_patch_does_not_20x(self, api_responses, api_token):
176-
expected_post_url = get_api_endpoint().format(username=getpass.getuser())
177-
expected_patch_url = get_api_endpoint().format(username=getpass.getuser()) + 'mydomain.com/'
176+
expected_post_url = get_api_endpoint().format(username=getpass.getuser(), flavor="webapps")
177+
expected_patch_url = get_api_endpoint().format(username=getpass.getuser(), flavor="webapps") + 'mydomain.com/'
178178
api_responses.add(responses.POST, expected_post_url, status=201, body=json.dumps({'status': 'OK'}))
179179
api_responses.add(responses.PATCH, expected_patch_url, status=400, json={'message': 'an error'})
180180

@@ -186,8 +186,8 @@ def test_raises_if_patch_does_not_20x(self, api_responses, api_token):
186186

187187

188188
def test_does_delete_first_for_nuke_call(self, api_responses, api_token):
189-
post_url = get_api_endpoint().format(username=getpass.getuser())
190-
webapp_url = get_api_endpoint().format(username=getpass.getuser()) + 'mydomain.com/'
189+
post_url = get_api_endpoint().format(username=getpass.getuser(), flavor="webapps")
190+
webapp_url = get_api_endpoint().format(username=getpass.getuser(), flavor="webapps") + 'mydomain.com/'
191191
api_responses.add(responses.DELETE, webapp_url, status=200)
192192
api_responses.add(responses.POST, post_url, status=201, body=json.dumps({'status': 'OK'}))
193193
api_responses.add(responses.PATCH, webapp_url, status=200)
@@ -201,8 +201,8 @@ def test_does_delete_first_for_nuke_call(self, api_responses, api_token):
201201

202202

203203
def test_ignores_404_from_delete_call_when_nuking(self, api_responses, api_token):
204-
post_url = get_api_endpoint().format(username=getpass.getuser())
205-
webapp_url = get_api_endpoint().format(username=getpass.getuser()) + 'mydomain.com/'
204+
post_url = get_api_endpoint().format(username=getpass.getuser(), flavor="webapps")
205+
webapp_url = get_api_endpoint().format(username=getpass.getuser(), flavor="webapps") + 'mydomain.com/'
206206
api_responses.add(responses.DELETE, webapp_url, status=404)
207207
api_responses.add(responses.POST, post_url, status=201, body=json.dumps({'status': 'OK'}))
208208
api_responses.add(responses.PATCH, webapp_url, status=200)
@@ -214,7 +214,7 @@ def test_ignores_404_from_delete_call_when_nuking(self, api_responses, api_token
214214
class TestAddDefaultStaticFilesMapping:
215215

216216
def test_does_two_posts_to_static_files_endpoint(self, api_token, api_responses):
217-
expected_url = get_api_endpoint().format(username=getpass.getuser()) + 'mydomain.com/static_files/'
217+
expected_url = get_api_endpoint().format(username=getpass.getuser(), flavor="webapps") + 'mydomain.com/static_files/'
218218
api_responses.add(responses.POST, expected_url, status=201)
219219
api_responses.add(responses.POST, expected_url, status=201)
220220

@@ -240,7 +240,7 @@ def test_does_two_posts_to_static_files_endpoint(self, api_token, api_responses)
240240
class TestReloadWebapp:
241241

242242
def test_does_post_to_reload_url(self, api_responses, api_token):
243-
expected_url = get_api_endpoint().format(username=getpass.getuser()) + 'mydomain.com/reload/'
243+
expected_url = get_api_endpoint().format(username=getpass.getuser(), flavor="webapps") + 'mydomain.com/reload/'
244244
api_responses.add(responses.POST, expected_url, status=200)
245245

246246
Webapp('mydomain.com').reload()
@@ -252,7 +252,7 @@ def test_does_post_to_reload_url(self, api_responses, api_token):
252252

253253

254254
def test_raises_if_post_does_not_20x(self, api_responses, api_token):
255-
expected_url = get_api_endpoint().format(username=getpass.getuser()) + 'mydomain.com/reload/'
255+
expected_url = get_api_endpoint().format(username=getpass.getuser(), flavor="webapps") + 'mydomain.com/reload/'
256256
api_responses.add(responses.POST, expected_url, status=404, body='nope')
257257

258258
with pytest.raises(Exception) as e:
@@ -265,7 +265,7 @@ def test_raises_if_post_does_not_20x(self, api_responses, api_token):
265265
class TestSetWebappSSL:
266266

267267
def test_does_post_to_ssl_url(self, api_responses, api_token):
268-
expected_url = get_api_endpoint().format(username=getpass.getuser()) + 'mydomain.com/ssl/'
268+
expected_url = get_api_endpoint().format(username=getpass.getuser(), flavor="webapps") + 'mydomain.com/ssl/'
269269
api_responses.add(responses.POST, expected_url, status=200)
270270
certificate = "certificate data"
271271
private_key = "private key data"
@@ -281,7 +281,7 @@ def test_does_post_to_ssl_url(self, api_responses, api_token):
281281

282282

283283
def test_raises_if_post_does_not_20x(self, api_responses, api_token):
284-
expected_url = get_api_endpoint().format(username=getpass.getuser()) + 'mydomain.com/ssl/'
284+
expected_url = get_api_endpoint().format(username=getpass.getuser(), flavor="webapps") + 'mydomain.com/ssl/'
285285
api_responses.add(responses.POST, expected_url, status=404, body='nope')
286286

287287
with pytest.raises(Exception) as e:
@@ -294,7 +294,7 @@ def test_raises_if_post_does_not_20x(self, api_responses, api_token):
294294
class TestGetWebappSSLInfo:
295295

296296
def test_returns_json_from_server_having_parsed_expiry(self, api_responses, api_token):
297-
expected_url = get_api_endpoint().format(username=getpass.getuser()) + 'mydomain.com/ssl/'
297+
expected_url = get_api_endpoint().format(username=getpass.getuser(), flavor="webapps") + 'mydomain.com/ssl/'
298298
api_responses.add(
299299
responses.GET, expected_url, status=200,
300300
body=json.dumps({
@@ -320,7 +320,7 @@ def test_returns_json_from_server_having_parsed_expiry(self, api_responses, api_
320320

321321

322322
def test_raises_if_get_does_not_return_200(self, api_responses, api_token):
323-
expected_url = get_api_endpoint().format(username=getpass.getuser()) + 'mydomain.com/ssl/'
323+
expected_url = get_api_endpoint().format(username=getpass.getuser(), flavor="webapps") + 'mydomain.com/ssl/'
324324
api_responses.add(responses.GET, expected_url, status=404, body='nope')
325325

326326
with pytest.raises(Exception) as e:
@@ -333,8 +333,8 @@ def test_raises_if_get_does_not_return_200(self, api_responses, api_token):
333333
class TestDeleteWebappLog:
334334

335335
def test_delete_current_access_log(self, api_responses, api_token):
336-
expected_url = get_api_endpoint(flavor="files").format(
337-
username=getpass.getuser()) + "path/var/log/mydomain.com.access.log/"
336+
expected_url = get_api_endpoint().format(
337+
username=getpass.getuser(), flavor="files") + "path/var/log/mydomain.com.access.log/"
338338
api_responses.add(responses.DELETE, expected_url, status=200)
339339

340340
Webapp("mydomain.com").delete_log(log_type="access")
@@ -345,8 +345,8 @@ def test_delete_current_access_log(self, api_responses, api_token):
345345
assert post.request.headers['Authorization'] == 'Token {api_token}'.format(api_token=api_token)
346346

347347
def test_delete_old_access_log(self, api_responses, api_token):
348-
expected_url = get_api_endpoint(flavor="files").format(
349-
username=getpass.getuser()) + "path/var/log/mydomain.com.access.log.1/"
348+
expected_url = get_api_endpoint().format(
349+
username=getpass.getuser(), flavor="files") + "path/var/log/mydomain.com.access.log.1/"
350350
api_responses.add(responses.DELETE, expected_url, status=200)
351351

352352
Webapp("mydomain.com").delete_log(log_type="access", index=1)
@@ -357,8 +357,8 @@ def test_delete_old_access_log(self, api_responses, api_token):
357357
assert post.request.headers['Authorization'] == 'Token {api_token}'.format(api_token=api_token)
358358

359359
def test_raises_if_post_does_not_20x(self, api_responses, api_token):
360-
expected_url = get_api_endpoint(flavor="files").format(
361-
username=getpass.getuser()) + "path/var/log/mydomain.com.access.log/"
360+
expected_url = get_api_endpoint().format(
361+
username=getpass.getuser(), flavor="files") + "path/var/log/mydomain.com.access.log/"
362362
api_responses.add(responses.DELETE, expected_url, status=404, body="nope")
363363

364364
with pytest.raises(Exception) as e:

0 commit comments

Comments
 (0)