Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 2 additions & 17 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "pythonanywhere-core"
version = "0.2.8"
version = "0.2.9"
description = "API wrapper for programmatic management of PythonAnywhere services."
authors = ["PythonAnywhere <[email protected]>"]
license = "MIT"
Expand All @@ -13,6 +13,7 @@ classifiers = [
"Intended Audience :: Developers",
"Topic :: Software Development :: Libraries",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3.14",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.11",
Expand All @@ -24,15 +25,14 @@ keywords = ["pythonanywhere", "api", "cloud", "web hosting"]
python = "^3.10"
python-dateutil = "^2.8.2"
requests = "^2.30.0"
snakesay = "^0.10.3"
typing_extensions = "^4.5.0"

[tool.poetry.group.dev.dependencies]
pytest = "^9.0.0"
pytest-cov = "^7.0.0"
pytest-mock = "^3.10.0"
responses = "^0.25.0"
sphinx = "7.4.7"
sphinx = "8.2.3"
sphinx-rtd-theme = "^3.0.0"

[tool.black]
Expand Down
2 changes: 1 addition & 1 deletion pythonanywhere_core/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.2.8"
__version__ = "0.2.9"
12 changes: 11 additions & 1 deletion pythonanywhere_core/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,14 @@ class NoTokenError(PythonAnywhereApiException):


class DomainAlreadyExistsException(PythonAnywhereApiException):
pass
pass


class MissingCNAMEException(PythonAnywhereApiException):
def __init__(self):
super().__init__(
"Could not find a CNAME for your website. If you're using an A record, "
"CloudFlare, or some other way of pointing your domain at PythonAnywhere "
"then that should not be a problem. If you're not, you should double-check "
"your DNS setup."
)
26 changes: 3 additions & 23 deletions pythonanywhere_core/webapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@
from typing import Any

from dateutil.parser import parse
from snakesay import snakesay

from pythonanywhere_core.base import call_api, get_api_endpoint, PYTHON_VERSIONS
from pythonanywhere_core.exceptions import SanityException, PythonAnywhereApiException
from pythonanywhere_core.exceptions import SanityException, PythonAnywhereApiException, MissingCNAMEException


class Webapp:
Expand Down Expand Up @@ -54,7 +53,6 @@ def sanity_checks(self, nuke: bool) -> None:

:raises SanityException: if API token is missing or webapp already exists
"""
print(snakesay("Running API sanity checks"))
token = os.environ.get("API_TOKEN")
if not token:
raise SanityException(
Expand Down Expand Up @@ -127,24 +125,13 @@ def add_default_static_files_mappings(self, project_path: Path) -> None:
def reload(self) -> None:
"""Reload webapp

:raises MissingCNAMEException: if CNAME not found (reload succeeded)
:raises PythonAnywhereApiException: if API call fails"""
url = f"{self.domain_url}reload/"
response = call_api(url, "post")
if not response.ok:
if response.status_code == 409 and response.json()["error"] == "cname_error":
print(
snakesay(
dedent(
"""
Could not find a CNAME for your website. If you're using an A record,
CloudFlare, or some other way of pointing your domain at PythonAnywhere
then that should not be a problem. If you're not, you should double-check
your DNS setup.
"""
)
)
)
return
raise MissingCNAMEException()
raise PythonAnywhereApiException(f"POST to reload webapp via API failed, got {response}:{response.text}")

def set_ssl(self, certificate: str, private_key: str) -> None:
Expand All @@ -155,7 +142,6 @@ def set_ssl(self, certificate: str, private_key: str) -> None:

:raises PythonAnywhereApiException: if API call fails
"""
print(snakesay(f"Setting up SSL for {self.domain} via API"))
url = f"{self.domain_url}ssl/"
response = call_api(url, "post", json={"cert": certificate, "private_key": private_key})
if not response.ok:
Expand Down Expand Up @@ -193,12 +179,6 @@ def delete_log(self, log_type: str, index: int = 0) -> None:

:raises PythonAnywhereApiException: if API call fails
"""
if index:
message = f"Deleting old (archive number {index}) {log_type} log file for {self.domain} via API"
else:
message = f"Deleting current {log_type} log file for {self.domain} via API"
print(snakesay(message))

if index == 1:
suffix = ".1"
elif index > 1:
Expand Down
9 changes: 6 additions & 3 deletions tests/test_webapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from urllib.parse import urlencode

from pythonanywhere_core.base import get_api_endpoint, PYTHON_VERSIONS
from pythonanywhere_core.exceptions import SanityException, PythonAnywhereApiException
from pythonanywhere_core.exceptions import SanityException, PythonAnywhereApiException, MissingCNAMEException
from pythonanywhere_core.webapp import Webapp


Expand Down Expand Up @@ -298,7 +298,7 @@ def test_raises_if_post_does_not_20x_that_is_not_a_cname_error(api_responses, ap
assert "nope" in str(e.value)


def test_does_not_raise_if_post_responds_with_a_cname_error(api_responses, api_token, domain_url, webapp):
def test_raises_missing_cname_exception_on_cname_error(api_responses, api_token, domain_url, webapp):
reload_url = f"{domain_url}reload/"
api_responses.add(
responses.POST,
Expand All @@ -307,7 +307,10 @@ def test_does_not_raise_if_post_responds_with_a_cname_error(api_responses, api_t
json={"status": "error", "error": "cname_error"},
)

webapp.reload() # Should not raise
with pytest.raises(MissingCNAMEException) as e:
webapp.reload()

assert "Could not find a CNAME for your website" in str(e.value)


# SET SSL
Expand Down
Loading