diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c135ee9..e95a76c 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,13 @@ Changelog ========= +v30.3.1 - 2024-08-13 +-------------------- + +This is a minor release without API changes: + +- Update link references of ownership from nexB to aboutcode-org + v30.3.0 - 2024-03-18 -------------------- diff --git a/NOTICE b/NOTICE index 82ebf8b..fa82b0b 100644 --- a/NOTICE +++ b/NOTICE @@ -1,19 +1,37 @@ # + # Copyright (c) nexB Inc. and others. + # SPDX-License-Identifier: Apache-2.0 + # -# Visit https://aboutcode.org and https://github.com/nexB/license-expression + +# Visit https://aboutcode.org and https://github.com/aboutcode-org/license-expression + # for support and download. + # + # Licensed under the Apache License, Version 2.0 (the "License"); + # you may not use this file except in compliance with the License. + # You may obtain a copy of the License at + # -# http://www.apache.org/licenses/LICENSE-2.0 + +# http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. + # diff --git a/README.rst b/README.rst index 0d672ce..6450f43 100644 --- a/README.rst +++ b/README.rst @@ -8,7 +8,7 @@ using boolean logic. - License: Apache-2.0 - Python: 3.8+ -- Homepage: https://github.com/nexB/license-expression/ +- Homepage: https://github.com/aboutcode-org/license-expression/ - Install: `pip install license-expression` also available in most Linux distro. Software project licenses are often a combination of several free and open @@ -32,20 +32,20 @@ See https://scancode-licensedb.aboutcode.org/ to get started quickly. ``license-expression`` is both powerful and simple to use and is a used as the license expression engine in several projects and products such as: -- AboutCode-toolkit https://github.com/nexB/aboutcode-toolkit +- AboutCode-toolkit https://github.com/aboutcode-org/aboutcode-toolkit - AlekSIS (School Information System) https://edugit.org/AlekSIS/official/AlekSIS-Core - Barista https://github.com/Optum/barista - Conda forge tools https://github.com/conda-forge/conda-smithy - DejaCode https://dejacode.com - DeltaCode https://github.com/nexB/deltacode - FenixscanX https://github.com/SmartsYoung/FenixscanX -- FetchCode https://github.com/nexB/fetchcode +- FetchCode https://github.com/aboutcode-org/fetchcode - Flict https://github.com/vinland-technology/flict and https://github.com/vinland-technology - license.sh https://github.com/webscopeio/license.sh - liferay_inbound_checker https://github.com/carmenbianca/liferay_inbound_checker - REUSE https://reuse.software/ and https://github.com/fsfe/reuse-tool -- ScanCode-io https://github.com/nexB/scancode.io -- ScanCode-toolkit https://github.com/nexB/scancode-toolkit +- ScanCode-io https://github.com/aboutcode-org/scancode.io +- ScanCode-toolkit https://github.com/aboutcode-org/scancode-toolkit See also for details: - https://spdx.github.io/spdx-spec/appendix-IV-SPDX-license-expressions/ @@ -78,7 +78,7 @@ Build and tests status Source code and download ======================== -- GitHub https://github.com/nexB/license-expression.git +- GitHub https://github.com/aboutcode-org/license-expression.git - PyPI https://pypi.python.org/pypi/license-expression Also available in several Linux distros: @@ -95,7 +95,7 @@ Also available in several Linux distros: Support ======= -- Submit bugs and questions at: https://github.com/nexB/license-expression/issues +- Submit bugs and questions at: https://github.com/aboutcode-org/license-expression/issues - Join the chat at: https://gitter.im/aboutcode-org/discuss Description @@ -233,7 +233,7 @@ Two expressions can be compared for equivalence and containment: Development =========== -- Checkout a clone from https://github.com/nexB/license-expression.git +- Checkout a clone from https://github.com/aboutcode-org/license-expression.git - Then run ``./configure --dev`` and then ``source tmp/bin/activate`` on Linux and POSIX. This will install all dependencies in a local virtualenv, including diff --git a/license-expression.ABOUT b/license-expression.ABOUT index 07ab9f1..665d2ca 100644 --- a/license-expression.ABOUT +++ b/license-expression.ABOUT @@ -6,4 +6,4 @@ copyright: Copyright (c) nexB Inc. and others. license_expression: apache-2.0 license_file: apache-2.0.LICENSE -homepage_url: https://github.com/nexB/license-expression +homepage_url: https://github.com/aboutcode-org/license-expression diff --git a/setup.cfg b/setup.cfg index 5daaa70..b51088e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,13 +1,13 @@ [metadata] name = license-expression -version = 30.3.0 +version = 30.3.1 license = Apache-2.0 # description must be on ONE line https://github.com/pypa/setuptools/issues/1390 description = license-expression is a comprehensive utility library to parse, compare, simplify and normalize license expressions (such as SPDX license expressions) using boolean logic. long_description = file:README.rst long_description_content_type = text/x-rst -url = https://github.com/nexB/license-expression +url = https://github.com/aboutcode-org/license-expression author = nexB. Inc. and others author_email = info@aboutcode.org @@ -20,7 +20,7 @@ classifiers = Topic :: Software Development Topic :: Utilities -keywords = +keywords = open source license expression license diff --git a/src/license_expression/__init__.py b/src/license_expression/__init__.py index 9f6bd30..57acb84 100644 --- a/src/license_expression/__init__.py +++ b/src/license_expression/__init__.py @@ -2,7 +2,7 @@ # Copyright (c) nexB Inc. and others. All rights reserved. # SPDX-License-Identifier: Apache-2.0 # See http://www.apache.org/licenses/LICENSE-2.0 for the license text. -# See https://github.com/nexB/license-expression for support or download. +# See https://github.com/aboutcode-org/license-expression for support or download. # See https://aboutcode.org for more information about nexB OSS projects. # """ diff --git a/src/license_expression/_pyahocorasick.py b/src/license_expression/_pyahocorasick.py index ddf4f88..9810fe2 100644 --- a/src/license_expression/_pyahocorasick.py +++ b/src/license_expression/_pyahocorasick.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # # SPDX-License-Identifier: LicenseRef-scancode-public-domain -# See https://github.com/nexB/license-expression for support or download. +# See https://github.com/aboutcode-org/license-expression for support or download. # See https://aboutcode.org for more information about nexB OSS projects. # """ @@ -343,10 +343,12 @@ def iter(self, tokens_string, include_unmatched=False, include_space=False): if match.output is not nil: matched_string, output_value = match.output if TRACE: - logger_debug(' type output', repr(output_value), type(matched_string)) + logger_debug(' type output', repr( + output_value), type(matched_string)) n = len(matched_string) start_pos = end_pos - n + 1 - if TRACE: logger_debug(' start_pos', start_pos) + if TRACE: + logger_debug(' start_pos', start_pos) yield Token(start_pos, end_pos, tokens_string[start_pos: end_pos + 1], output_value) yielded = True match = match.fail @@ -355,7 +357,8 @@ def iter(self, tokens_string, include_unmatched=False, include_space=False): logger_debug(' unmatched but known token') n = len(token_string) start_pos = end_pos - n + 1 - tok = Token(start_pos, end_pos, tokens_string[start_pos: end_pos + 1], None) + tok = Token(start_pos, end_pos, + tokens_string[start_pos: end_pos + 1], None) if TRACE: logger_debug(' unmatched tok 2:', tok) yield tok @@ -406,7 +409,7 @@ def tokenize(self, string, include_unmatched=True, include_space=False): True """ tokens = self.iter(string, - include_unmatched=include_unmatched, include_space=include_space) + include_unmatched=include_unmatched, include_space=include_space) tokens = list(tokens) if TRACE: logger_debug('tokenize.tokens:', tokens) @@ -544,7 +547,7 @@ def sort(cls, tokens): >>> expected == Token.sort(tokens) True """ - key = lambda s: (s.start, -len(s),) + def key(s): return (s.start, -len(s),) return sorted(tokens, key=key) def is_after(self, other): @@ -613,8 +616,8 @@ def overlap(self, other): | (?P[\(\)]) ''', - re.VERBOSE | re.MULTILINE | re.UNICODE -) + re.VERBOSE | re.MULTILINE | re.UNICODE + ) def get_tokens(tokens_string): diff --git a/tests/test__pyahocorasick.py b/tests/test__pyahocorasick.py index a18c21b..cccf43b 100644 --- a/tests/test__pyahocorasick.py +++ b/tests/test__pyahocorasick.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # # SPDX-License-Identifier: LicenseRef-scancode-public-domain -# See https://github.com/nexB/license-expression for support or download. +# See https://github.com/aboutcode-org/license-expression for support or download. # See https://aboutcode.org for more information about nexB OSS projects. """ @@ -158,7 +158,8 @@ def get_test_automaton(): # 0123456789012345678901234567890123456 t = get_test_automaton() - result = list(t.iter(test_string, include_unmatched=True, include_space=True)) + result = list( + t.iter(test_string, include_unmatched=True, include_space=True)) expected = [ Token(0, 1, u' ', None), Token(2, 3, u'he', u'he'), @@ -190,7 +191,8 @@ def get_test_automaton(): test_string = '((l-a + AND l-b) OR (l -c+))' t = get_test_automaton() - result = list(t.iter(test_string, include_unmatched=True, include_space=True)) + result = list( + t.iter(test_string, include_unmatched=True, include_space=True)) expected = [ Token(0, 0, u'(', u'('), Token(1, 1, u'(', u'('), @@ -215,7 +217,8 @@ def get_test_automaton(): assert expected == result - result = list(t.tokenize(test_string, include_unmatched=True, include_space=True)) + result = list(t.tokenize( + test_string, include_unmatched=True, include_space=True)) assert expected == result def test_tokenize_with_unmatched_and_space(self): @@ -232,7 +235,8 @@ def get_test_automaton(): # 111111111122222222223 # 0123456789012345678901234567890 t = get_test_automaton() - result = list(t.tokenize(test_string, include_unmatched=True, include_space=True)) + result = list(t.tokenize( + test_string, include_unmatched=True, include_space=True)) expected = [ Token(0, 0, u'(', u'('), Token(1, 1, u'(', u'('), diff --git a/tests/test_license_expression.py b/tests/test_license_expression.py index 77a06d0..a2d5c84 100644 --- a/tests/test_license_expression.py +++ b/tests/test_license_expression.py @@ -2,7 +2,7 @@ # Copyright (c) nexB Inc. and others. All rights reserved. # SPDX-License-Identifier: Apache-2.0 # See http://www.apache.org/licenses/LICENSE-2.0 for the license text. -# See https://github.com/nexB/license-expression for support or download. +# See https://github.com/aboutcode-org/license-expression for support or download. # See https://aboutcode.org for more information about nexB OSS projects. # import json @@ -155,7 +155,8 @@ def test_tokenize_plain4(self): (TOKEN_RPAR, ')', 24), (TOKEN_RPAR, ')', 25) ] - assert list(licensing.tokenize('((l-a+ AND l-b) OR (l-c+))')) == expected + assert list(licensing.tokenize( + '((l-a+ AND l-b) OR (l-c+))')) == expected def test_tokenize_plain5(self): licensing = Licensing() @@ -176,7 +177,7 @@ def test_tokenize_plain5(self): license_symbol=LicenseSymbol(key='gpl'), exception_symbol=LicenseSymbol(key='classpath')), 'gpl with classpath', 31 - ) + ) ] tokens = licensing.tokenize( '((l-a+ AND l-b) OR (l-c+)) and gpl with classpath' @@ -189,7 +190,7 @@ class LicensingTokenizeWithSymbolsTest(TestCase): def get_symbols_and_licensing(self): gpl_20 = LicenseSymbol('GPL-2.0', ['The GNU GPL 20']) gpl_20_plus = LicenseSymbol('gpl-2.0+', - ['The GNU GPL 20 or later', 'GPL-2.0 or later', 'GPL v2.0 or later']) + ['The GNU GPL 20 or later', 'GPL-2.0 or later', 'GPL v2.0 or later']) lgpl_21 = LicenseSymbol('LGPL-2.1', ['LGPL v2.1']) mit = LicenseSymbol('MIT', ['MIT license']) symbols = [gpl_20, gpl_20_plus, lgpl_21, mit] @@ -199,7 +200,8 @@ def get_symbols_and_licensing(self): def test_tokenize_1_with_symbols(self): gpl_20, _gpl_20_plus, lgpl_21, mit, licensing = self.get_symbols_and_licensing() - result = licensing.tokenize('The GNU GPL 20 or LGPL v2.1 AND MIT license ') + result = licensing.tokenize( + 'The GNU GPL 20 or LGPL v2.1 AND MIT license ') # 111111111122222222223333333333444 # 0123456789012345678901234567890123456789012 @@ -215,7 +217,8 @@ def test_tokenize_1_with_symbols(self): def test_tokenize_1_no_symbols(self): licensing = Licensing() - result = licensing.tokenize('The GNU GPL 20 or LGPL v2.1 AND MIT license') + result = licensing.tokenize( + 'The GNU GPL 20 or LGPL v2.1 AND MIT license') expected = [ (LicenseSymbol(u'The GNU GPL 20'), 'The GNU GPL 20', 0), @@ -242,7 +245,8 @@ def test_tokenize_with_trailing_unknown(self): def test_tokenize_3(self): gpl_20, gpl_20_plus, lgpl_21, mit, licensing = self.get_symbols_and_licensing() - result = licensing.tokenize('The GNU GPL 20 or later or (LGPL-2.1 and mit) or The GNU GPL 20 or mit') + result = licensing.tokenize( + 'The GNU GPL 20 or later or (LGPL-2.1 and mit) or The GNU GPL 20 or mit') expected = [ (gpl_20_plus, 'The GNU GPL 20 or later', 0), (TOKEN_OR, 'or', 24), @@ -280,7 +284,8 @@ def test_tokenize_with_unknown_symbol_containing_known_symbol_leading(self): def test_tokenize_with_unknown_symbol_containing_known_symbol_contained(self): l = Licensing(['gpl-2.0']) - result = list(l.tokenize('gpl-2.0 WITH exception-gpl-2.0-plus', strict=False)) + result = list(l.tokenize( + 'gpl-2.0 WITH exception-gpl-2.0-plus', strict=False)) result = [s for s, _, _ in result] expected = [ LicenseWithExceptionSymbol( @@ -292,7 +297,8 @@ def test_tokenize_with_unknown_symbol_containing_known_symbol_contained(self): def test_tokenize_with_unknown_symbol_containing_known_symbol_trailing(self): l = Licensing(['gpl-2.0']) - result = list(l.tokenize('gpl-2.0 AND exception-gpl-2.0', strict=False)) + result = list(l.tokenize( + 'gpl-2.0 AND exception-gpl-2.0', strict=False)) result = [s for s, _, _ in result] expected = [ LicenseSymbol(u'gpl-2.0'), @@ -336,7 +342,8 @@ def test_parse_raise_ExpressionError_when_validating(self): licensing.parse(expression, validate=True) self.fail('Exception not raised') except ExpressionError as ee: - assert 'Unknown license key(s): gpl, bsd, lgpl, exception' == str(ee) + assert 'Unknown license key(s): gpl, bsd, lgpl, exception' == str( + ee) def test_parse_raise_ParseError_when_validating_strict(self): expression = 'gpl and bsd or lgpl with exception' @@ -370,7 +377,8 @@ def test_parse_raise_ParseError_when_strict_no_validate(self): def test_parse_raise_ExpressionError_when_validating_strict_with_unknown(self): expression = 'gpl and bsd or lgpl with exception' - licensing = Licensing(symbols=[LicenseSymbol('exception', is_exception=True)]) + licensing = Licensing( + symbols=[LicenseSymbol('exception', is_exception=True)]) try: licensing.parse(expression, validate=True, strict=True) except ExpressionError as ee: @@ -416,7 +424,8 @@ def test_parse_invalid_expression_raise_exception5(self): licensing.parse(expr) self.fail("Exception not raised when validating '%s'" % expr) except ExpressionError as ee: - assert 'AND requires two or more licenses as in: MIT AND BSD' == str(ee) + assert 'AND requires two or more licenses as in: MIT AND BSD' == str( + ee) def test_parse_invalid_expression_raise_exception6(self): licensing = Licensing() @@ -519,7 +528,8 @@ def test_parse_errors_catch_invalid_non_unicode_byte_strings_on_python3(self): if py2: extra_bytes = bytes(chr(0) + chr(12) + chr(255)) try: - licensing.parse('mit (and LGPL 2.1)'.encode('utf-8') + extra_bytes) + licensing.parse('mit (and LGPL 2.1)'.encode( + 'utf-8') + extra_bytes) self.fail('Exception not raised') except ExpressionError as ee: assert str(ee).startswith('expression must be a string and') @@ -527,7 +537,8 @@ def test_parse_errors_catch_invalid_non_unicode_byte_strings_on_python3(self): if py3: extra_bytes = bytes(chr(0) + chr(12) + chr(255), encoding='utf-8') try: - licensing.parse('mit (and LGPL 2.1)'.encode('utf-8') + extra_bytes) + licensing.parse('mit (and LGPL 2.1)'.encode( + 'utf-8') + extra_bytes) self.fail('Exception not raised') except ExpressionError as ee: assert str(ee).startswith('Invalid license key') @@ -564,16 +575,22 @@ def test_license_expression_is_equivalent(self): lic = Licensing() is_equiv = lic.is_equivalent - self.assertTrue(is_equiv(lic.parse('mit AND gpl'), lic.parse('mit AND gpl'))) - self.assertTrue(is_equiv(lic.parse('mit AND gpl'), lic.parse('gpl AND mit'))) - self.assertTrue(is_equiv(lic.parse('mit AND gpl and apache'), lic.parse('apache and gpl AND mit'))) - self.assertTrue(is_equiv(lic.parse('mit AND (gpl AND apache)'), lic.parse('(mit AND gpl) AND apache'))) + self.assertTrue(is_equiv(lic.parse('mit AND gpl'), + lic.parse('mit AND gpl'))) + self.assertTrue(is_equiv(lic.parse('mit AND gpl'), + lic.parse('gpl AND mit'))) + self.assertTrue(is_equiv(lic.parse('mit AND gpl and apache'), + lic.parse('apache and gpl AND mit'))) + self.assertTrue(is_equiv( + lic.parse('mit AND (gpl AND apache)'), lic.parse('(mit AND gpl) AND apache'))) # same but without parsing: self.assertTrue(is_equiv('mit AND gpl', 'mit AND gpl')) self.assertTrue(is_equiv('mit AND gpl', 'gpl AND mit')) - self.assertTrue(is_equiv('mit AND gpl and apache', 'apache and gpl AND mit')) - self.assertTrue(is_equiv('mit AND (gpl AND apache)', '(mit AND gpl) AND apache')) + self.assertTrue(is_equiv('mit AND gpl and apache', + 'apache and gpl AND mit')) + self.assertTrue(is_equiv('mit AND (gpl AND apache)', + '(mit AND gpl) AND apache')) # Real-case example of generated expression vs. stored expression: ex1 = '''Commercial @@ -592,20 +609,27 @@ def test_license_expression_is_equivalent(self): AND w3c-documentation AND w3c''' self.assertTrue(is_equiv(lic.parse(ex1), lic.parse(ex2))) - self.assertFalse(is_equiv(lic.parse('mit AND gpl'), lic.parse('mit OR gpl'))) - self.assertFalse(is_equiv(lic.parse('mit AND gpl'), lic.parse('gpl OR mit'))) + self.assertFalse( + is_equiv(lic.parse('mit AND gpl'), lic.parse('mit OR gpl'))) + self.assertFalse( + is_equiv(lic.parse('mit AND gpl'), lic.parse('gpl OR mit'))) def test_license_expression_license_keys(self): licensing = Licensing() - assert ['mit', 'gpl'] == licensing.license_keys(licensing.parse(' ( mit ) and gpl')) - assert ['mit', 'gpl'] == licensing.license_keys(licensing.parse('(mit and gpl)')) + assert ['mit', 'gpl'] == licensing.license_keys( + licensing.parse(' ( mit ) and gpl')) + assert ['mit', 'gpl'] == licensing.license_keys( + licensing.parse('(mit and gpl)')) # these two are surprising for now: this is because the expression is a # logical expression so the order may be different on more complex expressions - assert ['mit', 'gpl'] == licensing.license_keys(licensing.parse('mit AND gpl or gpl')) - assert ['l-a+', 'l-b', '+l-c'] == licensing.license_keys(licensing.parse('((l-a+ AND l-b) OR (+l-c))')) + assert ['mit', 'gpl'] == licensing.license_keys( + licensing.parse('mit AND gpl or gpl')) + assert ['l-a+', 'l-b', '+l-c'] == licensing.license_keys( + licensing.parse('((l-a+ AND l-b) OR (+l-c))')) # same without parsing assert ['mit', 'gpl'] == licensing.license_keys('mit AND gpl or gpl') - assert ['l-a+', 'l-b', 'l-c+'] == licensing.license_keys('((l-a+ AND l-b) OR (l-c+))') + assert ['l-a+', 'l-b', + 'l-c+'] == licensing.license_keys('((l-a+ AND l-b) OR (l-c+))') def test_end_to_end(self): # these were formerly doctest ported to actual real code tests here @@ -694,7 +718,8 @@ def test_dedup_expressions_WITH_OR(self): def test_dedup_expressions_WITH_AND(self): l = Licensing() - exp = l.parse('gpl-2.0 AND gpl-2.0 with autoconf-exception-2.0 AND gpl-2.0') + exp = l.parse( + 'gpl-2.0 AND gpl-2.0 with autoconf-exception-2.0 AND gpl-2.0') result = l.dedup(exp) expected = l.parse('gpl-2.0 AND gpl-2.0 with autoconf-exception-2.0') assert result == expected @@ -708,14 +733,16 @@ def test_dedup_licensexpressions_can_be_simplified_3(self): def test_dedup_licensexpressions_works_with_subexpressions(self): l = Licensing() - exp = l.parse('(mit OR gpl-2.0) AND mit AND bsd-new AND (mit OR gpl-2.0)') + exp = l.parse( + '(mit OR gpl-2.0) AND mit AND bsd-new AND (mit OR gpl-2.0)') result = l.dedup(exp) expected = l.parse('(mit OR gpl-2.0) AND mit AND bsd-new') assert result == expected def test_simplify_and_equivalent_and_contains(self): l = Licensing() - expr2 = l.parse(' GPL-2.0 or (mit and LGPL-2.1) or bsd Or GPL-2.0 or (mit and LGPL-2.1)') + expr2 = l.parse( + ' GPL-2.0 or (mit and LGPL-2.1) or bsd Or GPL-2.0 or (mit and LGPL-2.1)') # note thats simplification does SORT the symbols such that they can # eventually be compared sequence-wise. This sorting is based on license key expected = 'GPL-2.0 OR bsd OR (LGPL-2.1 AND mit)' @@ -774,15 +801,15 @@ def test_create_from_python(self): a = licensing.OR( LicenseSymbol(key='gpl-2.0'), licensing.AND(LicenseSymbol(key='mit'), - LicenseSymbol(key='lgpl-2.1') - ) - ) + LicenseSymbol(key='lgpl-2.1') + ) + ) b = licensing.OR( - LicenseSymbol(key='gpl-2.0'), - licensing.AND(LicenseSymbol(key='mit'), - LicenseSymbol(key='lgpl-2.1') - ) - ) + LicenseSymbol(key='gpl-2.0'), + licensing.AND(LicenseSymbol(key='mit'), + LicenseSymbol(key='lgpl-2.1') + ) + ) assert a == b def test_parse_with_repeated_or_later_does_not_raise_parse_error(self): @@ -801,17 +828,17 @@ def test_render_complex(self): result = licensing.parse(expression) expected = ('EPL-1.0 AND Apache-1.1 AND Apache-2.0 AND BSD-Modified ' - 'AND CPL-1.0 AND ICU-Composite-License AND JPEG-License ' - 'AND JDOM-License AND LGPL-2.0 AND MIT-Open-Group AND MPL-1.1 ' - 'AND SAX-PD AND Unicode-Inc-License-Agreement ' - 'AND W3C-Software-Notice AND License AND W3C-Documentation-License') + 'AND CPL-1.0 AND ICU-Composite-License AND JPEG-License ' + 'AND JDOM-License AND LGPL-2.0 AND MIT-Open-Group AND MPL-1.1 ' + 'AND SAX-PD AND Unicode-Inc-License-Agreement ' + 'AND W3C-Software-Notice AND License AND W3C-Documentation-License') assert result.render('{symbol.key}') == expected expectedkey = ('EPL-1.0 AND Apache-1.1 AND Apache-2.0 AND BSD-Modified AND ' - 'CPL-1.0 AND ICU-Composite-License AND JPEG-License AND JDOM-License AND ' - 'LGPL-2.0 AND MIT-Open-Group AND MPL-1.1 AND SAX-PD AND ' - 'Unicode-Inc-License-Agreement AND W3C-Software-Notice AND License AND' - ' W3C-Documentation-License') + 'CPL-1.0 AND ICU-Composite-License AND JPEG-License AND JDOM-License AND ' + 'LGPL-2.0 AND MIT-Open-Group AND MPL-1.1 AND SAX-PD AND ' + 'Unicode-Inc-License-Agreement AND W3C-Software-Notice AND License AND' + ' W3C-Documentation-License') assert expectedkey == result.render('{symbol.key}') def test_render_with(self): @@ -826,7 +853,8 @@ def test_render_with(self): 'GPL-2.0 WITH ' 'Classpath-2.0 ' 'OR BSD-new') - assert expected_html == result.render('{symbol.key}') + assert expected_html == result.render( + '{symbol.key}') expected = 'GPL-2.0 WITH Classpath-2.0 OR BSD-new' assert result.render('{symbol.key}') == expected @@ -932,7 +960,8 @@ def test_parse_invalid_expression_with_trailing_or(self): licensing.parse(expr) self.fail("Exception not raised when validating '%s'" % expr) except ExpressionError as ee: - assert 'OR requires two or more licenses as in: MIT OR BSD' == str(ee) + assert 'OR requires two or more licenses as in: MIT OR BSD' == str( + ee) def test_parse_invalid_expression_with_trailing_or_and_valid_start_does_not_raise_exception(self): licensing = Licensing() @@ -976,7 +1005,8 @@ def test_parse_invalid_expression_with_single_trailing_and_raise_exception(self) licensing.parse(expression, simple=False) self.fail('Exception not raised') except ExpressionError as ee: - assert 'AND requires two or more licenses as in: MIT AND BSD' == str(ee) + assert 'AND requires two or more licenses as in: MIT AND BSD' == str( + ee) def test_parse_invalid_expression_with_single_leading_or_raise_exception(self): licensing = Licensing() @@ -1247,8 +1277,10 @@ def test_with_known_symbol_string_contained_in_known_symbol_does_not_crash_with( class LicensingSymbolsReplacement(TestCase): def get_symbols_and_licensing(self): - gpl2 = LicenseSymbol('gpl-2.0', ['The GNU GPL 20', 'GPL-2.0', 'GPL v2.0']) - gpl2plus = LicenseSymbol('gpl-2.0+', ['The GNU GPL 20 or later', 'GPL-2.0 or later', 'GPL v2.0 or later']) + gpl2 = LicenseSymbol( + 'gpl-2.0', ['The GNU GPL 20', 'GPL-2.0', 'GPL v2.0']) + gpl2plus = LicenseSymbol( + 'gpl-2.0+', ['The GNU GPL 20 or later', 'GPL-2.0 or later', 'GPL v2.0 or later']) lgpl = LicenseSymbol('LGPL-2.1', ['LGPL v2.1']) mit = LicenseSymbol('MIT', ['MIT license']) mitand2 = LicenseSymbol('mitand2', ['mitand2', 'mitand2 license']) @@ -1316,13 +1348,15 @@ def test_multiple_substitutions_complex(self): (source3, target3), ]) - expr = licensing.parse('(gpl-2.0 or gpl-2.0+ and mit) and (gpl-2.0 or gpl-2.0+ and mit)') + expr = licensing.parse( + '(gpl-2.0 or gpl-2.0+ and mit) and (gpl-2.0 or gpl-2.0+ and mit)') # step 1: yields 'gpl-2.0 or lgpl' # step 2: yields 'gpl-2.0+ or LGPL-2.1' result = expr.subs(subs) assert '(gpl-2.0+ OR LGPL-2.1) AND (gpl-2.0+ OR LGPL-2.1)' == result.render() - expr = licensing.parse('(gpl-2.0 or mit and gpl-2.0+) and (gpl-2.0 or gpl-2.0+ and mit)') + expr = licensing.parse( + '(gpl-2.0 or mit and gpl-2.0+) and (gpl-2.0 or gpl-2.0+ and mit)') # step 1: yields 'gpl-2.0 or lgpl' # step 2: yields 'gpl-2.0+ or LGPL-2.1' result = expr.subs(subs) @@ -1332,8 +1366,10 @@ def test_multiple_substitutions_complex(self): class LicensingParseWithSymbolsAdvancedTest(TestCase): def get_symbols_and_licensing(self): - gpl2 = LicenseSymbol('gpl-2.0', ['The GNU GPL 20', 'GPL-2.0', 'GPL v2.0']) - gpl2plus = LicenseSymbol('gpl-2.0+', ['The GNU GPL 20 or later', 'GPL-2.0 or later', 'GPL v2.0 or later']) + gpl2 = LicenseSymbol( + 'gpl-2.0', ['The GNU GPL 20', 'GPL-2.0', 'GPL v2.0']) + gpl2plus = LicenseSymbol( + 'gpl-2.0+', ['The GNU GPL 20 or later', 'GPL-2.0 or later', 'GPL v2.0 or later']) lgpl = LicenseSymbol('LGPL-2.1', ['LGPL v2.1']) mit = LicenseSymbol('MIT', ['MIT license']) mitand2 = LicenseSymbol('mitand2', ['mitand2', 'mitand2 license']) @@ -1343,13 +1379,15 @@ def get_symbols_and_licensing(self): def test_parse_trailing_char_does_not_raise_exception_without_validate(self): _gpl2, _gpl2plus, _lgpl, _mit, _mitand2, licensing = self.get_symbols_and_licensing() - e = licensing.parse('The GNU GPL 20 or LGPL-2.1 and mit2', validate=False) + e = licensing.parse( + 'The GNU GPL 20 or LGPL-2.1 and mit2', validate=False) assert 'gpl-2.0 OR (LGPL-2.1 AND mit2)' == str(e) def test_parse_trailing_char_raise_exception_with_validate(self): _gpl2, _gpl2plus, _lgpl, _mit, _mitand2, licensing = self.get_symbols_and_licensing() try: - licensing.parse('The GNU GPL 20 or LGPL-2.1 and mit2', validate=True) + licensing.parse( + 'The GNU GPL 20 or LGPL-2.1 and mit2', validate=True) self.fail('Exception not raised') except ExpressionError as ee: assert 'Unknown license key(s): mit2' == str(ee) @@ -1358,7 +1396,8 @@ def test_parse_expression_with_trailing_unknown_should_raise_exception(self): gpl2, gpl2plus, lgpl, mit, _mitand2, licensing = self.get_symbols_and_licensing() unknown = LicenseSymbol(key='123') - tokens = list(licensing.tokenize('The GNU GPL 20 or later or (LGPL-2.1 and mit) or The GNU GPL 20 or mit 123')) + tokens = list(licensing.tokenize( + 'The GNU GPL 20 or later or (LGPL-2.1 and mit) or The GNU GPL 20 or mit 123')) expected = [ (gpl2plus, 'The GNU GPL 20 or later', 0), (TOKEN_OR, 'or', 24), @@ -1376,7 +1415,8 @@ def test_parse_expression_with_trailing_unknown_should_raise_exception(self): assert tokens == expected try: - licensing.parse('The GNU GPL 20 or later or (LGPL-2.1 and mit) or The GNU GPL 20 or mit 123') + licensing.parse( + 'The GNU GPL 20 or later or (LGPL-2.1 and mit) or The GNU GPL 20 or mit 123') self.fail('Exception not raised') except ParseError as pe: expected = {'error_code': PARSE_INVALID_SYMBOL_SEQUENCE, 'position': 71, @@ -1398,7 +1438,8 @@ def test_parse_expression_with_trailing_unknown_should_raise_exception2(self): def test_parse_expression_with_WITH(self): gpl2, _gpl2plus, lgpl, mit, mitand2, _ = self.get_symbols_and_licensing() mitexp = LicenseSymbol('mitexp', ('mit exp',), is_exception=True) - gpl_20_or_later = LicenseSymbol('GPL-2.0+', ['The GNU GPL 20 or later']) + gpl_20_or_later = LicenseSymbol( + 'GPL-2.0+', ['The GNU GPL 20 or later']) symbols = [gpl2, lgpl, mit, mitand2, mitexp, gpl_20_or_later] licensing = Licensing(symbols) @@ -1429,7 +1470,8 @@ def test_parse_expression_with_WITH(self): def test_parse_expression_with_WITH_and_unknown_symbol(self): gpl2, _gpl2plus, lgpl, mit, mitand2, _ = self.get_symbols_and_licensing() mitexp = LicenseSymbol('mitexp', ('mit exp',), is_exception=True) - gpl_20_or_later = LicenseSymbol('GPL-2.0+', ['The GNU GPL 20 or later']) + gpl_20_or_later = LicenseSymbol( + 'GPL-2.0+', ['The GNU GPL 20 or later']) symbols = [gpl2, lgpl, mit, mitand2, mitexp, gpl_20_or_later] licensing = Licensing(symbols) @@ -1502,15 +1544,19 @@ def test_advanced_tokenizer_tokenize_with_overlapping_key_with_symbols_and_trail licensing = Licensing(symbols) results = list(licensing.get_advanced_tokenizer().tokenize(expression)) expected = [ - Token(0, 2, 'mit', LicenseSymbol(u'MIT', aliases=(u'MIT license',))), + Token(0, 2, 'mit', LicenseSymbol( + u'MIT', aliases=(u'MIT license',))), Token(4, 5, 'or', Keyword(value=u'or', type=2)), - Token(7, 9, 'mit', LicenseSymbol(u'MIT', aliases=(u'MIT license',))), + Token(7, 9, 'mit', LicenseSymbol( + u'MIT', aliases=(u'MIT license',))), Token(11, 13, 'AND', Keyword(value=u'and', type=1)), Token(15, 18, 'zlib', LicenseSymbol(u'zlib', aliases=(u'zlib',))), Token(20, 21, 'or', Keyword(value=u'or', type=2)), - Token(23, 25, 'mit', LicenseSymbol(u'MIT', aliases=(u'MIT license',))), + Token(23, 25, 'mit', LicenseSymbol( + u'MIT', aliases=(u'MIT license',))), Token(27, 28, 'or', Keyword(value=u'or', type=2)), - Token(30, 32, 'mit', LicenseSymbol(u'MIT', aliases=(u'MIT license',))), + Token(30, 32, 'mit', LicenseSymbol( + u'MIT', aliases=(u'MIT license',))), Token(34, 37, 'with', Keyword(value=u'with', type=10)), Token(39, 53, 'verylonglicense', None), ] @@ -1531,17 +1577,22 @@ def test_advanced_tokenizer_iter_with_overlapping_key_with_symbols_and_trailing_ LicenseSymbol('hmit', ['h verylonglicense']), ] licensing = Licensing(symbols) - results = list(licensing.get_advanced_tokenizer().iter(expression, include_unmatched=True)) + results = list(licensing.get_advanced_tokenizer().iter( + expression, include_unmatched=True)) expected = [ - Token(0, 2, 'mit', LicenseSymbol(u'MIT', aliases=(u'MIT license',))), + Token(0, 2, 'mit', LicenseSymbol( + u'MIT', aliases=(u'MIT license',))), Token(4, 5, 'or', Keyword(value=u'or', type=2)), - Token(7, 9, 'mit', LicenseSymbol(u'MIT', aliases=(u'MIT license',))), + Token(7, 9, 'mit', LicenseSymbol( + u'MIT', aliases=(u'MIT license',))), Token(11, 13, 'AND', Keyword(value=u'and', type=1)), Token(15, 18, 'zlib', LicenseSymbol(u'zlib', aliases=(u'zlib',))), Token(20, 21, 'or', Keyword(value=u'or', type=2)), - Token(23, 25, 'mit', LicenseSymbol(u'MIT', aliases=(u'MIT license',))), + Token(23, 25, 'mit', LicenseSymbol( + u'MIT', aliases=(u'MIT license',))), Token(27, 28, 'or', Keyword(value=u'or', type=2)), - Token(30, 32, 'mit', LicenseSymbol(u'MIT', aliases=(u'MIT license',))), + Token(30, 32, 'mit', LicenseSymbol( + u'MIT', aliases=(u'MIT license',))), Token(34, 37, 'with', Keyword(value=u'with', type=10)), Token(39, 53, 'verylonglicense', None), ] @@ -1554,9 +1605,11 @@ def test_advanced_tokenizer_iter_with_overlapping_key_with_symbols_and_trailing_ LicenseSymbol('hmit', ['h verylonglicense']), ] licensing = Licensing(symbols) - results = list(licensing.get_advanced_tokenizer().iter(expression, include_unmatched=True)) + results = list(licensing.get_advanced_tokenizer().iter( + expression, include_unmatched=True)) expected = [ - Token(0, 2, 'mit', LicenseSymbol(u'MIT', aliases=(u'MIT license',))), + Token(0, 2, 'mit', LicenseSymbol( + u'MIT', aliases=(u'MIT license',))), Token(4, 7, 'with', Keyword(value=u'with', type=10)), Token(9, 23, 'verylonglicense', None), ] @@ -1588,7 +1641,8 @@ def test_tokenize_with_overlapping_key_with_symbols_and_trailing_unknown(self): (LicenseSymbol(u'MIT', aliases=(u'MIT license',)), 'mit', 23), (2, 'or', 27), (LicenseWithExceptionSymbol( - license_symbol=LicenseSymbol(u'MIT', aliases=(u'MIT license',)), + license_symbol=LicenseSymbol( + u'MIT', aliases=(u'MIT license',)), exception_symbol=LicenseSymbol(u'verylonglicense')), 'mit with verylonglicense', 30) ] @@ -1609,7 +1663,8 @@ def test_get_license_symbols(self): LicenseSymbol('LGPL 2.1') ] l = Licensing(symbols) - assert symbols == l.license_symbols(l.parse(' GPL-2.0 and mit or LGPL 2.1 and mit ')) + assert symbols == l.license_symbols( + l.parse(' GPL-2.0 and mit or LGPL 2.1 and mit ')) def test_get_license_symbols2(self): symbols = [ @@ -1690,23 +1745,33 @@ def test_license_symbols(self): mitplus = LicenseSymbol(key='mit or later') mit = LicenseSymbol(key='mit') lgpl = LicenseSymbol(key='LGPL 2.1') - gpl_with_cp = LicenseWithExceptionSymbol(license_symbol=gpl2plus, exception_symbol=cpex) - mit_with_some = LicenseWithExceptionSymbol(license_symbol=mit, exception_symbol=someplus) - gpl2_with_someplus = LicenseWithExceptionSymbol(license_symbol=gpl2plus, exception_symbol=someplus) + gpl_with_cp = LicenseWithExceptionSymbol( + license_symbol=gpl2plus, exception_symbol=cpex) + mit_with_some = LicenseWithExceptionSymbol( + license_symbol=mit, exception_symbol=someplus) + gpl2_with_someplus = LicenseWithExceptionSymbol( + license_symbol=gpl2plus, exception_symbol=someplus) parsed = licensing.parse(expr) - expected = [gpl_with_cp, mit, mit_with_some, lgpl, gpl_with_cp, mitplus, lgpl, mit, gpl2_with_someplus, lgpl] + expected = [gpl_with_cp, mit, mit_with_some, lgpl, + gpl_with_cp, mitplus, lgpl, mit, gpl2_with_someplus, lgpl] - assert licensing.license_symbols(parsed, unique=False, decompose=False) == expected + assert licensing.license_symbols( + parsed, unique=False, decompose=False) == expected - expected = [gpl_with_cp, mit, mit_with_some, lgpl, mitplus, gpl2_with_someplus] - assert licensing.license_symbols(parsed, unique=True, decompose=False) == expected + expected = [gpl_with_cp, mit, mit_with_some, + lgpl, mitplus, gpl2_with_someplus] + assert licensing.license_symbols( + parsed, unique=True, decompose=False) == expected - expected = [gpl2plus, cpex, mit, mit, someplus, lgpl, gpl2plus, cpex, mitplus, lgpl, mit, gpl2plus, someplus, lgpl] - assert licensing.license_symbols(parsed, unique=False, decompose=True) == expected + expected = [gpl2plus, cpex, mit, mit, someplus, lgpl, + gpl2plus, cpex, mitplus, lgpl, mit, gpl2plus, someplus, lgpl] + assert licensing.license_symbols( + parsed, unique=False, decompose=True) == expected expected = [gpl2plus, cpex, mit, someplus, lgpl, mitplus] - assert licensing.license_symbols(parsed, unique=True, decompose=True) == expected + assert licensing.license_symbols( + parsed, unique=True, decompose=True) == expected def test_primary_license_symbol_and_primary_license_key(self): licensing = Licensing([ @@ -1722,7 +1787,8 @@ def test_primary_license_symbol_and_primary_license_key(self): cpex = LicenseSymbol('classpath Exception') expected = LicenseWithExceptionSymbol(gpl, cpex) parsed = licensing.parse(expr) - assert licensing.primary_license_symbol(parsed, decompose=False) == expected + assert licensing.primary_license_symbol( + parsed, decompose=False) == expected assert gpl == licensing.primary_license_symbol(parsed, decompose=True) assert 'GPL-2.0 or LATER' == licensing.primary_license_key(parsed) @@ -1742,13 +1808,15 @@ def test_render_plain(self): def test_render_as_readable_does_not_wrap_in_parens_single_with(self): l = Licensing() - result = l.parse('gpl-2.0 WITH exception-gpl-2.0-plus').render_as_readable() + result = l.parse( + 'gpl-2.0 WITH exception-gpl-2.0-plus').render_as_readable() expected = 'gpl-2.0 WITH exception-gpl-2.0-plus' assert result == expected def test_render_as_readable_wraps_in_parens_with_and_other_subexpressions(self): l = Licensing() - result = l.parse('mit AND gpl-2.0 WITH exception-gpl-2.0-plus').render_as_readable() + result = l.parse( + 'mit AND gpl-2.0 WITH exception-gpl-2.0-plus').render_as_readable() expected = 'mit AND (gpl-2.0 WITH exception-gpl-2.0-plus)' assert result == expected @@ -1893,7 +1961,7 @@ def test_tokenize_can_handle_expressions_with_tabs_and_new_lines(self): result = list(licensing.tokenize(expression, simple=False)) expected = [ (LicenseSymbol(u'this is an expression', is_exception=False), - u'this is an expression', 0) + u'this is an expression', 0) ] assert result == expected @@ -1915,7 +1983,8 @@ def test_tokenize_step_by_step_does_not_munge_trailing_symbols(self): cpex = LicenseSymbol(key='classpath Exception', is_exception=True) mitthing = LicenseSymbol(key='mithing') - mitthing_with_else = LicenseSymbol(key='mitthing with else+', is_exception=False) + mitthing_with_else = LicenseSymbol( + key='mitthing with else+', is_exception=False) mit = LicenseSymbol(key='mit') mitplus = LicenseSymbol(key='mit or later') @@ -1948,21 +2017,26 @@ def test_tokenize_step_by_step_does_not_munge_trailing_symbols(self): tokenizer = licensing.get_advanced_tokenizer() result = list(tokenizer.tokenize(expr)) expected = [ - Token(1, 16, 'GPL-2.0 or later', LicenseSymbol(u'GPL-2.0 or LATER')), + Token(1, 16, 'GPL-2.0 or later', + LicenseSymbol(u'GPL-2.0 or LATER')), Token(18, 21, 'with', Keyword(value=u'with', type=10)), - Token(23, 41, 'classpath Exception', LicenseSymbol(u'classpath Exception', is_exception=True)), + Token(23, 41, 'classpath Exception', LicenseSymbol( + u'classpath Exception', is_exception=True)), Token(43, 45, 'and', Keyword(value=u'and', type=1)), Token(47, 49, 'mit', LicenseSymbol(u'mit')), Token(51, 53, 'and', Keyword(value=u'and', type=1)), Token(55, 57, 'mit', LicenseSymbol(u'mit')), Token(59, 62, 'with', Keyword(value=u'with', type=10)), - Token(64, 82, 'mitthing with ELSE+', LicenseSymbol(u'mitthing with else+')), + Token(64, 82, 'mitthing with ELSE+', + LicenseSymbol(u'mitthing with else+')), Token(84, 85, 'or', Keyword(value=u'or', type=2)), Token(87, 94, 'LGPL 2.1', LicenseSymbol(u'LGPL 2.1')), Token(96, 98, 'and', Keyword(value=u'and', type=1)), - Token(100, 115, 'GPL-2.0 or LATER', LicenseSymbol(u'GPL-2.0 or LATER')), + Token(100, 115, 'GPL-2.0 or LATER', + LicenseSymbol(u'GPL-2.0 or LATER')), Token(117, 120, 'with', Keyword(value=u'with', type=10)), - Token(122, 140, 'Classpath Exception', LicenseSymbol(u'classpath Exception', is_exception=True)), + Token(122, 140, 'Classpath Exception', LicenseSymbol( + u'classpath Exception', is_exception=True)), Token(142, 144, 'and', Keyword(value=u'and', type=1)), Token(146, 157, 'mit or later', LicenseSymbol(u'mit or later')), Token(159, 160, 'or', Keyword(value=u'or', type=2)), @@ -1970,9 +2044,11 @@ def test_tokenize_step_by_step_does_not_munge_trailing_symbols(self): Token(171, 172, 'or', Keyword(value=u'or', type=2)), Token(174, 176, 'mit', LicenseSymbol(u'mit')), Token(178, 179, 'or', Keyword(value=u'or', type=2)), - Token(181, 196, 'GPL-2.0 or LATER', LicenseSymbol(u'GPL-2.0 or LATER')), + Token(181, 196, 'GPL-2.0 or LATER', + LicenseSymbol(u'GPL-2.0 or LATER')), Token(198, 201, 'with', Keyword(value=u'with', type=10)), - Token(203, 221, 'mitthing with ELSE+', LicenseSymbol(u'mitthing with else+')), + Token(203, 221, 'mitthing with ELSE+', + LicenseSymbol(u'mitthing with else+')), Token(223, 225, 'and', Keyword(value=u'and', type=1)), Token(227, 234, 'lgpl 2.1', LicenseSymbol(u'LGPL 2.1')), Token(236, 237, 'or', Keyword(value=u'or', type=2)), @@ -2024,10 +2100,13 @@ def test_tokenize_step_by_step_does_not_munge_trailing_symbols(self): # finally retest it all with tokenize - gpl2plus_with_cpex = LicenseWithExceptionSymbol(license_symbol=gpl2plus, exception_symbol=cpex) - gpl2plus_with_someplus = LicenseWithExceptionSymbol(license_symbol=gpl2plus, exception_symbol=mitthing_with_else) + gpl2plus_with_cpex = LicenseWithExceptionSymbol( + license_symbol=gpl2plus, exception_symbol=cpex) + gpl2plus_with_someplus = LicenseWithExceptionSymbol( + license_symbol=gpl2plus, exception_symbol=mitthing_with_else) - mit_with_mitthing_with_else = LicenseWithExceptionSymbol(license_symbol=mit, exception_symbol=mitthing_with_else) + mit_with_mitthing_with_else = LicenseWithExceptionSymbol( + license_symbol=mit, exception_symbol=mitthing_with_else) expected = [ (gpl2plus_with_cpex, 'GPL-2.0 or later with classpath Exception', 1), @@ -2116,13 +2195,16 @@ def test_is_equivalent_with_symbols_and_complex_expression(self): 'LGPL 2.1', ]) - parsed1 = licensing1.parse(' ((LGPL 2.1 or mit) and GPL-2.0 or LATER with classpath Exception) and agpl+') - parsed2 = licensing2.parse(' agpl+ and (GPL-2.0 or LATER with classpath Exception and (mit or LGPL 2.1))') + parsed1 = licensing1.parse( + ' ((LGPL 2.1 or mit) and GPL-2.0 or LATER with classpath Exception) and agpl+') + parsed2 = licensing2.parse( + ' agpl+ and (GPL-2.0 or LATER with classpath Exception and (mit or LGPL 2.1))') assert licensing1.is_equivalent(parsed1, parsed2) assert licensing2.is_equivalent(parsed1, parsed2) assert licensing_no_sym.is_equivalent(parsed1, parsed2) - parsed3 = licensing1.parse(' ((LGPL 2.1 or mit) OR GPL-2.0 or LATER with classpath Exception) and agpl+') + parsed3 = licensing1.parse( + ' ((LGPL 2.1 or mit) OR GPL-2.0 or LATER with classpath Exception) and agpl+') assert not licensing1.is_equivalent(parsed1, parsed3) assert not licensing2.is_equivalent(parsed1, parsed3) assert not licensing_no_sym.is_equivalent(parsed1, parsed3) @@ -2161,7 +2243,7 @@ def __init__(self, key, is_exception=False): l4 = LicenseSymbolLike(SymLike('c')) expected = [l1, lx, lx2, lx3, l3, l2, l4] - assert sorted([l4, l3, l2, l1, lx , lx2, lx3]) == expected + assert sorted([l4, l3, l2, l1, lx, lx2, lx3]) == expected class MockLicensesTest(TestCase): @@ -2172,14 +2254,16 @@ def test_licensing_can_use_mocklicense_tuple(self): licenses = [ MockLicense('gpl-2.0', ['GPL-2.0'], False), MockLicense('classpath-2.0', ['Classpath-Exception-2.0'], True), - MockLicense('gpl-2.0-plus', ['GPL-2.0-or-later', 'GPL-2.0 or-later'], False), + MockLicense('gpl-2.0-plus', + ['GPL-2.0-or-later', 'GPL-2.0 or-later'], False), MockLicense('lgpl-2.1-plus', ['LGPL-2.1-or-later'], False), ] licensing = Licensing(licenses) ex1 = '(GPL-2.0-or-later with Classpath-Exception-2.0 or GPL-2.0 or-later) and LGPL-2.1-or-later' expression1 = licensing.parse(ex1, validate=False, strict=False) - assert ['gpl-2.0-plus', 'classpath-2.0', 'lgpl-2.1-plus'] == licensing.license_keys(expression1) + assert ['gpl-2.0-plus', 'classpath-2.0', + 'lgpl-2.1-plus'] == licensing.license_keys(expression1) ex2 = 'LGPL-2.1-or-later and (GPL-2.0-or-later oR GPL-2.0-or-later with Classpath-Exception-2.0)' expression2 = licensing.parse(ex2, validate=True, strict=False) @@ -2261,38 +2345,44 @@ def test_validation_invalid_license_key(self): assert result.invalid_symbols == ['cool-license'] def test_validate_exception(self): - result = self.licensing.validate('GPL-2.0-or-later WITH WxWindows-exception-3.1') + result = self.licensing.validate( + 'GPL-2.0-or-later WITH WxWindows-exception-3.1') assert result.original_expression == 'GPL-2.0-or-later WITH WxWindows-exception-3.1' assert result.normalized_expression == 'GPL-2.0-or-later WITH WxWindows-exception-3.1' assert result.errors == [] assert result.invalid_symbols == [] def test_validation_exception_with_choice(self): - result = self.licensing.validate('GPL-2.0-or-later WITH WxWindows-exception-3.1 OR MIT') + result = self.licensing.validate( + 'GPL-2.0-or-later WITH WxWindows-exception-3.1 OR MIT') assert result.original_expression == 'GPL-2.0-or-later WITH WxWindows-exception-3.1 OR MIT' assert result.normalized_expression == 'GPL-2.0-or-later WITH WxWindows-exception-3.1 OR MIT' assert result.errors == [] assert result.invalid_symbols == [] def test_validation_exception_as_regular_key(self): - result = self.licensing.validate('GPL-2.0-or-later AND WxWindows-exception-3.1') + result = self.licensing.validate( + 'GPL-2.0-or-later AND WxWindows-exception-3.1') assert result.original_expression == 'GPL-2.0-or-later AND WxWindows-exception-3.1' assert not result.normalized_expression - assert result.errors == ['A license exception symbol can only be used as an exception in a "WITH exception" statement. for token: "WxWindows-exception-3.1" at position: 21'] + assert result.errors == [ + 'A license exception symbol can only be used as an exception in a "WITH exception" statement. for token: "WxWindows-exception-3.1" at position: 21'] assert result.invalid_symbols == ['WxWindows-exception-3.1'] def test_validation_bad_syntax(self): result = self.licensing.validate('Apache-2.0 + MIT') assert result.original_expression == 'Apache-2.0 + MIT' assert not result.normalized_expression - assert result.errors == ['Invalid symbols sequence such as (A B) for token: "+" at position: 11'] + assert result.errors == [ + 'Invalid symbols sequence such as (A B) for token: "+" at position: 11'] assert result.invalid_symbols == ['+'] def test_validation_invalid_license_exception(self): result = self.licensing.validate('Apache-2.0 WITH MIT') assert result.original_expression == 'Apache-2.0 WITH MIT' assert not result.normalized_expression - assert result.errors == ["A plain license symbol cannot be used as an exception in a \"WITH symbol\" statement. for token: \"MIT\" at position: 16"] + assert result.errors == [ + "A plain license symbol cannot be used as an exception in a \"WITH symbol\" statement. for token: \"MIT\" at position: 16"] assert result.invalid_symbols == ['MIT'] def test_validation_invalid_license_exception_strict_false(self): @@ -2307,7 +2397,8 @@ class UtilTest(TestCase): test_data_dir = join(dirname(__file__), 'data') def test_build_licensing(self): - test_license_index_location = join(self.test_data_dir, 'test_license_key_index.json') + test_license_index_location = join( + self.test_data_dir, 'test_license_key_index.json') with open(test_license_index_location) as f: license_info = json.load(f) lics = [ @@ -2319,7 +2410,8 @@ def test_build_licensing(self): syms = [LicenseSymbol(**l) for l in lics] expected = Licensing(syms) - test_license_index = get_license_index(license_index_location=test_license_index_location) + test_license_index = get_license_index( + license_index_location=test_license_index_location) result = build_licensing(test_license_index) assert result.known_symbols == expected.known_symbols @@ -2329,7 +2421,8 @@ def test_build_licensing(self): assert 'aladdin-md5' not in result.known_symbols_lowercase def test_build_spdx_licensing(self): - test_license_index_location = join(self.test_data_dir, 'test_license_key_index.json') + test_license_index_location = join( + self.test_data_dir, 'test_license_key_index.json') with open(test_license_index_location) as f: license_info = json.load(f) lics = [ @@ -2342,7 +2435,8 @@ def test_build_spdx_licensing(self): syms = [LicenseSymbol(**l) for l in lics] expected = Licensing(syms) - test_license_index = get_license_index(license_index_location=test_license_index_location) + test_license_index = get_license_index( + license_index_location=test_license_index_location) result = build_spdx_licensing(test_license_index) assert result.known_symbols == expected.known_symbols @@ -2352,7 +2446,8 @@ def test_build_spdx_licensing(self): assert 'aladdin-md5' not in result.known_symbols_lowercase def test_get_license_key_info(self): - test_license_index_location = join(self.test_data_dir, 'test_license_key_index.json') + test_license_index_location = join( + self.test_data_dir, 'test_license_key_index.json') with open(test_license_index_location) as f: expected = json.load(f) result = get_license_index(test_license_index_location) @@ -2380,11 +2475,13 @@ def test_combine_expressions_with_empty_input(self): assert combine_expressions([]) == None def test_combine_expressions_with_regular(self): - assert str(combine_expressions(['mit', 'apache-2.0'])) == 'mit AND apache-2.0' + assert str(combine_expressions( + ['mit', 'apache-2.0'])) == 'mit AND apache-2.0' def test_combine_expressions_with_duplicated_elements(self): - assert str(combine_expressions(['mit', 'apache-2.0', 'mit'])) == 'mit AND apache-2.0' + assert str(combine_expressions( + ['mit', 'apache-2.0', 'mit'])) == 'mit AND apache-2.0' def test_combine_expressions_with_or_relationship(self): - assert str(combine_expressions(['mit', 'apache-2.0'], 'OR')) == 'mit OR apache-2.0' - + assert str(combine_expressions( + ['mit', 'apache-2.0'], 'OR')) == 'mit OR apache-2.0'