scanoss 1.19.2__py3-none-any.whl → 1.19.4__py3-none-any.whl

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.
scanoss/__init__.py CHANGED
@@ -22,4 +22,4 @@
22
22
  THE SOFTWARE.
23
23
  """
24
24
 
25
- __version__ = "1.19.2"
25
+ __version__ = "1.19.4"
scanoss/cli.py CHANGED
@@ -334,7 +334,7 @@ def setup_args() -> None:
334
334
 
335
335
  for p in [p_copyleft, p_undeclared]:
336
336
  p.add_argument('-i', '--input', nargs='?', help='Path to results file')
337
- p.add_argument('-f', '--format',required=False ,choices=['json', 'md'], default='json', help='Output format (default: json)')
337
+ p.add_argument('-f', '--format',required=False ,choices=['json', 'md', 'jira_md'], default='json', help='Output format (default: json)')
338
338
  p.add_argument('-o', '--output', type=str, help='Save details into a file')
339
339
  p.add_argument('-s', '--status', type=str, help='Save summary data into Markdown file')
340
340
 
@@ -1 +1 @@
1
- date: 20250106152810, utime: 1736177290
1
+ date: 20250108144949, utime: 1736347789
@@ -58,6 +58,7 @@ class Copyleft(PolicyCheck):
58
58
  self.exclude = exclude
59
59
  self.explicit = explicit
60
60
 
61
+
61
62
  def _json(self, components: list) -> Dict[str, Any]:
62
63
  """
63
64
  Format the components with copyleft licenses as JSON.
@@ -100,6 +101,33 @@ class Copyleft(PolicyCheck):
100
101
  'summary' : f'{len(components)} component(s) with copyleft licenses were found.\n'
101
102
  }
102
103
 
104
+ def _jira_markdown(self, components: list) -> Dict[str,Any]:
105
+ """
106
+ Format the components with copyleft licenses as Markdown.
107
+
108
+ :param components: List of components with copyleft licenses
109
+ :return: Dictionary with formatted Markdown details and summary
110
+ """
111
+ headers = ['Component', 'Version', 'License', 'URL', 'Copyleft']
112
+ centered_columns = [1, 4]
113
+ rows: [[]]= []
114
+ for component in components:
115
+ for lic in component['licenses']:
116
+ row = [
117
+ component['purl'],
118
+ component['version'],
119
+ lic['spdxid'],
120
+ lic['url'],
121
+ 'YES' if lic['copyleft'] else 'NO'
122
+ ]
123
+ rows.append(row)
124
+ # End license loop
125
+ # End component loop
126
+ return {
127
+ 'details': f'{self.generate_jira_table(headers,rows,centered_columns)}',
128
+ 'summary' : f'{len(components)} component(s) with copyleft licenses were found.\n'
129
+ }
130
+
103
131
  def _filter_components_with_copyleft_licenses(self, components: list) -> list:
104
132
  """
105
133
  Filter the components list to include only those with copyleft licenses.
@@ -76,7 +76,7 @@ class PolicyCheck(ScanossBase):
76
76
  ScanossBase: A base class providing common functionality for SCANOSS-related operations.
77
77
  """
78
78
 
79
- VALID_FORMATS = {'md', 'json'}
79
+ VALID_FORMATS = {'md', 'json', 'jira_md'}
80
80
 
81
81
  def __init__(self, debug: bool = False, trace: bool = True, quiet: bool = False, filepath: str = None,
82
82
  format_type: str = None, status: str = None, output: str = None, name: str = None):
@@ -134,6 +134,19 @@ class PolicyCheck(ScanossBase):
134
134
  """
135
135
  pass
136
136
 
137
+ @abstractmethod
138
+ def _jira_markdown(self, components: list) -> Dict[str, Any]:
139
+ """
140
+ Generate Markdown output for the policy check results.
141
+
142
+ This method should be implemented by subclasses to create a Markdown representation
143
+ of the policy check results.
144
+
145
+ :param components: List of components to be included in the output.
146
+ :return: A dictionary representing the Markdown output.
147
+ """
148
+ pass
149
+
137
150
  def _append_component(self,components: Dict[str, Any], new_component: Dict[str, Any],
138
151
  id: str, status: str) -> Dict[str, Any]:
139
152
  """
@@ -270,6 +283,20 @@ class PolicyCheck(ScanossBase):
270
283
  table_rows.extend(col_sep + col_sep.join(row) + col_sep for row in rows)
271
284
  return '\n'.join(table_rows)
272
285
 
286
+ def generate_jira_table(self, headers, rows, centered_columns=None):
287
+ col_sep = '*|*'
288
+ if headers is None:
289
+ self.print_stderr('ERROR: Header are no set')
290
+ return None
291
+
292
+ table_header = '|*' + col_sep.join(headers) + '*|\n'
293
+ table = table_header
294
+ for row in rows:
295
+ if len(headers) == len(row):
296
+ table += '|' + '|'.join(row) + '|\n'
297
+
298
+ return table
299
+
273
300
  def _get_formatter(self)-> Callable[[List[dict]], Dict[str,Any]] or None:
274
301
  """
275
302
  Get the appropriate formatter function based on the specified format.
@@ -282,7 +309,8 @@ class PolicyCheck(ScanossBase):
282
309
  # a map of which format function to return
283
310
  function_map = {
284
311
  'json': self._json,
285
- 'md': self._markdown
312
+ 'md': self._markdown,
313
+ 'jira_md': self._jira_markdown,
286
314
  }
287
315
  return function_map[self.format_type]
288
316
 
@@ -71,6 +71,26 @@ class UndeclaredComponent(PolicyCheck):
71
71
  # end component loop
72
72
  return undeclared_components
73
73
 
74
+ def _get_jira_summary(self, components: list) -> str:
75
+ """
76
+ Get a summary of the undeclared components.
77
+
78
+ :param components: List of all components
79
+ :return: Component summary markdown
80
+ """
81
+ if len(components) > 0:
82
+ if self.sbom_format == 'settings':
83
+ json_str = (json.dumps(self._generate_scanoss_file(components), indent=2).replace('\n', '\\n')
84
+ .replace('"', '\\"'))
85
+ return f'{len(components)} undeclared component(s) were found.\nAdd the following snippet into your `scanoss.json` file\n{{code:json}}\n{json.dumps(self._generate_scanoss_file(components), indent=2)}\n{{code}}\n'
86
+ else:
87
+ json_str = (json.dumps(self._generate_scanoss_file(components), indent=2).replace('\n', '\\n')
88
+ .replace('"', '\\"'))
89
+ return f'{len(components)} undeclared component(s) were found.\nAdd the following snippet into your `sbom.json` file\n{{code:json}}\n{json.dumps(self._generate_scanoss_file(components), indent=2)}\n{{code}}\n'
90
+
91
+ return f'{len(components)} undeclared component(s) were found.\\n'
92
+
93
+
74
94
  def _get_summary(self, components: list) -> str:
75
95
  """
76
96
  Get a summary of the undeclared components.
@@ -122,6 +142,24 @@ class UndeclaredComponent(PolicyCheck):
122
142
  'summary': self._get_summary(components),
123
143
  }
124
144
 
145
+ def _jira_markdown(self, components: list) -> Dict[str,Any]:
146
+ """
147
+ Format the undeclared components as Markdown.
148
+
149
+ :param components: List of undeclared components
150
+ :return: Dictionary with formatted Markdown details and summary
151
+ """
152
+ headers = ['Component', 'Version', 'License']
153
+ rows: [[]]= []
154
+ # TODO look at using SpdxLite license name lookup method
155
+ for component in components:
156
+ licenses = " - ".join(lic.get('spdxid', 'Unknown') for lic in component['licenses'])
157
+ rows.append([component['purl'], component['version'], licenses])
158
+ return {
159
+ 'details': f'{self.generate_jira_table(headers,rows)}',
160
+ 'summary': self._get_jira_summary(components),
161
+ }
162
+
125
163
  def _get_unique_components(self, components: list) -> list:
126
164
  """
127
165
  Generate a list of unique components.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: scanoss
3
- Version: 1.19.2
3
+ Version: 1.19.4
4
4
  Summary: Simple Python library to leverage the SCANOSS APIs
5
5
  Home-page: https://scanoss.com
6
6
  Author: SCANOSS
@@ -4,8 +4,8 @@ protoc_gen_swagger/options/annotations_pb2.py,sha256=b25EDD6gssUWnFby9gxgcpLIROT
4
4
  protoc_gen_swagger/options/annotations_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
5
5
  protoc_gen_swagger/options/openapiv2_pb2.py,sha256=vYElGp8E1vGHszvWqX97zNG9GFJ7u2QcdK9ouq0XdyI,14939
6
6
  protoc_gen_swagger/options/openapiv2_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
7
- scanoss/__init__.py,sha256=LFxlOiEE6o2gMJ8Ense9Lo40AszUfC5GnL9PSe6VDhQ,1163
8
- scanoss/cli.py,sha256=8uvO6VFDqGTw4ZLySr0xhS9KTm-gdwq9K3mYv_LdxW8,51498
7
+ scanoss/__init__.py,sha256=lzQZL-XMupclTvPVGCfZB-UAGfik20RjvISPAt1i9Fo,1163
8
+ scanoss/cli.py,sha256=eJB6s1DVKJd3FPO7wVea8ggeAfua_-7CC8I10uSmdDc,51509
9
9
  scanoss/components.py,sha256=ZHZ1KA69shxOASZK7USD9yPTITpAc_RXL5q5zpDK23o,12590
10
10
  scanoss/csvoutput.py,sha256=hBwr_Fc6mBdOdXgyQcdFrockYH-PJ0jblowlExJ6OPg,9925
11
11
  scanoss/cyclonedx.py,sha256=ZbFNinMz_R68ko4-ZPo2w4bBORpASh271VCmYYRTUCg,12746
@@ -51,20 +51,20 @@ scanoss/api/vulnerabilities/__init__.py,sha256=FLQtiDiv85Q1Chk-sJ9ky9WOV1mulZhEK
51
51
  scanoss/api/vulnerabilities/v2/__init__.py,sha256=FLQtiDiv85Q1Chk-sJ9ky9WOV1mulZhEKjiBihlwiaM,1139
52
52
  scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2.py,sha256=CFhF80av8tenGvn9AIsGEtRJPuV2dC_syA5JLZb2lDw,5464
53
53
  scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2_grpc.py,sha256=HlS4k4Zmx6RIAqaO9I96jD-eyF5yU6Xx04pVm7pdqOg,6864
54
- scanoss/data/build_date.txt,sha256=k__FF_aFKkdz2X5QYLvhJbr2RTp-ZKpxxX0zfOi1D3g,40
54
+ scanoss/data/build_date.txt,sha256=I2tiS4Cw-x-eVSPBx4mOEQefstESmGedPYeWtb6B5W4,40
55
55
  scanoss/data/scanoss-settings-schema.json,sha256=ClkRYAkjAN0Sk704G8BE_Ok006oQ6YnIGmX84CF8h9w,8798
56
56
  scanoss/data/spdx-exceptions.json,sha256=s7UTYxC7jqQXr11YBlIWYCNwN6lRDFTR33Y8rpN_dA4,17953
57
57
  scanoss/data/spdx-licenses.json,sha256=A6Z0q82gaTLtnopBfzeIVZjJFxkdRW1g2TuumQc-lII,228794
58
58
  scanoss/inspection/__init__.py,sha256=z62680zKq4OmBOugSODvgpSwdsloZL7bvcaMbnx3xgU,1139
59
- scanoss/inspection/copyleft.py,sha256=dkiLkgNYz7cbIQZCzy6zThiIyHkqrper_xruZ9PQhAI,6563
60
- scanoss/inspection/policy_check.py,sha256=eo5VfEBwKoDSqIwRi0xwaVLy6EUR29HlH5Bl0Kpvx7I,14752
61
- scanoss/inspection/undeclared_component.py,sha256=HArm5xTxxpBBxbMggVYBy6zKEwcxsPYhHEJGawlm5bQ,7952
59
+ scanoss/inspection/copyleft.py,sha256=e6CQXL7G3kUwet4gNqMfGsi1XvLAS71OLDeoRuK2WGY,7621
60
+ scanoss/inspection/policy_check.py,sha256=mbtNwDydf2aBUCz9n2yNG6DV6rc7HH_ZaQuK2CSDBHw,15706
61
+ scanoss/inspection/undeclared_component.py,sha256=QvlBgYpytQhaWlVqrz3p8JPIGbsX8v8U59n-4Q2llLc,9951
62
62
  scanoss/inspection/utils/license_utils.py,sha256=mIaoVWXMA6shkRQmgmiP2mWchjxX4ex8LWs91Nf6rq4,5093
63
63
  scanoss/utils/__init__.py,sha256=0hjb5ktavp7utJzFhGMPImPaZiHWgilM2HwvTp5lXJE,1122
64
64
  scanoss/utils/file.py,sha256=W-XFLgaTM_td31Y5rzd5DimO4_qXafQhBtKtY_p3JIQ,2184
65
- scanoss-1.19.2.dist-info/LICENSE,sha256=LLUaXoiyOroIbr5ubAyrxBOwSRLTm35ETO2FmLpy8QQ,1074
66
- scanoss-1.19.2.dist-info/METADATA,sha256=K3b-9aVszTUmdEO5Dq7liPxe3jBw4Z_ub9f_NY4zgaQ,6019
67
- scanoss-1.19.2.dist-info/WHEEL,sha256=A3WOREP4zgxI0fKrHUG8DC8013e3dK3n7a6HDbcEIwE,91
68
- scanoss-1.19.2.dist-info/entry_points.txt,sha256=Uy28xnaDL5KQ7V77sZD5VLDXPNxYYzSr5tsqtiXVzAs,48
69
- scanoss-1.19.2.dist-info/top_level.txt,sha256=V11PrQ6Pnrc-nDF9xnisnJ8e6-i7HqSIKVNqduRWcL8,27
70
- scanoss-1.19.2.dist-info/RECORD,,
65
+ scanoss-1.19.4.dist-info/LICENSE,sha256=LLUaXoiyOroIbr5ubAyrxBOwSRLTm35ETO2FmLpy8QQ,1074
66
+ scanoss-1.19.4.dist-info/METADATA,sha256=aodKN8xCOP_yUP5w9Ey4SCrIoXVAIBDjbVBk-xZcNl0,6019
67
+ scanoss-1.19.4.dist-info/WHEEL,sha256=A3WOREP4zgxI0fKrHUG8DC8013e3dK3n7a6HDbcEIwE,91
68
+ scanoss-1.19.4.dist-info/entry_points.txt,sha256=Uy28xnaDL5KQ7V77sZD5VLDXPNxYYzSr5tsqtiXVzAs,48
69
+ scanoss-1.19.4.dist-info/top_level.txt,sha256=V11PrQ6Pnrc-nDF9xnisnJ8e6-i7HqSIKVNqduRWcL8,27
70
+ scanoss-1.19.4.dist-info/RECORD,,