Test Failed
Push — master ( 8d7155...079bd0 )
by Jan
03:02 queued 14s
created

utils.template_renderer   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 105
Duplicated Lines 12.38 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
eloc 75
dl 13
loc 105
ccs 0
cts 67
cp 0
rs 10
c 0
b 0
f 0
wmc 19

9 Methods

Rating   Name   Duplication   Size   Complexity  
A FlexibleLoader.__init__() 0 8 3
A Renderer.get_result() 0 6 1
A Renderer.__init__() 0 10 1
A Renderer.get_env_yaml() 13 13 3
A Renderer._set_rule_relative_definition_location() 0 4 1
A FlexibleLoader.get_source() 0 3 1
A FlexibleLoader._find_absolute_path() 0 8 4
A Renderer.output_results() 0 9 4
A Renderer.create_parser() 0 9 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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.yaml
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 = pathlib.Path(directory / path)
37
            if potential_location.exists():
38
                return str(potential_location.absolute())
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):
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
60 View Code Duplication
    def get_env_yaml(self, build_dir):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
61
        product_yaml = self.project_directory / self.product / "product.yml"
62
        build_config_yaml = pathlib.Path(build_dir) / "build_config.yml"
63
        if not (product_yaml.exists() and build_config_yaml.exists()):
64
            msg = (
65
                "No product yaml and/or build config found in "
66
                "'{product_yaml}' and/or '{build_config_yaml}', respectively, please make sure "
67
                "that you got the product right, and that it is built."
68
                .format(product_yaml=product_yaml, build_config_yaml=build_config_yaml)
69
            )
70
            raise ValueError(msg)
71
        env_yaml = ssg.yaml.open_environment(build_config_yaml, product_yaml)
72
        return env_yaml
73
74
    def _set_rule_relative_definition_location(self, rule):
75
        rule.relative_definition_location = (
76
            pathlib.PurePath(rule.definition_location)
77
            .relative_to(self.project_directory))
78
79
    def get_result(self):
80
        subst_dict = self.template_data.copy()
81
        subst_dict.update(self.env_yaml)
82
        html_jinja_template = os.path.join(os.path.dirname(__file__), self.TEMPLATE_NAME)
83
        ssg.jinja._get_jinja_environment.env.loader = FlexibleLoader([self.project_directory / "utils"])
84
        return ssg.jinja.process_file(html_jinja_template, subst_dict)
85
86
    def output_results(self, args):
87
        if "title" not in self.template_data:
88
            self.template_data["title"] = args.title
89
        result = self.get_result()
90
        if not args.output:
91
            print(result)
92
        else:
93
            with open(args.output, "w") as outfile:
94
                outfile.write(result)
95
96
    @staticmethod
97
    def create_parser(description):
98
        parser = argparse.ArgumentParser(description=description)
99
        parser.add_argument(
100
            "product", help="The product to be built")
101
        parser.add_argument("--build-dir", default="build", help="Path to the build directory")
102
        parser.add_argument("--title", "-t", default="", help="Title of the document")
103
        parser.add_argument("--output", help="The filename to generate")
104
        return parser
105