Test Failed
Push — master ( 1bab60...8e0a9b )
by Jan
02:31 queued 11s
created

Renderer._get_template_basedir()   A

Complexity

Conditions 3

Size

Total Lines 7
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 7
nop 1
dl 0
loc 7
rs 10
c 0
b 0
f 0
ccs 0
cts 7
cp 0
crap 12
1
#!/usr/bin/python3
2
3
from glob import glob
4
import collections
5
import os
6
import pathlib
7
8
import argparse
9
10
import ssg.build_yaml
11
import ssg.controls
12
import ssg.environment
13
import ssg.jinja
14
15
16
"""
17
Loader that extends the AbsolutePathFileSystemLoader so it accepts
18
relative paths of templates if those are located in selected directories.
19
20
This is intended to be used when templates reference other templates.
21
"""
22
class FlexibleLoader(ssg.jinja.AbsolutePathFileSystemLoader):
23
    def __init__(self, lookup_dirs=None, ** kwargs):
24
        super().__init__(** kwargs)
25
        self.lookup_dirs = []
26
        if lookup_dirs:
27
            if isinstance(lookup_dirs, str):
28
                self.lookup_dirs = [lookup_dirs]
29
            else:
30
                self.lookup_dirs = list(lookup_dirs)
31
32
    def _find_absolute_path(self, path):
33
        if os.path.isabs(path):
34
            return path
35
        for directory in self.lookup_dirs:
36
            potential_location = os.path.join(directory, path)
37
            if os.path.exists(potential_location):
38
                return str(os.path.abspath(potential_location))
39
        return path
40
41
    def get_source(self, environment, template):
42
        template = self._find_absolute_path(template)
43
        return super().get_source(environment, template)
44
45
46
class Renderer(object):
47
    TEMPLATE_NAME = ""
48
49
    def __init__(self, product, build_dir, verbose=False):
50
        self.project_directory = pathlib.Path(os.path.dirname(__file__)).parent.resolve()
51
52
        self.product = product
53
        self.env_yaml = self.get_env_yaml(build_dir)
54
55
        self.built_content_path = pathlib.Path(
56
            "{build_dir}/{product}".format(build_dir=build_dir, product=product))
57
58
        self.template_data = dict()
59
        self.verbose = verbose
60
61
    def get_env_yaml(self, build_dir):
62
        product_yaml = self.project_directory / "products" / self.product / "product.yml"
63
        build_config_yaml = pathlib.Path(build_dir) / "build_config.yml"
64
        if not (product_yaml.exists() and build_config_yaml.exists()):
65
            msg = (
66
                "No product yaml and/or build config found in "
67
                "'{product_yaml}' and/or '{build_config_yaml}', respectively, please make sure "
68
                "that you got the product right, and that it is built."
69
                .format(product_yaml=product_yaml, build_config_yaml=build_config_yaml)
70
            )
71
            raise ValueError(msg)
72
        env_yaml = ssg.environment.open_environment(build_config_yaml, product_yaml)
73
        return env_yaml
74
75
    def _set_rule_relative_definition_location(self, rule):
76
        rule.relative_definition_location = (
77
            pathlib.PurePath(rule.definition_location)
78
            .relative_to(self.project_directory))
79
80
    def _get_template_basedir(self):
81
        if not self.TEMPLATE_NAME:
82
            return None
83
        path_components = os.path.split(self.TEMPLATE_NAME)
84
        if len(path_components) == 1:
85
            return None
86
        return os.path.join(* path_components[:-1])
87
88
    def get_result(self):
89
        subst_dict = self.template_data.copy()
90
        subst_dict.update(self.env_yaml)
91
        html_jinja_template = os.path.join(os.path.dirname(__file__), self.TEMPLATE_NAME)
92
        lookup_dirs = [self.project_directory / "utils"]
93
94
        template_basedir = self._get_template_basedir()
95
        if template_basedir:
96
            abs_basedir = os.path.join(lookup_dirs[0], template_basedir)
97
            lookup_dirs.append(abs_basedir)
98
99
        ssg.jinja._get_jinja_environment.env.loader = FlexibleLoader(lookup_dirs)
100
        return ssg.jinja.process_file(html_jinja_template, subst_dict)
101
102
    def output_results(self, args):
103
        if "title" not in self.template_data:
104
            self.template_data["title"] = args.title
105
        result = self.get_result()
106
        if not args.output:
107
            print(result)
108
        else:
109
            with open(args.output, "w") as outfile:
110
                outfile.write(result)
111
112
    @staticmethod
113
    def create_parser(description):
114
        parser = argparse.ArgumentParser(description=description)
115
        parser.add_argument(
116
            "product", help="The product to be built")
117
        parser.add_argument("--build-dir", default="build", help="Path to the build directory")
118
        parser.add_argument("--title", "-t", default="", help="Title of the document")
119
        parser.add_argument("--output", help="The filename to generate")
120
        parser.add_argument("--verbose", action="store_true", default=False)
121
        return parser
122