Andrej Janchevski
fix(deploy): harden container runtime and unify research / checkpoint roots
5375c2e | import os | |
| import sys | |
| from pathlib import Path | |
| BASE_DIR = Path(__file__).resolve().parent.parent | |
| PROJECT_ROOT = BASE_DIR.parent.parent # Website root in dev; ignored in the container | |
| # Research code root. In the deployment image this is /app/research; in dev | |
| # it defaults to <repo>/src/research. Defined early because the sys.path | |
| # additions below depend on it. | |
| RESEARCH_ROOT = Path(os.environ.get("RESEARCH_ROOT", PROJECT_ROOT / "src" / "research")) | |
| # Add research repos to sys.path so their modules can be imported | |
| _COINS_KG_ROOT = str(RESEARCH_ROOT / "COINs-KGGeneration") | |
| _DIGRESS_KG_SRC = str(RESEARCH_ROOT / "COINs-KGGeneration" / "graph_generation" / "src") | |
| _MULTIPROXAN_ROOT = str(RESEARCH_ROOT / "MultiProxAn") | |
| _MULTIPROXAN_SRC = str(RESEARCH_ROOT / "MultiProxAn" / "src") | |
| for _path in (_COINS_KG_ROOT, _DIGRESS_KG_SRC, _MULTIPROXAN_ROOT, _MULTIPROXAN_SRC): | |
| if _path not in sys.path: | |
| sys.path.insert(0, _path) | |
| SECRET_KEY = os.environ.get("DJANGO_SECRET_KEY", "dev-insecure-key-change-in-production") | |
| DEBUG = os.environ.get("DJANGO_DEBUG", "True").lower() in ("true", "1") | |
| ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS", "localhost,127.0.0.1").split(",") | |
| INSTALLED_APPS = [ | |
| "corsheaders", | |
| "rest_framework", | |
| "django.contrib.staticfiles", | |
| "api", | |
| ] | |
| MIDDLEWARE = [ | |
| "corsheaders.middleware.CorsMiddleware", | |
| "django.middleware.security.SecurityMiddleware", | |
| "whitenoise.middleware.WhiteNoiseMiddleware", | |
| "django.middleware.common.CommonMiddleware", | |
| "django.middleware.csrf.CsrfViewMiddleware", | |
| "django.middleware.clickjacking.XFrameOptionsMiddleware", | |
| ] | |
| ROOT_URLCONF = "research_api.urls" | |
| WSGI_APPLICATION = "research_api.wsgi.application" | |
| DATABASES = {} | |
| REST_FRAMEWORK = { | |
| "DEFAULT_RENDERER_CLASSES": ["rest_framework.renderers.JSONRenderer"], | |
| "DEFAULT_PARSER_CLASSES": ["rest_framework.parsers.JSONParser"], | |
| "DEFAULT_PAGINATION_CLASS": None, | |
| "DEFAULT_AUTHENTICATION_CLASSES": [], | |
| "DEFAULT_PERMISSION_CLASSES": ["rest_framework.permissions.AllowAny"], | |
| "EXCEPTION_HANDLER": "api.exceptions.api_exception_handler", | |
| "UNAUTHENTICATED_USER": None, | |
| } | |
| CORS_ALLOWED_ORIGINS = [ | |
| o.strip() for o in os.environ.get( | |
| "CORS_ALLOWED_ORIGINS", "https://bani57-website.hf.space" | |
| ).split(",") if o.strip() | |
| ] | |
| if DEBUG: | |
| CORS_ALLOW_ALL_ORIGINS = True | |
| # Security headers (active when DEBUG=False). Gated on DEBUG so local dev | |
| # over plain HTTP doesn't get redirected/blocked. | |
| SECURE_CONTENT_TYPE_NOSNIFF = True | |
| SECURE_REFERRER_POLICY = "same-origin" | |
| X_FRAME_OPTIONS = "DENY" | |
| if not DEBUG: | |
| SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") | |
| SECURE_SSL_REDIRECT = False # HF Spaces terminates TLS upstream; redirect would loop | |
| SECURE_HSTS_SECONDS = 31536000 | |
| SECURE_HSTS_INCLUDE_SUBDOMAINS = True | |
| SECURE_HSTS_PRELOAD = False | |
| CSRF_COOKIE_SECURE = True | |
| SESSION_COOKIE_SECURE = True | |
| CSRF_TRUSTED_ORIGINS = [o for o in CORS_ALLOWED_ORIGINS if o.startswith("https://")] | |
| # Checkpoints land here at runtime via huggingface_hub.snapshot_download. | |
| # Defaults to RESEARCH_ROOT (defined above) for dev where weights sit alongside | |
| # the research code; the deployment image overrides to /app/checkpoints. | |
| CHECKPOINTS_ROOT = Path(os.environ.get("CHECKPOINTS_ROOT", RESEARCH_ROOT)) | |
| # Research code paths | |
| COINS_DATA_DIR = RESEARCH_ROOT / "COINs-KGGeneration" / "data" | |
| COINS_COMPLETION_DIR = CHECKPOINTS_ROOT / "COINs-KGGeneration" / "graph_completion" | |
| DIGRESS_KG_DIR = CHECKPOINTS_ROOT / "COINs-KGGeneration" / "graph_generation" | |
| MULTIPROXAN_DIR = CHECKPOINTS_ROOT / "MultiProxAn" | |
| # Static files & SPA dist (Vue's npm run build output, copied into the image) | |
| STATIC_URL = "/static/" | |
| STATIC_ROOT = BASE_DIR / "staticfiles" | |
| STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage" | |
| SPA_DIST_DIR = Path(os.environ.get("SPA_DIST_DIR", BASE_DIR / "dist")) | |
| WHITENOISE_ROOT = str(SPA_DIST_DIR) | |
| WHITENOISE_INDEX_FILE = "index.html" | |
| DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" | |
| # PyTorch device: auto-detect CUDA, allow override via env var | |
| import warnings | |
| warnings.filterwarnings("ignore", message="TypedStorage is deprecated") | |
| import torch as _torch | |
| TORCH_DEVICE = os.environ.get("TORCH_DEVICE", "cuda:0" if _torch.cuda.is_available() else "cpu") | |