Skip to content

Commit 4b10ff6

Browse files
committed
Small changes for using VcProject API as a @contextlib.contextmanager and some error detection
1 parent b95a9b6 commit 4b10ff6

14 files changed

+137
-212
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,9 @@ By selecting individual cases, you can view the execution reports, providing ins
348348

349349
## Known Issues
350350

351+
### Imported Results with Cobertura and LCOV output
352+
New output formats were added, extended cobertura format output for use with Jenkins Coverage Plugin and LCOV output support. These reporting scripts do not currently support generating coverage metrics based off of imported results.
353+
351354
### VectorCAST Reports and Jenkins Content Security
352355

353356
VectorCAST HTML reports for metrics were updated to use cascading style sheets (CSS) in the 2019 release and 2020 for top level project metrics. This was done to offer users greater flexibility in displaying metrics. To maintain single file HTML format, VectorCAST Reports used inline CSS. Inline CSS was disallowed under Jenkins more restrictive CSP.

src/main/resources/scripts/cobertura.py

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -389,23 +389,26 @@ def procesCoverage(coverXML, coverApi, extended = False, source_root = ""):
389389
return processStatementBranchMCDC(coverApi, lines, extended)
390390

391391
def runCoverageResultsMP(packages, mpFile, verbose = False, extended=False, source_root = ""):
392-
vcproj = VCProjectApi(mpFile)
392+
393+
with VCProjectApi(mpFile) as vcproj:
393394

394-
anyLocalResults, anyImportedResults = checkProjectResults(vcproj)
395+
anyLocalResults, anyImportedResults = checkProjectResults(vcproj)
395396

396-
if anyImportedResults:
397-
importedResultsError = " ** Cobertura results does not processing imported results at this time\n\n"
398-
print(importedResultsError)
399-
return [-1] * 19
400-
401-
if not anyLocalResults:
402-
localResultsError = " ** No local results in project to process\n\n"
403-
print(localResultsError)
404-
return [-1] * 19
397+
if anyImportedResults:
398+
importedResultsError = " ** Cobertura results does not processing imported results at this time\n\n"
399+
print(importedResultsError)
400+
return [-1] * 19
401+
402+
if not anyLocalResults:
403+
localResultsError = " ** No local results in project to process\n\n"
404+
print(localResultsError)
405+
return [-1] * 19
405406

406-
api = vcproj.project.cover_api
407+
api = vcproj.project.cover_api
408+
409+
results = runCoberturaResults(packages, api, verbose = False, extended = extended, source_root = source_root)
407410

408-
return runCoberturaResults(packages, api, verbose = False, extended = extended, source_root = source_root)
411+
return results
409412

410413
def runCoberturaResults(packages, api, verbose = False, extended = False, source_root = ""):
411414

src/main/resources/scripts/copy_build_dir.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -237,9 +237,8 @@ def run(ManageProjectName, Level, BaseName, Env, workspace, vCastProjectWorkspac
237237

238238
def getVcastProjectWorkspace(args):
239239

240-
vc_api = VCProjectApi(args.ManageProject)
241-
vCastProjectWorkspace = vc_api.project.workspace
242-
vc_api.close()
240+
with VCProjectApi(args.ManageProject) as vcproj:
241+
vCastProjectWorkspace = vcproj.project.workspace
243242

244243
return vCastProjectWorkspace
245244

src/main/resources/scripts/create_index_html.py

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -104,26 +104,24 @@ def create_index_html(mpName, isGitLab = False, output_dir = ""):
104104
global baseOutputDir
105105
baseOutputDir = output_dir
106106

107-
api = VCProjectApi(mpName)
108-
# Set custom report directory to the where this script was
109-
# found. Must contain sections/index_section.py
110-
rep_path = pathlib.Path(__file__).parent.resolve()
107+
with VCProjectApi(mpName) as vcproj:
108+
# Set custom report directory to the where this script was
109+
# found. Must contain sections/index_section.py
110+
rep_path = pathlib.Path(__file__).parent.resolve()
111111

112-
if usingGitLabCI:
113-
output_file=os.path.join(baseOutputDir,"index.html")
114-
else:
115-
output_file=os.path.join(baseOutputDir,"index.html")
116-
117-
CustomReport.report_from_api(
118-
api=api,
119-
title="HTML Reports",
120-
report_type="INDEX_FILE",
121-
formats=["HTML"],
122-
output_file=output_file,
123-
sections=['CUSTOM_HEADER', 'REPORT_TITLE', 'TABLE_OF_CONTENTS','INDEX_SECTION', 'CUSTOM_FOOTER'],
124-
customization_dir=rep_path)
125-
126-
api.close()
112+
if usingGitLabCI:
113+
output_file=os.path.join(baseOutputDir,"index.html")
114+
else:
115+
output_file=os.path.join(baseOutputDir,"index.html")
116+
117+
CustomReport.report_from_api(
118+
api=vcproj,
119+
title="HTML Reports",
120+
report_type="INDEX_FILE",
121+
formats=["HTML"],
122+
output_file=output_file,
123+
sections=['CUSTOM_HEADER', 'REPORT_TITLE', 'TABLE_OF_CONTENTS','INDEX_SECTION', 'CUSTOM_FOOTER'],
124+
customization_dir=rep_path)
127125

128126
def create_index_html_body ():
129127

src/main/resources/scripts/full_report_no_toc.py

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -36,23 +36,6 @@ def generate_full_status(manageProject):
3636
mpName = os.path.splitext(os.path.basename(manageProject))[0]
3737
full_report_name = mpName + "_full_report.html"
3838
metrics_report_name = mpName + "_metrics_report.html"
39-
40-
# try:
41-
# from vector.apps.DataAPI.vcproject_api import VCProjectApi
42-
# api = VCProjectApi(manageProject)
43-
44-
# api.report(report_type="MANAGE_STATUS_FULL_REPORT", formats=["HTML"], output_file=full_report_name , environments=api.Environment.all(), levels = [])
45-
# api.report(report_type="MANAGE_METRICS_REPORT" , formats=["HTML"], output_file=metrics_report_name, environments=api.Environment.all(), levels = [])
46-
47-
# shutil.copy(full_report_name,full_report_name + "_tmp")
48-
# fixup_reports.fixup_2020_reports(full_report_name + "_tmp")
49-
50-
# shutil.copy(metrics_report_name,metrics_report_name + "_tmp")
51-
# fixup_reports.fixup_2020_reports(metrics_report_name + "_tmp")
52-
53-
# api.close()
54-
55-
# except:
5639

5740
from managewait import ManageWait
5841

src/main/resources/scripts/generate-results.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -556,15 +556,13 @@ def buildReports(FullManageProjectName = None,
556556
print("Cleanup: " + str(time.time()))
557557
if useNewReport and not legacy:
558558
try:
559-
api = VCProjectApi(FullManageProjectName)
560-
tool_version = api.tool_version
561-
if tool_version.startswith("20"):
562-
use_manage_api = False
563-
else:
564-
use_manage_api = True
565-
api.close()
559+
with VCProjectApi(FullManageProjectName) as vcproj:
560+
tool_version = vcproj.tool_version
561+
if tool_version.startswith("20"):
562+
use_manage_api = False
563+
else:
564+
use_manage_api = True
566565
except:
567-
##teePrint.teePrint(" *INFO: Issue getting tool version from: " + FullManageProjectName)
568566
use_manage_api = False
569567

570568
if use_manage_api:

src/main/resources/scripts/generate_lcov.py

Lines changed: 16 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -39,85 +39,22 @@
3939
from pprint import pprint
4040
import subprocess
4141
import argparse
42-
import inspect
4342

4443
from vcast_utils import dump, checkVectorCASTVersion, getVectorCASTEncoding, checkProjectResults
4544
try:
4645
from safe_open import open
4746
except:
4847
pass
4948

50-
from vector.apps.DataAPI.coverdb import SourceFunction
51-
52-
orig_iter = SourceFunction.iterate_coverage # snapshot original method
53-
5449
try:
5550
import math
5651
INF = math.inf
5752
except Exception:
5853
INF = float("inf") # Py2-compatible
59-
6054
encFmt = getVectorCASTEncoding()
6155

6256
fileList = []
6357

64-
# specifically for 2022sp8 issue with start/end being None
65-
def _safe_iterate_coverage(self, **kwargs):
66-
67-
# Drop-in wrapper for SourceFile.iterate_coverage()
68-
# - Accepts any kwargs (future-proof)
69-
# - Provides sane defaults for start/end
70-
# - Adds encoding only if supported
71-
# - Filters kwargs to match the original method's signature (no TypeError)
72-
73-
74-
# Always present in VC versions
75-
kwargs.setdefault("aggregate", True)
76-
77-
# Pull caller/attributes (don't coerce yet)
78-
start = kwargs.get("start", getattr(self, "start_line", None))
79-
end = kwargs.get("end", getattr(self, "end_line", None))
80-
81-
# --- IMPORTANT: handle the "both missing" case FIRST ---
82-
if start is None and end is None:
83-
start = 0
84-
try:
85-
if getattr(self, "instrumented_files", None):
86-
end = os.path.getsize(self.instrumented_files[0].display_path)
87-
else:
88-
end = INF
89-
except Exception:
90-
end = INF
91-
92-
# Now handle single-None cases (keep legitimate 0)
93-
if start is None:
94-
start = 0
95-
if end is None:
96-
end = INF
97-
98-
kwargs["start"] = start
99-
kwargs["end"] = end
100-
101-
# Let caller override; otherwise provide encoding
102-
kwargs.setdefault("encoding", encFmt)
103-
104-
# Filter kwargs to what the current VectorCAST build supports
105-
try:
106-
sig = inspect.signature(orig_iter) # Py3
107-
valid = set(sig.parameters.keys())
108-
except Exception:
109-
spec = inspect.getargspec(orig_iter) # Py2
110-
valid = set(spec.args)
111-
112-
safe_kwargs = {k: v for k, v in kwargs.items() if k in valid}
113-
114-
for line in orig_iter(self, **safe_kwargs):
115-
yield line
116-
117-
def lcov_iterate_coverage(sf, **kwargs):
118-
# Your safe wrapper logic here
119-
return _safe_iterate_coverage(sf, **kwargs)
120-
12158
def getCoveredFunctionCount(source):
12259
if len(source.functions) == 0:
12360
return 0,0
@@ -205,23 +142,25 @@ def get_function_name_line_number(file_path, function, initial_guess):
205142

206143
def runCoverageResultsMP(mpFile, verbose = False, testName = "", source_root = ""):
207144

208-
vcproj = VCProjectApi(mpFile)
145+
with VCProjectApi(mpFile) as vcproj:
209146

210-
anyLocalResults, anyImportedResults = checkProjectResults(vcproj)
147+
anyLocalResults, anyImportedResults = checkProjectResults(vcproj)
211148

212-
if anyImportedResults:
213-
importedResultsError = " ** LCOV results does not processing imported results at this time\n\n"
214-
print(importedResultsError)
215-
return importedResultsError
216-
217-
if not anyLocalResults:
218-
localResultsError = " ** No local results in project to process\n\n"
219-
print(localResultsError)
220-
return localResultsError
149+
if anyImportedResults:
150+
importedResultsError = " ** LCOV results does not processing imported results at this time\n\n"
151+
print(importedResultsError)
152+
return importedResultsError
153+
154+
if not anyLocalResults:
155+
localResultsError = " ** No local results in project to process\n\n"
156+
print(localResultsError)
157+
return localResultsError
221158

222-
api = vcproj.project.cover_api
159+
api = vcproj.project.cover_api
160+
161+
results = runGcovResults(api, verbose = verbose, testName = vcproj.project.name, source_root=source_root)
223162

224-
return runGcovResults(api, verbose = verbose, testName = vcproj.project.name, source_root=source_root)
163+
return results
225164

226165
def runGcovResults(api, verbose = False, testName = "", source_root = "") :
227166

@@ -305,7 +244,7 @@ def runGcovResults(api, verbose = False, testName = "", source_root = "") :
305244

306245
lastLine = None
307246

308-
for line in lcov_iterate_coverage(func):
247+
for line in func.iterate_coverage():
309248
if has_any_coverage(line):
310249
lastLine = line
311250
LF += 1

src/main/resources/scripts/generate_pclp_reports.py

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -324,21 +324,19 @@ def generate_html_report(mpName, input_xml, output_html):
324324
if output_html is None:
325325
output_html = "pclp_findings.html"
326326

327-
api = VCProjectApi(mpName)
328-
329-
# Set custom report directory to the where this script was
330-
# found. Must contain sections/index_section.py
331-
rep_path = pathlib.Path(__file__).parent.resolve()
332-
CustomReport.report_from_api(
333-
api=api,
334-
title="PC-Lint Plus Results",
335-
report_type="INDEX_FILE",
336-
formats=["HTML"],
337-
output_file=output_html,
338-
sections=['CUSTOM_HEADER', 'REPORT_TITLE', 'TABLE_OF_CONTENTS','PCLP_SUMMARY_SECTION','PCLP_DETAILS_SECTION','PCLP_SOURCE_SECTION', 'CUSTOM_FOOTER'],
339-
customization_dir=rep_path)
340-
341-
api.close()
327+
with VCProjectApi(mpName) as vcproj:
328+
329+
# Set custom report directory to the where this script was
330+
# found. Must contain sections/index_section.py
331+
rep_path = pathlib.Path(__file__).parent.resolve()
332+
CustomReport.report_from_api(
333+
api=vcproj,
334+
title="PC-Lint Plus Results",
335+
report_type="INDEX_FILE",
336+
formats=["HTML"],
337+
output_file=output_html,
338+
sections=['CUSTOM_HEADER', 'REPORT_TITLE', 'TABLE_OF_CONTENTS','PCLP_SUMMARY_SECTION','PCLP_DETAILS_SECTION','PCLP_SOURCE_SECTION', 'CUSTOM_FOOTER'],
339+
customization_dir=rep_path)
342340

343341
def has_any_coverage(line):
344342

src/main/resources/scripts/generate_sonarqube_testresults.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,12 @@ def __init__(self, FullManageProjectName, verbose = False,
275275

276276
self.cleanupXmlDataDir()
277277

278+
def __del__(self):
279+
try:
280+
self.api.close()
281+
except:
282+
pass
283+
278284
def cleanupXmlDataDir(self):
279285
path=os.path.join(self.xml_data_dir,"sonarqube")
280286
import glob
@@ -296,11 +302,6 @@ def cleanupXmlDataDir(self):
296302
print(" *INFO: File System Error creating directory: " + path + ". Check console for environment build/execution errors")
297303
if print_exc: traceback.print_exc()
298304

299-
def __del__(self):
300-
try:
301-
self.api.close()
302-
except:
303-
pass
304305

305306
def generate_local_results(self, results, key):
306307
# get the level from the name

src/main/resources/scripts/generate_xml.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -690,7 +690,10 @@ def cleanupXmlDataDir(self):
690690
if print_exc: traceback.print_exc()
691691

692692
def __del__(self):
693-
self.api.close()
693+
try:
694+
self.api.close()
695+
except:
696+
pass
694697

695698
# GenerateManageXml
696699

0 commit comments

Comments
 (0)