Skip to content
Merged
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
10 changes: 10 additions & 0 deletions dsd_pythonanywhere/deploy_messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@
$ ...
"""

settings_found_pythonanywhere = """
A PythonAnywhere-specific settings block was already found in settings.py.
That block will be replaced with a fresh copy.
"""

settings_cant_overwrite_pythonanywhere = """
Can't overwrite the existing PythonAnywhere-specific settings block. Please
remove it from settings.py manually and run the deploy command again.
"""


# --- Dynamic strings ---
# These need to be generated in functions, to display information that's determined as
Expand Down
11 changes: 11 additions & 0 deletions dsd_pythonanywhere/platform_deployer.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,17 @@ def _validate_platform(self) -> None:
"Please verify your API_USER and API_TOKEN are correct."
)

self._check_pythonanywhere_settings()

def _check_pythonanywhere_settings(self) -> None:
"""Check to see if a PythonAnywhere settings block already exists."""
plugin_utils.check_settings(
"PythonAnywhere",
"# PythonAnywhere settings.",
platform_msgs.settings_found_pythonanywhere,
platform_msgs.settings_cant_overwrite_pythonanywhere,
)

def _get_origin_url(self) -> str:
"""Get the git remote origin URL."""
origin_url = (
Expand Down
38 changes: 32 additions & 6 deletions tests/unit_tests/test_platform_deployer.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@
)


@pytest.fixture
def settings_path(tmp_path: Path):
settings_path = tmp_path / "settings.py"
settings_content = "# Existing settings"
settings_path.write_text(settings_content)
yield settings_path


def test_modify_gitignore(tmp_path: Path, monkeypatch):
"""_modify_gitignore adds patterns correctly."""
deployer = PlatformDeployer()
Expand Down Expand Up @@ -40,12 +48,8 @@ def test_modify_gitignore(tmp_path: Path, monkeypatch):
assert contents == original_contents


def test_modify_settings(tmp_path: Path, monkeypatch):
def test_modify_settings(settings_path, monkeypatch):
"""_modify_settings modifies settings.py as expected."""
settings_path = tmp_path / "settings.py"
settings_content = "# Existing settings"
settings_path.write_text(settings_content)

monkeypatch.setenv("API_USER", "testuser")
deployer = PlatformDeployer()
monkeypatch.setattr(dsd_config, "settings_path", settings_path)
Expand Down Expand Up @@ -175,11 +179,12 @@ def test_validate_platform_api_connection_fails(monkeypatch, mocker):
deployer._validate_platform()


def test_validate_platform_success(monkeypatch, mocker):
def test_validate_platform_success(settings_path, monkeypatch, mocker):
"""_validate_platform succeeds with valid credentials."""
monkeypatch.setenv("API_USER", "test_user")
monkeypatch.setenv("API_TOKEN", "test_token")
monkeypatch.setattr(dsd_config, "automate_all", True)
monkeypatch.setattr(dsd_config, "settings_path", settings_path)

deployer = PlatformDeployer()
mock_request = mocker.patch.object(deployer.client, "request")
Expand All @@ -200,3 +205,24 @@ def test_validate_platform_skipped_without_automate_all(monkeypatch):
deployer = PlatformDeployer()
# Should not raise any exception even without credentials
deployer._validate_platform()


def test_validate_platform_removes_existing_settings(settings_path, monkeypatch, mocker):
"""_validate_platform replaces settings block, preventing stacking copies."""
monkeypatch.setenv("API_USER", "test_user")
monkeypatch.setenv("API_TOKEN", "test_token")
monkeypatch.setattr(dsd_config, "automate_all", True)
monkeypatch.setattr(dsd_config, "settings_path", settings_path)
monkeypatch.setattr(dsd_config, "stdout", sys.stdout)
monkeypatch.setattr(dsd_config, "unit_testing", True)

deployer = PlatformDeployer()
mock_request = mocker.patch.object(deployer.client, "request")
mock_response = mocker.Mock()
mock_response.ok = True
mock_request.return_value = mock_response

settings_path.write_text("# PythonAnywhere settings.")
deployer._validate_platform()
modified_content = settings_path.read_text()
assert modified_content.count("# PythonAnywhere settings.") == 0