From 9d845e857e26ba17956828a320c4eddb1cf2245d Mon Sep 17 00:00:00 2001 From: Cameron Hyde Date: Sat, 4 Jan 2025 09:58:23 +1000 Subject: [PATCH 1/2] Labs engine pip-installable local serve command --- .vscode/launch.json | 20 ++++++++++++++--- app/app/cli.py | 46 ++++++++++++++++++++++++++++++++++++++++ app/app/settings/base.py | 27 +++++++---------------- app/app/settings/cli.py | 32 ++++++++++++++++++++++++++++ app/labs/views.py | 5 +++-- setup.py | 25 ++++++++++++++++++++++ 6 files changed, 131 insertions(+), 24 deletions(-) create mode 100644 app/app/cli.py create mode 100644 app/app/settings/cli.py create mode 100644 setup.py diff --git a/.vscode/launch.json b/.vscode/launch.json index d43e346..d4b7b40 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -6,7 +6,7 @@ "configurations": [ { "name": "Django runserver", - "type": "python", + "type": "debugpy", "purpose": ["debug-test"], "request": "launch", "program": "${workspaceFolder}/app/manage.py", @@ -20,7 +20,7 @@ }, { "name": "Django shell", - "type": "python", + "type": "debugpy", "purpose": ["debug-test"], "request": "launch", "program": "${workspaceFolder}/app/manage.py", @@ -34,7 +34,7 @@ }, { "name": "Django test", - "type": "python", + "type": "debugpy", "purpose": ["debug-test"], "request": "launch", "program": "${workspaceFolder}/app/manage.py", @@ -46,5 +46,19 @@ "django": true, "justMyCode": true, }, + { + "name": "Lab serve", + "type": "debugpy", + "purpose": ["debug-test"], + "request": "launch", + "program": "${workspaceFolder}/app/app/cli.py", + "cwd": "/home/cameron/dev/galaxy/galaxy_codex/communities/genome/lab", + "env": { + "GITHUB_API_TOKEN": "", + }, + "args": ["serve"], + "django": true, + "justMyCode": true, + }, ] } diff --git a/app/app/cli.py b/app/app/cli.py new file mode 100644 index 0000000..703bd98 --- /dev/null +++ b/app/app/cli.py @@ -0,0 +1,46 @@ +"""Command line interface for launching a development server. + +This is intended to be used for rendering Lab pages in development. +""" + +import os +import sys +from pathlib import Path + + +def main(): + """CLI entry point for running the development server.""" + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Make sure it's installed and " + "available on your PYTHONPATH environment variable." + ) from exc + + os.environ["DJANGO_SETTINGS_MODULE"] = "app.settings.cli" + set_required_env_vars() + + if sys.argv[1] == "serve": + BASE_DIR = Path(__file__).resolve().parent.parent + os.chdir(BASE_DIR) + sys.path.insert(0, str(BASE_DIR)) + if len(sys.argv) > 2: + os.environ["LAB_CONTENT_ENTRYPOINT"] = sys.argv[2] + execute_from_command_line(["manage.py", "runserver"]) + else: + print(f"Unknown command: {sys.argv[1]}") + + +def set_required_env_vars(): + """Set required environment variables for the CLI.""" + os.environ.setdefault("LAB_CONTENT_ROOT", os.getcwd()) + os.environ.setdefault("HOSTNAME", "localhost:8000") + os.environ.setdefault("MAIL_HOSTNAME", "localhost") + os.environ.setdefault("MAIL_SMTP_PORT", "22") + os.environ.setdefault("MAIL_FROM_ADDRESS", "labs@example.com") + os.environ.setdefault("MAIL_TO_ADDRESS", "admin@example.com") + + +if __name__ == "__main__": + main() diff --git a/app/app/settings/base.py b/app/app/settings/base.py index ab2b6cb..1e5cd98 100644 --- a/app/app/settings/base.py +++ b/app/app/settings/base.py @@ -1,26 +1,14 @@ -""" -Django settings for app project. - -Generated by 'django-admin startproject' using Django 3.2. - -For more information on this file, see -https://docs.djangoproject.com/en/3.2/topics/settings/ - -For the full list of settings and their values, see -https://docs.djangoproject.com/en/3.2/ref/settings/ - -*These settings are the base for all other settings. Variables declared here -may be overidden by the importing file.* -""" +"""Django settings for Labs Engine project.""" # flake8: noqa import os from pathlib import Path -from dotenv import load_dotenv from utils.paths import ensure_dir -load_dotenv('../.env', override=True) +if os.getenv('DJANGO_SETTINGS_MODULE') != "app.settings.cli": + from dotenv import load_dotenv + load_dotenv('../.env', override=True) # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent.parent @@ -193,9 +181,10 @@ GITHUB_API_TOKEN = os.getenv('GITHUB_API_TOKEN') if not GITHUB_API_TOKEN: - print("Warning: GITHUB_API_TOKEN not set. Requests to api.github.com will" - " be rate-limited at 60 requests per hour which may result in" - " errors.") + print("\n\033[33mWarning: env variable GITHUB_API_TOKEN not set. Requests" + " to api.github.com will be rate-limited at 60 requests per hour" + " which may result in errors (this is used for fetching CONTRIBUTORS" + " information).\n\033[0m") CACHE_TIMEOUT = 60 * 60 # 1 hour diff --git a/app/app/settings/cli.py b/app/app/settings/cli.py new file mode 100644 index 0000000..4a0f10a --- /dev/null +++ b/app/app/settings/cli.py @@ -0,0 +1,32 @@ +"""Local Lab development settings. + +To be used when pip-installed and running as `labs-engine serve`. +""" + +# flake8: noqa + +import os + +from .base import * + +DEBUG = True +CLI_DEV = True +LAB_CONTENT_ROOT = os.environ.get('LAB_CONTENT_ROOT') +if not LAB_CONTENT_ROOT: + raise EnvironmentError('Env variable LAB_CONTENT_ROOT not set') +LAB_CONTENT_ENTRYPOINT = os.environ.get('LAB_CONTENT_ENTRYPOINT', 'base.yml') + +INTERNAL_IPS = [ + "127.0.0.1", +] + +EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend" + +STATICFILES_DIRS = [ + ("local", LAB_CONTENT_ROOT), +] + +DEFAULT_EXPORTED_LAB_CONTENT_ROOT = ( + f"http://{HOSTNAME}/static/local/{LAB_CONTENT_ENTRYPOINT}") + +INSTALLED_APPS.remove('django_light') diff --git a/app/labs/views.py b/app/labs/views.py index 45ddf5d..71af77b 100644 --- a/app/labs/views.py +++ b/app/labs/views.py @@ -31,8 +31,9 @@ def export_lab(request): repo with a YAML file root which is specified as a GET parameter. """ - if response := LabCache.get(request): - return response + if not settings.CLI_DEV: + if response := LabCache.get(request): + return response template = 'labs/exported.html' diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..0f0ed8e --- /dev/null +++ b/setup.py @@ -0,0 +1,25 @@ +from setuptools import setup, find_packages + +setup( + name="galaxy-labs-engine", + version="1.0.0", + packages=find_packages(where='app'), + package_dir={'': 'app'}, + include_package_data=True, + install_requires=[ + "django>=4.0", # Add any dependencies here + "django>=5.0", + "pyyaml>=6.0", + "pydantic>=2.0", + "markdown2>=2.0", + "beautifulsoup4>=4.0", + "requests>=2.0", + "django-crispy-forms>=2.0", + "crispy-bootstrap5>=2024.0", + ], + entry_points={ + "console_scripts": [ + "labs-engine=app.cli:main", + ], + }, +) From da79adefb7e1fab6dfcf75b391972a2cf0d22b2f Mon Sep 17 00:00:00 2001 From: Cameron Hyde Date: Sat, 4 Jan 2025 10:00:11 +1000 Subject: [PATCH 2/2] Fix base.py settings --- app/app/settings/base.py | 1 + 1 file changed, 1 insertion(+) diff --git a/app/app/settings/base.py b/app/app/settings/base.py index 1e5cd98..52235c8 100644 --- a/app/app/settings/base.py +++ b/app/app/settings/base.py @@ -15,6 +15,7 @@ # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True +CLI_DEV = False AUTH_USER_MODEL = 'labs.User' SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY') or "secretkey" SILENCED_SYSTEM_CHECKS = ['django_recaptcha.recaptcha_test_key_error']