diff --git a/README.md b/README.md index f09f86d..85ea224 100644 --- a/README.md +++ b/README.md @@ -16,10 +16,10 @@ In a PythonAnywhere Bash console, run: pip3.10 install --user pythonanywhere -If there is no `python3.9` on your PythonAnywhere account, +If there is no `python3.10` on your PythonAnywhere account, you should upgrade your account to the newest system image. See [here](https://help.pythonanywhere.com/pages/ChangingSystemImage) how to do that. -`pa` works with python 3.7, 3.8 and 3.9, but we recommend using the latest system image. +`pa` works with python 3.8, 3.9, and 3.10 but we recommend using the latest system image. ### On your own machine Install the `pythonanywhere` package from [PyPI](https://pypi.org/project/pythonanywhere/). diff --git a/cli/django.py b/cli/django.py index 2d81ce3..f15fc65 100644 --- a/cli/django.py +++ b/cli/django.py @@ -19,7 +19,7 @@ def autoconfigure( help="Domain name, eg www.mydomain.com", ), python_version: str = typer.Option( - "3.7", + "3.8", "-p", "--python-version", help="Python version, eg '3.9'", diff --git a/cli/webapp.py b/cli/webapp.py index a8428b4..e31f5b3 100644 --- a/cli/webapp.py +++ b/cli/webapp.py @@ -22,7 +22,7 @@ def create( help="Domain name, eg www.mydomain.com", ), python_version: str = typer.Option( - "3.7", + "3.8", "-p", "--python-version", help="Python version, eg '3.9'", diff --git a/pythonanywhere/api/base.py b/pythonanywhere/api/base.py index 661cc76..615a2f6 100644 --- a/pythonanywhere/api/base.py +++ b/pythonanywhere/api/base.py @@ -3,7 +3,6 @@ import requests PYTHON_VERSIONS = { - "3.7": "python37", "3.8": "python38", "3.9": "python39", "3.10": "python310", diff --git a/pythonanywhere/snakesay.py b/pythonanywhere/snakesay.py index f6f197c..357df40 100755 --- a/pythonanywhere/snakesay.py +++ b/pythonanywhere/snakesay.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.7 +#!/usr/bin/env python3.8 import sys import textwrap diff --git a/scripts/pa_autoconfigure_django.py b/scripts/pa_autoconfigure_django.py index 255f671..8272da1 100755 --- a/scripts/pa_autoconfigure_django.py +++ b/scripts/pa_autoconfigure_django.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3.7 +#!/usr/bin/python3.8 """Autoconfigure a Django project from on a github URL. - downloads the repo @@ -13,7 +13,7 @@ Options: --branch= Branch name in case of multiple branches [default: None] --domain= Domain name, eg www.mydomain.com [default: your-username.pythonanywhere.com] - --python= Python version, eg "3.8" [default: 3.7] + --python= Python version, eg "3.9" [default: 3.8] --nuke *Irrevocably* delete any existing web app config on this domain. Irrevocably. """ diff --git a/scripts/pa_create_scheduled_task.py b/scripts/pa_create_scheduled_task.py index 6590fec..9fd2e3d 100755 --- a/scripts/pa_create_scheduled_task.py +++ b/scripts/pa_create_scheduled_task.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3.7 +#!/usr/bin/python3.8 """Create a scheduled task. Two categories of tasks are available: daily and hourly. diff --git a/scripts/pa_create_webapp_with_virtualenv.py b/scripts/pa_create_webapp_with_virtualenv.py index c2cdf46..2d205ef 100755 --- a/scripts/pa_create_webapp_with_virtualenv.py +++ b/scripts/pa_create_webapp_with_virtualenv.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3.7 +#!/usr/bin/python3.8 """Create a web app with a virtualenv - creates a simple hello world web app @@ -11,7 +11,7 @@ Options: --domain= Domain name, eg www.mydomain.com [default: your-username.pythonanywhere.com] - --python= Python version, eg "3.8" [default: 3.7] + --python= Python version, eg "3.9" [default: 3.8] --nuke *Irrevocably* delete any existing web app config on this domain. Irrevocably. """ diff --git a/scripts/pa_delete_scheduled_task.py b/scripts/pa_delete_scheduled_task.py index b1103cb..80efb04 100755 --- a/scripts/pa_delete_scheduled_task.py +++ b/scripts/pa_delete_scheduled_task.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3.7 +#!/usr/bin/python3.8 """Delete scheduled task(s) by id or nuke'em all. Usage: diff --git a/scripts/pa_delete_webapp_logs.py b/scripts/pa_delete_webapp_logs.py index d854142..0a06a84 100755 --- a/scripts/pa_delete_webapp_logs.py +++ b/scripts/pa_delete_webapp_logs.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3.7 +#!/usr/bin/python3.8 """Deletes webapp logs. - gets list of logs via api diff --git a/scripts/pa_get_scheduled_task_specs.py b/scripts/pa_get_scheduled_task_specs.py index 1332b68..8b0796d 100755 --- a/scripts/pa_get_scheduled_task_specs.py +++ b/scripts/pa_get_scheduled_task_specs.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3.7 +#!/usr/bin/python3.8 """Get current scheduled task's specs file by task id. Available specs are: command, enabled, interval, hour, minute, printable-time, diff --git a/scripts/pa_get_scheduled_tasks_list.py b/scripts/pa_get_scheduled_tasks_list.py index 7bfcc4c..6dbd0c3 100755 --- a/scripts/pa_get_scheduled_tasks_list.py +++ b/scripts/pa_get_scheduled_tasks_list.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3.7 +#!/usr/bin/python3.8 """Get list of user's scheduled tasks as a table with columns: id, interval, at (hour:minute/minute past), status (enabled/disabled), command. diff --git a/scripts/pa_install_webapp_letsencrypt_ssl.py b/scripts/pa_install_webapp_letsencrypt_ssl.py index 7fa13aa..9bcfb12 100755 --- a/scripts/pa_install_webapp_letsencrypt_ssl.py +++ b/scripts/pa_install_webapp_letsencrypt_ssl.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3.7 +#!/usr/bin/python3.8 """Set the HTTPS certificate and private key for a website, assuming that these have been generated by the dehydrated script that gets them from Let's Encrypt, and that they're in the standard place. This script should normally only be run on PythonAnywhere. diff --git a/scripts/pa_install_webapp_ssl.py b/scripts/pa_install_webapp_ssl.py index 44faaf4..25b6098 100755 --- a/scripts/pa_install_webapp_ssl.py +++ b/scripts/pa_install_webapp_ssl.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3.7 +#!/usr/bin/python3.8 """Set the HTTPS certificate and private key for a website to the contents of two files, and reload the site. Usage: diff --git a/scripts/pa_reload_webapp.py b/scripts/pa_reload_webapp.py index 61cfed7..252363d 100755 --- a/scripts/pa_reload_webapp.py +++ b/scripts/pa_reload_webapp.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3.7 +#!/usr/bin/python3.8 """Reloads the given site Usage: diff --git a/scripts/pa_start_django_webapp_with_virtualenv.py b/scripts/pa_start_django_webapp_with_virtualenv.py index 017b51d..a10cb2f 100755 --- a/scripts/pa_start_django_webapp_with_virtualenv.py +++ b/scripts/pa_start_django_webapp_with_virtualenv.py @@ -1,6 +1,6 @@ -#!/usr/bin/python3.7 +#!/usr/bin/python3.8 """Create a new Django webapp with a virtualenv. Defaults to -your free domain, the latest version of Django and Python 3.6 +your free domain, the latest version of Django and Python 3.8 Usage: pa_start_django_webapp_with_virtualenv.py [--domain= --django= --python=] [--nuke] @@ -8,7 +8,7 @@ Options: --domain= Domain name, eg www.mydomain.com [default: your-username.pythonanywhere.com] --django= Django version, eg "1.8.4" [default: latest] - --python= Python version, eg "2.7" [default: 3.7] + --python= Python version, eg "2.7" [default: 3.8] --nuke *Irrevocably* delete any existing web app config on this domain. Irrevocably. """ diff --git a/scripts/pa_update_scheduled_task.py b/scripts/pa_update_scheduled_task.py index 0641010..77ceea8 100755 --- a/scripts/pa_update_scheduled_task.py +++ b/scripts/pa_update_scheduled_task.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3.7 +#!/usr/bin/python3.8 """Update a scheduled task using id and proper specs. Note that logfile name will change after updating the task but it won't be diff --git a/tests/test_api_webapp.py b/tests/test_api_webapp.py index 6cd5b3f..b8f882b 100644 --- a/tests/test_api_webapp.py +++ b/tests/test_api_webapp.py @@ -90,13 +90,13 @@ def test_does_post_to_create_webapp(self, api_responses, api_token): api_responses.add(responses.PATCH, expected_patch_url, status=200) Webapp("mydomain.com").create( - "3.7", "/virtualenv/path", "/project/path", nuke=False + "3.8", "/virtualenv/path", "/project/path", nuke=False ) post = api_responses.calls[0] assert post.request.url == expected_post_url assert post.request.body == urlencode( - {"domain_name": "mydomain.com", "python_version": PYTHON_VERSIONS["3.7"]} + {"domain_name": "mydomain.com", "python_version": PYTHON_VERSIONS["3.8"]} ) assert post.request.headers["Authorization"] == f"Token {api_token}" @@ -119,7 +119,7 @@ def test_does_patch_to_update_virtualenv_path_and_source_directory( api_responses.add(responses.PATCH, expected_patch_url, status=200) Webapp("mydomain.com").create( - "3.7", "/virtualenv/path", "/project/path", nuke=False + "3.8", "/virtualenv/path", "/project/path", nuke=False ) patch = api_responses.calls[1] @@ -139,7 +139,7 @@ def test_raises_if_post_does_not_20x(self, api_responses, api_token): with pytest.raises(Exception) as e: Webapp("mydomain.com").create( - "3.7", "/virtualenv/path", "/project/path", nuke=False + "3.8", "/virtualenv/path", "/project/path", nuke=False ) assert "POST to create webapp via API failed" in str(e.value) @@ -166,7 +166,7 @@ def test_raises_if_post_returns_a_200_with_status_error( with pytest.raises(Exception) as e: Webapp("mydomain.com").create( - "3.7", "/virtualenv/path", "/project/path", nuke=False + "3.8", "/virtualenv/path", "/project/path", nuke=False ) assert "POST to create webapp via API failed" in str(e.value) @@ -195,7 +195,7 @@ def test_raises_if_patch_does_not_20x(self, api_responses, api_token): with pytest.raises(Exception) as e: Webapp("mydomain.com").create( - "3.7", "/virtualenv/path", "/project/path", nuke=False + "3.8", "/virtualenv/path", "/project/path", nuke=False ) assert ( @@ -219,7 +219,7 @@ def test_does_delete_first_for_nuke_call(self, api_responses, api_token): api_responses.add(responses.PATCH, webapp_url, status=200) Webapp("mydomain.com").create( - "3.7", "/virtualenv/path", "/project/path", nuke=True + "3.8", "/virtualenv/path", "/project/path", nuke=True ) delete = api_responses.calls[0] @@ -242,7 +242,7 @@ def test_ignores_404_from_delete_call_when_nuking(self, api_responses, api_token api_responses.add(responses.PATCH, webapp_url, status=200) Webapp("mydomain.com").create( - "3.7", "/virtualenv/path", "/project/path", nuke=True + "3.8", "/virtualenv/path", "/project/path", nuke=True ) diff --git a/tests/test_django_project.py b/tests/test_django_project.py index 68a3d6a..10507ff 100644 --- a/tests/test_django_project.py +++ b/tests/test_django_project.py @@ -514,7 +514,7 @@ def test_actually_produces_wsgi_file_that_can_import_project_non_nested( running_python_version = ".".join(python_version().split(".")[:2]) project = DjangoProject("mydomain.com", running_python_version) shutil.copytree(str(non_nested_submodule), str(project.project_path)) - if running_python_version in ["3.7", "3.8", "3.9", "3.10"]: + if running_python_version in ["3.8", "3.9", "3.10", "3.11"]: project.create_virtualenv(django_version="latest") else: project.create_virtualenv() @@ -534,7 +534,7 @@ def test_actually_produces_wsgi_file_that_can_import_nested_project( running_python_version = ".".join(python_version().split(".")[:2]) project = DjangoProject("mydomain.com", running_python_version) shutil.copytree(str(more_nested_submodule), str(project.project_path)) - if running_python_version in ["3.7", "3.8", "3.9", "3.10"]: + if running_python_version in ["3.8", "3.9", "3.10", "3.11"]: project.create_virtualenv(django_version="latest") else: project.create_virtualenv() diff --git a/tests/test_virtualenvs.py b/tests/test_virtualenvs.py index 7edc3cc..783afad 100644 --- a/tests/test_virtualenvs.py +++ b/tests/test_virtualenvs.py @@ -12,7 +12,7 @@ def test_path(self, virtualenvs_folder): assert v.path == Path(virtualenvs_folder) / "domain.com" def test_create_uses_bash_and_sources_virtualenvwrapper(self, mock_subprocess, virtualenvs_folder): - v = Virtualenv("domain.com", "3.7") + v = Virtualenv("domain.com", "3.8") v.create(nuke=False) args, kwargs = mock_subprocess.check_call.call_args command_list = args[0] @@ -20,15 +20,15 @@ def test_create_uses_bash_and_sources_virtualenvwrapper(self, mock_subprocess, v assert command_list[2].startswith("source virtualenvwrapper.sh && mkvirtualenv") def test_create_calls_mkvirtualenv_with_python_version_and_domain(self, mock_subprocess, virtualenvs_folder): - v = Virtualenv("domain.com", "3.7") + v = Virtualenv("domain.com", "3.8") v.create(nuke=False) args, kwargs = mock_subprocess.check_call.call_args command_list = args[0] bash_command = command_list[2] - assert "mkvirtualenv --python=python3.7 domain.com" in bash_command + assert "mkvirtualenv --python=python3.8 domain.com" in bash_command def test_nuke_option_deletes_virtualenv(self, mock_subprocess, virtualenvs_folder): - v = Virtualenv("domain.com", "3.7") + v = Virtualenv("domain.com", "3.8") v.create(nuke=True) args, kwargs = mock_subprocess.check_call.call_args command_list = args[0] @@ -36,7 +36,7 @@ def test_nuke_option_deletes_virtualenv(self, mock_subprocess, virtualenvs_folde assert command_list[2].startswith("source virtualenvwrapper.sh && rmvirtualenv domain.com") def test_install_pip_installs_each_package(self, mock_subprocess, virtualenvs_folder): - v = Virtualenv("domain.com", "3.7") + v = Virtualenv("domain.com", "3.8") v.create(nuke=False) v.pip_install("package1 package2==1.1.2") args, kwargs = mock_subprocess.check_call.call_args_list[-1] @@ -60,4 +60,4 @@ def test_gets_version(self, fake_home, virtualenvs_folder): v.create(nuke=False) v.pip_install("aafigure==0.6") - assert v.get_version("aafigure") == "0.6" \ No newline at end of file + assert v.get_version("aafigure") == "0.6"