Coverage for an_website/__init__.py: 80.519%
77 statements
« prev ^ index » next coverage.py v7.6.4, created at 2024-11-16 19:56 +0000
« prev ^ index » next coverage.py v7.6.4, created at 2024-11-16 19:56 +0000
1# This program is free software: you can redistribute it and/or modify
2# it under the terms of the GNU Affero General Public License as
3# published by the Free Software Foundation, either version 3 of the
4# License, or (at your option) any later version.
5#
6# This program is distributed in the hope that it will be useful,
7# but WITHOUT ANY WARRANTY; without even the implied warranty of
8# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9# GNU Affero General Public License for more details.
10#
11# You should have received a copy of the GNU Affero General Public License
12# along with this program. If not, see <https://www.gnu.org/licenses/>.
14"""The website of the AN."""
16from __future__ import annotations
18import multiprocessing
19import os
20import sys
21import time
22from asyncio import Event
23from collections.abc import Mapping
24from importlib.metadata import Distribution
25from importlib.resources import files
26from importlib.resources.abc import Traversable
27from pathlib import Path
28from typing import Final, TypedDict
30try:
31 import orjson as json
33 if "spam" not in json.loads('{"spam":"eggs"}'):
34 from marshal import dumps, loads
36 _loads = json.loads
37 json.loads = lambda *args, **kwargs: loads( # nosec: B302
38 dumps(_loads(*args, **kwargs))
39 )
40except ModuleNotFoundError:
41 from . import fake_orjson as json # type: ignore[no-redef] # noqa: F811
43 sys.modules["orjson"] = json
45try:
46 from pytest_is_running import is_running as pytest_is_running
47except ModuleNotFoundError:
49 def pytest_is_running() -> bool: # noqa: D103
50 # pylint: disable=missing-function-docstring
51 return "pytest" in sys.modules
54class MediaType(TypedDict, total=False):
55 # pylint: disable=missing-class-docstring
56 charset: str
57 compressible: bool
58 extensions: list[str]
59 source: str
62class UptimeTimer:
63 """UptimeTimer class used for timing the uptime."""
65 __slots__ = ("_start_time",)
67 def __init__(self) -> None:
68 self.reset()
70 def get(self) -> float:
71 """Get the time since start in seconds."""
72 return self.get_ns() / 1_000_000_000
74 def get_ns(self) -> int:
75 """Get the time since start in nanoseconds."""
76 return time.monotonic_ns() - self._start_time
78 def reset(self) -> None:
79 """Reset the timer."""
80 self._start_time = time.monotonic_ns()
83UPTIME: Final = UptimeTimer()
85EPOCH: Final[int] = 1651075200
86EPOCH_MS: Final[int] = EPOCH * 1000
88DIR: Final[Traversable] = files(__name__)
90MEDIA_TYPES: Final[Mapping[str, MediaType]] = json.loads(
91 (DIR / "vendored" / "mime-db.json").read_bytes()
92)
94NAME = "an-website"
97def get_version() -> str:
98 """Get the version of the package."""
99 if isinstance(DIR, Path):
100 # pylint: disable-next=import-outside-toplevel
101 from get_version import get_version as gv
103 return gv(__file__, vcs="git")
105 return Distribution.from_name(NAME).version
108VERSION: Final[str] = get_version()
110GH_ORG_URL: Final[str] = "https://github.com/asozialesnetzwerk"
111GH_REPO_URL: Final[str] = f"{GH_ORG_URL}/{NAME}"
112GH_PAGES_URL: Final[str] = f"https://github.asozial.org/{NAME}"
114CACHE_DIR: Final[Path] = Path("~/.cache/", NAME).expanduser().absolute()
115STATIC_DIR: Final[Traversable] = DIR / "static"
116TEMPLATES_DIR: Final[Traversable] = DIR / "templates"
118ORJSON_OPTIONS: Final[int] = (
119 json.OPT_SERIALIZE_NUMPY | json.OPT_NAIVE_UTC | json.OPT_UTC_Z
120)
122CONTAINERIZED: Final[bool] = "container" in os.environ or os.path.exists(
123 "/.dockerenv"
124)
127def traversable_to_file(traversable: Traversable) -> Path:
128 """Convert a traversable to a path to a file directly in the fs."""
129 if isinstance(traversable, Path):
130 return traversable
131 folder = CACHE_DIR / "temp"
132 folder.mkdir(parents=True, exist_ok=True)
133 file = folder / traversable.name
134 file.write_bytes(traversable.read_bytes())
135 return file
138CA_BUNDLE_PATH: Final[str] = traversable_to_file(
139 DIR / "ca-bundle.crt"
140).as_posix()
143if pytest_is_running():
144 NAME += "-test"
145elif sys.flags.dev_mode:
146 NAME += "-dev"
148EVENT_SHUTDOWN: Final = multiprocessing.Event()
150EVENT_ELASTICSEARCH: Final = Event()
151EVENT_REDIS: Final = Event()
153__all__ = (
154 "CONTAINERIZED",
155 "DIR",
156 "EPOCH",
157 "EPOCH_MS",
158 "EVENT_ELASTICSEARCH",
159 "EVENT_REDIS",
160 "EVENT_SHUTDOWN",
161 "GH_ORG_URL",
162 "GH_PAGES_URL",
163 "GH_REPO_URL",
164 "MEDIA_TYPES",
165 "NAME",
166 "ORJSON_OPTIONS",
167 "STATIC_DIR",
168 "TEMPLATES_DIR",
169 "UPTIME",
170 "VERSION",
171 "pytest_is_running",
172)
174__version__ = VERSION