pythonanywhere-core 0.3.2__py3-none-any.whl → 0.3.3__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.
@@ -1 +1 @@
1
- __version__ = "0.3.2"
1
+ __version__ = "0.3.3"
@@ -117,15 +117,16 @@ class Files:
117
117
  """Starts sharing a file at `path`.
118
118
 
119
119
  Returns a tuple with a message and sharing link on
120
- success, raises otherwise. Message is "successfully shared" on success,
121
- "was already shared" if file has been already shared."""
120
+ HTTP 200/201, raises otherwise. Message is "successfully shared" on 201,
121
+ "was already shared" on 200."""
122
122
 
123
123
  url = self.sharing_endpoint
124
124
 
125
125
  result = call_api(url, "POST", json={"path": path})
126
126
 
127
- if result.ok:
128
- msg = {200: "was already shared", 201: "successfully shared"}[result.status_code]
127
+ messages = {200: "was already shared", 201: "successfully shared"}
128
+ if result.status_code in messages:
129
+ msg = messages[result.status_code]
129
130
  sharing_url_suffix = result.json()["url"]
130
131
  return msg, self._make_sharing_url(sharing_url_suffix)
131
132
 
@@ -1,4 +1,4 @@
1
- from typing import List, Optional
1
+ from typing import List
2
2
 
3
3
  from typing_extensions import Literal
4
4
 
@@ -29,30 +29,31 @@ class Schedule:
29
29
 
30
30
  base_url: str = get_api_endpoint(username=get_username(), flavor="schedule")
31
31
 
32
- def create(self, params: dict) -> Optional[dict]:
32
+ def create(self, params: dict) -> dict:
33
33
  """Creates new scheduled task using `params`.
34
34
 
35
35
  Params should be: command, enabled (True or False), interval (daily or
36
36
  hourly), hour (24h format) and minute.
37
37
 
38
38
  :param params: dictionary with required scheduled task specs
39
- :returns: dictionary with created task specs"""
39
+ :returns: dictionary with created task specs on HTTP 201
40
+ :raises PythonAnywhereApiException: if the response is not HTTP 201"""
40
41
 
41
42
  result = call_api(self.base_url, "POST", json=params)
42
43
 
43
44
  if result.status_code == 201:
44
45
  return result.json()
45
46
 
46
- if not result.ok:
47
- raise PythonAnywhereApiException(
48
- f"POST to set new task via API failed, got {result}: {result.text}"
49
- )
47
+ raise PythonAnywhereApiException(
48
+ f"POST to set new task via API failed, got {result}: {result.text}"
49
+ )
50
50
 
51
51
  def delete(self, task_id: int) -> Literal[True]:
52
52
  """Deletes scheduled task by id.
53
53
 
54
54
  :param task_id: scheduled task to be deleted id number
55
- :returns: True when API response is 204"""
55
+ :returns: True when API response is 204
56
+ :raises PythonAnywhereApiException: if the response is not HTTP 204"""
56
57
 
57
58
  result = call_api(
58
59
  f"{self.base_url}{task_id}/", "DELETE"
@@ -61,17 +62,22 @@ class Schedule:
61
62
  if result.status_code == 204:
62
63
  return True
63
64
 
64
- if not result.ok:
65
- raise PythonAnywhereApiException(
66
- f"DELETE via API on task {task_id} failed, got {result}: {result.text}"
67
- )
65
+ raise PythonAnywhereApiException(
66
+ f"DELETE via API on task {task_id} failed, got {result}: {result.text}"
67
+ )
68
68
 
69
69
  def get_list(self) -> List[dict]:
70
70
  """Gets list of existing scheduled tasks.
71
71
 
72
- :returns: list of existing scheduled tasks specs"""
72
+ :returns: list of existing scheduled tasks specs on HTTP 200
73
+ :raises PythonAnywhereApiException: if the response is not HTTP 200"""
73
74
 
74
- return call_api(self.base_url, "GET").json()
75
+ result = call_api(self.base_url, "GET")
76
+ if result.status_code != 200:
77
+ raise PythonAnywhereApiException(
78
+ f"GET scheduled tasks via API failed, got {result}: {result.text}"
79
+ )
80
+ return result.json()
75
81
 
76
82
  def get_specs(self, task_id: int) -> dict:
77
83
  """Get task specs by id.
@@ -51,6 +51,7 @@ class Webapp:
51
51
  :param nuke: if True, skip the check for existing webapp
52
52
 
53
53
  :raises SanityException: if API token is missing or webapp already exists
54
+ :raises PythonAnywhereApiException: if the existence check returns neither 200 nor 404
54
55
  """
55
56
  token = os.environ.get("API_TOKEN")
56
57
  if not token:
@@ -73,18 +74,28 @@ class Webapp:
73
74
  f"You already have a webapp for {self.domain}.\n\nUse the --nuke option if you want to replace it."
74
75
  )
75
76
 
77
+ if response.status_code != 404:
78
+ raise PythonAnywhereApiException(
79
+ f"GET to check webapp existence via API failed, got {response}:{response.text}"
80
+ )
81
+
76
82
  def create(self, python_version: str, virtualenv_path: Path | None, project_path: Path, nuke: bool) -> None:
77
83
  """Create a webapp for the given domain, using the given python version and virtualenv path
78
84
 
79
85
  :param python_version: python version to use
80
86
  :param virtualenv_path: path to the virtualenv, or None to skip setting it
81
87
  :param project_path: path to the project
82
- :param nuke: if True, delete any existing webapp for this domain
88
+ :param nuke: if True, delete any existing webapp for this domain;
89
+ continue only on HTTP 204 (deleted) or 404 (absent)
83
90
 
84
91
  :raises PythonAnywhereApiException: if API call fails
85
92
  """
86
93
  if nuke:
87
- call_api(self.domain_url, "delete")
94
+ response = call_api(self.domain_url, "delete")
95
+ if response.status_code not in (204, 404):
96
+ raise PythonAnywhereApiException(
97
+ f"DELETE before replacing webapp via API failed, got {response}:{response.text}"
98
+ )
88
99
  response = call_api(
89
100
  self.webapps_url,
90
101
  "post",
@@ -106,10 +117,14 @@ class Webapp:
106
117
  :param url_path: URL path (e.g., '/static/')
107
118
  :param directory_path: Filesystem path to serve (as Path)
108
119
 
109
- :raises PythonAnywhereApiException: if API call fails
120
+ :raises PythonAnywhereApiException: if the response is not HTTP 201
110
121
  """
111
122
  url = f"{self.domain_url}static_files/"
112
- call_api(url, "post", json=dict(url=url_path, path=str(directory_path)))
123
+ response = call_api(url, "post", json=dict(url=url_path, path=str(directory_path)))
124
+ if response.status_code != 201:
125
+ raise PythonAnywhereApiException(
126
+ f"POST to create static file mapping via API failed, got {response}:{response.text}"
127
+ )
113
128
 
114
129
  def add_default_static_files_mappings(self, project_path: Path) -> None:
115
130
  """Add default static files mappings for /static/ and /media/.
@@ -52,33 +52,48 @@ class Website:
52
52
  def get(self, domain_name: str) -> dict:
53
53
  """Returns dictionary with website info for ``domain_name``.
54
54
  :param domain_name:
55
- :return: dictionary with website info"""
55
+ :return: dictionary with website info on HTTP 200
56
+ :raises PythonAnywhereApiException: if the response is not HTTP 200"""
56
57
 
57
58
  response = call_api(
58
59
  f"{self.websites_base_url}{domain_name}/",
59
60
  "get",
60
61
  )
62
+ if response.status_code != 200:
63
+ raise PythonAnywhereApiException(
64
+ f"GET website via API failed, got {response}:{response.text}"
65
+ )
61
66
  return response.json()
62
67
 
63
68
  def list(self) -> list:
64
69
  """Returns list of dictionaries with all websites info.
65
- :return: list of dictionaries with websites info"""
70
+ :return: list of dictionaries with websites info on HTTP 200
71
+ :raises PythonAnywhereApiException: if the response is not HTTP 200"""
66
72
 
67
73
  response = call_api(
68
74
  self.websites_base_url,
69
75
  "get",
70
76
  )
77
+ if response.status_code != 200:
78
+ raise PythonAnywhereApiException(
79
+ f"GET websites via API failed, got {response}:{response.text}"
80
+ )
71
81
  return response.json()
72
82
 
73
83
  def reload(self, domain_name: str) -> dict:
74
84
  """Reloads website with ``domain_name``.
75
85
  :param domain_name: domain name for website to reload
76
- :return: dictionary with response"""
86
+ :return: dictionary with response on HTTP 200
87
+ :raises PythonAnywhereApiException: if the response is not HTTP 200"""
77
88
 
78
89
  response = call_api(
79
90
  f"{self.websites_base_url}{domain_name}/reload/",
80
91
  "post",
81
92
  )
93
+ if response.status_code != 200:
94
+ raise PythonAnywhereApiException(
95
+ f"POST to reload website via API failed, got {response}:{response.text}"
96
+ )
82
97
  return response.json()
83
98
 
84
99
  def auto_ssl(self, domain_name: str) -> dict:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pythonanywhere-core
3
- Version: 0.3.2
3
+ Version: 0.3.3
4
4
  Summary: API wrapper for programmatic management of PythonAnywhere services.
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -0,0 +1,13 @@
1
+ pythonanywhere_core/__init__.py,sha256=8KcCYTXH99C2-gCLuPILJvtT9YftRWJsartIx6TQ2ZY,22
2
+ pythonanywhere_core/base.py,sha256=nyyX53D0O5o_1a9rHhJDHUM24wlCr0SS544ZZbXbOYw,3415
3
+ pythonanywhere_core/exceptions.py,sha256=37aZy6txVFuiXfUdRJA5d7NQ1N5vbkdOveqv8rwnDbk,691
4
+ pythonanywhere_core/files.py,sha256=vksw1ZEPvCn9Hv1YrRhc1fea72cuzUzzeyr67u9CvKM,7765
5
+ pythonanywhere_core/resources.py,sha256=VBXspr1sGhfAVSFoTQtwpeN5CDG9-wHZwXJ3-5vy7dY,1167
6
+ pythonanywhere_core/schedule.py,sha256=9YHKvSql9p6VtLGLn7IqXzmdtg2U9ZG287hAcv8Je5g,4261
7
+ pythonanywhere_core/students.py,sha256=VfdftRrwPFEb-m2LW7pbiS9LiffwFNTfHpVeLXMQLLc,1774
8
+ pythonanywhere_core/webapp.py,sha256=dniwSCxogsKuqHI25TyVpk5vTxusrqgJjR4coaq9CYE,12126
9
+ pythonanywhere_core/website.py,sha256=yAosA61uQ7dEIsqX5qUFzNZflWDevMiS25FzNfXeArc,5625
10
+ pythonanywhere_core-0.3.3.dist-info/METADATA,sha256=Wd3dJ_-lZlurXDit_oMnvIr2xUM-nXM-DO_4hWaqNeM,1931
11
+ pythonanywhere_core-0.3.3.dist-info/WHEEL,sha256=L-WvLdSBvJWHXv5zrQxDvNRnIgoBzLUpcbuiw19KCuQ,88
12
+ pythonanywhere_core-0.3.3.dist-info/licenses/LICENSE,sha256=zOJT_E5Fv8crFEKS5ulv0btbjnUiIkdsEBPEBmLHRlQ,1080
13
+ pythonanywhere_core-0.3.3.dist-info/RECORD,,
@@ -1,13 +0,0 @@
1
- pythonanywhere_core/__init__.py,sha256=vNiWJ14r_cw5t_7UDqDQIVZvladKFGyHH2avsLpN7Vg,22
2
- pythonanywhere_core/base.py,sha256=nyyX53D0O5o_1a9rHhJDHUM24wlCr0SS544ZZbXbOYw,3415
3
- pythonanywhere_core/exceptions.py,sha256=37aZy6txVFuiXfUdRJA5d7NQ1N5vbkdOveqv8rwnDbk,691
4
- pythonanywhere_core/files.py,sha256=UfC7GroBnsIQd_9YYPFhadTDmGc9DC_nEdvFuDWDifM,7741
5
- pythonanywhere_core/resources.py,sha256=VBXspr1sGhfAVSFoTQtwpeN5CDG9-wHZwXJ3-5vy7dY,1167
6
- pythonanywhere_core/schedule.py,sha256=payqSYJf92gQzsZwVBtccXH4m_C--AAbdbf5DOtImhs,3900
7
- pythonanywhere_core/students.py,sha256=VfdftRrwPFEb-m2LW7pbiS9LiffwFNTfHpVeLXMQLLc,1774
8
- pythonanywhere_core/webapp.py,sha256=inwCDOHY_7IVQXJTeAxucn5vYPpJNdn-JLM3ji5gHwQ,11308
9
- pythonanywhere_core/website.py,sha256=O4RcvhBDPCdlaF7h432cr-D1XWb7IbeKPh_TuPNnBh4,4815
10
- pythonanywhere_core-0.3.2.dist-info/METADATA,sha256=9-_iLzlyOEL3EjItF3ciHp59EJ1IUyWF2odjGFH60QM,1931
11
- pythonanywhere_core-0.3.2.dist-info/WHEEL,sha256=L-WvLdSBvJWHXv5zrQxDvNRnIgoBzLUpcbuiw19KCuQ,88
12
- pythonanywhere_core-0.3.2.dist-info/licenses/LICENSE,sha256=zOJT_E5Fv8crFEKS5ulv0btbjnUiIkdsEBPEBmLHRlQ,1080
13
- pythonanywhere_core-0.3.2.dist-info/RECORD,,