Python comprehensive utility library to parse, compare, simplify
and normalize license expressions (such as SPDX license expressions)
using boolean logic.

For more information see the project home pages:

        https://github.com/nexB/license-expression

        https://pypi.org/project/license-expression

License:        Apache-2.0

I would like to provide a Cygwin package for license-expression Python
package to do SPDX licence checks, developed by the same team doing
SPDX-toolkit for SPDX, using the same current data, by and working with
Fedora folks et al.

It is in PyPI and packaged by major Linux and BSD distros, and Msys2:

        https://repology.org/project/python:license-expression/versions

Attached cygport and at:

https://cygwin.com/cgit/cygwin-packages/playground/tree/python-license-expression.cygport?h=playground

package job fails as files.pythonhosted.org recent package
directory paths now require "_" instead of "-"!

https://cygwin.com/cgi-bin2/jobs.cgi?id=8987&srcpkg=playground&user=Brian+Inglis

log at:

https://github.com/cygwin/scallywag/actions/runs/11517043356/job/32060933142

which could be fixed by the python.org cygclass patch attached.

The package has been installed and running on my system for many weeks using
the PoC script attached in spdx-license-expression.py hooked into
/usr/share/cygport/lib/pkg_pkg.cygpart by the license hint addition
patch attached.

I also reran a test of the Python script and module against all package
source cygport files declaring licences which I maintain or ever looked
at, including a git/cygwin-packages/*.cygport download from 2023-02.


Recent changes:

2024-10-21      30.4

- Use latest skeleton
- Update license list to latest ScanCode and SPDX 3.25
- Drop support for Python 3.8

2024-08-13      30.3.1

- Update link references of ownership from nexB to aboutcode-org

2024-03-18      30.3

- Use latest skeleton
- Update license list to latest ScanCode and SPDX 3.23
- Drop support for Python 3.7

2023-11-29      30.2

- Use latest skeleton
- Update license list to latest ScanCode and SPDX 3.22
- Add Python 3.12 support in CI

2023-01-16      30.1.1

- Use latest skeleton
- Update license list to latest ScanCode and SPDX 3.20

2023-01-16      30.1

- Use latest skeleton (and updated configure script)
- Update license list to latest ScanCode and SPDX 3.19
- Use correct syntax for python_require
- Drop using Travis and Appveyor
- Drop support for Python 3.7 and add Python 3.11 in CI

2022-05-10      30.0

This is a minor release with API changes

- Use latest skeleton (and updated configure script)
- Drop using calver
- Improve error checking when combining licenses
#|/usr/bin/cygport
# python-license-expression.cygport - Python license-expression Cygwin package 
build control script definitions

inherit python3-wheel

NAME=python-license-expression
VERSION=30.4.0
RELEASE=1

BASE=${NAME#python-}

CATEGORY=Python
SUMMARY="Python license expression utility library"
DESCRIPTION="Python comprehensive utility library to parse, compare, simplify
and normalize license expressions (such as SPDX license expressions)
using boolean logic."

ARCH=noarch

LICENSE=Apache-2.0
LICENSE_SPDX="SPDX-License-Identifier: $LICENSE"
# SPDX-License-Identifier: Apache-2.0
LICENSE_URI="NOTICE apache-2.0.LICENSE"

DOCS="
        license-expression.ABOUT
        AUTHORS.rst CHANGELOG.rst CODE_OF_CONDUCT.rst README.rst
        $LICENSE_URI
"

From 9c39a99af74e597d71b5fde490b4bdf384db634d Mon Sep 17 00:00:00 2001
Message-ID: 
<9c39a99af74e597d71b5fde490b4bdf384db634d.1723619679.git.brian.ing...@systematicsw.ab.ca>
From: Brian Inglis <brian.ing...@systematicsw.ab.ca>
Bcc: Brian Inglis <brian.ing...@shaw.ca>
To: Cygwin Apps <cygwin-apps@cygwin.com>
Date: Wed, 14 Aug 2024 01:14:28 -0600
Subject: [PATCH] cygport cygclass/python.org.cygclass pythonhosted archives may 
require underscores not dashes
Organization: Systematic Software

new source packages on pythonhosted appear to change dashes in package
names to underscores in archive names and directories, for example:

python-license-expression ->
license-expression ->
https://files.pythonhosted.org/packages/source/l/license_expression/license_expression-30.3.1.tar.gz
-> license_expression-30.3.1/

although dashes in pythonhosted package directory names
still seem to work as an alternative:

https://files.pythonhosted.org/packages/source/l/license{-,_}expression/license_expression-30.3.1.tar.gz

but dashes work and underscores do not in older package version
archives, although underscores in pythonhosted package directory names
still seem to work as an alternative:

https://files.pythonhosted.org/packages/source/l/license{-,_}expression/license-expression-30.3.0.tar.gz

so keep pythonhosted package directory names verbatim and iterate setting
SRC_DIR to package name verbatim or underscored and test availability with:

    wget -q --spider ...
or
    curl --silent --fail -o /dev/null 2> /dev/null ...

Signed-off-by: Brian Inglis <brian.ing...@systematicsw.ab.ca>
---
 cygclass/python.org.cygclass | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/cygclass/python.org.cygclass b/cygclass/python.org.cygclass
index 51434ba6c08f..a1b8fb89ec73 100644
--- a/cygclass/python.org.cygclass
+++ b/cygclass/python.org.cygclass
@@ -50,4 +50,8 @@ HOMEPAGE="https://pypi.org/project/${PYTHON_ORG_NAME}";
 #  DESCRIPTION
 #  Download location of the Python module on the Python Package Index.
 #****
-SRC_URI="https://files.pythonhosted.org/packages/source/${PYTHON_ORG_NAME:0:1}/${PYTHON_ORG_NAME}/${PYTHON_ORG_NAME}-${PV}.tar.gz";
+for SRC_DIR in ${PYTHON_ORG_NAME}-${PV} ${PYTHON_ORG_NAME//-/_}-${PV}
+do
+    
SRC_URI=https://files.pythonhosted.org/packages/source/${PYTHON_ORG_NAME:0:1}/${PYTHON_ORG_NAME}/${SRC_DIR}.tar.gz
+    wget --quiet --spider $SRC_URI && break
+done
-- 
2.45.1

#!/usr/bin/python
"""spdx-license-expression.py - validate SPDX licence expression

Usage: spdx-license-expression.py <SPDX-License-Identifier Expression>

Author: Brian Inglis <brian.ing...@systematicsw.ab.ca>
"""

import re
import sys
   
try:
    import license_expression
except ModuleNotFoundError:
    licensing = None
else:
    licensing = license_expression.get_spdx_licensing()

def main(args):
    prog = re.sub(r'\.py$', '', re.sub(r'^.*/', '', sys.argv[0]))

    if len(args) != 1:
        print("%s: usage: %s <SPDX-License-Identifier Expression>" % (prog, prog),
              file=sys.stderr)
        return 1

    # normalize expression whitespace
    expression = re.sub(r'\s+', ' ', args[0])
    errors = []
    warnings = []

    if expression and licensing:
        try:
            licensing.parse(expression, strict=True)
            le = licensing.validate(expression, strict=True)
#ExpressionInfo(
#   original_expression='... and MIT and GPL-2.0+',
#   normalized_expression=None,
#   errors=['Unknown license key(s): ...'],
#   invalid_symbols=['...']
#)
        except license_expression.ExpressionParseError as e:
            errors.append('parse errors: ' + str(e))
        except license_expression.ExpressionError as e:
            errors.append(str(e))
        else:
            if not le.normalized_expression:
                if len(le.errors) >= 1:
                    # add warnings if not ...Ref-
                    non_ref = False
                    for i_s in le.invalid_symbols:
                        non_ref = non_ref or not i_s.startswith(('LicenseRef-',
                                                                 'ExceptionRef-'))

                    if non_ref:
                        warnings.append('; '.join(le.errors))
            elif le.original_expression.lower() != le.normalized_expression.lower():
                warnings.append("'%s' normalizes to '%s'" % (le.original_expression,
                                                             le.normalized_expression))

        if len(warnings):
            print("%s: %s" % (prog, '; '.join(warnings)), file=sys.stderr)

        if len(errors):
            print("%s: %s" % (prog, '; '.join(errors)), file=sys.stderr)
            return 2

#       if le.normalized_expression:
#           print("%s: %s" % (prog, le.normalized_expression))
#       elif le.original_expression:
#           print("%s: %s" % (prog, le.original_expression))
#       else:
#           print("%s: %s" % (prog, expression))

if __name__ == "__main__":
    sys.exit(main(sys.argv[1:]))
--- origsrc/lib/pkg_pkg.cygpart.orig    2023-03-08 06:07:57.000000000 -0700
+++ src/lib/pkg_pkg.cygpart     2024-05-29 14:18:46.534998000 -0600
@@ -625,6 +641,7 @@ _EOF
                        fi
                        if [ -n "${LICENSE}" ]
                        then
+                               spdx-license-expression.py "${LICENSE}" || true
                                cat >> ${distdir}/${PN}/${PN}-${PVR}-src.hint 
<<-_EOF
 license: ${LICENSE}
 _EOF

Reply via email to