GCC Code Coverage Report


Directory: ./
File: src/wrapper_generator.cpp
Date: 2025-04-25 19:10:50
Exec Total Coverage
Lines: 120 127 94.5%
Branches: 181 220 82.3%

Line Branch Exec Source
1 /***************************************
2 Auteur : Pierre Aubert
3 Mail : pierre.aubert@lapp.in2p3.fr
4 Licence : CeCILL-C
5 ****************************************/
6
7 #include "cmakelist_generator.h"
8 #include "wrapper_module_generator.h"
9 #include "wrapper_test.h"
10 #include "wrapper_generator.h"
11
12 ///Create the config of the wrapper
13 /** @param projectConfig : main configuration
14 * @return wrapper configuration
15 */
16 5 ProjectConfig project_createWrapperConfig(const ProjectConfig & projectConfig){
17 5 ProjectConfig wrapper(projectConfig);
18
2/2
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
5 wrapper.name = "Py"+projectConfig.name;
19
2/2
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
5 wrapper.url = wrapper.url.replace(projectConfig.name, wrapper.name);
20
21 5 return wrapper;
22 }
23
24 ///Create the readme of the project directory
25 /** @param fileName : name of the file to be created
26 * @param projectConfig : config of the project
27 * @return true on success, false otherwise
28 */
29 5 bool project_wrapper_generator_readme(const PPath & fileName, const ProjectConfig & projectConfig){
30
1/1
✓ Branch 1 taken 5 times.
5 PString body;
31
1/1
✓ Branch 1 taken 5 times.
5 body += "![PLIBS_9 logo](doc/logo.png)\n\n";
32
33
1/1
✓ Branch 1 taken 5 times.
5 body += "# Remarks\n\n";
34
1/1
✓ Branch 1 taken 5 times.
5 body += "This project was generated automatically by [phoenix_filegenerator](https://gitlab.in2p3.fr/CTA-LAPP/PHOENIX_LIBS2/PhoenixFileGenerator)\n";
35
1/1
✓ Branch 1 taken 5 times.
5 body += "using [phoenix_generator](https://gitlab.in2p3.fr/CTA-LAPP/PHOENIX_LIBS2/PhoenixGenerator) library\n\n";
36
37
1/1
✓ Branch 1 taken 5 times.
5 body += "# Code\n\n";
38
3/3
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
✓ Branch 7 taken 5 times.
5 body += "Version : " + projectConfig.version + "\n\n";
39
2/2
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
5 body += projectConfig.url + "\n\n";
40
1/1
✓ Branch 1 taken 5 times.
5 body += "# Description\n\n";
41
1/1
✓ Branch 1 taken 5 times.
5 body += "Python wrapper version.\n";
42
2/2
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
5 body += projectConfig.description + "\n\n";
43
44
1/1
✓ Branch 1 taken 5 times.
10 return fileName.saveFileContent(body);
45 5 }
46
47 ///Create the readme of the project directory
48 /** @param fileName : name of the file to be created
49 * @param projectConfig : config of the project
50 * @param baseImplInclude : basic include of the module implementation
51 * @param vecClassConfig : vector of class confoguration
52 * @param vecInclude : vector of includes
53 * @return true on success, false otherwise
54 */
55 5 bool project_wrapper_generator_setuppy(const PPath & fileName, const ProjectConfig & projectConfig, const PString & baseImplInclude, const std::vector<PClassConfig> & vecClassConfig, const PVecPath & vecInclude){
56
4/4
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
✓ Branch 7 taken 5 times.
✓ Branch 10 taken 5 times.
10 PString body, moduleName = "py" + projectConfig.name.toLower();
57
1/1
✓ Branch 1 taken 5 times.
5 body += "\n";
58
2/2
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
5 body += getCMakeListsHeader();
59
1/1
✓ Branch 1 taken 5 times.
5 body += "from setuptools import setup\n";
60
1/1
✓ Branch 1 taken 5 times.
5 body += "from setuptools import Extension\n";
61
1/1
✓ Branch 1 taken 5 times.
5 body += "import sys\n";
62
1/1
✓ Branch 1 taken 5 times.
5 body += "import numpy as np\n";
63
1/1
✓ Branch 1 taken 5 times.
5 body += "import subprocess\n";
64
1/1
✓ Branch 1 taken 5 times.
5 body += "\n";
65
1/1
✓ Branch 1 taken 5 times.
5 body += "dataStreamIncludeDir = subprocess.run(['phoenixdatastream-config', '--include'], capture_output = True, text = True).stdout.strip(\"\\n\")\n";
66
1/1
✓ Branch 1 taken 5 times.
5 body += "dataStreamLibDir = subprocess.run(['phoenixdatastream-config', '--lib'], capture_output = True, text = True).stdout.strip(\"\\n\")\n";
67
1/1
✓ Branch 1 taken 5 times.
5 body += "\n";
68
1/1
✓ Branch 1 taken 5 times.
5 body += "ext_modules = [\n";
69
3/3
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
✓ Branch 7 taken 5 times.
5 body += "\tExtension(\""+moduleName+"\", sources=([\n";
70
5/5
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
✓ Branch 7 taken 5 times.
✓ Branch 10 taken 5 times.
✓ Branch 13 taken 5 times.
5 body += "\t\t\""+moduleName+"/"+baseImplInclude+"_wrapper.cpp\",\n";
71
6/6
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
✓ Branch 7 taken 5 times.
✓ Branch 10 taken 5 times.
✓ Branch 13 taken 5 times.
✓ Branch 16 taken 5 times.
5 body += "\t\t\""+moduleName+"/"+projectConfig.name.toLower()+"_module.cpp\"\n";
72
1/1
✓ Branch 1 taken 5 times.
5 body += "\t]),\n";
73
1/1
✓ Branch 1 taken 5 times.
5 body += "\textra_compile_args = [\"-O3\", \"-Werror\", \"-g\"],\n";
74
75
3/3
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
✓ Branch 7 taken 5 times.
5 body += "\tinclude_dirs = [np.get_include(), dataStreamIncludeDir, \"./\", \""+moduleName+"/\"],\n";
76
1/1
✓ Branch 1 taken 5 times.
5 body += "\tlibraries=[\"phoenix_data_stream\"],\n";
77
1/1
✓ Branch 1 taken 5 times.
5 body += "\tlibrary_dirs=[dataStreamLibDir],\n";
78
1/1
✓ Branch 1 taken 5 times.
5 body += "\t)\n";
79
1/1
✓ Branch 1 taken 5 times.
5 body += "]\n\n";
80
81
1/1
✓ Branch 1 taken 5 times.
5 body += "try:\n";
82
1/1
✓ Branch 1 taken 5 times.
5 body += "\tsetup(\n";
83
3/3
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
✓ Branch 7 taken 5 times.
5 body += "\t\tname=\""+moduleName+"\",\n";
84
3/3
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
✓ Branch 7 taken 5 times.
5 body += "\t\tversion=\""+projectConfig.version+"\",\n";
85
1/1
✓ Branch 1 taken 5 times.
5 body += "\t\text_modules=ext_modules,\n";
86
1/1
✓ Branch 1 taken 5 times.
5 body += "\t)\n";
87
1/1
✓ Branch 1 taken 5 times.
5 body += "except Exception as e:\n";
88
1/1
✓ Branch 1 taken 5 times.
5 body += "\tprint(str(e))\n";
89
1/1
✓ Branch 1 taken 5 times.
5 body += "\tsys.exit(-1)\n";
90
1/1
✓ Branch 1 taken 5 times.
5 body += "\n";
91
1/1
✓ Branch 1 taken 5 times.
10 return fileName.saveFileContent(body);
92 5 }
93
94 ///Create the readme of the project directory
95 /** @param fileName : name of the file to be created
96 * @param projectConfig : config of the project
97 * @param baseImplInclude : basic include of the module implementation
98 * @param vecClassConfig : vector of class confoguration
99 * @param vecInclude : vector of includes
100 * @return true on success, false otherwise
101 */
102 5 bool project_wrapper_generator_pyprojectToml(const PPath & fileName, const ProjectConfig & projectConfig, const PString & baseImplInclude, const std::vector<PClassConfig> & vecClassConfig, const PVecPath & vecInclude){
103
1/1
✓ Branch 1 taken 5 times.
5 PString body;
104
1/1
✓ Branch 1 taken 5 times.
5 body += "\n";
105
2/2
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
5 body += getCMakeListsHeader();
106
1/1
✓ Branch 1 taken 5 times.
5 body += "[project]\n";
107
4/4
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
✓ Branch 7 taken 5 times.
✓ Branch 10 taken 5 times.
5 body += "name = \"py"+projectConfig.name.toLower()+"\"\n";
108
3/3
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
✓ Branch 7 taken 5 times.
5 body += "version = \""+projectConfig.version+"\"\n";
109
6/6
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
✓ Branch 7 taken 5 times.
✓ Branch 10 taken 5 times.
✓ Branch 13 taken 5 times.
✓ Branch 16 taken 5 times.
5 body += "description = \""+projectConfig.description.replace("\n", " ")+"\"\n";
110
1/1
✓ Branch 1 taken 5 times.
5 body += "readme = \"README.md\"\n";
111
1/1
✓ Branch 1 taken 5 times.
5 body += "license = \"CeCILL-C\"\n";
112
1/1
✓ Branch 1 taken 5 times.
5 body += "dependencies = [\n";
113
1/1
✓ Branch 1 taken 5 times.
5 body += "\t\"numpy\"\n";
114
1/1
✓ Branch 1 taken 5 times.
5 body += "]\n";
115
1/1
✓ Branch 1 taken 5 times.
5 body += "\n";
116
1/1
✓ Branch 1 taken 5 times.
5 body += "[build-system]\n";
117
1/1
✓ Branch 1 taken 5 times.
5 body += "requires = [\n";
118
1/1
✓ Branch 1 taken 5 times.
5 body += "\t\"numpy\",\n";
119
1/1
✓ Branch 1 taken 5 times.
5 body += "\t\"setuptools >= 74.1\",\n";
120
1/1
✓ Branch 1 taken 5 times.
5 body += "\t\"cython\"\n";
121
1/1
✓ Branch 1 taken 5 times.
5 body += "]\n";
122
1/1
✓ Branch 1 taken 5 times.
5 body += "build-backend = \"setuptools.build_meta\"\n";
123
1/1
✓ Branch 1 taken 5 times.
5 body += "\n";
124 // body += "[tool.setuptools]\n";
125 // body += "ext-modules = [\n";
126 // body += "\t{\n";
127 // body += "\t\tname = \""+projectConfig.name.toLower()+"\",\n";
128 // body += "\t\tsources = [\n";
129 // body += "\t\t\t\""+projectConfig.name.toLower()+"/"+baseImplInclude+"_wrapper.cpp\",\n";
130 // body += "\t\t\t\""+projectConfig.name.toLower()+"/"+projectConfig.name+"_module.cpp\"\n";
131 // body += "\t\t],\n";
132 // body += "\t\textra_compile_args = [\"-O3\", \"-Werror\", \"-g\"]\n";
133 // body += "\t}\n";
134 // body += "\n";
135 // body += "]\n";
136
1/1
✓ Branch 1 taken 5 times.
5 body += "\n";
137
1/1
✓ Branch 1 taken 5 times.
10 return fileName.saveFileContent(body);
138 5 }
139
140 ///Update the vector of class configuration
141 /** @param[out] vecClassConfig : vector of class configuration to be updated
142 */
143 5 void updateVecClassConfig(std::vector<PClassConfig> & vecClassConfig){
144 5 std::map<std::string, std::string> mapEnum;
145
2/2
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 5 times.
12 for(std::vector<PClassConfig>::iterator it(vecClassConfig.begin()); it != vecClassConfig.end(); ++it){
146
3/3
✓ Branch 2 taken 7 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 6 times.
7 if(it->getIsEnum()){
147
7/7
✓ Branch 2 taken 1 times.
✓ Branch 6 taken 1 times.
✓ Branch 10 taken 1 times.
✓ Branch 13 taken 1 times.
✓ Branch 16 taken 1 times.
✓ Branch 19 taken 1 times.
✓ Branch 22 taken 1 times.
1 mapEnum[it->getName() + "::" + it->getName()] = it->getName();
148 1 size_t i(0lu);
149
1/1
✓ Branch 2 taken 1 times.
1 std::vector<PClassAttribute> & vecAttr = it->getListAttribute();
150
2/2
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 1 times.
3 for(std::vector<PClassAttribute>::iterator itAttr(vecAttr.begin()); itAttr != vecAttr.end(); ++itAttr){
151
2/3
✓ Branch 2 taken 2 times.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
2 if(itAttr->getDefaultValue() == ""){
152
2/2
✓ Branch 2 taken 2 times.
✓ Branch 5 taken 2 times.
2 itAttr->setDefaultValue(PString::toString(i));
153 }
154 2 ++i;
155 }
156 }
157 }
158
2/2
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 5 times.
12 for(std::vector<PClassConfig>::iterator itClass(vecClassConfig.begin()); itClass != vecClassConfig.end(); ++itClass){
159
1/1
✓ Branch 2 taken 7 times.
7 std::vector<PClassAttribute> & vecAttr = itClass->getListAttribute();
160
2/2
✓ Branch 4 taken 20 times.
✓ Branch 5 taken 7 times.
27 for(std::vector<PClassAttribute>::iterator itAttr(vecAttr.begin()); itAttr != vecAttr.end(); ++itAttr){
161
2/2
✓ Branch 2 taken 20 times.
✓ Branch 5 taken 20 times.
20 std::map<std::string, std::string>::iterator it(mapEnum.find(itAttr->getType()));
162
2/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 19 times.
20 if(it != mapEnum.end()){
163
2/2
✓ Branch 3 taken 1 times.
✓ Branch 6 taken 1 times.
1 itAttr->setType(it->second);
164
1/1
✓ Branch 2 taken 1 times.
1 itAttr->setIsEnum(true);
165 }
166
5/8
✓ Branch 2 taken 20 times.
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 20 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 20 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 20 times.
20 if(itAttr->getType() == "PPath" || itAttr->getType() == "PString"){
167 itAttr->setType("std::string");
168 }
169 }
170 }
171 5 }
172
173 ///Generate a full python wrapper project with PhoenixDataStream and PhoenixTypeStream
174 /** @param projectConfig : description of the full project
175 * @param configFile : configuration file of the
176 * @return true on success, false otherwise
177 */
178 5 bool project_wrapper_generator(const ProjectConfig & projectConfig, const PPath & configFile){
179
1/1
✓ Branch 1 taken 5 times.
5 ProjectConfig wrapperConfig(project_createWrapperConfig(projectConfig));
180 5 PVecPath vecInclude;
181 5 std::vector<PClassConfig> vecClassConfig;
182
2/3
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
5 if(!parserClassConfig(vecClassConfig, vecInclude, configFile)){
183 std::cerr << "project_wrapper_generator : can't load file '" << configFile << "'" << std::endl;
184 return false;
185 }
186 //TODO : pass through vecClassConfig and replace PPath and PString by std::string to ensure PhoenixDataStream will work well on them for the wrapper
187
1/1
✓ Branch 1 taken 5 times.
5 updateVecClassConfig(vecClassConfig);
188
189 //Then, let's create the hierarchy
190
1/1
✓ Branch 1 taken 5 times.
5 PPath mainProjectDir(wrapperConfig.name);
191
2/3
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
5 if(!mainProjectDir.createDirectory()){
192 std::cerr << "project_wrapper_generator : cannot create main directory of project '"<<mainProjectDir<<"'" << std::endl;
193 return false;
194 }
195 //And module dir
196
3/3
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
✓ Branch 7 taken 5 times.
10 PPath mainProjectModule(mainProjectDir / PPath(wrapperConfig.name.toLower()));
197
2/3
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
5 if(!mainProjectModule.createDirectory()){
198 std::cerr << "project_generator : cannot create module directory of project '"<<mainProjectModule<<"'" << std::endl;
199 return false;
200 }
201 //The readme
202
3/3
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
✓ Branch 7 taken 5 times.
10 PPath readmeFile(mainProjectDir / PPath("README.md"));
203
2/3
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
5 if(!project_wrapper_generator_readme(readmeFile, projectConfig)){return false;}
204
205
3/3
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
✓ Branch 7 taken 5 times.
5 PString baseImplInclude = configFile.getFileName().eraseExtension();
206 //The readme
207
3/3
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
✓ Branch 7 taken 5 times.
10 PPath setupFile(mainProjectDir / PPath("setup.py"));
208
2/3
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
5 if(!project_wrapper_generator_setuppy(setupFile, projectConfig, baseImplInclude, vecClassConfig, vecInclude)){return false;}
209
210
3/3
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
✓ Branch 7 taken 5 times.
10 PPath pyprojectFile(mainProjectDir / PPath("pyproject.toml"));
211
2/3
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
5 if(!project_wrapper_generator_pyprojectToml(pyprojectFile, projectConfig, baseImplInclude, vecClassConfig, vecInclude)){return false;}
212 //The unit tests
213
5/6
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
✓ Branch 7 taken 5 times.
✓ Branch 10 taken 5 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 5 times.
5 if(!project_wrapper_moduleGeneratorTest(mainProjectDir, projectConfig, "py"+projectConfig.name.toLower(), vecClassConfig, vecInclude)){return false;}
214 //The full module
215
1/1
✓ Branch 1 taken 5 times.
5 return project_wrapper_moduleGenerator(mainProjectModule, projectConfig, baseImplInclude, vecClassConfig, vecInclude);
216 5 }
217
218
219
220