Path:
strictdoc/server/reload_config.py
Lines:
128
Non-empty lines:
112
Non-empty lines covered with requirements:
112 / 112 (100.0%)
Functions:
3
Functions covered by requirements:
3 / 3 (100.0%)
1
"""2
@relation(SDOC-SRS-126, scope=file)3
"""4
5
import os
6
from dataclasses import dataclass
7
from typing import List, Optional
8
9
from strictdoc.commands.server_config import ServerCommandConfig
10
from strictdoc.core.project_config import ProjectConfig
11
12
13
@dataclass14
class UvicornReloadConfig:
15
"""
16
Class that encapsulate the Uvicorn server configuration details.17
18
Uvicorn has an opinionated system for configuring the reloading of a server19
when the specified files are changed on the file system. This class20
centralized the reload configuration details in one place.21
22
One responsibility of this class is to give a correct configuration when23
the files must be reloaded and give a completely empty configuration when24
the reload is False. In particular, if a configuration specifies reload=False25
but the reload_dirs or reload_includes or reload_excludes are specified,26
then the following warning is shown.27
WARNING: Current configuration will not reload as not all conditions are met, please refer to documentation.28
The create() method of this class ensures that uvicorn is happy and the29
warning does not appear.30
"""31
32
reload: bool
33
reload_dirs: Optional[List[str]]
34
reload_includes: Optional[List[str]]
35
reload_excludes: Optional[List[str]]
36
37
@classmethod38
def create(
39
cls, project_config: ProjectConfig, server_config: ServerCommandConfig
40
) -> "UvicornReloadConfig":
41
reload: bool = server_config.reload
42
reload_dirs: Optional[List[str]] = None
43
reload_includes: Optional[List[str]] = None
44
reload_excludes: Optional[List[str]] = None
45
46
if server_config.reload:
47
# This doesn't seem to be effect because we still must provide the48
# reload_excludes outside this folder. Maybe it has to do with the49
# presence of reload_includes that includes all files with given50
# file extensions below. Anyway this works well enough with the51
# given reload_excludes.52
reload_dirs = [
53
os.path.join(
54
project_config.get_strictdoc_root_path(), "strictdoc"
55
)56
]57
# It is important that StrictDoc's artifacts are excluded because58
# StrictDoc's web server will be triggered to restart every time the59
# contents of these folders changes.60
reload_excludes = (
61
cls.expand_folder("build", max_depth=15)
62
+ cls.expand_folder("docs", max_depth=3)
63
+ cls.expand_folder("dist", max_depth=3)
64
+ cls.expand_folder("tests", max_depth=15)
65
+ cls.expand_folder("output", max_depth=15)
66
+ cls.expand_folder("Output", max_depth=15)
67
)68
69
# Changing typical StrictDoc's own source code files should trigger70
# restarting of the web server. Whitelisting them here.71
reload_includes = [
72
"*.py",
73
"*.html",
74
"*.jinja",
75
"*.svg",
76
"*.css",
77
"*.js",
78
"*.toml",
79
]80
return UvicornReloadConfig(
81
reload=reload,
82
reload_dirs=reload_dirs,
83
reload_includes=reload_includes,
84
reload_excludes=reload_excludes,
85
)86
87
@classmethod88
def expand_folder(cls, folder: str, max_depth: int) -> List[str]:
89
"""
90
Create a list of wildcard-based paths for a given folder.91
92
It looks like the regex engine of the uvicorn file watching library93
does not support proper ** globs.94
95
Examples:96
"tests", # Doesn't work.97
"tests/", # Doesn't work.98
"tests/*", # Doesn't work.99
"tests/**", # Makes the process hang, server doesn't start.100
101
Example of a possible StrictDoc path that must be excluded:102
output/cache/server/html/_source_files/strictdoc/backend/reqif/sdoc_reqif_fields.py.html103
104
This function produces output like this:105
[106
"output/*.*",107
"output/*/*.*",108
"output/*/*/*.*",109
"output/*/*/*/*.*",110
"output/*/*/*/*/*.*",111
"output/*/*/*/*/*/*.*",112
"output/*/*/*/*/*/*/*.*",113
"output/*/*/*/*/*/*/*/*.*",114
"output/*/*/*/*/*/*/*/*/*.*",115
"output/*/*/*/*/*/*/*/*/*/*.*",116
"output/*/*/*/*/*/*/*/*/*/*/*.*",117
"output/*/*/*/*/*/*/*/*/*/*/*/*.*",118
"output/*/*/*/*/*/*/*/*/*/*/*/*/*.*",119
"output/*/*/*/*/*/*/*/*/*/*/*/*/*/*.*",120
"output/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*.*",121
]122
"""123
124
patterns = []
125
for depth in range(1, max_depth + 1):
126
pattern = folder + "/" + "*/" * (depth - 1) + "*.*"
127
patterns.append(pattern)
128
return patterns