pythonanywhere-core 0.2.9__py3-none-any.whl → 0.3.0__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.
- pythonanywhere_core/__init__.py +1 -1
- pythonanywhere_core/base.py +8 -0
- pythonanywhere_core/files.py +23 -3
- pythonanywhere_core/resources.py +2 -4
- pythonanywhere_core/schedule.py +2 -3
- pythonanywhere_core/students.py +2 -3
- pythonanywhere_core/webapp.py +4 -5
- pythonanywhere_core/website.py +3 -6
- {pythonanywhere_core-0.2.9.dist-info → pythonanywhere_core-0.3.0.dist-info}/METADATA +1 -1
- pythonanywhere_core-0.3.0.dist-info/RECORD +13 -0
- {pythonanywhere_core-0.2.9.dist-info → pythonanywhere_core-0.3.0.dist-info}/WHEEL +1 -1
- pythonanywhere_core-0.2.9.dist-info/RECORD +0 -13
- {pythonanywhere_core-0.2.9.dist-info → pythonanywhere_core-0.3.0.dist-info}/licenses/LICENSE +0 -0
pythonanywhere_core/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.
|
|
1
|
+
__version__ = "0.3.0"
|
pythonanywhere_core/base.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import getpass
|
|
1
2
|
import os
|
|
2
3
|
import platform
|
|
3
4
|
from typing import Dict
|
|
@@ -20,6 +21,13 @@ PYTHON_VERSIONS: Dict[str, str] = {
|
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
|
|
24
|
+
def get_username() -> str:
|
|
25
|
+
"""Returns PythonAnywhere username from ``PYTHONANYWHERE_USERNAME``
|
|
26
|
+
environment variable, falling back to :func:`getpass.getuser`."""
|
|
27
|
+
|
|
28
|
+
return os.environ.get("PYTHONANYWHERE_USERNAME", getpass.getuser())
|
|
29
|
+
|
|
30
|
+
|
|
23
31
|
def get_api_endpoint(username: str, flavor: str) -> str:
|
|
24
32
|
hostname = os.environ.get(
|
|
25
33
|
"PYTHONANYWHERE_SITE",
|
pythonanywhere_core/files.py
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
from pathlib import Path
|
|
2
2
|
from typing import Tuple, Union
|
|
3
3
|
from urllib.parse import urljoin
|
|
4
4
|
|
|
5
5
|
from requests.models import Response
|
|
6
6
|
|
|
7
|
-
from pythonanywhere_core.base import call_api, get_api_endpoint
|
|
7
|
+
from pythonanywhere_core.base import call_api, get_api_endpoint, get_username
|
|
8
8
|
from pythonanywhere_core.exceptions import PythonAnywhereApiException
|
|
9
9
|
|
|
10
10
|
|
|
@@ -38,7 +38,7 @@ class Files:
|
|
|
38
38
|
"""
|
|
39
39
|
|
|
40
40
|
|
|
41
|
-
base_url = get_api_endpoint(username=
|
|
41
|
+
base_url = get_api_endpoint(username=get_username(), flavor="files")
|
|
42
42
|
path_endpoint = urljoin(base_url, "path")
|
|
43
43
|
sharing_endpoint = urljoin(base_url, "sharing/")
|
|
44
44
|
tree_endpoint = urljoin(base_url, "tree/")
|
|
@@ -174,3 +174,23 @@ class Files:
|
|
|
174
174
|
return result.json()
|
|
175
175
|
|
|
176
176
|
raise PythonAnywhereApiException(f"GET to {url} failed, got {result}{self._error_msg(result)}")
|
|
177
|
+
|
|
178
|
+
def tree_post(self, local_dir_path: str, remote_dir_path: str) -> None:
|
|
179
|
+
"""Uploads contents of a local directory to remote path on
|
|
180
|
+
PythonAnywhere. Walks `local_dir_path` recursively and uploads
|
|
181
|
+
each file using :meth:`path_post`, preserving directory structure.
|
|
182
|
+
|
|
183
|
+
Raises :exc:`PythonAnywhereApiException` on first upload failure."""
|
|
184
|
+
|
|
185
|
+
local_dir = Path(local_dir_path)
|
|
186
|
+
if not local_dir.is_dir():
|
|
187
|
+
raise ValueError(f"{local_dir_path} is not a directory")
|
|
188
|
+
for path in sorted(local_dir.rglob("*")):
|
|
189
|
+
if path.is_file():
|
|
190
|
+
relative = path.relative_to(local_dir)
|
|
191
|
+
remote_path = f"{remote_dir_path}/{relative}"
|
|
192
|
+
self.path_post(remote_path, path.read_bytes())
|
|
193
|
+
elif path.is_dir() and not any(path.iterdir()):
|
|
194
|
+
placeholder = f"{remote_dir_path}/{path.relative_to(local_dir)}/.empty"
|
|
195
|
+
self.path_post(placeholder, b"")
|
|
196
|
+
self.path_delete(placeholder)
|
pythonanywhere_core/resources.py
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
from pythonanywhere_core.base import call_api, get_api_endpoint
|
|
1
|
+
from pythonanywhere_core.base import call_api, get_api_endpoint, get_username
|
|
4
2
|
from pythonanywhere_core.exceptions import PythonAnywhereApiException
|
|
5
3
|
|
|
6
4
|
|
|
@@ -17,7 +15,7 @@ class CPU:
|
|
|
17
15
|
"""
|
|
18
16
|
|
|
19
17
|
def __init__(self):
|
|
20
|
-
self.base_url = get_api_endpoint(username=
|
|
18
|
+
self.base_url = get_api_endpoint(username=get_username(), flavor="cpu")
|
|
21
19
|
|
|
22
20
|
def get_cpu_usage(self):
|
|
23
21
|
"""Get current CPU usage information.
|
pythonanywhere_core/schedule.py
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import getpass
|
|
2
1
|
from typing import List, Optional
|
|
3
2
|
|
|
4
3
|
from typing_extensions import Literal
|
|
5
4
|
|
|
6
|
-
from pythonanywhere_core.base import call_api, get_api_endpoint
|
|
5
|
+
from pythonanywhere_core.base import call_api, get_api_endpoint, get_username
|
|
7
6
|
from pythonanywhere_core.exceptions import PythonAnywhereApiException
|
|
8
7
|
|
|
9
8
|
|
|
@@ -28,7 +27,7 @@ class Schedule:
|
|
|
28
27
|
- :meth:`Schedule.update`: Update an existing task.
|
|
29
28
|
"""
|
|
30
29
|
|
|
31
|
-
base_url: str = get_api_endpoint(username=
|
|
30
|
+
base_url: str = get_api_endpoint(username=get_username(), flavor="schedule")
|
|
32
31
|
|
|
33
32
|
def create(self, params: dict) -> Optional[dict]:
|
|
34
33
|
"""Creates new scheduled task using `params`.
|
pythonanywhere_core/students.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import getpass
|
|
2
1
|
from typing import Optional
|
|
3
2
|
|
|
4
|
-
from pythonanywhere_core.base import call_api, get_api_endpoint
|
|
3
|
+
from pythonanywhere_core.base import call_api, get_api_endpoint, get_username
|
|
5
4
|
|
|
6
5
|
|
|
7
6
|
class StudentsAPI:
|
|
@@ -22,7 +21,7 @@ class StudentsAPI:
|
|
|
22
21
|
- :meth:`StudentsAPI.delete`: Remove a student.
|
|
23
22
|
"""
|
|
24
23
|
|
|
25
|
-
base_url: str = get_api_endpoint(username=
|
|
24
|
+
base_url: str = get_api_endpoint(username=get_username(), flavor="students")
|
|
26
25
|
|
|
27
26
|
def get(self) -> Optional[dict]:
|
|
28
27
|
"""Returns list of PythonAnywhere students related with user's account.
|
pythonanywhere_core/webapp.py
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
|
-
import getpass
|
|
5
4
|
from pathlib import Path
|
|
6
5
|
from textwrap import dedent
|
|
7
6
|
from typing import Any
|
|
8
7
|
|
|
9
8
|
from dateutil.parser import parse
|
|
10
9
|
|
|
11
|
-
from pythonanywhere_core.base import call_api, get_api_endpoint, PYTHON_VERSIONS
|
|
10
|
+
from pythonanywhere_core.base import call_api, get_api_endpoint, get_username, PYTHON_VERSIONS
|
|
12
11
|
from pythonanywhere_core.exceptions import SanityException, PythonAnywhereApiException, MissingCNAMEException
|
|
13
12
|
|
|
14
13
|
|
|
@@ -35,7 +34,7 @@ class Webapp:
|
|
|
35
34
|
Class Methods:
|
|
36
35
|
- :meth:`Webapp.list_webapps`: List all webapps for the current user.
|
|
37
36
|
"""
|
|
38
|
-
username =
|
|
37
|
+
username = get_username()
|
|
39
38
|
files_url = get_api_endpoint(username=username, flavor="files")
|
|
40
39
|
webapps_url = get_api_endpoint(username=username, flavor="webapps")
|
|
41
40
|
|
|
@@ -74,11 +73,11 @@ class Webapp:
|
|
|
74
73
|
f"You already have a webapp for {self.domain}.\n\nUse the --nuke option if you want to replace it."
|
|
75
74
|
)
|
|
76
75
|
|
|
77
|
-
def create(self, python_version: str, virtualenv_path: Path, project_path: Path, nuke: bool) -> None:
|
|
76
|
+
def create(self, python_version: str, virtualenv_path: Path | None, project_path: Path, nuke: bool) -> None:
|
|
78
77
|
"""Create a webapp for the given domain, using the given python version and virtualenv path
|
|
79
78
|
|
|
80
79
|
:param python_version: python version to use
|
|
81
|
-
:param virtualenv_path: path to the virtualenv
|
|
80
|
+
:param virtualenv_path: path to the virtualenv, or None to skip setting it
|
|
82
81
|
:param project_path: path to the project
|
|
83
82
|
:param nuke: if True, delete any existing webapp for this domain
|
|
84
83
|
|
pythonanywhere_core/website.py
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
from pythonanywhere_core.base import call_api, get_api_endpoint
|
|
1
|
+
from pythonanywhere_core.base import call_api, get_api_endpoint, get_username
|
|
5
2
|
from pythonanywhere_core.exceptions import DomainAlreadyExistsException, PythonAnywhereApiException
|
|
6
3
|
|
|
7
4
|
|
|
@@ -24,8 +21,8 @@ class Website:
|
|
|
24
21
|
"""
|
|
25
22
|
|
|
26
23
|
def __init__(self) -> None:
|
|
27
|
-
self.websites_base_url = get_api_endpoint(username=
|
|
28
|
-
self.domains_base_url = get_api_endpoint(username=
|
|
24
|
+
self.websites_base_url = get_api_endpoint(username=get_username(), flavor="websites")
|
|
25
|
+
self.domains_base_url = get_api_endpoint(username=get_username(), flavor="domains")
|
|
29
26
|
|
|
30
27
|
|
|
31
28
|
def create(self, domain_name: str, command: str) -> dict:
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
pythonanywhere_core/__init__.py,sha256=VrXpHDu3erkzwl_WXrqINBm9xWkcyUy53IQOj042dOs,22
|
|
2
|
+
pythonanywhere_core/base.py,sha256=l4GiEa-oe-EyAc_knX9kqmzQsPEIAH3ec1CivkWeK3Q,3454
|
|
3
|
+
pythonanywhere_core/exceptions.py,sha256=37aZy6txVFuiXfUdRJA5d7NQ1N5vbkdOveqv8rwnDbk,691
|
|
4
|
+
pythonanywhere_core/files.py,sha256=XjOsxei_tDgrubUVMmH4iYgc4sTmoFNk5EtZMJR3-0Q,7531
|
|
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=t2CIASC2WPQ051z2kbUgWNh_f6TfpWL4bKXqZHlqHSw,4339
|
|
10
|
+
pythonanywhere_core-0.3.0.dist-info/METADATA,sha256=bBzG7pSRywkSwgbg0HHGyvmiVLNKJ1EX7ba1-aU2jV8,1880
|
|
11
|
+
pythonanywhere_core-0.3.0.dist-info/WHEEL,sha256=kJCRJT_g0adfAJzTx2GUMmS80rTJIVHRCfG0DQgLq3o,88
|
|
12
|
+
pythonanywhere_core-0.3.0.dist-info/licenses/LICENSE,sha256=zOJT_E5Fv8crFEKS5ulv0btbjnUiIkdsEBPEBmLHRlQ,1080
|
|
13
|
+
pythonanywhere_core-0.3.0.dist-info/RECORD,,
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
pythonanywhere_core/__init__.py,sha256=F8OVhAhMXSkvvXYgZtbPn2SG1AQC3joK4yu-FrHt81Y,22
|
|
2
|
-
pythonanywhere_core/base.py,sha256=fMdyaccJdpeB8ZN2QqqEmUPYSaAp3ZdvFxgDexR0Bfg,3195
|
|
3
|
-
pythonanywhere_core/exceptions.py,sha256=37aZy6txVFuiXfUdRJA5d7NQ1N5vbkdOveqv8rwnDbk,691
|
|
4
|
-
pythonanywhere_core/files.py,sha256=qIfbcg472TPeOejpif_i64PtWP_qROlxoz5JbePzX8Q,6491
|
|
5
|
-
pythonanywhere_core/resources.py,sha256=NzzL-eNyo26Lr5FVJSAaxTq0Ia0vP3tIew_N7yFiFlk,1172
|
|
6
|
-
pythonanywhere_core/schedule.py,sha256=giSO-Gssshkto9de2hSA3VeNKotXYu-lBG-iyqDolIw,3904
|
|
7
|
-
pythonanywhere_core/students.py,sha256=PeBLUP7AOCRwCDiaH71wURwFx3H3PLQW91f5AjOPQmU,1778
|
|
8
|
-
pythonanywhere_core/webapp.py,sha256=Fg-c_qnoXYK_VN3bMQjBPoVkRj49KZt_7OkWdqwW_Us,11277
|
|
9
|
-
pythonanywhere_core/website.py,sha256=6Q_37QDKkuKE3771V056aiPmrQ0v8ot6U59CIaZwQzk,4348
|
|
10
|
-
pythonanywhere_core-0.2.9.dist-info/METADATA,sha256=eYEs0j3fTbw5u1ayGidBnCzzFFKzECKpMWWQYPSnWl0,1880
|
|
11
|
-
pythonanywhere_core-0.2.9.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
12
|
-
pythonanywhere_core-0.2.9.dist-info/licenses/LICENSE,sha256=zOJT_E5Fv8crFEKS5ulv0btbjnUiIkdsEBPEBmLHRlQ,1080
|
|
13
|
-
pythonanywhere_core-0.2.9.dist-info/RECORD,,
|
{pythonanywhere_core-0.2.9.dist-info → pythonanywhere_core-0.3.0.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|