spdx 0.0.1.0 → 0.1.0.0
raw patch · 16 files changed
+840/−655 lines, 16 filesdep +xmldep ~basenew-component:exe:spdx-dataPVP ok
version bump matches the API change (PVP)
Dependencies added: xml
Dependency ranges changed: base
API changes (from Hackage documentation)
- Distribution.SPDX: EConjunction :: !LicenseExpression -> !LicenseExpression -> LicenseExpression
- Distribution.SPDX: EDisjunction :: !LicenseExpression -> !LicenseExpression -> LicenseExpression
- Distribution.SPDX: ELicense :: !Bool -> !(Either LicenseRef LicenseId) -> !(Maybe LicenseExceptionId) -> LicenseExpression
- Distribution.SPDX: LicenseRef :: !(Maybe String) -> !String -> LicenseRef
- Distribution.SPDX: data LicenseExpression
- Distribution.SPDX: data LicenseRef
- Distribution.SPDX: instance Eq Lic
- Distribution.SPDX: instance Ord Lic
- Distribution.SPDX: instance Read Lic
- Distribution.SPDX: instance Show Lic
- Distribution.SPDX: licenseExceptions :: [LicenseExceptionId]
- Distribution.SPDX: licenseIdentifiers :: [LicenseId]
- Distribution.SPDX: licenseRanges :: [[LicenseId]]
- Distribution.SPDX: lookupLicenseRange :: LicenseId -> [LicenseId]
- Distribution.SPDX: lrDocument :: LicenseRef -> !(Maybe String)
- Distribution.SPDX: lrLicense :: LicenseRef -> !String
- Distribution.SPDX: parseExpression :: String -> [LicenseExpression]
- Distribution.SPDX: satisfies :: LicenseExpression -> LicenseExpression -> Bool
- Distribution.SPDX: type LicenseExceptionId = String
- Distribution.SPDX: type LicenseId = String
- Distribution.SPDX: unsafeParseExpr :: String -> LicenseExpression
- Distribution.SPDX.LatticeSyntax: LBound :: Bool -> LatticeSyntax a
- Distribution.SPDX.LatticeSyntax: LJoin :: (LatticeSyntax a) -> (LatticeSyntax a) -> LatticeSyntax a
- Distribution.SPDX.LatticeSyntax: LMeet :: (LatticeSyntax a) -> (LatticeSyntax a) -> LatticeSyntax a
- Distribution.SPDX.LatticeSyntax: LVar :: a -> LatticeSyntax a
- Distribution.SPDX.LatticeSyntax: data LatticeSyntax a
- Distribution.SPDX.LatticeSyntax: dual :: LatticeSyntax a -> LatticeSyntax a
- Distribution.SPDX.LatticeSyntax: equivalent :: Eq a => LatticeSyntax a -> LatticeSyntax a -> Bool
- Distribution.SPDX.LatticeSyntax: freeVars :: LatticeSyntax a -> [a]
- Distribution.SPDX.LatticeSyntax: instance Alternative (Eval v)
- Distribution.SPDX.LatticeSyntax: instance Applicative (Eval v)
- Distribution.SPDX.LatticeSyntax: instance Applicative LatticeSyntax
- Distribution.SPDX.LatticeSyntax: instance Data a => Data (LatticeSyntax a)
- Distribution.SPDX.LatticeSyntax: instance Eq a => Eq (LatticeSyntax a)
- Distribution.SPDX.LatticeSyntax: instance Foldable LatticeSyntax
- Distribution.SPDX.LatticeSyntax: instance Functor (Eval v)
- Distribution.SPDX.LatticeSyntax: instance Functor LatticeSyntax
- Distribution.SPDX.LatticeSyntax: instance Monad (Eval v)
- Distribution.SPDX.LatticeSyntax: instance Monad LatticeSyntax
- Distribution.SPDX.LatticeSyntax: instance MonadPlus (Eval v)
- Distribution.SPDX.LatticeSyntax: instance Ord a => Ord (LatticeSyntax a)
- Distribution.SPDX.LatticeSyntax: instance Read a => Read (LatticeSyntax a)
- Distribution.SPDX.LatticeSyntax: instance Show a => Show (LatticeSyntax a)
- Distribution.SPDX.LatticeSyntax: instance Traversable LatticeSyntax
- Distribution.SPDX.LatticeSyntax: instance Typeable LatticeSyntax
- Distribution.SPDX.LatticeSyntax: preorder :: Eq a => LatticeSyntax a -> LatticeSyntax a -> Bool
- Distribution.SPDX.LatticeSyntax: satisfiable :: Eq a => LatticeSyntax a -> Bool
+ Data.SPDX: EConjunction :: !LicenseExpression -> !LicenseExpression -> LicenseExpression
+ Data.SPDX: EDisjunction :: !LicenseExpression -> !LicenseExpression -> LicenseExpression
+ Data.SPDX: ELicense :: !Bool -> !(Either LicenseRef LicenseId) -> !(Maybe LicenseExceptionId) -> LicenseExpression
+ Data.SPDX: LicenseRef :: !(Maybe String) -> !String -> LicenseRef
+ Data.SPDX: data LicenseExceptionId
+ Data.SPDX: data LicenseExpression
+ Data.SPDX: data LicenseId
+ Data.SPDX: data LicenseRef
+ Data.SPDX: getLicenseExceptionId :: LicenseExceptionId -> String
+ Data.SPDX: getLicenseId :: LicenseId -> String
+ Data.SPDX: instance Eq Lic
+ Data.SPDX: instance Ord Lic
+ Data.SPDX: instance Read Lic
+ Data.SPDX: instance Show Lic
+ Data.SPDX: isOsiApproved :: LicenseId -> Bool
+ Data.SPDX: licenseExceptions :: [LicenseExceptionId]
+ Data.SPDX: licenseIdentifiers :: [LicenseId]
+ Data.SPDX: licenseRanges :: [[LicenseId]]
+ Data.SPDX: licenses :: [(LicenseId, String, Bool)]
+ Data.SPDX: lookupLicenseRange :: LicenseId -> [LicenseId]
+ Data.SPDX: lrDocument :: LicenseRef -> !(Maybe String)
+ Data.SPDX: lrLicense :: LicenseRef -> !String
+ Data.SPDX: mkLicenseId :: String -> Maybe LicenseId
+ Data.SPDX: parseExpression :: String -> [LicenseExpression]
+ Data.SPDX: satisfies :: LicenseExpression -> LicenseExpression -> Bool
+ Data.SPDX: unsafeParseExpr :: String -> LicenseExpression
+ Data.SPDX.LatticeSyntax: LBound :: Bool -> LatticeSyntax a
+ Data.SPDX.LatticeSyntax: LJoin :: (LatticeSyntax a) -> (LatticeSyntax a) -> LatticeSyntax a
+ Data.SPDX.LatticeSyntax: LMeet :: (LatticeSyntax a) -> (LatticeSyntax a) -> LatticeSyntax a
+ Data.SPDX.LatticeSyntax: LVar :: a -> LatticeSyntax a
+ Data.SPDX.LatticeSyntax: data LatticeSyntax a
+ Data.SPDX.LatticeSyntax: dual :: LatticeSyntax a -> LatticeSyntax a
+ Data.SPDX.LatticeSyntax: equivalent :: Eq a => LatticeSyntax a -> LatticeSyntax a -> Bool
+ Data.SPDX.LatticeSyntax: freeVars :: LatticeSyntax a -> [a]
+ Data.SPDX.LatticeSyntax: instance Alternative (Eval v)
+ Data.SPDX.LatticeSyntax: instance Applicative (Eval v)
+ Data.SPDX.LatticeSyntax: instance Applicative LatticeSyntax
+ Data.SPDX.LatticeSyntax: instance Data a => Data (LatticeSyntax a)
+ Data.SPDX.LatticeSyntax: instance Eq a => Eq (LatticeSyntax a)
+ Data.SPDX.LatticeSyntax: instance Foldable LatticeSyntax
+ Data.SPDX.LatticeSyntax: instance Functor (Eval v)
+ Data.SPDX.LatticeSyntax: instance Functor LatticeSyntax
+ Data.SPDX.LatticeSyntax: instance Monad (Eval v)
+ Data.SPDX.LatticeSyntax: instance Monad LatticeSyntax
+ Data.SPDX.LatticeSyntax: instance MonadPlus (Eval v)
+ Data.SPDX.LatticeSyntax: instance Ord a => Ord (LatticeSyntax a)
+ Data.SPDX.LatticeSyntax: instance Read a => Read (LatticeSyntax a)
+ Data.SPDX.LatticeSyntax: instance Show a => Show (LatticeSyntax a)
+ Data.SPDX.LatticeSyntax: instance Traversable LatticeSyntax
+ Data.SPDX.LatticeSyntax: instance Typeable LatticeSyntax
+ Data.SPDX.LatticeSyntax: preorder :: Eq a => LatticeSyntax a -> LatticeSyntax a -> Bool
+ Data.SPDX.LatticeSyntax: satisfiable :: Eq a => LatticeSyntax a -> Bool
Files
- README.md +1/−1
- dev/Main.hs +55/−0
- spdx.cabal +23/−9
- src/Data/SPDX.hs +70/−0
- src/Data/SPDX/LatticeSyntax.hs +126/−0
- src/Data/SPDX/Licenses.hs +352/−0
- src/Data/SPDX/Parser.hs +87/−0
- src/Data/SPDX/Ranges.hs +47/−0
- src/Data/SPDX/Types.hs +38/−0
- src/Distribution/SPDX.hs +0/−65
- src/Distribution/SPDX/LatticeSyntax.hs +0/−101
- src/Distribution/SPDX/Licenses.hs +0/−322
- src/Distribution/SPDX/Parser.hs +0/−81
- src/Distribution/SPDX/Ranges.hs +0/−47
- src/Distribution/SPDX/Types.hs +0/−20
- tests/Tests.hs +41/−9
README.md view
@@ -1,4 +1,4 @@-# sdpx +# sdpx [](https://travis-ci.org/phadej/spdx)
+ dev/Main.hs view
@@ -0,0 +1,55 @@+module Main (main) where++import Control.Applicative+import Data.List+import Data.Maybe+import Data.Traversable+import Text.XML.Light++simplify :: Element -> [[[String]]]+simplify el = + let worksheets = filter isWorksheetElement $ childrenElements el+ Just tables = traverse tableFromWorksheet worksheets+ in map tableElements tables++toElem :: Content -> Maybe Element+toElem (Elem e) = Just e+toElem _ = Nothing++isElement :: String -> Element -> Bool+isElement name = (name ==) . qName . elName++isWorksheetElement :: Element -> Bool+isWorksheetElement = isElement "Worksheet"++childrenElements :: Element -> [Element]+childrenElements = mapMaybe toElem . elContent++tableFromWorksheet :: Element -> Maybe Element+tableFromWorksheet = listToMaybe . filter (isElement "Table") . childrenElements++textContent :: Content -> Maybe String+textContent (Text t) = Just $ cdData t+textContent _ = Nothing++extractData :: Element -> String+extractData el = maybe "" id $ do dataEl <- listToMaybe . filter (isElement "Data") . childrenElements $ el+ textEl <- listToMaybe $ elContent dataEl+ text <- textContent textEl+ return text++tableElements :: Element -> [[String]] +tableElements = map cells . filter (isElement "Row") . childrenElements+ where cells = map extractData . filter (isElement "Cell") . childrenElements++extractLicense :: [String] -> (String, String, Bool)+extractLicense row = (row !! 1, row !! 0, (row !! 4) == "YES")++main :: IO ()+main = do+ contents <- readFile "data/spdx_licenselist.xml"+ let Just el = parseXMLDoc contents+ let parsed = simplify el+ let licenses = filter (not . null) $ parsed !! 0+ f `mapM_` (sort $ map extractLicense licenses)+ where f (l, n, osi) = putStrLn $ " , (LicenseId " ++ show l ++ ", " ++ show n ++ ", " ++ show osi ++ ")"
spdx.cabal view
@@ -1,5 +1,5 @@ name: spdx-version: 0.0.1.0+version: 0.1.0.0 synopsis: SPDX license expression language description: Implementation of <http://spdx.org/sites/spdx/files/SPDX-2.0.pdf SPDX> related functionality. homepage: https://github.com/phadej/spdx@@ -8,19 +8,24 @@ author: Oleg Grenrus maintainer: Oleg Grenrus <oleg.grenrus@iki.fi> copyright: (c) 2015 Oleg Grenrus-category: Distribution+category: Data build-type: Simple extra-source-files: README.md cabal-version: >=1.10 +flag developer+ description: Whether to build development tools+ default: False+ manual: True+ library default-language: Haskell2010- exposed-modules: Distribution.SPDX,- Distribution.SPDX.LatticeSyntax- other-modules: Distribution.SPDX.Licenses,- Distribution.SPDX.Types,- Distribution.SPDX.Parser,- Distribution.SPDX.Ranges+ exposed-modules: Data.SPDX,+ Data.SPDX.LatticeSyntax+ other-modules: Data.SPDX.Licenses,+ Data.SPDX.Types,+ Data.SPDX.Parser,+ Data.SPDX.Ranges other-extensions: CPP DeriveFunctor, GeneralizedNewtypeDeriving,@@ -39,7 +44,16 @@ default-language: Haskell2010 hs-source-dirs: tests ghc-options: -Wall- build-depends: base >=4.5 && <5,+ build-depends: base >=4.5 && <4.9, tasty >=0.10 && <0.11, tasty-quickcheck >=0.8 && <0.9, spdx++executable spdx-data+ if !flag(developer)+ buildable: False+ main-is: Main.hs+ default-language: Haskell2010+ hs-source-dirs: dev+ build-depends: base >=4.5 && <4.9,+ xml >=1.3 && <1.4
+ src/Data/SPDX.hs view
@@ -0,0 +1,70 @@+-- |+-- Module : Data.SPDX+-- Description : SPDX licenses and expression language+-- Copyright : (c) 2015 Oleg Grenrus+-- License : BSD3+-- Maintainer : Oleg Grenrus <oleg.grenrus@iki.fi>+--+module Data.SPDX (+ -- * Types+ LicenseId+ , getLicenseId+ , LicenseExceptionId+ , getLicenseExceptionId+ , LicenseRef(..)+ , LicenseExpression(..)+ -- * Data+ , licenses+ , licenseIdentifiers+ , mkLicenseId+ , isOsiApproved+ , licenseExceptions+ -- ** Ranges+ , licenseRanges+ , lookupLicenseRange+ -- * Parsing+ , parseExpression+ , unsafeParseExpr+ -- * Logic+ , satisfies+ ) where++import Data.SPDX.Types+import Data.SPDX.Ranges+import Data.SPDX.Licenses+import Data.SPDX.Parser+import Data.SPDX.LatticeSyntax++data Lic = Lic (Either LicenseRef LicenseId) (Maybe LicenseExceptionId)+ deriving (Eq, Ord, Show, Read)++exprToLSLic :: LicenseExpression -> LatticeSyntax Lic+exprToLSLic (ELicense False l e) = LVar (Lic l e)+exprToLSLic (ELicense True (Right l) e) = foldr1 LJoin $ map (\l' -> LVar $ Lic (Right l') e) $ lookupLicenseRange l+-- We don't know anything about newer license references+exprToLSLic (ELicense True (Left l) e) = LVar (Lic (Left l) e)+exprToLSLic (EConjunction a b) = LMeet (exprToLSLic a) (exprToLSLic b)+exprToLSLic (EDisjunction a b) = LJoin (exprToLSLic a) (exprToLSLic b)++-- |+--+-- @⟦ satisfies a b ⟧ ≡ a ≥ b ≡ a ∧ b = b @+--+-- >>> unsafeParseExpr "GPL-3.0" `satisfies` unsafeParseExpr "ISC AND MIT"+-- False+--+-- >>> unsafeParseExpr "Zlib" `satisfies` unsafeParseExpr "ISC AND MIT AND Zlib"+-- True+--+-- >>> unsafeParseExpr "(MIT OR GPL-2.0)" `satisfies` unsafeParseExpr "(ISC AND MIT)"+-- True+--+-- >>> unsafeParseExpr "(MIT AND GPL-2.0)" `satisfies` unsafeParseExpr "(MIT AND GPL-2.0)"+-- True+--+-- >>> unsafeParseExpr "(MIT AND GPL-2.0)" `satisfies` unsafeParseExpr "(ISC AND GPL-2.0)"+-- False+satisfies :: LicenseExpression -- ^ package license+ -> LicenseExpression -- ^ license policy+ -> Bool+satisfies a b = exprToLSLic b `preorder` exprToLSLic a
+ src/Data/SPDX/LatticeSyntax.hs view
@@ -0,0 +1,126 @@+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE DeriveFoldable #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE DeriveDataTypeable #-}+-- |+-- Module : Data.SPDX.LatticeSyntax+-- Description : General lattice tools+-- Copyright : (c) 2015 Oleg Grenrus+-- License : BSD3+-- Maintainer : Oleg Grenrus <oleg.grenrus@iki.fi>+--+-- Inspired by <http://www.well-typed.com/blog/2014/12/simple-smt-solver/ Simple SMT Solver>.+--+-- In future this module will probably be moved into separate package.+module Data.SPDX.LatticeSyntax (LatticeSyntax(..), dual, freeVars, equivalent, preorder, satisfiable) where++import Control.Applicative+import Control.Monad+import Control.Monad.Trans.State+import Data.Data+import Data.Foldable+import Data.Traversable+import Prelude hiding (all, or)++data LatticeSyntax a = LVar a+ | LBound Bool+ | LJoin (LatticeSyntax a) (LatticeSyntax a)+ | LMeet (LatticeSyntax a) (LatticeSyntax a)+ deriving (Eq, Ord, Read, Show, Functor, Foldable, Traversable, Typeable, Data)++instance Applicative LatticeSyntax where+ pure = return+ (<*>) = ap++instance Monad LatticeSyntax where+ return = LVar+ LVar x >>= f = f x+ LBound b >>= _ = LBound b+ LJoin a b >>= f = LJoin (a >>= f) (b >>= f)+ LMeet a b >>= f = LMeet (a >>= f) (b >>= f)++freeVars :: LatticeSyntax a -> [a]+freeVars = toList++dual :: LatticeSyntax a -> LatticeSyntax a+dual (LVar v) = LVar v+dual (LBound t) = LBound $ not t+dual (LJoin a b) = LMeet (dual a) (dual b)+dual (LMeet a b) = LJoin (dual a) (dual b)++-- | Test for equivalence.+--+-- >>> equivalent (LMeet (LVar 'a') (LVar 'b')) (LMeet (LVar 'b') (LVar 'a'))+-- True+--+-- >>> equivalent (LVar 'a') (LMeet (LVar 'a') (LVar 'a'))+-- True+--+-- >>> equivalent (LMeet (LVar 'a') (LVar 'b')) (LMeet (LVar 'b') (LVar 'b'))+-- False+equivalent :: Eq a => LatticeSyntax a -> LatticeSyntax a -> Bool+equivalent a b = all (uncurry (==)) . runEval $ p+ where p = (,) <$> evalLattice a <*> evalLattice b++-- | Test for preorder.+--+-- @ a ≤ b ⇔ a ∨ b ≡ b ⇔ a ≡ a ∧ b @+--+-- >>> preorder (LVar 'a' `LMeet` LVar 'b') (LVar 'a')+-- True+--+-- >>> preorder (LVar 'a') (LVar 'a' `LMeet` LVar 'b')+-- False+preorder :: Eq a => LatticeSyntax a -> LatticeSyntax a -> Bool+preorder a b = (a `LJoin` b) `equivalent` b++-- | Return `True` if for some variable assigment expression evaluates to `True`.+satisfiable :: Eq a => LatticeSyntax a -> Bool +satisfiable = or . runEval . evalLattice++newtype Eval v a = Eval { unEval :: StateT [(v, Bool)] [] a }+ deriving (Functor, Applicative, Alternative, Monad, MonadPlus)++runEval :: Eval v a -> [a]+runEval act = evalStateT (unEval act) []++evalLattice :: Eq v => LatticeSyntax v -> Eval v Bool+evalLattice (LVar v) = guess v+evalLattice (LBound b) = return b+evalLattice (LJoin a b) = evalLattice a ||^ evalLattice b+evalLattice (LMeet a b) = evalLattice a &&^ evalLattice b++guess :: Eq v => v -> Eval v Bool+guess v = Eval $ do+ st <- get+ let remember b = put ((v, b) : st) >> return b+ case lookup v st of+ Just b -> return b+ Nothing -> remember True <|> remember False++-- From Control.Monad.Extra of extra++-- | Like @if@, but where the test can be monadic.+ifM :: Monad m => m Bool -> m a -> m a -> m a+ifM b t f = do b' <- b; if b' then t else f++-- | The lazy '||' operator lifted to a monad. If the first+-- argument evaluates to 'True' the second argument will not+-- be evaluated.+--+-- > Just True ||^ undefined == Just True+-- > Just False ||^ Just True == Just True+-- > Just False ||^ Just False == Just False+(||^) :: Monad m => m Bool -> m Bool -> m Bool+(||^) a b = ifM a (return True) b++-- | The lazy '&&' operator lifted to a monad. If the first+-- argument evaluates to 'False' the second argument will not+-- be evaluated.+--+-- > Just False &&^ undefined == Just False+-- > Just True &&^ Just True == Just True+-- > Just True &&^ Just False == Just False+(&&^) :: Monad m => m Bool -> m Bool -> m Bool+(&&^) a b = ifM a b (return False)
+ src/Data/SPDX/Licenses.hs view
@@ -0,0 +1,352 @@+module Data.SPDX.Licenses (+ licenses+ , licenseIdentifiers+ , mkLicenseId+ , isOsiApproved+ , licenseExceptions+ ) where++import Data.Foldable+import Data.Maybe++import Data.SPDX.Types++licenseExceptions :: [LicenseExceptionId]+licenseExceptions = map LicenseExceptionId [+ "Autoconf-exception-2.0",+ "Autoconf-exception-3.0",+ "Bison-exception-2.2",+ "Classpath-exception-2.0",+ "eCos-exception-2.0",+ "Font-exception-2.0",+ "GCC-exception-2.0",+ "GCC-exception-3.1",+ "WxWindows-exception-3.1"+ ]++-- | A list of SPDX licenses identifiers.+--+-- See <http://spdx.org/licenses/>.+licenseIdentifiers :: [LicenseId]+licenseIdentifiers = map fstOf3 licenses++fstOf3 :: (a, b, c) -> a+fstOf3 (x,_,_) = x++--sndOf3 :: (a, b, c) -> b+--sndOf3 (_,x,_) = x++trdOf3 :: (a, b, c) -> c+trdOf3 (_,_,x) = x++-- | Lookup `LicenseId` by string representation+mkLicenseId :: String -> Maybe LicenseId+mkLicenseId str = find ((== str) . getLicenseId) licenseIdentifiers++-- | Whether license is OSI approved+--+-- See <http://opensource.org/licenses/alphabetical>+isOsiApproved :: LicenseId -> Bool+isOsiApproved l = trdOf3 $ fromJust $ find ((==l) . fstOf3) licenses++-- | A list of `LicenseId`, license name and whether the license is OSI approved.+--+-- See <http://spdx.org/licenses/>.+licenses :: [(LicenseId, String, Bool)]+licenses =+ [ (LicenseId "AAL", "Attribution Assurance License", True)+ , (LicenseId "ADSL", "Amazon Digital Services License", False)+ , (LicenseId "AFL-1.1", "Academic Free License v1.1", True)+ , (LicenseId "AFL-1.2", "Academic Free License v1.2", True)+ , (LicenseId "AFL-2.0", "Academic Free License v2.0", True)+ , (LicenseId "AFL-2.1", "Academic Free License v2.1", True)+ , (LicenseId "AFL-3.0", "Academic Free License v3.0", True)+ , (LicenseId "AGPL-1.0", "Affero General Public License v1.0", False)+ , (LicenseId "AGPL-3.0", "GNU Affero General Public License v3.0", True)+ , (LicenseId "AMDPLPA", "AMD's plpa_map.c License", False)+ , (LicenseId "AML", "Apple MIT License", False)+ , (LicenseId "AMPAS", "Academy of Motion Picture Arts and Sciences BSD", False)+ , (LicenseId "ANTLR-PD", "ANTLR Software Rights Notice", False)+ , (LicenseId "APAFML", "Adobe Postscript AFM License", False)+ , (LicenseId "APL-1.0", "Adaptive Public License 1.0", True)+ , (LicenseId "APSL-1.0", "Apple Public Source License 1.0", True)+ , (LicenseId "APSL-1.1", "Apple Public Source License 1.1", True)+ , (LicenseId "APSL-1.2", "Apple Public Source License 1.2", True)+ , (LicenseId "APSL-2.0", "Apple Public Source License 2.0", True)+ , (LicenseId "Abstyles", "Abstyles License", False)+ , (LicenseId "Adobe-2006", "Adobe Systems Incorporated Source Code License Agreement", False)+ , (LicenseId "Adobe-Glyph", "Adobe Glyph List License", False)+ , (LicenseId "Afmparse", "Afmparse License", False)+ , (LicenseId "Aladdin", "Aladdin Free Public License", False)+ , (LicenseId "Apache-1.0", "Apache License 1.0", False)+ , (LicenseId "Apache-1.1", "Apache License 1.1", True)+ , (LicenseId "Apache-2.0", "Apache License 2.0", True)+ , (LicenseId "Artistic-1.0", "Artistic License 1.0", True)+ , (LicenseId "Artistic-1.0-Perl", "Artistic License 1.0 (Perl)", True)+ , (LicenseId "Artistic-1.0-cl8", "Artistic License 1.0 w/clause 8", True)+ , (LicenseId "Artistic-2.0", "Artistic License 2.0", True)+ , (LicenseId "BSD-2-Clause", "BSD 2-clause \"Simplified\" License", True)+ , (LicenseId "BSD-2-Clause-FreeBSD", "BSD 2-clause FreeBSD License", False)+ , (LicenseId "BSD-2-Clause-NetBSD", "BSD 2-clause NetBSD License", False)+ , (LicenseId "BSD-3-Clause", "BSD 3-clause \"New\" or \"Revised\" License", True)+ , (LicenseId "BSD-3-Clause-Attribution", "BSD with attribution", False)+ , (LicenseId "BSD-3-Clause-Clear", "BSD 3-clause Clear License", False)+ , (LicenseId "BSD-3-Clause-LBNL", "Lawrence Berkeley National Labs BSD variant license", False)+ , (LicenseId "BSD-4-Clause", "BSD 4-clause \"Original\" or \"Old\" License", False)+ , (LicenseId "BSD-4-Clause-UC", "BSD-4-Clause (University of California-Specific)", False)+ , (LicenseId "BSD-Protection", "BSD Protection License", False)+ , (LicenseId "BSL-1.0", "Boost Software License 1.0", True)+ , (LicenseId "Bahyph", "Bahyph License", False)+ , (LicenseId "Barr", "Barr License", False)+ , (LicenseId "Beerware", "Beerware License", False)+ , (LicenseId "BitTorrent-1.0", "BitTorrent Open Source License v1.0", False)+ , (LicenseId "BitTorrent-1.1", "BitTorrent Open Source License v1.1", False)+ , (LicenseId "Borceux", "Borceux license", False)+ , (LicenseId "CATOSL-1.1", "Computer Associates Trusted Open Source License 1.1", True)+ , (LicenseId "CC-BY-1.0", "Creative Commons Attribution 1.0", False)+ , (LicenseId "CC-BY-2.0", "Creative Commons Attribution 2.0", False)+ , (LicenseId "CC-BY-2.5", "Creative Commons Attribution 2.5", False)+ , (LicenseId "CC-BY-3.0", "Creative Commons Attribution 3.0", False)+ , (LicenseId "CC-BY-4.0", "Creative Commons Attribution 4.0", False)+ , (LicenseId "CC-BY-NC-1.0", "Creative Commons Attribution Non Commercial 1.0", False)+ , (LicenseId "CC-BY-NC-2.0", "Creative Commons Attribution Non Commercial 2.0", False)+ , (LicenseId "CC-BY-NC-2.5", "Creative Commons Attribution Non Commercial 2.5", False)+ , (LicenseId "CC-BY-NC-3.0", "Creative Commons Attribution Non Commercial 3.0", False)+ , (LicenseId "CC-BY-NC-4.0", "Creative Commons Attribution Non Commercial 4.0", False)+ , (LicenseId "CC-BY-NC-ND-1.0", "Creative Commons Attribution Non Commercial No Derivatives 1.0", False)+ , (LicenseId "CC-BY-NC-ND-2.0", "Creative Commons Attribution Non Commercial No Derivatives 2.0", False)+ , (LicenseId "CC-BY-NC-ND-2.5", "Creative Commons Attribution Non Commercial No Derivatives 2.5", False)+ , (LicenseId "CC-BY-NC-ND-3.0", "Creative Commons Attribution Non Commercial No Derivatives 3.0", False)+ , (LicenseId "CC-BY-NC-ND-4.0", "Creative Commons Attribution Non Commercial No Derivatives 4.0", False)+ , (LicenseId "CC-BY-NC-SA-1.0", "Creative Commons Attribution Non Commercial Share Alike 1.0", False)+ , (LicenseId "CC-BY-NC-SA-2.0", "Creative Commons Attribution Non Commercial Share Alike 2.0", False)+ , (LicenseId "CC-BY-NC-SA-2.5", "Creative Commons Attribution Non Commercial Share Alike 2.5", False)+ , (LicenseId "CC-BY-NC-SA-3.0", "Creative Commons Attribution Non Commercial Share Alike 3.0", False)+ , (LicenseId "CC-BY-NC-SA-4.0", "Creative Commons Attribution Non Commercial Share Alike 4.0", False)+ , (LicenseId "CC-BY-ND-1.0", "Creative Commons Attribution No Derivatives 1.0", False)+ , (LicenseId "CC-BY-ND-2.0", "Creative Commons Attribution No Derivatives 2.0", False)+ , (LicenseId "CC-BY-ND-2.5", "Creative Commons Attribution No Derivatives 2.5", False)+ , (LicenseId "CC-BY-ND-3.0", "Creative Commons Attribution No Derivatives 3.0", False)+ , (LicenseId "CC-BY-ND-4.0", "Creative Commons Attribution No Derivatives 4.0", False)+ , (LicenseId "CC-BY-SA-1.0", "Creative Commons Attribution Share Alike 1.0", False)+ , (LicenseId "CC-BY-SA-2.0", "Creative Commons Attribution Share Alike 2.0", False)+ , (LicenseId "CC-BY-SA-2.5", "Creative Commons Attribution Share Alike 2.5", False)+ , (LicenseId "CC-BY-SA-3.0", "Creative Commons Attribution Share Alike 3.0", False)+ , (LicenseId "CC-BY-SA-4.0", "Creative Commons Attribution Share Alike 4.0", False)+ , (LicenseId "CC0-1.0", "Creative Commons Zero v1.0 Universal", False)+ , (LicenseId "CDDL-1.0", "Common Development and Distribution License 1.0", True)+ , (LicenseId "CDDL-1.1", "Common Development and Distribution License 1.1", False)+ , (LicenseId "CECILL-1.0", "CeCILL Free Software License Agreement v1.0", False)+ , (LicenseId "CECILL-1.1", "CeCILL Free Software License Agreement v1.1", False)+ , (LicenseId "CECILL-2.0", "CeCILL Free Software License Agreement v2.0", False)+ , (LicenseId "CECILL-B", "CeCILL-B Free Software License Agreement", False)+ , (LicenseId "CECILL-C", "CeCILL-C Free Software License Agreement", False)+ , (LicenseId "CNRI-Python", "CNRI Python License", True)+ , (LicenseId "CNRI-Python-GPL-Compatible", "CNRI Python Open Source GPL Compatible License Agreement", False)+ , (LicenseId "CPAL-1.0", "Common Public Attribution License 1.0", True)+ , (LicenseId "CPL-1.0", "Common Public License 1.0", True)+ , (LicenseId "CPOL-1.02", "Code Project Open License 1.02", False)+ , (LicenseId "CUA-OPL-1.0", "CUA Office Public License v1.0", True)+ , (LicenseId "Caldera", "Caldera License", False)+ , (LicenseId "ClArtistic", "Clarified Artistic License", False)+ , (LicenseId "Condor-1.1", "Condor Public License v1.1", False)+ , (LicenseId "Crossword", "Crossword License", False)+ , (LicenseId "Cube", "Cube License", False)+ , (LicenseId "D-FSL-1.0", "Deutsche Freie Software Lizenz", False)+ , (LicenseId "DOC", "DOC License", False)+ , (LicenseId "DSDP", "DSDP License", False)+ , (LicenseId "Dotseqn", "Dotseqn License", False)+ , (LicenseId "ECL-1.0", "Educational Community License v1.0", True)+ , (LicenseId "ECL-2.0", "Educational Community License v2.0", True)+ , (LicenseId "EFL-1.0", "Eiffel Forum License v1.0", True)+ , (LicenseId "EFL-2.0", "Eiffel Forum License v2.0", True)+ , (LicenseId "EPL-1.0", "Eclipse Public License 1.0", True)+ , (LicenseId "EUDatagrid", "EU DataGrid Software License", True)+ , (LicenseId "EUPL-1.0", "European Union Public License 1.0", False)+ , (LicenseId "EUPL-1.1", "European Union Public License 1.1", True)+ , (LicenseId "Entessa", "Entessa Public License v1.0", True)+ , (LicenseId "ErlPL-1.1", "Erlang Public License v1.1", False)+ , (LicenseId "Eurosym", "Eurosym License", False)+ , (LicenseId "FSFUL", "FSF Unlimited License", False)+ , (LicenseId "FSFULLR", "FSF Unlimited License (with License Retention)", False)+ , (LicenseId "FTL", "Freetype Project License", False)+ , (LicenseId "Fair", "Fair License", True)+ , (LicenseId "Frameworx-1.0", "Frameworx Open License 1.0", True)+ , (LicenseId "FreeImage", "FreeImage Public License v1.0", False)+ , (LicenseId "GFDL-1.1", "GNU Free Documentation License v1.1", False)+ , (LicenseId "GFDL-1.2", "GNU Free Documentation License v1.2", False)+ , (LicenseId "GFDL-1.3", "GNU Free Documentation License v1.3", False)+ , (LicenseId "GL2PS", "GL2PS License", False)+ , (LicenseId "GPL-1.0", "GNU General Public License v1.0 only", False)+ , (LicenseId "GPL-2.0", "GNU General Public License v2.0 only", True)+ , (LicenseId "GPL-3.0", "GNU General Public License v3.0 only", True)+ , (LicenseId "Giftware", "Giftware License", False)+ , (LicenseId "Glide", "3dfx Glide License", False)+ , (LicenseId "Glulxe", "Glulxe License", False)+ , (LicenseId "HPND", "Historic Permission Notice and Disclaimer", True)+ , (LicenseId "HaskellReport", "Haskell Language Report License", False)+ , (LicenseId "IBM-pibs", "IBM PowerPC Initialization and Boot Software", False)+ , (LicenseId "ICU", "ICU License", False)+ , (LicenseId "IJG", "Independent JPEG Group License", False)+ , (LicenseId "IPA", "IPA Font License", True)+ , (LicenseId "IPL-1.0", "IBM Public License v1.0", True)+ , (LicenseId "ISC", "ISC License", True)+ , (LicenseId "ImageMagick", "ImageMagick License", False)+ , (LicenseId "Imlib2", "Imlib2 License", False)+ , (LicenseId "Intel", "Intel Open Source License", True)+ , (LicenseId "Intel-ACPI", "Intel ACPI Software License Agreement", False)+ , (LicenseId "JSON", "JSON License", False)+ , (LicenseId "JasPer-2.0", "JasPer License", False)+ , (LicenseId "LGPL-2.0", "GNU Library General Public License v2 only", True)+ , (LicenseId "LGPL-2.1", "GNU Lesser General Public License v2.1 only", True)+ , (LicenseId "LGPL-3.0", "GNU Lesser General Public License v3.0 only", True)+ , (LicenseId "LPL-1.0", "Lucent Public License Version 1.0", True)+ , (LicenseId "LPL-1.02", "Lucent Public License v1.02", True)+ , (LicenseId "LPPL-1.0", "LaTeX Project Public License v1.0", False)+ , (LicenseId "LPPL-1.1", "LaTeX Project Public License v1.1", False)+ , (LicenseId "LPPL-1.2", "LaTeX Project Public License v1.2", False)+ , (LicenseId "LPPL-1.3a", "LaTeX Project Public License 1.3a", False)+ , (LicenseId "LPPL-1.3c", "LaTeX Project Public License v1.3c", True)+ , (LicenseId "Latex2e", "Latex2e License", False)+ , (LicenseId "Leptonica", "Leptonica License", False)+ , (LicenseId "Libpng", "libpng License", False)+ , (LicenseId "License Identifier", "Full name of License", False)+ , (LicenseId "MIT", "MIT License", True)+ , (LicenseId "MIT-CMU", "CMU License", False)+ , (LicenseId "MIT-advertising", "Enlightenment License (e16)", False)+ , (LicenseId "MIT-enna", "enna License", False)+ , (LicenseId "MIT-feh", "feh License", False)+ , (LicenseId "MITNFA", "MIT +no-false-attribs license", False)+ , (LicenseId "MPL-1.0", "Mozilla Public License 1.0", True)+ , (LicenseId "MPL-1.1", "Mozilla Public License 1.1", True)+ , (LicenseId "MPL-2.0", "Mozilla Public License 2.0", True)+ , (LicenseId "MPL-2.0-no-copyleft-exception", "Mozilla Public License 2.0 (no copyleft exception)", True)+ , (LicenseId "MS-PL", "Microsoft Public License", True)+ , (LicenseId "MS-RL", "Microsoft Reciprocal License", True)+ , (LicenseId "MTLL", "Matrix Template Library License", False)+ , (LicenseId "MakeIndex", "MakeIndex License", False)+ , (LicenseId "MirOS", "MirOS Licence", True)+ , (LicenseId "Motosoto", "Motosoto License", True)+ , (LicenseId "Multics", "Multics License", True)+ , (LicenseId "Mup", "Mup License", False)+ , (LicenseId "NASA-1.3", "NASA Open Source Agreement 1.3", True)+ , (LicenseId "NBPL-1.0", "Net Boolean Public License v1", False)+ , (LicenseId "NCSA", "University of Illinois/NCSA Open Source License", True)+ , (LicenseId "NGPL", "Nethack General Public License", True)+ , (LicenseId "NLPL", "No Limit Public License", False)+ , (LicenseId "NOSL", "Netizen Open Source License", False)+ , (LicenseId "NPL-1.0", "Netscape Public License v1.0", False)+ , (LicenseId "NPL-1.1", "Netscape Public License v1.1", False)+ , (LicenseId "NPOSL-3.0", "Non-Profit Open Software License 3.0", True)+ , (LicenseId "NRL", "NRL License", False)+ , (LicenseId "NTP", "NTP License", True)+ , (LicenseId "Naumen", "Naumen Public License", True)+ , (LicenseId "NetCDF", "NetCDF license", False)+ , (LicenseId "Newsletr", "Newsletr License", False)+ , (LicenseId "Nokia", "Nokia Open Source License", True)+ , (LicenseId "Noweb", "Noweb License", False)+ , (LicenseId "Nunit", "Nunit License", False)+ , (LicenseId "OCLC-2.0", "OCLC Research Public License 2.0", True)+ , (LicenseId "ODbL-1.0", "ODC Open Database License v1.0", False)+ , (LicenseId "OFL-1.0", "SIL Open Font License 1.0", False)+ , (LicenseId "OFL-1.1", "SIL Open Font License 1.1", True)+ , (LicenseId "OGTSL", "Open Group Test Suite License", True)+ , (LicenseId "OLDAP-1.1", "Open LDAP Public License v1.1", False)+ , (LicenseId "OLDAP-1.2", "Open LDAP Public License v1.2", False)+ , (LicenseId "OLDAP-1.3", "Open LDAP Public License v1.3", False)+ , (LicenseId "OLDAP-1.4", "Open LDAP Public License v1.4", False)+ , (LicenseId "OLDAP-2.0", "Open LDAP Public License v2.0 (or possibly 2.0A and 2.0B)", False)+ , (LicenseId "OLDAP-2.0.1", "Open LDAP Public License v2.0.1", False)+ , (LicenseId "OLDAP-2.1", "Open LDAP Public License v2.1", False)+ , (LicenseId "OLDAP-2.2", "Open LDAP Public License v2.2", False)+ , (LicenseId "OLDAP-2.2.1", "Open LDAP Public License v2.2.1", False)+ , (LicenseId "OLDAP-2.2.2", "Open LDAP Public License 2.2.2", False)+ , (LicenseId "OLDAP-2.3", "Open LDAP Public License v2.3", False)+ , (LicenseId "OLDAP-2.4", "Open LDAP Public License v2.4", False)+ , (LicenseId "OLDAP-2.5", "Open LDAP Public License v2.5", False)+ , (LicenseId "OLDAP-2.6", "Open LDAP Public License v2.6", False)+ , (LicenseId "OLDAP-2.7", "Open LDAP Public License v2.7", False)+ , (LicenseId "OLDAP-2.8", "Open LDAP Public License v2.8", False)+ , (LicenseId "OML", "Open Market License", False)+ , (LicenseId "OPL-1.0", "Open Public License v1.0", False)+ , (LicenseId "OSL-1.0", "Open Software License 1.0", True)+ , (LicenseId "OSL-1.1", "Open Software License 1.1", False)+ , (LicenseId "OSL-2.0", "Open Software License 2.0", True)+ , (LicenseId "OSL-2.1", "Open Software License 2.1", True)+ , (LicenseId "OSL-3.0", "Open Software License 3.0", True)+ , (LicenseId "OpenSSL", "OpenSSL License", False)+ , (LicenseId "PDDL-1.0", "ODC Public Domain Dedication & License 1.0", False)+ , (LicenseId "PHP-3.0", "PHP License v3.0", True)+ , (LicenseId "PHP-3.01", "PHP License v3.01", False)+ , (LicenseId "Plexus", "Plexus Classworlds License", False)+ , (LicenseId "PostgreSQL", "PostgreSQL License", True)+ , (LicenseId "Python-2.0", "Python License 2.0", True)+ , (LicenseId "QPL-1.0", "Q Public License 1.0", True)+ , (LicenseId "Qhull", "Qhull License", False)+ , (LicenseId "RHeCos-1.1", "Red Hat eCos Public License v1.1", False)+ , (LicenseId "RPL-1.1", "Reciprocal Public License 1.1", True)+ , (LicenseId "RPL-1.5", "Reciprocal Public License 1.5", True)+ , (LicenseId "RPSL-1.0", "RealNetworks Public Source License v1.0", True)+ , (LicenseId "RSCPL", "Ricoh Source Code Public License", True)+ , (LicenseId "Rdisc", "Rdisc License", False)+ , (LicenseId "Ruby", "Ruby License", False)+ , (LicenseId "SAX-PD", "Sax Public Domain Notice", False)+ , (LicenseId "SCEA", "SCEA Shared Source License", False)+ , (LicenseId "SGI-B-1.0", "SGI Free Software License B v1.0", False)+ , (LicenseId "SGI-B-1.1", "SGI Free Software License B v1.1", False)+ , (LicenseId "SGI-B-2.0", "SGI Free Software License B v2.0", False)+ , (LicenseId "SISSL", "Sun Industry Standards Source License v1.1", True)+ , (LicenseId "SISSL-1.2", "Sun Industry Standards Source License v1.2", False)+ , (LicenseId "SMLNJ", "Standard ML of New Jersey License", False)+ , (LicenseId "SNIA", "SNIA Public License 1.1", False)+ , (LicenseId "SPL-1.0", "Sun Public License v1.0", True)+ , (LicenseId "SWL", "Scheme Widget Library (SWL) Software License Agreement", False)+ , (LicenseId "Saxpath", "Saxpath License", False)+ , (LicenseId "SimPL-2.0", "Simple Public License 2.0", True)+ , (LicenseId "Sleepycat", "Sleepycat License", True)+ , (LicenseId "SugarCRM-1.1.3", "SugarCRM Public License v1.1.3", False)+ , (LicenseId "TCL", "TCL/TK License", False)+ , (LicenseId "TMate", "TMate Open Source License", False)+ , (LicenseId "TORQUE-1.1", "TORQUE v2.5+ Software License v1.1", False)+ , (LicenseId "TOSL", "Trusster Open Source License", False)+ , (LicenseId "Unicode-TOU", "Unicode Terms of Use", False)+ , (LicenseId "Unlicense", "The Unlicense", False)+ , (LicenseId "VOSTROM", "VOSTROM Public License for Open Source", False)+ , (LicenseId "VSL-1.0", "Vovida Software License v1.0", True)+ , (LicenseId "Vim", "Vim License", False)+ , (LicenseId "W3C", "W3C Software Notice and License (2002-12-31)", True)+ , (LicenseId "W3C-19980720", "W3C Software Notice and License (1998-07-20)", False)+ , (LicenseId "WTFPL", "Do What The F*ck You Want To Public License", False)+ , (LicenseId "Watcom-1.0", "Sybase Open Watcom Public License 1.0", True)+ , (LicenseId "Wsuipa", "Wsuipa License", False)+ , (LicenseId "X11", "X11 License", False)+ , (LicenseId "XFree86-1.1", "XFree86 License 1.1", False)+ , (LicenseId "XSkat", "XSkat License", False)+ , (LicenseId "Xerox", "Xerox License", False)+ , (LicenseId "Xnet", "X.Net License", True)+ , (LicenseId "YPL-1.0", "Yahoo! Public License v1.0", False)+ , (LicenseId "YPL-1.1", "Yahoo! Public License v1.1", False)+ , (LicenseId "ZPL-1.1", "Zope Public License 1.1", False)+ , (LicenseId "ZPL-2.0", "Zope Public License 2.0", True)+ , (LicenseId "ZPL-2.1", "Zope Public License 2.1", False)+ , (LicenseId "Zed", "Zed License", False)+ , (LicenseId "Zend-2.0", "Zend License v2.0", False)+ , (LicenseId "Zimbra-1.3", "Zimbra Public License v1.3", False)+ , (LicenseId "Zimbra-1.4", "Zimbra Public License v1.4", False)+ , (LicenseId "Zlib", "zlib License", True)+ , (LicenseId "bzip2-1.0.5", "bzip2 and libbzip2 License v1.0.5", False)+ , (LicenseId "bzip2-1.0.6", "bzip2 and libbzip2 License v1.0.6", False)+ , (LicenseId "diffmark", "diffmark license", False)+ , (LicenseId "dvipdfm", "dvipdfm License", False)+ , (LicenseId "eGenix", "eGenix.com Public License 1.1.0", False)+ , (LicenseId "gSOAP-1.3b", "gSOAP Public License v1.3b", False)+ , (LicenseId "gnuplot", "gnuplot License", False)+ , (LicenseId "iMatix", "iMatix Standard Function Library Agreement", False)+ , (LicenseId "libtiff", "libtiff License", False)+ , (LicenseId "mpich2", "mpich2 License", False)+ , (LicenseId "psfrag", "psfrag License", False)+ , (LicenseId "psutils", "psutils License", False)+ , (LicenseId "xinetd", "xinetd License", False)+ , (LicenseId "xpp", "XPP License", False)+ , (LicenseId "zlib-acknowledgement", "zlib/libpng License with Acknowledgement", False)+ ]
+ src/Data/SPDX/Parser.hs view
@@ -0,0 +1,87 @@+{-# LANGUAGE CPP #-}+module Data.SPDX.Parser (parseExpression, unsafeParseExpr) where++#ifndef MIN_VERSION_base+#define MIN_VERSION_base(x,y,z) 0+#endif++#if !MIN_VERSION_base(4, 8, 0)+import Control.Applicative+#endif++import Data.Char+import Text.ParserCombinators.ReadP++import Data.SPDX.Types+import Data.SPDX.Licenses (licenseIdentifiers, licenseExceptions)++license :: ReadP LicenseId+license = choice (map f licenseIdentifiers)+ where f l = l <$ string (getLicenseId l)++licenseException :: ReadP LicenseExceptionId+licenseException = choice (map f licenseExceptions)+ where f l = l <$ string (getLicenseExceptionId l)++elicense :: ReadP LicenseExpression+elicense = (\l -> ELicense False (Right l) Nothing) <$> license++elicenseWith :: ReadP LicenseExpression+elicenseWith = (\l e -> ELicense False (Right l) (Just e)) <$> license <* skipSpaces1 <* string "WITH" <* skipSpaces1 <*> licenseException++elicenseAndNewer :: ReadP LicenseExpression+elicenseAndNewer = (\l -> ELicense True (Right l) Nothing) <$> license <* char '+'++elicenseWithAndNewer :: ReadP LicenseExpression+elicenseWithAndNewer = (\l e -> ELicense True (Right l) (Just e)) <$> license <* char '+' <* string " WITH " <*> licenseException++elicenseRef :: ReadP LicenseExpression+elicenseRef = (\licId -> ELicense False (Left $ LicenseRef Nothing licId) Nothing) <$ string "LicenseRef-" <*> idString++elicenseDocRef :: ReadP LicenseExpression+elicenseDocRef = f <$ string "DocumentRef-" <*> idString <* char ':' <* string "LicenseRef-" <*> idString+ where f docId licId = ELicense False (Left $ LicenseRef (Just docId) licId) Nothing++idString :: ReadP String+idString = munch1 p+ where p '.' = True+ p '-' = True+ p c = isAlphaNum c++skipSpaces1 :: ReadP ()+skipSpaces1 = () <$ char ' ' <* skipSpaces++parens :: ReadP a -> ReadP a+parens = between (char '(') (skipSpaces <* char ')')++terminal :: ReadP LicenseExpression+terminal = choice [ elicense+ , elicenseWith+ , elicenseAndNewer+ , elicenseWithAndNewer+ , elicenseRef+ , elicenseDocRef+ , parens expression+ ]++conjunction :: ReadP LicenseExpression+conjunction = chainr1 terminal (EConjunction <$ skipSpaces1 <* string "AND" <* skipSpaces1)++disjunction :: ReadP LicenseExpression+disjunction = chainr1 conjunction (EDisjunction <$ skipSpaces1 <* string "OR" <* skipSpaces1)++expression :: ReadP LicenseExpression+expression = skipSpaces *> disjunction++-- | Parse SPDX License Expression+--+-- >>> parseExpression "LGPL-2.1 OR MIT"+-- [EDisjunction (ELicense False (Right (LicenseId "LGPL-2.1")) Nothing) (ELicense False (Right (LicenseId "MIT")) Nothing)]+parseExpression :: String -> [LicenseExpression]+parseExpression = map fst . readP_to_S (expression <* skipSpaces <* eof)++unsafeParseExpr :: String -> LicenseExpression+unsafeParseExpr s = f . parseExpression $ s+ where f [] = error $ "Failed parse of license expression: " ++ s+ f [l] = l+ f (_:_:_) = error $ "Ambigious parse of license expression: " ++ s
+ src/Data/SPDX/Ranges.hs view
@@ -0,0 +1,47 @@+module Data.SPDX.Ranges (licenseRanges, lookupLicenseRange) where++import Data.Char+import Data.List+import Data.Maybe++import Data.SPDX.Types+import Data.SPDX.Licenses++licenseRanges :: [[LicenseId]]+licenseRanges = filter longerThanSingleton . map f $ prefixes+ where f p = filter (\l -> p `isPrefixOf` getLicenseId l && restIsNumber (getLicenseId l) p) licenseIdentifiers++-- | Lookup newer licenses we know about+--+-- >>> lookupLicenseRange $ fromJust $ mkLicenseId "MIT"+-- [LicenseId "MIT"]+--+-- >>> lookupLicenseRange $ fromJust $ mkLicenseId "GPL-2.0"+-- [LicenseId "GPL-2.0",LicenseId "GPL-3.0"]+--+-- >>> lookupLicenseRange $ fromJust $ mkLicenseId "LGPL-2.0"+-- [LicenseId "LGPL-2.0",LicenseId "LGPL-2.1",LicenseId "LGPL-3.0"]+lookupLicenseRange :: LicenseId -> [LicenseId]+lookupLicenseRange l = fromMaybe [l] $ lookup l ranges'++ranges' :: [(LicenseId, [LicenseId])]+ranges' = map (\r -> (head r, r)) . filter (not . nullOrSingleton) . concatMap tails $ licenseRanges++nullOrSingleton :: [a] -> Bool+nullOrSingleton [] = True+nullOrSingleton [_] = True+nullOrSingleton (_:_:_) = False++restIsNumber :: String -> String -> Bool+restIsNumber l p = all (\c -> isDigit c || c == 'a' || c == 'b' || c == 'c' || c == '.') (drop (length p) l)++pref :: String -> String+pref = reverse . dropWhile (/= '-') . reverse++prefixes :: [String]+prefixes = nub (filter (not . null) $ map (pref . getLicenseId) licenseIdentifiers)++longerThanSingleton :: [a] -> Bool+longerThanSingleton [] = False+longerThanSingleton [_] = False+longerThanSingleton (_:_:_) = True
+ src/Data/SPDX/Types.hs view
@@ -0,0 +1,38 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+module Data.SPDX.Types (+ LicenseId(..)+ , getLicenseId+ , LicenseExceptionId(..)+ , getLicenseExceptionId+ , LicenseRef(..)+ , LicenseExpression(..)+ ) where++import Data.Data+import GHC.Generics++data LicenseRef = LicenseRef+ { lrDocument :: !(Maybe String)+ , lrLicense :: !String+ }+ deriving (Eq, Ord, Show, Read, Typeable, Data, Generic)++-- | Opaque license identifier type.+newtype LicenseId = LicenseId String+ deriving (Eq, Ord, Show, Read, Typeable, Data, Generic)++getLicenseId :: LicenseId -> String+getLicenseId (LicenseId l) = l++-- | Opaque license exception identifier type.+newtype LicenseExceptionId = LicenseExceptionId String+ deriving (Eq, Ord, Show, Read, Typeable, Data, Generic)++getLicenseExceptionId :: LicenseExceptionId -> String+getLicenseExceptionId (LicenseExceptionId l) = l++data LicenseExpression = ELicense !Bool !(Either LicenseRef LicenseId) !(Maybe LicenseExceptionId)+ | EConjunction !LicenseExpression !LicenseExpression+ | EDisjunction !LicenseExpression !LicenseExpression+ deriving (Eq, Ord, Show, Read, Typeable, Data, Generic)
− src/Distribution/SPDX.hs
@@ -1,65 +0,0 @@--- |--- Module : Distribution.SPDX--- Description : SPDX licenses and expression language--- Copyright : (c) 2015 Oleg Grenrus--- License : BSD3--- Maintainer : Oleg Grenrus <oleg.grenrus@iki.fi>----module Distribution.SPDX (- -- * Types- LicenseId- , LicenseExceptionId- , LicenseRef(..)- , LicenseExpression(..)- -- * Data- , licenseIdentifiers- , licenseExceptions- -- ** Ranges- , licenseRanges- , lookupLicenseRange- -- * Parsing- , parseExpression- , unsafeParseExpr- -- * Logic- , satisfies- ) where--import Distribution.SPDX.Types-import Distribution.SPDX.Ranges-import Distribution.SPDX.Licenses-import Distribution.SPDX.Parser-import Distribution.SPDX.LatticeSyntax--data Lic = Lic (Either LicenseRef String) (Maybe String)- deriving (Eq, Ord, Show, Read)--exprToLSLic :: LicenseExpression -> LatticeSyntax Lic-exprToLSLic (ELicense False l e) = LVar (Lic l e)-exprToLSLic (ELicense True (Right l) e) = foldr1 LJoin $ map (\l' -> LVar $ Lic (Right l') e) $ lookupLicenseRange l--- We don't know anything about newer license references-exprToLSLic (ELicense True (Left l) e) = LVar (Lic (Left l) e)-exprToLSLic (EConjunction a b) = LMeet (exprToLSLic a) (exprToLSLic b)-exprToLSLic (EDisjunction a b) = LJoin (exprToLSLic a) (exprToLSLic b)---- |------ @⟦ satisfies a b ⟧ ≡ a ≥ b ≡ a ∧ b = b @------ >>> unsafeParseExpr "GPL-3.0" `satisfies` unsafeParseExpr "ISC AND MIT"--- False------ >>> unsafeParseExpr "Zlib" `satisfies` unsafeParseExpr "ISC AND MIT AND Zlib"--- True------ >>> unsafeParseExpr "(MIT OR GPL-2.0)" `satisfies` unsafeParseExpr "(ISC AND MIT)"--- True------ >>> unsafeParseExpr "(MIT AND GPL-2.0)" `satisfies` unsafeParseExpr "(MIT AND GPL-2.0)"--- True------ >>> unsafeParseExpr "(MIT AND GPL-2.0)" `satisfies` unsafeParseExpr "(ISC AND GPL-2.0)"--- False-satisfies :: LicenseExpression -- ^ package license- -> LicenseExpression -- ^ license policy- -> Bool-satisfies a b = exprToLSLic b `preorder` exprToLSLic a
− src/Distribution/SPDX/LatticeSyntax.hs
@@ -1,101 +0,0 @@-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE DeriveFoldable #-}-{-# LANGUAGE DeriveTraversable #-}-{-# LANGUAGE DeriveDataTypeable #-}--- |--- Module : Distribution.SPDX.LatticeSyntax--- Description : General lattice tools--- Copyright : (c) 2015 Oleg Grenrus--- License : BSD3--- Maintainer : Oleg Grenrus <oleg.grenrus@iki.fi>------ Inspired by <http://www.well-typed.com/blog/2014/12/simple-smt-solver/ Simple SMT Solver>.------ In future this module will probably be moved into separate package.-module Distribution.SPDX.LatticeSyntax (LatticeSyntax(..), dual, freeVars, equivalent, preorder, satisfiable) where--import Control.Applicative-import Control.Monad-import Control.Monad.Trans.State-import Data.Data-import Data.Foldable-import Data.Traversable-import Prelude hiding (all, or)--data LatticeSyntax a = LVar a- | LBound Bool- | LJoin (LatticeSyntax a) (LatticeSyntax a)- | LMeet (LatticeSyntax a) (LatticeSyntax a)- deriving (Eq, Ord, Read, Show, Functor, Foldable, Traversable, Typeable, Data)--instance Applicative LatticeSyntax where- pure = return- (<*>) = ap--instance Monad LatticeSyntax where- return = LVar- LVar x >>= f = f x- LBound b >>= _ = LBound b- LJoin a b >>= f = LJoin (a >>= f) (b >>= f)- LMeet a b >>= f = LMeet (a >>= f) (b >>= f)--freeVars :: LatticeSyntax a -> [a]-freeVars = toList--dual :: LatticeSyntax a -> LatticeSyntax a-dual (LVar v) = LVar v-dual (LBound t) = LBound $ not t-dual (LJoin a b) = LMeet (dual a) (dual b)-dual (LMeet a b) = LJoin (dual a) (dual b)---- | Test for equivalence.------ >>> equivalent (LMeet (LVar 'a') (LVar 'b')) (LMeet (LVar 'b') (LVar 'a'))--- True------ >>> equivalent (LVar 'a') (LMeet (LVar 'a') (LVar 'a'))--- True------ >>> equivalent (LMeet (LVar 'a') (LVar 'b')) (LMeet (LVar 'b') (LVar 'b'))--- False-equivalent :: Eq a => LatticeSyntax a -> LatticeSyntax a -> Bool-equivalent a b = all (uncurry (==)) . runEval $ p- where p = (,) <$> evalLattice a <*> evalLattice b---- | Test for preorder.------ @ a ≤ b ⇔ a ∨ b ≡ b ⇔ a ≡ a ∧ b@------ >>> preorder (LVar 'a' `LMeet` LVar 'b') (LVar 'a')--- True------ >>> preorder (LVar 'a') (LVar 'a' `LMeet` LVar 'b')--- False-preorder :: Eq a => LatticeSyntax a -> LatticeSyntax a -> Bool-preorder a b = (a `LJoin` b) `equivalent` b---- | Return `True` if for some variable assigment expression evaluates to `True`.-satisfiable :: Eq a => LatticeSyntax a -> Bool -satisfiable = or . runEval . evalLattice--newtype Eval v a = Eval { unEval :: StateT [(v, Bool)] [] a }- deriving (Functor, Applicative, Alternative, Monad, MonadPlus)--runEval :: Eval v a -> [a]-runEval act = evalStateT (unEval act) []--evalLattice :: Eq v => LatticeSyntax v -> Eval v Bool-evalLattice (LVar v) = guess v-evalLattice (LBound b) = return b-evalLattice (LJoin a b) = (||) <$> evalLattice a <*> evalLattice b-evalLattice (LMeet a b) = (&&) <$> evalLattice a <*> evalLattice b--guess :: Eq v => v -> Eval v Bool-guess v = Eval $ do- st <- get- let remember b = put ((v, b) : st) >> return b- case lookup v st of- Just b -> return b- Nothing -> remember True <|> remember False-
− src/Distribution/SPDX/Licenses.hs
@@ -1,322 +0,0 @@-module Distribution.SPDX.Licenses (LicenseId, LicenseExceptionId, licenseIdentifiers, licenseExceptions) where--import Distribution.SPDX.Types--import Data.List--licenseExceptions :: [LicenseExceptionId]-licenseExceptions = [- "Autoconf-exception-2.0",- "Autoconf-exception-3.0",- "Bison-exception-2.2",- "Classpath-exception-2.0",- "eCos-exception-2.0",- "Font-exception-2.0",- "GCC-exception-2.0",- "GCC-exception-3.1",- "WxWindows-exception-3.1"- ]---- | A list of SPDX licenses identifiers.------ See <http://spdx.org/licenses/>.-licenseIdentifiers :: [LicenseId]-licenseIdentifiers = sort $ [- "Glide",- "Abstyles",- "AFL-1.1",- "AFL-1.2",- "AFL-2.0",- "AFL-2.1",- "AFL-3.0",- "AMPAS",- "APL-1.0",- "Adobe-Glyph",- "APAFML",- "Adobe-2006",- "AGPL-1.0",- "Afmparse",- "Aladdin",- "ADSL",- "AMDPLPA",- "ANTLR-PD",- "Apache-1.0",- "Apache-1.1",- "Apache-2.0",- "AML",- "APSL-1.0",- "APSL-1.1",- "APSL-1.2",- "APSL-2.0",- "Artistic-1.0",- "Artistic-1.0-Perl",- "Artistic-1.0-cl8",- "Artistic-2.0",- "AAL",- "Bahyph",- "Barr",- "Beerware",- "BitTorrent-1.0",- "BitTorrent-1.1",- "BSL-1.0",- "Borceux",- "BSD-2-Clause",- "BSD-2-Clause-FreeBSD",- "BSD-2-Clause-NetBSD",- "BSD-3-Clause",- "BSD-3-Clause-Clear",- "BSD-4-Clause",- "BSD-Protection",- "BSD-3-Clause-Attribution",- "BSD-4-Clause-UC",- "bzip2-1.0.5",- "bzip2-1.0.6",- "Caldera",- "CECILL-1.0",- "CECILL-1.1",- "CECILL-2.0",- "CECILL-B",- "CECILL-C",- "ClArtistic",- "MIT-CMU",- "CNRI-Jython",- "CNRI-Python",- "CNRI-Python-GPL-Compatible",- "CPOL-1.02",- "CDDL-1.0",- "CDDL-1.1",- "CPAL-1.0",- "CPL-1.0",- "CATOSL-1.1",- "Condor-1.1",- "CC-BY-1.0",- "CC-BY-2.0",- "CC-BY-2.5",- "CC-BY-3.0",- "CC-BY-4.0",- "CC-BY-ND-1.0",- "CC-BY-ND-2.0",- "CC-BY-ND-2.5",- "CC-BY-ND-3.0",- "CC-BY-ND-4.0",- "CC-BY-NC-1.0",- "CC-BY-NC-2.0",- "CC-BY-NC-2.5",- "CC-BY-NC-3.0",- "CC-BY-NC-4.0",- "CC-BY-NC-ND-1.0",- "CC-BY-NC-ND-2.0",- "CC-BY-NC-ND-2.5",- "CC-BY-NC-ND-3.0",- "CC-BY-NC-ND-4.0",- "CC-BY-NC-SA-1.0",- "CC-BY-NC-SA-2.0",- "CC-BY-NC-SA-2.5",- "CC-BY-NC-SA-3.0",- "CC-BY-NC-SA-4.0",- "CC-BY-SA-1.0",- "CC-BY-SA-2.0",- "CC-BY-SA-2.5",- "CC-BY-SA-3.0",- "CC-BY-SA-4.0",- "CC0-1.0",- "Crossword",- "CUA-OPL-1.0",- "Cube",- "D-FSL-1.0",- "diffmark",- "WTFPL",- "DOC",- "Dotseqn",- "DSDP",- "dvipdfm",- "EPL-1.0",- "ECL-1.0",- "ECL-2.0",- "eGenix",- "EFL-1.0",- "EFL-2.0",- "MIT-advertising",- "MIT-enna",- "Entessa",- "ErlPL-1.1",- "EUDatagrid",- "EUPL-1.0",- "EUPL-1.1",- "Eurosym",- "Fair",- "MIT-feh",- "Frameworx-1.0",- "FreeImage",- "FTL",- "FSFUL",- "FSFULLR",- "Giftware",- "GL2PS",- "Glulxe",- "AGPL-3.0",- "GFDL-1.1",- "GFDL-1.2",- "GFDL-1.3",- "GPL-1.0",- "GPL-2.0",- "GPL-3.0",- "LGPL-2.1",- "LGPL-3.0",- "LGPL-2.0",- "gnuplot",- "gSOAP-1.3b",- "HaskellReport",- "HPND",- "IBM-pibs",- "IPL-1.0",- "ICU",- "ImageMagick",- "iMatix",- "Imlib2",- "IJG",- "Intel-ACPI",- "Intel",- "IPA",- "ISC",- "JasPer-2.0",- "JSON",- "LPPL-1.3a",- "LPPL-1.0",- "LPPL-1.1",- "LPPL-1.2",- "LPPL-1.3c",- "Latex2e",- "BSD-3-Clause-LBNL",- "Leptonica",- "Libpng",- "libtiff",- "LPL-1.02",- "LPL-1.0",- "MakeIndex",- "MTLL",- "MS-PL",- "MS-RL",- "MirOS",- "MITNFA",- "MIT",- "Motosoto",- "MPL-1.0",- "MPL-1.1",- "MPL-2.0",- "MPL-2.0-no-copyleft-exception",- "mpich2",- "Multics",- "Mup",- "NASA-1.3",- "Naumen",- "NBPL-1.0",- "NetCDF",- "NGPL",- "NOSL",- "NPL-1.0",- "NPL-1.1",- "Newsletr",- "NLPL",- "Nokia",- "NPOSL-3.0",- "Noweb",- "NRL",- "NTP",- "Nunit",- "OCLC-2.0",- "ODbL-1.0",- "PDDL-1.0",- "OGTSL",- "OLDAP-2.2.2",- "OLDAP-1.1",- "OLDAP-1.2",- "OLDAP-1.3",- "OLDAP-1.4",- "OLDAP-2.0",- "OLDAP-2.0.1",- "OLDAP-2.1",- "OLDAP-2.2",- "OLDAP-2.2.1",- "OLDAP-2.3",- "OLDAP-2.4",- "OLDAP-2.5",- "OLDAP-2.6",- "OLDAP-2.7",- "OLDAP-2.8",- "OML",- "OPL-1.0",- "OSL-1.0",- "OSL-1.1",- "OSL-2.0",- "OSL-2.1",- "OSL-3.0",- "OpenSSL",- "PHP-3.0",- "PHP-3.01",- "Plexus",- "PostgreSQL",- "psfrag",- "psutils",- "Python-2.0",- "QPL-1.0",- "Qhull",- "Rdisc",- "RPSL-1.0",- "RPL-1.1",- "RPL-1.5",- "RHeCos-1.1",- "RSCPL",- "RSA-MD",- "Ruby",- "SAX-PD",- "Saxpath",- "SCEA",- "SWL",- "SGI-B-1.0",- "SGI-B-1.1",- "SGI-B-2.0",- "OFL-1.0",- "OFL-1.1",- "SimPL-2.0",- "Sleepycat",- "SNIA",- "SMLNJ",- "SugarCRM-1.1.3",- "SISSL",- "SISSL-1.2",- "SPL-1.0",- "Watcom-1.0",- "TCL",- "Unlicense",- "TMate",- "TORQUE-1.1",- "TOSL",- "Unicode-TOU",- "UPL-1.0",- "NCSA",- "Vim",- "VOSTROM",- "VSL-1.0",- "W3C-19980720",- "W3C",- "Wsuipa",- "Xnet",- "X11",- "Xerox",- "XFree86-1.1",- "xinetd",- "xpp",- "XSkat",- "YPL-1.0",- "YPL-1.1",- "Zed",- "Zend-2.0",- "Zimbra-1.3",- "Zimbra-1.4",- "Zlib",- "zlib-acknowledgement",- "ZPL-1.1",- "ZPL-2.0",- "ZPL-2.1"- ]
− src/Distribution/SPDX/Parser.hs
@@ -1,81 +0,0 @@-{-# LANGUAGE CPP #-}-module Distribution.SPDX.Parser (parseExpression, unsafeParseExpr) where--#if !MIN_VERSION_base(4, 8, 0)-import Control.Applicative-#endif--import Data.Char-import Text.ParserCombinators.ReadP--import Distribution.SPDX.Types-import Distribution.SPDX.Licenses (licenseIdentifiers, licenseExceptions)--license :: ReadP LicenseId-license = choice (map string licenseIdentifiers)--licenseException :: ReadP LicenseExceptionId-licenseException = choice (map string licenseExceptions)--elicense :: ReadP LicenseExpression-elicense = (\l -> ELicense False (Right l) Nothing) <$> license--elicenseWith :: ReadP LicenseExpression-elicenseWith = (\l e -> ELicense False (Right l) (Just e)) <$> license <* skipSpaces1 <* string "WITH" <* skipSpaces1 <*> licenseException--elicenseAndNewer :: ReadP LicenseExpression-elicenseAndNewer = (\l -> ELicense True (Right l) Nothing) <$> license <* char '+'--elicenseWithAndNewer :: ReadP LicenseExpression-elicenseWithAndNewer = (\l e -> ELicense True (Right l) (Just e)) <$> license <* char '+' <* string " WITH " <*> licenseException--elicenseRef :: ReadP LicenseExpression-elicenseRef = (\licId -> ELicense False (Left $ LicenseRef Nothing licId) Nothing) <$ string "LicenseRef-" <*> idString--elicenseDocRef :: ReadP LicenseExpression-elicenseDocRef = f <$ string "DocumentRef-" <*> idString <* char ':' <* string "LicenseRef-" <*> idString- where f docId licId = ELicense False (Left $ LicenseRef (Just docId) licId) Nothing--idString :: ReadP String-idString = munch1 p- where p '.' = True- p '-' = True- p c = isAlphaNum c--skipSpaces1 :: ReadP ()-skipSpaces1 = () <$ char ' ' <* skipSpaces--parens :: ReadP a -> ReadP a-parens = between (char '(') (skipSpaces <* char ')')--terminal :: ReadP LicenseExpression-terminal = choice [ elicense- , elicenseWith- , elicenseAndNewer- , elicenseWithAndNewer- , elicenseRef- , elicenseDocRef- , parens expression- ]--conjunction :: ReadP LicenseExpression-conjunction = chainr1 terminal (EConjunction <$ skipSpaces1 <* string "AND" <* skipSpaces1)--disjunction :: ReadP LicenseExpression-disjunction = chainr1 conjunction (EDisjunction <$ skipSpaces1 <* string "OR" <* skipSpaces1)--expression :: ReadP LicenseExpression-expression = skipSpaces *> disjunction---- | Parse SPDX License Expression------ >>> parseExpression "LGPL-2.1 OR MIT"--- [EDisjunction (ELicense False "LGPL-2.1" Nothing) (ELicense False "MIT" Nothing)]-parseExpression :: String -> [LicenseExpression]-parseExpression = map fst . readP_to_S (expression <* skipSpaces <* eof)--unsafeParseExpr :: String -> LicenseExpression-unsafeParseExpr s = f . parseExpression $ s- where f [] = error $ "Failed parse of license expression: " ++ s- f [l] = l- f (_:_:_) = error $ "Ambigious parse of license expression: " ++ s
− src/Distribution/SPDX/Ranges.hs
@@ -1,47 +0,0 @@-module Distribution.SPDX.Ranges (licenseRanges, lookupLicenseRange) where--import Data.Char-import Data.List-import Data.Maybe--import Distribution.SPDX.Types-import Distribution.SPDX.Licenses--licenseRanges :: [[LicenseId]]-licenseRanges = filter longerThanSingleton . map f $ prefixes- where f p = filter (\l -> p `isPrefixOf` l && restIsNumber l p) licenseIdentifiers---- | Lookup newer licenses we know about------ >>> lookupLicenseRange "MIT"--- ["MIT"]------ >>> lookupLicenseRange "GPL-2.0"--- ["GPL-2.0","GPL-3.0"]------ >>> lookupLicenseRange "LGPL-2.0"--- ["LGPL-2.0","LGPL-2.1","LGPL-3.0"]-lookupLicenseRange :: LicenseId -> [LicenseId]-lookupLicenseRange l = fromMaybe [l] $ lookup l ranges'--ranges' :: [(LicenseId, [LicenseId])]-ranges' = map (\r -> (head r, r)) . filter (not . nullOrSingleton) . concatMap tails $ licenseRanges--nullOrSingleton :: [a] -> Bool-nullOrSingleton [] = True-nullOrSingleton [_] = True-nullOrSingleton (_:_:_) = False--restIsNumber :: String -> String -> Bool-restIsNumber l p = all (\c -> isDigit c || c == 'a' || c == 'b' || c == 'c' || c == '.') (drop (length p) l)--pref :: String -> String-pref = reverse . dropWhile (/= '-') . reverse--prefixes :: [String]-prefixes = nub (filter (not . null) $ map pref licenseIdentifiers)--longerThanSingleton :: [a] -> Bool-longerThanSingleton [] = False-longerThanSingleton [_] = False-longerThanSingleton (_:_:_) = True
− src/Distribution/SPDX/Types.hs
@@ -1,20 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-module Distribution.SPDX.Types where--import Data.Data-import GHC.Generics--data LicenseRef = LicenseRef- { lrDocument :: !(Maybe String)- , lrLicense :: !String- }- deriving (Eq, Ord, Show, Read, Typeable, Data, Generic)--type LicenseId = String-type LicenseExceptionId = String--data LicenseExpression = ELicense !Bool !(Either LicenseRef LicenseId) !(Maybe LicenseExceptionId)- | EConjunction !LicenseExpression !LicenseExpression- | EDisjunction !LicenseExpression !LicenseExpression- deriving (Eq, Ord, Show, Read, Typeable, Data, Generic)
tests/Tests.hs view
@@ -5,8 +5,8 @@ import Test.Tasty import Test.Tasty.QuickCheck as QC -import Distribution.SPDX-import Distribution.SPDX.LatticeSyntax+import Data.SPDX+import Data.SPDX.LatticeSyntax main :: IO () main = defaultMain tests@@ -35,19 +35,29 @@ , rangeUnit ] -simpleExprGen :: Gen String+simpleExprGen :: Gen LicenseId simpleExprGen = elements licenseIdentifiers latticeSyntaxGen :: Gen (LatticeSyntax Char) latticeSyntaxGen = sized gen- where var = elements "abcdef"- gen 0 = LVar <$> var- gen n = oneof [ LVar <$> var+ where var = LVar <$> elements "abcdef"+ gen 0 = var+ gen n = oneof [ var , LMeet <$> gen' <*> gen' , LJoin <$> gen' <*> gen' ] where gen' = gen (n `div` 2) +exprGen :: Gen LicenseExpression+exprGen = sized gen+ where sim = ELicense <$> arbitrary <*> (Right <$> simpleExprGen) <*> (pure Nothing)+ gen 0 = sim+ gen n = oneof [ sim+ , EDisjunction <$> gen' <*> gen'+ , EConjunction <$> gen' <*> gen'+ ]+ where gen' = gen (n `div` 2)+ simpleUnits :: TestTree simpleUnits = testGroup "Simple License Expressions" [ invalidExpr "Invalid-Identifier"@@ -70,7 +80,7 @@ ] rangeUnit :: TestTree-rangeUnit = QC.testProperty "calculated license ranges" $ once $ property $ sort licenseRanges == sort ranges+rangeUnit = QC.testProperty "calculated license ranges" $ once $ property $ sort (map (map getLicenseId) licenseRanges) == sort ranges lsProps :: TestTree lsProps = testGroup "LatticeSyntax"@@ -82,13 +92,35 @@ , QC.testProperty "preorder reflexive" $ forAll latticeSyntaxGen $ \a -> a `preorder` a ] +osiLicenseIds :: [LicenseId]+osiLicenseIds = filter isOsiApproved licenseIdentifiers++osiLicenseExpr :: LicenseExpression+osiLicenseExpr = foldr1 EConjunction $ map (\l -> ELicense False (Right l) Nothing) osiLicenseIds++isOsiApprovedExpr :: LicenseExpression -> Bool+isOsiApprovedExpr (ELicense _ (Left _) _) = False+isOsiApprovedExpr (ELicense _ _ (Just _)) = False+isOsiApprovedExpr (ELicense False (Right e) Nothing) = isOsiApproved e+isOsiApprovedExpr (ELicense True (Right e2) Nothing) = any isOsiApproved $ lookupLicenseRange e2+isOsiApprovedExpr (EConjunction e1 e2) = isOsiApprovedExpr e1 && isOsiApprovedExpr e2+isOsiApprovedExpr (EDisjunction e1 e2) = isOsiApprovedExpr e1 || isOsiApprovedExpr e2++isOsiApprovedExpr' :: LicenseExpression -> Bool+isOsiApprovedExpr' e = e `satisfies` osiLicenseExpr++scaleGen :: (Int -> Int) -> Gen a -> Gen a+scaleGen f g = sized (\n -> resize (f n) g)+ qcProps :: TestTree qcProps = testGroup "By Quickcheck"- [ QC.testProperty "licence identifiers are valid licenses" $ forAll simpleExprGen $ valid+ [ QC.testProperty "licence identifiers are valid licenses" $ forAll simpleExprGen $ valid . getLicenseId+ , QC.testProperty "satisfies osi checked" $ forAll (scaleGen (`div` 2) exprGen) $+ \e -> isOsiApprovedExpr e == isOsiApprovedExpr' e -- Skip , lsProps ] -ranges :: [[LicenseId]]+ranges :: [[String]] ranges = [ [ "AFL-1.1",