elixir/elixir/web_utils.py
2025-02-14 12:50:29 +01:00

83 lines
2.5 KiB
Python

import os
import re
import logging
import threading
from urllib import parse
from typing import Any, Dict, NamedTuple
import falcon
import jinja2
from .lib import validFamily, run_cmd
ELIXIR_DIR = os.path.normpath(os.path.dirname(__file__) + "/../")
ELIXIR_REPO_LINK = 'https://github.com/bootlin/elixir/'
def get_elixir_version_string():
version = os.environ.get('ELIXIR_VERSION')
if version is not None and len(version) != 0:
return version
try:
# try to get Elixir version from git
result, return_code = run_cmd('git',
'-C', ELIXIR_DIR,
'-c', f'safe.directory={ ELIXIR_DIR }',
'rev-parse', '--short', 'HEAD'
)
if return_code == 0:
return result.decode('utf-8')
except Exception:
logging.exception("failed to get elixir commit hash")
return ''
def get_elixir_repo_url(version):
if re.match('^[0-9a-f]{5,12}$', version) or version.startswith('v'):
return ELIXIR_REPO_LINK + f'tree/{ version }'
else:
return ELIXIR_REPO_LINK
# Elixir config, currently contains only path to directory with projects
class Config(NamedTuple):
project_dir: str
version_string: str
repo_url: str
# Basic information about handled request - current Elixir configuration, configured Jinja environment
# and logger
class RequestContext(NamedTuple):
config: Config
jinja_env: jinja2.Environment
logger: logging.Logger
versions_cache: Dict[str, str]
versions_cache_lock: threading.Lock
def validate_project(project: str) -> str|None:
if project is not None and re.match(r'^[a-zA-Z0-9_.,:/-]+$', project):
return project.strip()
# Validates and unquotes project parameter
class ProjectConverter(falcon.routing.BaseConverter):
def convert(self, value: str) -> str:
value = parse.unquote(value)
project = validate_project(value)
if project is None:
raise falcon.HTTPBadRequest('Error', 'Invalid project name')
return project
def validate_version(version) -> str|None:
if version is not None and re.match(r'^[a-zA-Z0-9_.,:/-]+$', version):
return version.strip()
def validate_ident(ident: str) -> str|None:
if ident is not None and re.match(r'^[A-Za-z0-9_,.+?#-]+$', ident):
return ident.strip()
# Validates and unquotes identifier parameter
class IdentConverter(falcon.routing.BaseConverter):
def convert(self, value: str) -> str|None:
value = parse.unquote(value)
return validate_ident(value)