|
1 |
| -import os |
| 1 | +from pathlib import Path |
2 | 2 | from typing import Sequence
|
3 | 3 |
|
4 | 4 | from docutils import nodes
|
5 | 5 | from docutils.parsers.rst import directives
|
6 | 6 | from jinja2 import Template
|
7 |
| -from sphinx.errors import SphinxError |
| 7 | +from sphinx.util import logging |
8 | 8 | from sphinx.util.docutils import SphinxDirective
|
9 | 9 |
|
10 | 10 | from sphinx_needs.config import NeedsSphinxConfig
|
11 | 11 | from sphinx_needs.directives.utils import analyse_needs_metrics
|
12 | 12 | from sphinx_needs.utils import add_doc
|
13 | 13 |
|
14 |
| - |
15 |
| -class NeedsReportException(SphinxError): |
16 |
| - pass |
| 14 | +LOGGER = logging.getLogger(__name__) |
17 | 15 |
|
18 | 16 |
|
19 | 17 | class NeedReportDirective(SphinxDirective):
|
20 | 18 | final_argument_whitespace = True
|
21 | 19 | option_spec = {
|
22 |
| - "types": directives.unchanged, |
23 |
| - "links": directives.unchanged, |
24 |
| - "options": directives.unchanged, |
25 |
| - "usage": directives.unchanged, |
| 20 | + "types": directives.flag, |
| 21 | + "links": directives.flag, |
| 22 | + "options": directives.flag, |
| 23 | + "usage": directives.flag, |
| 24 | + "template": directives.unchanged, |
26 | 25 | }
|
27 | 26 |
|
28 | 27 | def run(self) -> Sequence[nodes.raw]:
|
29 | 28 | env = self.env
|
30 | 29 | needs_config = NeedsSphinxConfig(env.config)
|
31 | 30 |
|
32 |
| - if len(self.options.keys()) == 0: # Check if options is empty |
33 |
| - error_file, error_line = self.state_machine.input_lines.items[0] |
34 |
| - error_msg = "{}:{}: NeedReportError: No options specified to generate need report.".format( |
35 |
| - error_file, error_line + self.state_machine.input_lines.data.index(".. needreport::") + 1 |
| 31 | + if not set(self.options).intersection({"types", "links", "options", "usage"}): |
| 32 | + LOGGER.warning( |
| 33 | + "No options specified to generate need report [needs.report]", |
| 34 | + location=self.get_location(), |
| 35 | + type="needs", |
| 36 | + subtype="report", |
36 | 37 | )
|
37 |
| - raise NeedsReportException(error_msg) |
38 |
| - |
39 |
| - types = self.options.get("types") |
40 |
| - extra_links = self.options.get("links") |
41 |
| - extra_options = self.options.get("options") |
42 |
| - usage = self.options.get("usage") |
43 |
| - |
44 |
| - needs_types = [] |
45 |
| - needs_extra_links = [] |
46 |
| - needs_extra_options = [] |
47 |
| - needs_metrics = {} |
48 |
| - |
49 |
| - if types is not None and isinstance(types, str): |
50 |
| - needs_types = needs_config.types |
51 |
| - if extra_links is not None and isinstance(extra_links, str): |
52 |
| - needs_extra_links = needs_config.extra_links |
53 |
| - if extra_options is not None and isinstance(extra_options, str): |
54 |
| - needs_extra_options = needs_config.extra_options |
55 |
| - if usage is not None and isinstance(usage, str): |
56 |
| - needs_metrics = analyse_needs_metrics(env) |
| 38 | + return [] |
57 | 39 |
|
58 | 40 | report_info = {
|
59 |
| - "types": needs_types, |
60 |
| - "options": needs_extra_options, |
61 |
| - "links": needs_extra_links, |
62 |
| - "usage": needs_metrics, |
| 41 | + "types": needs_config.types if "types" in self.options else [], |
| 42 | + "options": needs_config.extra_options if "options" in self.options else [], |
| 43 | + "links": needs_config.extra_links if "links" in self.options else [], |
| 44 | + "usage": analyse_needs_metrics(env) if "usage" in self.options else {}, |
| 45 | + "report_directive": "dropdown", |
63 | 46 | }
|
64 | 47 | report_info.update(**needs_config.render_context)
|
65 | 48 |
|
66 |
| - need_report_template_path: str = needs_config.report_template |
67 |
| - # Absolute path starts with /, based on the conf.py directory. The / need to be striped |
68 |
| - correct_need_report_template_path = os.path.join(env.app.srcdir, need_report_template_path.lstrip("/")) |
69 |
| - |
70 |
| - if len(need_report_template_path) == 0: |
71 |
| - default_template_path = "needreport_template.rst" |
72 |
| - correct_need_report_template_path = os.path.join(os.path.dirname(__file__), default_template_path) |
73 |
| - |
74 |
| - if not os.path.exists(correct_need_report_template_path): |
75 |
| - raise ReferenceError(f"Could not load needs report template file {correct_need_report_template_path}") |
| 49 | + if "template" in self.options: |
| 50 | + need_report_template_path = Path(self.env.relfn2path(self.options["template"], self.env.docname)[1]) |
| 51 | + elif needs_config.report_template: |
| 52 | + # Absolute path starts with /, based on the conf.py directory. The / need to be striped |
| 53 | + need_report_template_path = Path(str(env.app.srcdir)) / needs_config.report_template.lstrip("/") |
| 54 | + else: |
| 55 | + need_report_template_path = Path(__file__).parent / "needreport_template.rst" |
| 56 | + |
| 57 | + if not need_report_template_path.is_file(): |
| 58 | + LOGGER.warning( |
| 59 | + f"Could not load needs report template file {need_report_template_path} [needs.report]", |
| 60 | + location=self.get_location(), |
| 61 | + type="needs", |
| 62 | + subtype="report", |
| 63 | + ) |
| 64 | + return [] |
76 | 65 |
|
77 |
| - with open(correct_need_report_template_path) as needs_report_template_file: |
78 |
| - needs_report_template_file_content = needs_report_template_file.read() |
| 66 | + needs_report_template_file_content = need_report_template_path.read_text(encoding="utf8") |
79 | 67 |
|
80 | 68 | template = Template(needs_report_template_file_content, autoescape=True)
|
81 |
| - |
82 | 69 | text = template.render(**report_info)
|
83 | 70 | self.state_machine.insert_input(text.split("\n"), self.state_machine.document.attributes["source"])
|
84 | 71 |
|
|
0 commit comments