def _get_json_data(self): try: if self.project_file == "-": file_name = "sys.stdin" return json.load(sys.stdin) else: file_name = self.project_file with open(self.project_file) as fp: return json.load(fp) except json.JSONDecodeError: raise FlictError(ReturnCodes.RET_INVALID_PROJECT, f'File "{file_name}" does not contain valid JSON data') except (FileNotFoundError, IsADirectoryError): raise FlictError(ReturnCodes.RET_FILE_NOT_FOUND, f'File "{file_name}" could not be found or is a directory')
def sanity(self, json_obj, requirements): logger.debug(f"Checking sanity of report {json_obj}") def exists(json_, chain): key = chain.pop( 0) # this empties list, hence reqscopy as list.copy() if key in json_: return exists(json_[key], chain) if chain else key return None expected = [req[-1] for req in requirements] reqscopy = [[it for it in line] for line in requirements] # noqa: C416 checked = [exists(json_obj, req) for req in requirements] on_failure = "Improper file format, missing key: '{expected}' in {path}" fail = False for i, _ in enumerate(expected): expected_it, pathway = expected[i], " -> ".join(reqscopy[i]) error = on_failure.format(expected=expected_it, path=pathway) try: if checked[i] != expected[i]: logger.error(error) fail = True except IndexError: logger.error(error) fail = True if fail: on_error = "Internal error, file is missing required keys" raise FlictError(ReturnCodes.RET_INTERNAL_ERROR, on_error)
def display_compatibility(self): try: # build up license string from all expressions lic_str = " ".join(self._args.license_expression) # encode (flict) all the license expression lic_str = encode_license_expression(lic_str) # build up license string from the expression string _licenses = [] for lic in lic_str.split(): lic_list = self._license_handler.translate_and_relicense( lic).replace("(", "").replace(")", "").replace(" ", "").replace( "OR", " ").replace("AND", " ").strip().split(" ") for lic in lic_list: _licenses.append(decode_license_expression(lic)) # Diry trick to remove all duplicates licenses = list(set(_licenses)) compats = self._compatibility.check_compatibilities( licenses, self._args.extended_licenses) except: raise FlictError( ReturnCodes.RET_INVALID_EXPRESSSION, f'Could not parse license expression: {self._args.license_expression}' ) return self._formatter.format_compats(compats)
def _read_compliance_report(self, report_file): on_error = "Internal error, report file has improper format, required: JSON" try: with open(report_file) as file_: return json.load(file_) except json.decoder.JSONDecodeError: raise FlictError(ReturnCodes.RET_INTERNAL_ERROR, on_error)
def verify(self): if self._args.project_file: return self._verify_project_file() elif self._args.license_expression: return self._verify_license_expression() else: raise FlictError(ReturnCodes.RET_MISSING_ARGS, "Missing argument to the verify command")
def __init__(self, policy_file): self.policy_report = {} self.policy_report['meta'] = self.meta() self.policy_report['policy_file'] = policy_file try: with open(policy_file) as file_: self.policy_report['policy'] = json.load(file_) except json.decoder.JSONDecodeError: error = "Internal error, policy file has improper JSON format" raise FlictError(ReturnCodes.RET_INTERNAL_ERROR, error)
def _verify_license_expression(self): lic_str = " ".join(self._args.license_expression) try: report = self._empty_project_report(lic_str) candidates = report.outbound_candidates() return self._formatter.format_verified_license(lic_str, candidates) except: raise FlictError( ReturnCodes.RET_INVALID_EXPRESSSION, f'Could not parse expression "{self._args.license_expression}"' )
def simplify(self): lic_str = " ".join(self._args.license_expression) try: license = self._license_handler.license_expression_list(lic_str) return self._formatter.format_simplified(lic_str, license.simplified) except: raise FlictError( ReturnCodes.RET_INVALID_EXPRESSSION, f'Invalid expression to simplify: {self._args.license_expression}' )
def suggest_outbound_candidate(self): lic_str = " ".join(self._args.license_expression) try: _report = self._empty_project_report(lic_str) _outbound_candidates = _report.outbound_candidates() return self._formatter.format_outbound_license( _outbound_candidates) except: raise FlictError( ReturnCodes.RET_INVALID_EXPRESSSION, f'Invalid license expression: {self._args.license_expression}')
def _manage_list_item_or(self, license_list, lep): if isinstance(lep, LicenseExpressionList): raise FlictError(ReturnCodes.RET_INTERNAL_ERROR, f"Internal failure. Wrong type {lep} for: {lep}") # single license if len(license_list) == 0: return lep new_list = license_list for lep_item in lep: new_list.append(lep_item) return new_list
def _combinations(self, lel): if not isinstance(lel, LicenseExpressionList): return 1 if lel.op == "AND": prod = 1 for item in lel.list: prod = prod * self._combinations(item) return prod elif lel.op == "OR": sum = 0 for item in lel.list: sum = sum + self._combinations(item) return sum else: FlictError(ReturnCodes.RET_INTERNAL_ERROR, f"Internal failure. Failed identifying operator: {lel}")
def _verify_project_file(self): try: project = Project(self._args.project_file, self._license_handler) except FlictError as e: raise (e) except: raise FlictError(ReturnCodes.RET_INVALID_PROJECT) if self._args.list_project_licenses: return self._formatter.format_license_list( list(project.license_set())) elif self._args.license_combination_count: return self._formatter.format_license_combinations(project) else: report = Report(project, self._compatibility) return self._formatter.format_report(report)
def interim_license_expression_set_list(self, interim_license_expression_list): """ Transforms a boolean symbolic expression Turns an expression like this: AND [G, OR [A, B]] into: [ { G, A }, { G, B } ] The latter is an interim format. """ expanded_list = [] if not isinstance(interim_license_expression_list, LicenseExpressionList): # single license license_set = {decode_license_expression(interim_license_expression_list)} expanded_list.append(list(license_set)) return expanded_list current_op = interim_license_expression_list.op for lep in interim_license_expression_list.list: if current_op is None: raise FlictError(ReturnCodes.RET_INTERNAL_ERROR, "Internal failure. No operator found") lep_list = self.interim_license_expression_set_list(lep) if current_op == "OR": expanded_list = self._manage_list_item_or( expanded_list, lep_list) elif current_op == "AND": expanded_list = self._manage_list_item_and( expanded_list, lep_list) return expanded_list
def interim_license_expression_list(self, license_expression, licensing): """ Transforms and boolean symbolic expression Turns an expression like this: G AND (A OR B) into: AND [G, OR [A, B]] The latter is an interim format. """ encoded = encode_license_expression(license_expression) tokenizer = licensing.get_advanced_tokenizer() tokenized = tokenizer.tokenize(encoded) current_license = None current_licenses = [] current_op = None paren_expr = None paren_count = 0 for token in tokenized: tok = token.string if tok == '(': if paren_expr is None: paren_expr = "" else: paren_expr = paren_expr + " " + tok paren_count = paren_count + 1 elif tok == ')': if paren_count == 0: current_license = self.interim_license_expression_list( paren_expr, licensing) paren_expr = None else: paren_count = paren_count - 1 paren_expr = paren_expr + " " + tok elif tok == 'OR' or tok == 'AND': if paren_expr is not None: paren_expr = paren_expr + " " + tok else: if current_licenses is None: raise FlictError(ReturnCodes.RET_INTERNAL_ERROR, "Internal failure. Failed creating interim license expression. current_licenses is None") if current_op is None: # first operator current_op = tok current_licenses.append(current_license) elif current_op == tok: # same operator current_licenses.append(current_license) else: # different operator raise FlictError(ReturnCodes.RET_INTERNAL_ERROR, "Internal failure. Failed creating interim license expression.") else: if paren_expr is not None: paren_expr = paren_expr + " " + tok else: current_license = tok current_licenses.append(current_license) if current_op is None: current_op = "AND" list = LicenseExpressionList(current_op, current_licenses) return list