lupin-danquin 0.0.1.dev0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. lupin-danquin-0.0.1.dev0/LICENCE +19 -0
  2. lupin-danquin-0.0.1.dev0/PKG-INFO +15 -0
  3. lupin-danquin-0.0.1.dev0/README.md +38 -0
  4. lupin-danquin-0.0.1.dev0/lupin_danquin/__init__.py +1 -0
  5. lupin-danquin-0.0.1.dev0/lupin_danquin/check_coding_rules.py +31 -0
  6. lupin-danquin-0.0.1.dev0/lupin_danquin/core/__init__.py +0 -0
  7. lupin-danquin-0.0.1.dev0/lupin_danquin/core/application.py +126 -0
  8. lupin-danquin-0.0.1.dev0/lupin_danquin/core/external_resources.py +18 -0
  9. lupin-danquin-0.0.1.dev0/lupin_danquin/core/global_variable.py +52 -0
  10. lupin-danquin-0.0.1.dev0/lupin_danquin/core/line_ended.py +2 -0
  11. lupin-danquin-0.0.1.dev0/lupin_danquin/core/local_variable.py +35 -0
  12. lupin-danquin-0.0.1.dev0/lupin_danquin/core/parameter.py +42 -0
  13. lupin-danquin-0.0.1.dev0/lupin_danquin/core/program.py +135 -0
  14. lupin-danquin-0.0.1.dev0/lupin_danquin/core/rules.py +19 -0
  15. lupin-danquin-0.0.1.dev0/lupin_danquin/core/tools/__init__.py +0 -0
  16. lupin-danquin-0.0.1.dev0/lupin_danquin/core/tools/utils.py +37 -0
  17. lupin-danquin-0.0.1.dev0/lupin_danquin/core/val3_doc_generator/__init__.py +0 -0
  18. lupin-danquin-0.0.1.dev0/lupin_danquin/core/val3_doc_generator/val3_doc_generator.py +45 -0
  19. lupin-danquin-0.0.1.dev0/lupin_danquin/documentation_extraction.py +54 -0
  20. lupin-danquin-0.0.1.dev0/lupin_danquin.egg-info/PKG-INFO +15 -0
  21. lupin-danquin-0.0.1.dev0/lupin_danquin.egg-info/SOURCES.txt +26 -0
  22. lupin-danquin-0.0.1.dev0/lupin_danquin.egg-info/dependency_links.txt +1 -0
  23. lupin-danquin-0.0.1.dev0/lupin_danquin.egg-info/not-zip-safe +1 -0
  24. lupin-danquin-0.0.1.dev0/lupin_danquin.egg-info/requires.txt +7 -0
  25. lupin-danquin-0.0.1.dev0/lupin_danquin.egg-info/top_level.txt +1 -0
  26. lupin-danquin-0.0.1.dev0/setup.cfg +37 -0
  27. lupin-danquin-0.0.1.dev0/setup.py +10 -0
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2018 The Python Packaging Authority
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
@@ -0,0 +1,15 @@
1
+ Metadata-Version: 2.1
2
+ Name: lupin-danquin
3
+ Version: 0.0.1.dev0
4
+ Summary: Testing - Documentation VAL3 from Code
5
+ License: MIT License
6
+ Keywords: documentation,testing
7
+ Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Intended Audience :: Information Technology
9
+ Classifier: Topic :: Software Development :: Testing
10
+ Classifier: Topic :: Documentation
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Requires-Python: >=3.10
14
+ Provides-Extra: test
15
+ License-File: LICENCE
@@ -0,0 +1,38 @@
1
+ # Documentation extraction
2
+
3
+ ## Purpose
4
+
5
+ "documentation_extraction.py" Python script allow to create SDD documentation from source code.
6
+
7
+ The goal is to replace the hand written wiki page accessible here: https://gitlab.com/lupindental/arsene/robotics/production/lupin.robot.staubli/-/wikis/Software-Detailed-Design-Robot-Application-unit
8
+
9
+ ## Run it
10
+
11
+ 1. Go to current directory.
12
+ 2. Execute
13
+ > python documentation_extraction.py
14
+ 3. Result is available in "./val3_documentation.md"
15
+
16
+ ## Add documentation
17
+
18
+ ### For a program (pgx file)
19
+
20
+ Edit your program and add one or more lines of comments the line after "begin" keyword.
21
+
22
+ ### For an application
23
+
24
+ Create a text file named "README.md" at the same level as "pjx" file. And add one or more lines of description.
25
+
26
+ ## Improvements oportunities
27
+
28
+ - Improve table for sockets
29
+ - Allow to end docstring with 10 * "/"
30
+
31
+ ## Other ideas
32
+
33
+ To create a sanitizer:
34
+
35
+ - detect unused variables (private, public?): already done for local variables and parameters (not global variables)
36
+ - detect wrongly named variables (l_, x_, s/b/n/st, t, Out): DONE
37
+ - validate plantuml diagram from pjx files
38
+ - code coverage ? find if all return values are tested
@@ -0,0 +1 @@
1
+ __version__ = "0.0.1.dev0"
@@ -0,0 +1,31 @@
1
+ import os
2
+
3
+ from core.application import Application
4
+
5
+
6
+ if __name__ == "__main__":
7
+ base_program_path = (
8
+ os.path.abspath(os.path.dirname(__file__) + r"/../../danquin/val3/usrapp/")
9
+ + "/"
10
+ )
11
+ application_names = [
12
+ "TaskManager",
13
+ ]
14
+ result = []
15
+ for application_name in application_names:
16
+ program_path = base_program_path + application_name
17
+ app = Application(program_path, application_name)
18
+ result += app.check_coding_rules()
19
+
20
+ if len(result) > 0:
21
+ print(f"{len(result)} errors found while checking coding rules:")
22
+ print()
23
+ print(
24
+ """
25
+ """.join(
26
+ result
27
+ )
28
+ )
29
+ else:
30
+ print("No error found while checking coding rules.")
31
+ exit(len(result))
@@ -0,0 +1,126 @@
1
+ from typing import Any, Dict, List
2
+ from xml.dom import minidom
3
+
4
+ from .global_variable import GlobalVariable
5
+ from .program import Program
6
+ from .line_ended import LINE_ENDED
7
+
8
+
9
+ def get_program_list(
10
+ program_path,
11
+ application_name,
12
+ exclude=["UT.pgx", "start.pgx", "stop.pgx", "test.pgx"],
13
+ ) -> List[Program]:
14
+ file_path = program_path + "/" + application_name + ".pjx"
15
+ doc = minidom.parse(file_path)
16
+ progs = doc.getElementsByTagName("Program")
17
+ return_progs = []
18
+ for prog in progs:
19
+ name = prog.getAttribute("file")
20
+ should_exclude = False
21
+ for e in exclude:
22
+ if e in name:
23
+ should_exclude = True
24
+ if not should_exclude:
25
+ return_progs.append(Program(program_path, name))
26
+ return return_progs
27
+
28
+
29
+ def get_dependencies(program_path, application_name, exclude=["Logger"]) -> List[str]:
30
+ file_path = program_path + "/" + application_name + ".pjx"
31
+ doc = minidom.parse(file_path)
32
+ deps = doc.getElementsByTagName("Library")
33
+ return_deps = []
34
+ for dep in deps:
35
+ name = dep.getAttribute("alias")
36
+ should_exclude = False
37
+ for e in exclude:
38
+ if e in name:
39
+ should_exclude = True
40
+ if not should_exclude:
41
+ return_deps.append(name)
42
+ return return_deps
43
+
44
+
45
+ def get_type_dependencies(
46
+ program_path, application_name, exclude=["Logger"]
47
+ ) -> List[str]:
48
+ file_path = program_path + "/" + application_name + ".pjx"
49
+ doc = minidom.parse(file_path)
50
+ deps = doc.getElementsByTagName("Type")
51
+ return_deps = []
52
+ for dep in deps:
53
+ name = dep.getAttribute("name")
54
+ should_exclude = False
55
+ for e in exclude:
56
+ if e in name:
57
+ should_exclude = True
58
+ if not should_exclude:
59
+ return_deps.append(name)
60
+ return return_deps
61
+
62
+
63
+ def get_global_variables(
64
+ program_path, application_name, exclude=["UT"]
65
+ ) -> List[GlobalVariable]:
66
+ file_path = program_path + "/" + application_name + ".dtx"
67
+ doc = minidom.parse(file_path)
68
+ vars = doc.getElementsByTagName("Data")
69
+ return_vars = []
70
+ for var in vars:
71
+ name = var.getAttribute("name")
72
+ should_exclude = False
73
+ for e in exclude:
74
+ if e in name:
75
+ should_exclude = True
76
+ if not should_exclude:
77
+ xsi = var.getAttribute("xsi:type")
78
+ access = var.getAttribute("access")
79
+ type_ = var.getAttribute("type")
80
+ size = var.getAttribute("size")
81
+ return_vars.append(
82
+ GlobalVariable(name, access, type_, xsi, size, file_path)
83
+ )
84
+ return return_vars
85
+
86
+
87
+ def get_application_description(program_path) -> str:
88
+ file_path = program_path + "/README.md"
89
+ lines = []
90
+ try:
91
+ with open(file_path, "r") as f:
92
+ lines = f.readlines()
93
+ except FileNotFoundError:
94
+ print("Missing documentation file " + file_path)
95
+ return LINE_ENDED.join(lines)
96
+
97
+
98
+ class Application:
99
+ def __init__(self, program_path: str, application_name: str):
100
+ self.application_name = application_name
101
+ self.dependencies = get_dependencies(program_path, application_name)
102
+ self.type_dependencies = get_type_dependencies(program_path, application_name)
103
+ self.program_list = get_program_list(program_path, application_name)
104
+ self.global_variables = get_global_variables(program_path, application_name)
105
+ self.application_description = get_application_description(program_path)
106
+
107
+ def check_coding_rules(self) -> List[str]:
108
+ result = []
109
+ for p in self.program_list:
110
+ result += p.check_coding_rules()
111
+ for gv in self.global_variables:
112
+ result += gv.check_coding_rules()
113
+ return result
114
+
115
+ def get_all_information_from_app(self) -> Dict[str, Any]:
116
+ """Return all information from the application in a dict for the documentation generation"""
117
+ all_information = {
118
+ "name": self.application_name,
119
+ "description": self.application_description,
120
+ "dependencies": self.dependencies,
121
+ "type_dependencies": self.type_dependencies,
122
+ "global_variables": self.global_variables,
123
+ "private_program_list": [p for p in self.program_list if not p.public],
124
+ "public_program_list": [p for p in self.program_list if p.public],
125
+ }
126
+ return all_information
@@ -0,0 +1,18 @@
1
+ import codecs
2
+ import os
3
+
4
+
5
+ def read_begining_of_file() -> str:
6
+ result = ""
7
+ path = os.path.dirname(__file__) + os.sep + ".." + os.sep + "assets" + os.sep
8
+ with codecs.open(path + "BeginingOfFile.md", encoding="utf-8") as f:
9
+ result = f.read()
10
+ return result
11
+
12
+
13
+ def read_end_of_file() -> str:
14
+ result = ""
15
+ path = os.path.dirname(__file__) + os.sep + ".." + os.sep + "assets" + os.sep
16
+ with codecs.open(path + "EndOfFile.md", encoding="utf-8") as f:
17
+ result = f.read()
18
+ return result
@@ -0,0 +1,52 @@
1
+ from typing import List
2
+
3
+ from .rules import OTHER_TYPES, TYPE_RULES
4
+
5
+
6
+ class GlobalVariable:
7
+ def __init__(
8
+ self,
9
+ name: str,
10
+ access: str,
11
+ type_data: str,
12
+ xsi: str,
13
+ size: str,
14
+ context: str = "",
15
+ ):
16
+ self.name = name
17
+ self.type_data = type_data
18
+ self.xsi = xsi
19
+ self.size = size
20
+ self.access = access
21
+ self.context = context
22
+
23
+ def check_coding_rules(self) -> List:
24
+ result = []
25
+ if self.access == "private" and not self.name.startswith("_"):
26
+ result += [
27
+ f"Global private variable {self.name} should begin by '_'. {self.context}"
28
+ ]
29
+ if self.access != "private" and self.name.startswith("_"):
30
+ result += [
31
+ f"Global public variable {self.name} should not begin by '_'. {self.context}"
32
+ ]
33
+
34
+ name = self.name[1:] if self.name.startswith("_") else self.name
35
+ if self.type_data in TYPE_RULES.keys():
36
+ rule = TYPE_RULES.get(self.type_data)
37
+ if not name.startswith(rule):
38
+ result += [
39
+ (
40
+ f"Global variable {self.name} of type {self.type_data} should begin by "
41
+ f"'{'_' if self.access == 'private' else ''}{rule}'. {self.context}"
42
+ )
43
+ ]
44
+ else:
45
+ if not name.startswith(OTHER_TYPES):
46
+ result += [
47
+ (
48
+ f"Global variable {self.name} of type CUSTOM should begin by "
49
+ f"'{'_' if self.access == 'private' else ''}{OTHER_TYPES}'. {self.context}"
50
+ )
51
+ ]
52
+ return result
@@ -0,0 +1,2 @@
1
+ LINE_ENDED = """
2
+ """
@@ -0,0 +1,35 @@
1
+ from typing import List
2
+
3
+ from .rules import OTHER_TYPES, TYPE_RULES
4
+
5
+
6
+ class LocalVariable:
7
+ def __init__(
8
+ self, name: str, type_data: str, xsi: str, size: str, context: str = ""
9
+ ):
10
+ self.name = name
11
+ self.type_data = type_data
12
+ self.xsi = xsi
13
+ self.size = size
14
+ self.context = context
15
+
16
+ def check_coding_rules(self) -> List:
17
+ result = []
18
+ if not self.name.startswith("l_"):
19
+ result += [
20
+ f"Local variable {self.name} should begin by 'l_'. {self.context}"
21
+ ]
22
+
23
+ if self.type_data in TYPE_RULES.keys():
24
+ rule = TYPE_RULES.get(self.type_data)
25
+ if not self.name.startswith("l_" + rule):
26
+ result += [
27
+ f"Local variable {self.name} of type {self.type_data} should begin by 'l_{rule}'. {self.context}"
28
+ ]
29
+ else:
30
+ if not self.name.startswith("l_" + OTHER_TYPES):
31
+ result += [
32
+ f"Local variable {self.name} of type CUSTOM should begin by 'l_{OTHER_TYPES}'. {self.context}"
33
+ ]
34
+
35
+ return result
@@ -0,0 +1,42 @@
1
+ from typing import List
2
+
3
+ from .rules import OTHER_TYPES, TYPE_RULES
4
+
5
+
6
+ class Parameter:
7
+ def __init__(
8
+ self, name: str, type_data: str, xsi: str, use: str, context: str = ""
9
+ ):
10
+ self.name = name
11
+ self.type_data = type_data
12
+ self.xsi = xsi
13
+ self.use = use
14
+ if len(use) == 0:
15
+ self.use = "value"
16
+ self.context = context
17
+
18
+ def check_coding_rules(self) -> List:
19
+ result = []
20
+ if not self.name.startswith("x_"):
21
+ result += [f"Parameter {self.name} should begin by 'x_'. {self.context}"]
22
+ if (
23
+ self.use != "value"
24
+ and self.xsi == "element"
25
+ and not self.name.endswith("Out")
26
+ ):
27
+ result += [
28
+ f"Output parameter {self.name} should ends by 'Out'. {self.context}"
29
+ ]
30
+
31
+ if self.type_data in TYPE_RULES.keys():
32
+ rule = TYPE_RULES.get(self.type_data)
33
+ if not self.name.startswith("x_" + rule):
34
+ result += [
35
+ f"Parameter {self.name} of type {self.type_data} should begin by 'x_{rule}'. {self.context}"
36
+ ]
37
+ else:
38
+ if not self.name.startswith("x_" + OTHER_TYPES):
39
+ result += [
40
+ f"Parameter {self.name} of type CUSTOM should begin by 'x_{OTHER_TYPES}'. {self.context}"
41
+ ]
42
+ return result
@@ -0,0 +1,135 @@
1
+ from typing import List
2
+ from xml.dom import minidom
3
+
4
+ from .parameter import Parameter
5
+ from .local_variable import LocalVariable
6
+
7
+
8
+ def get_parameters(program_path: str, program_file: str) -> List[Parameter]:
9
+ file_path = program_path + "/" + program_file
10
+ doc = minidom.parse(file_path)
11
+ params = doc.getElementsByTagName("Parameter")
12
+ returned_params = []
13
+ for param in params:
14
+ returned_params.append(
15
+ Parameter(
16
+ param.getAttribute("name"),
17
+ param.getAttribute("type"),
18
+ param.getAttribute("xsi:type"),
19
+ param.getAttribute("use"),
20
+ file_path,
21
+ )
22
+ )
23
+ return returned_params
24
+
25
+
26
+ def get_program_description(program_path: str, program_file: str) -> str:
27
+ file_path = program_path + "/" + program_file
28
+ input_txt = []
29
+ with open(file_path, "r") as f_input:
30
+ input_txt = f_input.readlines()
31
+ comment_txt = r"//"
32
+ doc = ""
33
+ start_doc = False
34
+ for line in input_txt:
35
+ if start_doc:
36
+ if comment_txt in line:
37
+ doc += line.split(comment_txt)[-1]
38
+ else:
39
+ break
40
+ # first code line
41
+ if "<Code><![CDATA[begin" in line:
42
+ start_doc = True
43
+ # last code line
44
+ if "end]]></Code>" in line:
45
+ break
46
+ if len(doc) == 0:
47
+ print("Missing description for program " + file_path)
48
+ return doc
49
+
50
+
51
+ def get_code(program_path: str, program_file: str) -> str:
52
+ file_path = program_path + "/" + program_file
53
+ input_txt = ""
54
+ with open(file_path, "r") as f_input:
55
+ input_txt = f_input.read()
56
+ return input_txt.split("<Code><![CDATA[begin")[-1].split("end]]></Code>")[0]
57
+
58
+
59
+ def is_public(program_path: str, program_file: str) -> bool:
60
+ file_path = program_path + "/" + program_file
61
+ doc = minidom.parse(file_path)
62
+ prog = doc.getElementsByTagName("Program")
63
+ for p in prog:
64
+ return p.getAttribute("access") == "public"
65
+ return False
66
+
67
+
68
+ def get_local_variables(program_path: str, program_file: str) -> List[LocalVariable]:
69
+ file_path = program_path + "/" + program_file
70
+ doc = minidom.parse(file_path)
71
+ vars = doc.getElementsByTagName("Local")
72
+ returned_vars = []
73
+ for var in vars:
74
+ returned_vars.append(
75
+ LocalVariable(
76
+ var.getAttribute("name"),
77
+ var.getAttribute("type"),
78
+ var.getAttribute("xsi:type"),
79
+ var.getAttribute("size"),
80
+ file_path,
81
+ )
82
+ )
83
+ return returned_vars
84
+
85
+
86
+ def get_program_signature(program_name: str, parameters: List[Parameter]) -> str:
87
+ return (
88
+ program_name.removesuffix(".pgx")
89
+ + "("
90
+ + ", ".join(
91
+ [
92
+ param.type_data
93
+ + ("& " if (param.use == "reference") else " ")
94
+ + param.name
95
+ for param in parameters
96
+ ]
97
+ )
98
+ + ")"
99
+ )
100
+
101
+
102
+ class Program:
103
+ def __init__(self, program_path: str, program_name: str):
104
+ self.program_path = program_path
105
+ self.program_name = program_name
106
+ self.param_list = get_parameters(program_path, program_name)
107
+ self.variable_list = get_local_variables(program_path, program_name)
108
+ self.description = get_program_description(program_path, program_name)
109
+ self.signature = get_program_signature(program_name, self.param_list)
110
+ self.public = is_public(program_path, program_name)
111
+ self.code = get_code(program_path, program_name)
112
+ self.check_has_unused_parameter()
113
+ self.check_has_unused_variable()
114
+
115
+ def check_coding_rules(self) -> List[str]:
116
+ return self.check_has_unused_parameter() + self.check_has_unused_variable()
117
+
118
+ def check_has_unused_parameter(self) -> List[str]:
119
+ result = []
120
+ for param in self.param_list:
121
+ if param.name not in self.code:
122
+ result += [
123
+ f"Unused parameter {param.name} in program {self.program_path}/{self.program_name}"
124
+ ]
125
+ result += param.check_coding_rules()
126
+ return result
127
+
128
+ def check_has_unused_variable(self) -> List[str]:
129
+ result = []
130
+ for var in self.variable_list:
131
+ if var.name not in self.code:
132
+ result += [
133
+ f"Unused local variable {var.name} in program {self.program_path}/{self.program_name}"
134
+ ]
135
+ return result
@@ -0,0 +1,19 @@
1
+ TYPE_RULES = {
2
+ "aio": "aio",
3
+ "bool": "b",
4
+ "configRs": "c",
5
+ "configRx": "c",
6
+ "dio": "dio",
7
+ "frame": "f",
8
+ "jointRs": "j",
9
+ "jointRx": "j",
10
+ "mdesc": "m",
11
+ "num": "n",
12
+ "pointRs": "p",
13
+ "pointRx": "p",
14
+ "sio": "sio",
15
+ "string": "s",
16
+ "tool": "t",
17
+ "trsf": "trsf",
18
+ }
19
+ OTHER_TYPES = "st"
@@ -0,0 +1,37 @@
1
+ import logging
2
+ import re
3
+ import sys
4
+
5
+
6
+ def configure_logging():
7
+ logging.basicConfig(
8
+ format="%(asctime)s %(levelname)s: %(message)s", level=logging.INFO
9
+ )
10
+
11
+
12
+ def die(msg: str) -> None:
13
+ logging.error(msg)
14
+ sys.exit(1)
15
+
16
+
17
+ def get_version():
18
+ """get version from setup.cfg file and
19
+ update __version__ in lupin_danquin.__init__.py
20
+ """
21
+ with open("setup.cfg", "r", encoding="utf-8") as f:
22
+ setup_cfg = f.read()
23
+ print(setup_cfg)
24
+ _version = re.search(
25
+ r"(^version = )(\d{1,2}\.\d{1,2}\.\d{1,2})(\.[a-z]{1,})?(\d{1,2})?",
26
+ setup_cfg,
27
+ re.MULTILINE,
28
+ )
29
+ version = ""
30
+ for group in _version.group(2, 3, 4):
31
+ if group is not None:
32
+ version = version + str(group)
33
+ content = f'__version__ = "{version}"\n'
34
+
35
+ with open("lupin_danquin/__init__.py", "w", encoding="utf-8") as outfile:
36
+ outfile.write(content)
37
+ return version
@@ -0,0 +1,45 @@
1
+ import codecs
2
+
3
+ from jinja2 import (
4
+ Environment,
5
+ FileSystemLoader,
6
+ select_autoescape,
7
+ Template,
8
+ TemplateNotFound,
9
+ TemplateError,
10
+ TemplateRuntimeError,
11
+ )
12
+
13
+ from core.tools.utils import die
14
+
15
+
16
+ class Val3Documentation:
17
+ def _get_local_template(self) -> Template:
18
+ try:
19
+ # Create jinja2 environment
20
+ env = Environment(
21
+ loader=FileSystemLoader("lupin_danquin/templates"),
22
+ autoescape=select_autoescape(),
23
+ trim_blocks=True,
24
+ lstrip_blocks=True,
25
+ )
26
+ # Charge template
27
+ template = env.get_template("val3_documentation_md.j2")
28
+ return template
29
+ except TemplateNotFound:
30
+ print(
31
+ "Template 'lupin_danquin/templates/val3_documentation_md.j2 not found"
32
+ )
33
+
34
+ def generate_markdown(self, context={}) -> None:
35
+ """Generate the documentation"""
36
+ template = self._get_local_template()
37
+ try:
38
+ content = template.render(context)
39
+ except (TemplateError, TemplateRuntimeError) as e:
40
+ die(msg=f"Error rendering Jinja2 template: {e}")
41
+
42
+ with codecs.open(
43
+ "lupin_danquin/val3_documentation.md", "w", encoding="utf-8"
44
+ ) as f:
45
+ f.write(content)
@@ -0,0 +1,54 @@
1
+ import os
2
+
3
+ from core.application import Application
4
+ from core.external_resources import read_begining_of_file, read_end_of_file
5
+ from core.tools.utils import configure_logging, die
6
+ from core.val3_doc_generator.val3_doc_generator import Val3Documentation
7
+
8
+
9
+ APPLICATION_NAMES = [
10
+ "TaskManager",
11
+ "Watchdog",
12
+ ]
13
+ USR_APP_DIR = "usrapp"
14
+
15
+
16
+ def find_usrapp_dir() -> str:
17
+ """Find the usrapp directory"""
18
+ for dirpath, dirnames, filenames in os.walk(os.getcwd()):
19
+ if USR_APP_DIR in dirnames:
20
+ return os.path.join(dirpath, USR_APP_DIR)
21
+ die(msg=f"'{USR_APP_DIR}' directory not found")
22
+
23
+
24
+ def get_informations_from_applications() -> list:
25
+ """Get all informations from applications"""
26
+
27
+ apps_information = []
28
+ base_program_path = find_usrapp_dir() + os.sep
29
+
30
+ for application_name in APPLICATION_NAMES:
31
+ program_path = base_program_path + application_name
32
+ apps_information.append(
33
+ Application(program_path, application_name).get_all_information_from_app()
34
+ )
35
+
36
+ return apps_information
37
+
38
+
39
+ def main() -> None:
40
+ """Main function"""
41
+
42
+ configure_logging()
43
+
44
+ context = {
45
+ "begining_of_file": read_begining_of_file(),
46
+ "end_of_file": read_end_of_file(),
47
+ "applications": get_informations_from_applications(),
48
+ }
49
+
50
+ Val3Documentation().generate_markdown(context=context)
51
+
52
+
53
+ if __name__ == "__main__":
54
+ main()
@@ -0,0 +1,15 @@
1
+ Metadata-Version: 2.1
2
+ Name: lupin-danquin
3
+ Version: 0.0.1.dev0
4
+ Summary: Testing - Documentation VAL3 from Code
5
+ License: MIT License
6
+ Keywords: documentation,testing
7
+ Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Intended Audience :: Information Technology
9
+ Classifier: Topic :: Software Development :: Testing
10
+ Classifier: Topic :: Documentation
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Requires-Python: >=3.10
14
+ Provides-Extra: test
15
+ License-File: LICENCE
@@ -0,0 +1,26 @@
1
+ LICENCE
2
+ README.md
3
+ setup.cfg
4
+ setup.py
5
+ lupin_danquin/__init__.py
6
+ lupin_danquin/check_coding_rules.py
7
+ lupin_danquin/documentation_extraction.py
8
+ lupin_danquin.egg-info/PKG-INFO
9
+ lupin_danquin.egg-info/SOURCES.txt
10
+ lupin_danquin.egg-info/dependency_links.txt
11
+ lupin_danquin.egg-info/not-zip-safe
12
+ lupin_danquin.egg-info/requires.txt
13
+ lupin_danquin.egg-info/top_level.txt
14
+ lupin_danquin/core/__init__.py
15
+ lupin_danquin/core/application.py
16
+ lupin_danquin/core/external_resources.py
17
+ lupin_danquin/core/global_variable.py
18
+ lupin_danquin/core/line_ended.py
19
+ lupin_danquin/core/local_variable.py
20
+ lupin_danquin/core/parameter.py
21
+ lupin_danquin/core/program.py
22
+ lupin_danquin/core/rules.py
23
+ lupin_danquin/core/tools/__init__.py
24
+ lupin_danquin/core/tools/utils.py
25
+ lupin_danquin/core/val3_doc_generator/__init__.py
26
+ lupin_danquin/core/val3_doc_generator/val3_doc_generator.py
@@ -0,0 +1,7 @@
1
+ typer[all]==0.7.0
2
+ python-dotenv==1.0.0
3
+ Jinja2==3.1.2
4
+
5
+ [test]
6
+ pytest==7.2.2
7
+ flake8==6.0.0
@@ -0,0 +1 @@
1
+ lupin_danquin
@@ -0,0 +1,37 @@
1
+ [metadata]
2
+ name = lupin-danquin
3
+ version = 0.0.1.dev0
4
+ description = Testing - Documentation VAL3 from Code
5
+ keywords = documentation, testing
6
+ license = MIT License
7
+ classifiers =
8
+ Development Status :: 3 - Alpha
9
+ Intended Audience :: Information Technology
10
+ Topic :: Software Development :: Testing
11
+ Topic :: Documentation
12
+ Programming Language :: Python :: 3.10
13
+ License :: OSI Approved :: MIT License
14
+
15
+ [options]
16
+ zip_safe = False
17
+ include_package_data = True
18
+ packages = find:
19
+ python_requires = >=3.10
20
+ install_requires =
21
+ typer[all]==0.7.0
22
+ python-dotenv==1.0.0
23
+ Jinja2==3.1.2
24
+
25
+ [options.extras_require]
26
+ test =
27
+ pytest==7.2.2
28
+ flake8==6.0.0
29
+
30
+ [options.packages.find]
31
+ exclude =
32
+ lupin_danquin.tests*
33
+
34
+ [egg_info]
35
+ tag_build =
36
+ tag_date = 0
37
+
@@ -0,0 +1,10 @@
1
+ from setuptools import setup
2
+
3
+
4
+ from lupin_danquin.core.tools.utils import get_version
5
+
6
+
7
+ if __name__ == '__main__':
8
+ setup(
9
+ version=get_version()
10
+ )