Coverage for portality/cms/build_sass.py: 57%
63 statements
« prev ^ index » next coverage.py v6.4.2, created at 2022-07-22 15:59 +0100
« prev ^ index » next coverage.py v6.4.2, created at 2022-07-22 15:59 +0100
1"""
2Build the SASS - main.css and optionally the widgets
3~~CMSBuildSASS:Script->CMS:Script~~
4~~->SASS:Technology~~
5"""
7import sass
8import os
9import shutil
11from datetime import datetime
13# SASS directory
14SASS = os.path.join("cms", "sass")
16# Output style
17STYLE = "compressed"
19# SASS and error file for the main CSS
20MAIN_SETTINGS = (os.path.join(SASS, "main.scss"),
21 os.path.join("portality", "static", "doaj", "css", "main.css"),
22 os.path.join("cms", "error_sass.txt"))
24# SASS file and error file for each widget
25FQ_WIDGET_SETTINGS = (os.path.join(SASS, "fq_widget.scss"),
26 os.path.join("portality", "static", "doaj", "css", "fq_widget.css"),
27 os.path.join("cms", "error_fqw_sass.txt"))
28SS_WIDGET_SETTINGS = (os.path.join(SASS, "simple_widget.scss"),
29 os.path.join("portality", "static", "doaj", "css", "simple_widget.css"),
30 os.path.join("cms", "error_ssw_sass.txt"))
33def _localise_paths(paths, base_path=None):
34 SCSS_IN, CSS_OUT, ERROR_OUT = paths
35 SOURCE_MAP = CSS_OUT + ".map"
37 now = datetime.utcnow().timestamp()
38 if base_path is None:
39 return SASS, SCSS_IN, CSS_OUT, CSS_OUT + "." + str(now), SOURCE_MAP, SOURCE_MAP + "." + str(now), ERROR_OUT
40 return (os.path.join(base_path, SASS),
41 os.path.join(base_path, SCSS_IN),
42 os.path.join(base_path, CSS_OUT),
43 os.path.join(base_path, CSS_OUT + "." + str(now)),
44 os.path.join(base_path, SOURCE_MAP),
45 os.path.join(base_path, SOURCE_MAP + "." + str(now)),
46 os.path.join(base_path, ERROR_OUT))
49def _swap(old, new):
50 if os.path.exists(old):
51 os.rename(old, old + ".old")
52 os.rename(new, old)
53 if os.path.exists(old + ".old"):
54 try:
55 shutil.rmtree(old + ".old")
56 except OSError:
57 os.remove(old + ".old")
60def build(paths, base_path=None):
61 # ~~->CMSSASS:Build~~
62 sass_file, main_file, css_file, css_tmp, map_file, map_tmp, error_file = None, None, None, None, None, None, None
63 try:
64 sass_file, main_file, css_file, css_tmp, map_file, map_tmp, error_file = _localise_paths(paths, base_path)
66 css, src_map = sass.compile(filename=main_file,
67 output_style=STYLE,
68 source_map_filename=map_file,
69 include_paths=[sass_file],
70 omit_source_map_url=True)
72 # Enable the following line to add the sourcemap URL, since it was being generated incorrectly. Requires serving /cms/sass in STATIC_PATHS
73 # css += f'\n/*# sourceMappingURL={os.path.basename(map_file)} */'
75 with open(css_tmp, "w") as f:
76 f.write(css)
78 with open(map_tmp, "w") as f:
79 f.write(src_map)
81 _swap(css_file, css_tmp)
82 _swap(map_file, map_tmp)
84 except Exception as e:
85 try:
86 print("Error occurred building sass")
87 if error_file:
88 with open(error_file, "w") as f:
89 f.write(str(e))
91 if css_tmp and os.path.exists(css_tmp):
92 os.remove(css_tmp)
94 if css_file and os.path.exists(css_file + ".old"):
95 os.rename(css_file + ".old", css_file)
97 if map_tmp and os.path.exists(map_tmp):
98 os.remove(map_tmp)
100 if map_file and os.path.exists(map_file + ".old"):
101 os.rename(map_file + ".old", map_file)
103 raise e
105 except:
106 print("Error occurred building sass and could not complete cleanup")
107 raise e
110if __name__ == "__main__":
111 import argparse
113 parser = argparse.ArgumentParser()
114 parser.add_argument("-w", "--widgets", help="Generate the widgets CSS", action="store_true")
115 args = parser.parse_args()
117 # Build the site CSS
118 build(MAIN_SETTINGS)
120 # If this is run manually with the widget arg, also build the widgets (intended to commit result to the tree)
121 if args.widgets:
122 build(SS_WIDGET_SETTINGS)
123 build(FQ_WIDGET_SETTINGS)