Files
website-v2/libraries/utils.py

193 lines
5.8 KiB
Python

import random
import string
import re
import structlog
import tempfile
from datetime import datetime
from dateutil.relativedelta import relativedelta
from dateutil.parser import ParserError, parse
from django.utils.text import slugify
from libraries.constants import (
DEFAULT_LIBRARIES_LANDING_VIEW,
SELECTED_BOOST_VERSION_COOKIE_NAME,
SELECTED_LIBRARY_VIEW_COOKIE_NAME,
LATEST_RELEASE_URL_PATH_STR,
)
from versions.models import Version
logger = structlog.get_logger()
def decode_content(content):
"""Decode bytes to string."""
if isinstance(content, bytes):
return content.decode("utf-8")
return content
def generate_fake_email(val: str) -> str:
"""Slugify a string to make a fake email.
Would not necessarily be unique -- this is a lazy way for us to avoid creating
multiple new user records for one contributor who contributes to multiple libraries.
"""
slug = slugify(val)
local_email = slug.replace("-", "_")[:50]
return f"{local_email}@example.com"
def generate_random_string(length=4):
characters = string.ascii_letters
random_string = "".join(random.choice(characters) for _ in range(length))
return random_string
def version_within_range(
version: str, min_version: str = None, max_version: str = None
):
"""Direct string comparison, assuming 'version', 'min_version', and 'max_version'
follow the same format.
Expects format `boost-1.84.0`
"""
if min_version and version < min_version:
return False
if max_version and version > max_version:
return False
return True
def get_first_last_day_last_month():
now = datetime.now()
first_day_this_month = now.replace(day=1)
last_day_last_month = first_day_this_month - relativedelta(days=1)
first_day_last_month = last_day_last_month.replace(day=1)
return first_day_last_month, last_day_last_month
def parse_date(date_str):
"""Parses a date string to a datetime. Does not return an error."""
try:
return parse(date_str)
except ParserError:
logger.info("parse_date_invalid_date", date_str=date_str)
return None
def write_content_to_tempfile(content):
"""Accepts string or bytes content, writes it to a temporary file, and returns the
file object."""
with tempfile.NamedTemporaryFile(delete=False) as temp_file:
if isinstance(content, bytes):
temp_file = open(temp_file.name, "wb")
temp_file.write(content)
temp_file.close()
return temp_file
def get_version_from_url(request):
return request.GET.get("version")
def get_version_from_cookie(request):
return request.COOKIES.get(SELECTED_BOOST_VERSION_COOKIE_NAME)
def get_view_from_url(request):
return request.resolver_match.kwargs.get("library_view_str")
def get_view_from_cookie(request):
return request.COOKIES.get(SELECTED_LIBRARY_VIEW_COOKIE_NAME)
def set_view_in_cookie(response, view):
allowed_views = {"grid", "list", "categorized"}
if view not in allowed_views:
return
response.set_cookie(SELECTED_LIBRARY_VIEW_COOKIE_NAME, view)
def get_prioritized_version(request):
"""
Version Priorities:
1. URL parameter
2. Cookie
3. Default to latest version
"""
url_version = get_version_from_url(request)
cookie_version = get_version_from_cookie(request)
default_version = None
return url_version or cookie_version or default_version
def get_prioritized_library_view(request):
"""
View Priorities:
1. URL parameter
2. Cookie
3. Default to grid view
"""
url_view = get_view_from_url(request)
cookie_view = get_view_from_cookie(request)
return url_view or cookie_view or DEFAULT_LIBRARIES_LANDING_VIEW
def get_category(request):
return request.GET.get("category", "")
def determine_selected_boost_version(request_value, request):
valid_versions = Version.objects.version_dropdown_strict()
version_slug = request_value or get_version_from_cookie(request)
if version_slug in [v.slug for v in valid_versions] + [LATEST_RELEASE_URL_PATH_STR]:
return version_slug
else:
logger.warning(f"Invalid version slug in cookies: {version_slug}")
return None
def set_selected_boost_version(version_slug: str, response) -> None:
"""Update the selected version in the cookies."""
valid_versions = Version.objects.version_dropdown_strict()
if version_slug in [v.slug for v in valid_versions]:
response.set_cookie(SELECTED_BOOST_VERSION_COOKIE_NAME, version_slug)
elif version_slug == LATEST_RELEASE_URL_PATH_STR:
response.delete_cookie(SELECTED_BOOST_VERSION_COOKIE_NAME)
else:
logger.warning(f"Attempted to set invalid version slug: {version_slug}")
def library_doc_latest_transform(url):
p = re.compile(r"^(/doc/libs/)[0-9_]+(/\S+)$")
if p.match(url):
url = p.sub(rf"\1{LATEST_RELEASE_URL_PATH_STR}\2", url)
return url
def get_documentation_url(library_version, latest):
"""Get the documentation URL for the current library."""
def find_documentation_url(library_version):
# If we know the library-version docs are missing, return the version docs
if library_version.missing_docs:
return library_version.version.documentation_url
# If we have the library-version docs and they are valid, return those
elif library_version.documentation_url:
return library_version.documentation_url
# If we wind up here, return the version docs
else:
return library_version.version.documentation_url
# Get the URL for the version.
url = find_documentation_url(library_version)
# Remove the "boost_" prefix from the URL.
url = url.replace("boost_", "")
if latest:
url = library_doc_latest_transform(url)
return url