|
39 | 39 | from copy import deepcopy |
40 | 40 | from functools import total_ordering |
41 | 41 | import itertools |
| 42 | +import json |
42 | 43 | import re |
43 | 44 | import string |
44 | 45 |
|
@@ -599,6 +600,102 @@ def simple_tokenizer(self, expression): |
599 | 600 | sym = LicenseSymbol(key=sym_or_op) |
600 | 601 | yield Token(start, end, sym_or_op, sym) |
601 | 602 |
|
| 603 | + def validate(self, expression, strict=False, simple=False, **kwargs): |
| 604 | + data = { |
| 605 | + 'normalized_license_expression': '', |
| 606 | + 'errors': [], |
| 607 | + 'valid_symbols': [], |
| 608 | + 'invalid_symbols': [], |
| 609 | + 'exception_symbols': [], |
| 610 | + } |
| 611 | + |
| 612 | + if expression is None: |
| 613 | + return data |
| 614 | + |
| 615 | + if isinstance(expression, LicenseExpression): |
| 616 | + data['normalized_license_expression'] = expression.render() |
| 617 | + return data |
| 618 | + |
| 619 | + if isinstance(expression, bytes): |
| 620 | + try: |
| 621 | + expression = str(expression) |
| 622 | + except: |
| 623 | + ext = type(expression) |
| 624 | + data['errors'].append('expression must be a string and not: %(ext)r' % locals()) |
| 625 | + return data |
| 626 | + |
| 627 | + if not isinstance(expression, str): |
| 628 | + ext = type(expression) |
| 629 | + data['errors'].append('expression must be a string and not: %(ext)r' % locals()) |
| 630 | + return data |
| 631 | + |
| 632 | + if not expression or not expression.strip(): |
| 633 | + return |
| 634 | + try: |
| 635 | + # this will raise a ParseError on errors |
| 636 | + tokens = list(self.tokenize(expression, strict=strict, simple=simple)) |
| 637 | + expression = super(Licensing, self).parse(tokens) |
| 638 | + except ParseError as e: |
| 639 | + new_error = ExpressionParseError( |
| 640 | + token_type=e.token_type, token_string=e.token_string, |
| 641 | + position=e.position, error_code=e.error_code) |
| 642 | + data['errors'].append(str(new_error)) |
| 643 | + data['invalid_symbols'].append(e.token_string) |
| 644 | + return data |
| 645 | + |
| 646 | + if not isinstance(expression, LicenseExpression): |
| 647 | + data['errors'].append('expression must be a LicenseExpression once parsed.') |
| 648 | + return data |
| 649 | + |
| 650 | + unknown_keys = self.unknown_license_keys(expression, unique=True) |
| 651 | + if unknown_keys: |
| 652 | + msg = 'Unknown license key(s): {}'.format(', '.join(unknown_keys)) |
| 653 | + data['errors'].append(msg) |
| 654 | + data['invalid_symbols'].extend(unknown_keys) |
| 655 | + return data |
| 656 | + |
| 657 | + symbols = list(expression.symbols) |
| 658 | + data['normalized_license_expression'] = expression.render() |
| 659 | + data['valid_symbols'] = [s.render() for s in symbols] |
| 660 | + data['exception_symbols'] = [s.render() for s in symbols if isinstance(s, LicenseWithExceptionSymbol) or s.is_exception] |
| 661 | + return data |
| 662 | + |
| 663 | + |
| 664 | +def build_spdx_licensing(index_json_location=None): |
| 665 | + # if no index_json, use vendored version |
| 666 | + # TODO: vendor index.json |
| 667 | + |
| 668 | + if index_json_location: |
| 669 | + with open(index_json_location, 'r') as f: |
| 670 | + license_info = json.load(f) |
| 671 | + else: |
| 672 | + with open(vendored_index_json_location, 'r') as f: |
| 673 | + license_info = json.load(f) |
| 674 | + |
| 675 | + lics = [ |
| 676 | + { |
| 677 | + 'key': l.get('spdx_license_key', ''), |
| 678 | + 'aliases': l.get('other_spdx_license_keys', ''), |
| 679 | + 'is_exception': l.get('is_exception', ''), |
| 680 | + } for l in license_info |
| 681 | + ] |
| 682 | + syms = [LicenseSymbol(**l) for l in lics] |
| 683 | + return Licensing(syms) |
| 684 | + |
| 685 | + |
| 686 | +def build_spdx_licensing_scancode(): |
| 687 | + from licensedcode.cache import get_licenses_db |
| 688 | + ld = get_licenses_db() |
| 689 | + ld_spdx = [ |
| 690 | + { |
| 691 | + 'key': l.spdx_license_key, |
| 692 | + 'aliases': l.other_spdx_license_keys, |
| 693 | + 'is_exception': l.is_exception |
| 694 | + } for _, l in ld.items() |
| 695 | + ] |
| 696 | + syms = [LicenseSymbol(**l) for l in ld_spdx] |
| 697 | + return Licensing(syms) |
| 698 | + |
602 | 699 |
|
603 | 700 | def build_symbols_from_unknown_tokens(tokens): |
604 | 701 | """ |
|
0 commit comments