
    ܖiU                     n   d Z ddlZddlZddlZddlZddlmZ ddlmZ ddlmZ ddl	m	Z	 ddl	m
Z
 ddlmZ dd	lmZ dd
lmZ ddlmZ ddlZddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlm Z  ddlm!Z! ddl"m#Z$ ddl"m%Z%  e ee&            Z' ee'd      Z( ee(d      Z)dZ*e*evrdee*<   d Z+e+evrd!ee+<   d"Z,e,evrd#ee,<   d$Z-e-evrd%ee-<    G d& d'e.      Z/ G d( d)ee/      Z0 ed*d+      Z1d, e1_2        d-Z3 e1d.e       Z4 e1d/e!      Z5 e1d0e      Z6 e1d1e      Z7 e1d2e3      Z8e6e7e4e5e8fZ9 e:d3 e9D              Z;e6e7e8d4Z< ejz                  d5ej|                  ej~                  z  ej                  z        j                  ZB G d6 d7      ZC G d8 d9ej                        ZEe)fd:ZFe)fd;ZGe)fd<ZHd= ZId> ZJd? ZKd@ ZLdA ZMdB ZNdZdCZO G dD dEeP      ZQ G dF dGeQej                        ZS ejz                  dHej                        j                  ZUe G dI dJeS             ZVe G dK dLeV             ZWe G dM dNeS             ZX G dO dPeQ      ZY G dQ dReYej                        ZZ G dS dTeYej                        Z[dU Z\dV Z]dZdWZ^dRdX eE       fdYZ_y)[a  
Define a mini language to parse, validate, deduplicate, simplify,
normalize and compare license expressions using a boolean logic engine.

This module supports SPDX and ScanCode license expressions and also accepts other
license naming conventions and license identifiers aliases to recognize and
normalize licenses.

Using boolean logic, license expressions can be tested for equality,
containment, equivalence and can be normalized, deduplicated or simplified.

The main entry point is the Licensing object.
    N)defaultdict)deque)
namedtuple)copy)deepcopy)total_ordering)abspath)dirname)join)
Expression)PARSE_ERRORS)PARSE_INVALID_EXPRESSION)PARSE_INVALID_NESTING)PARSE_INVALID_OPERATOR_SEQUENCE)PARSE_INVALID_SYMBOL_SEQUENCE)PARSE_UNBALANCED_CLOSING_PARENS)PARSE_UNKNOWN_TOKEN)
ParseError)TOKEN_SYMBOL)	TOKEN_AND)TOKEN_OR)
TOKEN_LPAR)
TOKEN_RPAR)Trie)Tokendatazscancode-licensedb-index.jsond   z#Expression string must be a string.e   z\A license exception symbol can only be used as an exception in a "WITH exception" statement.f   zSA plain license symbol cannot be used as an exception in a "WITH symbol" statement.g   z"A proper license symbol is needed.c                       e Zd Zy)ExpressionErrorN__name__
__module____qualname__     _/var/www/html/content-pipeline/venv/lib/python3.12/site-packages/license_expression/__init__.pyr"   r"   Y       r(   r"   c                       e Zd Zy)ExpressionParseErrorNr#   r'   r(   r)   r,   r,   ]   r*   r(   r,   Keywordz
value typec                 ,    t        | j                        S N)lenvalueselfs    r)   <lambda>r4   c   s    s4:: r(   
   ()andorwithc              #   4   K   | ]  }|j                     y wr/   )r1   ).0kws     r)   	<genexpr>r>   x   s     3Brxx3s   )r8   r9   r:   zi
    (?P<symop>[^\s\(\)]+)
     |
    (?P<space>\s+)
     |
    (?P<lpar>\()
     |
    (?P<rpar>\))
    c                   $    e Zd ZdZ	 	 	 ddZd Zy)ExpressionInfoa  
    The ExpressionInfo class is returned by Licensing.validate() where it stores
    information about a given license expression passed into
    Licensing.validate().

    The ExpressionInfo class has the following fields:

    - original_expression: str.
        - This is the license expression that was originally passed into
          Licensing.validate()

    - normalized_expression: str.
        - If a valid license expression has been passed into `validate()`,
          then the license expression string will be set in this field.

    - errors: list
        - If there were errors validating a license expression,
          the error messages will be appended here.

    - invalid_symbols: list
        - If the license expression that has been passed into `validate()` has
          license keys that are invalid (either that they are unknown or not used
          in the right context), or the syntax is incorrect because an invalid
          symbol was used, then those symbols will be appended here.
    Nc                 L    || _         || _        |xs g | _        |xs g | _        y r/   original_expressionnormalized_expressionerrorsinvalid_symbols)r3   rC   rD   rE   rF   s        r)   __init__zExpressionInfo.__init__   s,     $7 %:"l.4"r(   c           	      p    d| j                   d| j                  d| j                  d| j                  d	S )Nz(ExpressionInfo(
    original_expression=z,
    normalized_expression=z,
    errors=z,
    invalid_symbols=z
)rB   r2   s    r)   __repr__zExpressionInfo.__repr__   sT    ''+'?'?&B C))-)C)C(F G++ )##'#7#7": ;		
r(   )NNN)r$   r%   r&   __doc__rG   rI   r'   r(   r)   r@   r@      s    : #
5
r(   r@   c                        e Zd ZdZ e       df fd	Zd Zd Zd ZddZ	ddZ
d	 Zdd
ZddZddZddZd Zd fd	ZddZd Zd Zd Zd ZddZ xZS )	Licensinga!  
    Licensing defines a mini language to parse, validate and compare license
    expressions. This is the main entry point in this library.

    Some of the features are:

    - licenses can be validated against user-provided lists of known licenses
      "symbols" (such as ScanCode licenses or the SPDX list).

    - flexible expression parsing and recognition of licenses (including
      licenses with spaces and keywords (such as AND, OR WITH) or parens in
      their names).

    - in an expression licenses can be more than just identifiers such as short
      or long names with spaces, symbols and even parenthesis.

    - A license can have multiple aliases (such as GPL-2.0, GPLv2 or GPL2) and
      each will be properly recognized when parsing. The expression is rendered
      normalized using the canononical license keys.

    - expressions can be deduplicated, simplified, normalized, sorted and
      compared for containment and/or logical equivalence thanks to a built-in
      boolean logic engine.

    - Once parsed, expressions can be rendered using simple templates (for
      instance to render as HTML links in a web UI).

    For example::

    >>> l = Licensing()
    >>> expr = l.parse(" GPL-2.0 or LGPL-2.1 and mit ")
    >>> expected = 'GPL-2.0 OR (LGPL-2.1 AND mit)'
    >>> assert expected == expr.render('{symbol.key}')

    >>> expected = [
    ...   LicenseSymbol('GPL-2.0'),
    ...   LicenseSymbol('LGPL-2.1'),
    ...   LicenseSymbol('mit')
    ... ]
    >>> assert expected == l.license_symbols(expr)

    >>> symbols = ['GPL-2.0+', 'Classpath', 'BSD']
    >>> l = Licensing(symbols)
    >>> expression = 'GPL-2.0+ with Classpath or (bsd)'
    >>> parsed = l.parse(expression)
    >>> expected = 'GPL-2.0+ WITH Classpath OR BSD'
    >>> assert expected == parsed.render('{symbol.key}')

    >>> expected = [
    ...   LicenseSymbol('GPL-2.0+'),
    ...   LicenseSymbol('Classpath'),
    ...   LicenseSymbol('BSD')
    ... ]
    >>> assert expected == l.license_symbols(parsed)
    >>> assert expected == l.license_symbols(expression)
    Tc                     t         t        |   t        t        t
               | j                  | _        | j                  | j                  | j                  | j                  | j
                  | j                  d}|j                         D ]  \  }}t        t        ||        |xs
 t               }|rmt        t        |            }t        |      \  }}|r|s|D ]  }t!        |        |r|s|D ]  }	t!        |	        |rt#        dj%                  ||z               |D 
ci c]  }
|
j&                  |
 c}
| _        |D 
ci c]  }
|
j&                  j+                         |
 c}
| _        d| _        yc c}
w c c}
w )a4  
        Initialize a Licensing with an optional ``symbols`` sequence of
        LicenseSymbol or LicenseSymbol-like objects or license key strings. If
        provided and this list data is invalid, raise a ValueError. Print
        warning and errors found in the symbols unless ``quiet`` is True.
        )Symbol_class	AND_classOR_class)TRUEFALSENOTANDORSymbol
N)superrL   rG   LicenseSymbolrT   rU   rV   rQ   rR   rS   itemssetattrLicenseWithExceptionSymboltuple
as_symbolsvalidate_symbolsprint
ValueErrorr   keyknown_symbolslowerknown_symbols_lowercaseadvanced_tokenizer)r3   symbolsquiettf_naonamer1   warnsrE   wesymbol	__class__s              r)   rG   zLicensing.__init__   sm    	i'& 	( 	
 "[[ IIZZ8888''kk
 "<<> 	=KD%.e<	= $UWJw/0G,W5ME6U A!H e A!H  56>!:;; @GGVfjj&0G RY'Yv

(8(8(:F(B'Y$ #' H (Zs   $E6"E;c                 X     | j                   |fi |} | j                   |fi |}||k(  S )a/  
        Return True if both ``expression1`` and ``expression2``
        LicenseExpression objects are equivalent. If a string is provided, it
        will be parsed and simplified. Extra ``kwargs`` are passed down to the
        parse() function.
        Raise ExpressionError on parse errors.
        _parse_and_simplifyr3   expression1expression2kwargsex1ex2s         r)   is_equivalentzLicensing.is_equivalent.  s<     'd&&{=f=&d&&{=f=czr(   c                 V     | j                   |fi |} | j                   |fi |}||v S )a   
        Return True if ``expression1`` contains ``expression2``. where each
        expression is either a string or a LicenseExpression object. If a string
        is provided, it will be parsed and simplified.

        Extra ``kwargs`` are passed down to the parse() function.
        rq   rs   s         r)   containszLicensing.contains:  s<     'd&&{=f=&d&&{=f=czr(   c                      | j                   |fi |}|y t        |t              st        d|      |j	                         S )Nz-expression must be LicenseExpression object: )parse
isinstanceLicenseExpression	TypeErrorsimplify)r3   
expressionrv   s      r)   rr   zLicensing._parse_and_simplifyF  sM    TZZ
5f5
*&78KJ>Z[[""$$r(   c                      | j                   |fi |}|g S d |j                         D        }|r&t        j                  j	                  d |D              }|rt        |      }t        |      S )ao  
        Return a list of LicenseSymbol objects used in an expression in the same
        order as they first appear in the expression tree.

        ``expression`` is either a string or a LicenseExpression object.
        If a string is provided, it will be parsed.

        If ``unique`` is True only return unique symbols.

        If ``decompose`` is True then composite LicenseWithExceptionSymbol
        instances are not returned directly; instead their underlying license
        and exception symbols are returned.

        Extra ``kwargs`` are passed down to the parse() function.

        For example:
        >>> l = Licensing()
        >>> expected = [
        ...   LicenseSymbol('GPL-2.0'),
        ...   LicenseSymbol('LGPL-2.1+')
        ... ]
        >>> result = l.license_symbols(l.parse('GPL-2.0 or LGPL-2.1+'))
        >>> assert expected == result
        c              3   B   K   | ]  }t        |t              s|  y wr/   )r~   
BaseSymbolr<   ss     r)   r>   z,Licensing.license_symbols.<locals>.<genexpr>l  s     U:a;T1Us   c              3   <   K   | ]  }|j                           y wr/   )	decomposer   s     r)   r>   z,Licensing.license_symbols.<locals>.<genexpr>n  s     3SaAKKM3Ss   )r}   get_literals	itertoolschainfrom_iterableordered_uniquelist)r3   r   uniquer   rv   rg   s         r)   license_symbolszLicensing.license_symbolsP  sk    2  TZZ
5f5
IUj557Uoo333S73SSG$W-GG}r(   c                 <     | j                   |fd|i|}|r|d   S y)a  
        Return the left-most license symbol of an ``expression`` or None.
        ``expression`` is either a string or a LicenseExpression object.

        If ``decompose`` is True, only the left-hand license symbol of a
        decomposed LicenseWithExceptionSymbol symbol will be returned if this is
        the left most member. Otherwise a composite LicenseWithExceptionSymbol
        is returned in this case.

        Extra ``kwargs`` are passed down to the parse() function.
        r   r   N)r   )r3   r   r   rv   rg   s        r)   primary_license_symbolz Licensing.primary_license_symbols  s2     '$&&zQYQ&Q1: r(   c                 J     | j                   d|dd|}|r|j                  S y)a  
        Return the left-most license key of an ``expression`` or None. The
        underlying symbols are decomposed.

        ``expression`` is either a string or a LicenseExpression object.

        Extra ``kwargs`` are passed down to the parse() function.
        T)r   r   Nr'   )r   rb   )r3   r   rv   prims       r)   primary_license_keyzLicensing.primary_license_key  s>     +t** 
!
 

 88O r(   c                 R     | j                   d|ddd|}| j                  ||      S )an  
        Return a list of licenses keys used in an ``expression`` in the same
        order as they first appear in the expression. ``expression`` is either a
        string or a LicenseExpression object.

        If ``unique`` is True only return unique symbols.
        Extra ``kwargs`` are passed down to the parse() function.

        For example:
        >>> l = Licensing()
        >>> expr = ' GPL-2.0 and mit+ with blabla and mit or LGPL-2.1 and mit and mit+ with GPL-2.0'
        >>> expected = ['GPL-2.0', 'mit+', 'blabla', 'mit', 'LGPL-2.1']
        >>> assert expected == l.license_keys(l.parse(expr))
        FTr   r   r   r'   )r   _keysr3   r   r   rv   rg   s        r)   license_keyszLicensing.license_keys  sA     '$&& 
!
 	
 zz'6**r(   c                 \    |D cg c]  }|j                    }}|rt        |      }|S c c}w r/   )rb   r   )r3   rg   r   lskeyss        r)   r   zLicensing._keys  s2    !()2)) !$'D *s   )c                      | j                   d||dd|}|D cg c]  }|j                  | j                  vs| c}S c c}w )a`  
        Return a list of unknown license symbols used in an ``expression`` in
        the same order as they first appear in the ``expression``.
        ``expression`` is either a string or a LicenseExpression object.

        If ``unique`` is True only return unique symbols.
        Extra ``kwargs`` are passed down to the parse() function.
        Tr   r'   )r   rb   rc   )r3   r   r   rv   rg   r   s         r)   unknown_license_symbolsz!Licensing.unknown_license_symbols  sU     '$&& 
!
 	
 %IrBFFd6H6H,HIIIs
   A A c                 P     | j                   d|dd|}| j                  ||      S )a  
        Return a list of unknown licenses keys used in an ``expression`` in the
        same order as they first appear in the ``expression``.

        ``expression`` is either a string or a LicenseExpression object.
        If a string is provided, it will be parsed.

        If ``unique`` is True only return unique keys.
        Extra ``kwargs`` are passed down to the parse() function.
        F)r   r   r'   )r   r   r   s        r)   unknown_license_keyszLicensing.unknown_license_keys  s>     /$.. 
!
 

 zz'6**r(   c                     | j                  |d      }|r+dj                  dj                  |            }t        |      y )NT)r   zUnknown license key(s): {}, )r   formatr   r"   )r3   r   unknown_keysmsgs       r)   validate_license_keyszLicensing.validate_license_keys  sC    00D0I.55dii6MNC!#&& r(   c                 n   |yt        |t              r|S t        |t              r	 t        |      }t        |t              st	        |      }t        d|      |r|j                         sy	 t        | j                  |||            }t        t        | /  |      }t        |t              st        d      |r| j%                  |       |S #  t	        |      }t        d|      xY w# t        $ r=}t        |j                  |j                  |j                   |j"                        |d}~ww xY w)a  
        Return a new license LicenseExpression object by parsing a license
        ``expression``. Check that the ``expression`` syntax is valid and
        raise an ExpressionError or an ExpressionParseError on errors.

        Return None for empty expressions. ``expression`` is either a string or
        a LicenseExpression object. If ``expression`` is a LicenseExpression it
        is returned as-is.

        Symbols are always recognized from known Licensing symbols if `symbols`
        were provided at Licensing creation time: each license and exception is
        recognized from known license keys (and from aliases for a symbol if
        available).

        If ``validate`` is True and a license is unknown, an ExpressionError
        error is raised with a message listing the unknown license keys.

        If ``validate`` is False, no error is raised if the ``expression``
        syntax is correct. You can call further call the
        `unknown_license_keys()` or `unknown_license_symbols()` methods to get
        unknown license keys or symbols found in the parsed LicenseExpression.

        If ``strict`` is True, an ExpressionError will be raised if in a
        "WITH" expression such as "XXX with ZZZ" if the XXX symbol has
        `is_exception` set to True or the YYY symbol has `is_exception` set to
        False. This checks that symbols are used strictly as intended in a
        "WITH" subexpression using a license on the left and an exception on thr
        right.

        If ``simple`` is True, parsing will use a simple tokenizer that assumes
        that license symbols are all license keys and do not contain spaces.

        For example:
        >>> expression = 'EPL-1.0 and Apache-1.1 OR GPL-2.0 with Classpath-exception'
        >>> parsed = Licensing().parse(expression)
        >>> expected = '(EPL-1.0 AND Apache-1.1) OR GPL-2.0 WITH Classpath-exception'
        >>> assert expected == parsed.render(template='{symbol.key}')
        Nz%expression must be a string and not: )r   strictsimple
token_typetoken_stringposition
error_codez3expression must be a LicenseExpression once parsed.)r~   r   bytesstrtyper"   stripr   tokenizerX   rL   r}   r   r,   r   r   r   r   r   )
r3   r   validater   r   rv   exttokensrm   ro   s
            r)   r}   zLicensing.parse  sD   N j"34j%(W _

 *c*z"C!$I#"QRR!1!1!3	)!!  F y$5f=J *&78!"WXX&&z2GW:&%(McW&UVV&  	&<<^^<<	
 	s#   C 00C. C+.	D478D//D4c              #     K   |syt        |t              st        t              |r| j	                  |      }n!| j                         }|j                  |      }t        |      }d |D        }t        ||      }|D ]m  }|j                  }|j                  }|j                  }	t        |	t              r|	}
n-t        |	t              r|	j                  }
nt        t              |
||f o yw)a8  
        Return an iterable of 3-tuple describing each token given an
        ``expression`` string. See boolean.BooleanAlgreba.tokenize() for API
        details.

        This 3-tuple contains these items: (token, token string, position):
        - token: either a Symbol instance or one of TOKEN_* token types..
        - token string: the original token string.
        - position: the starting index of the token string in the `expr` string.

        If ``strict`` is True, additional exceptions will be raised in a
        expression such as "XXX with ZZZ" if the XXX symbol has is_exception`
        set to True or the ZZZ symbol has `is_exception` set to False.

        If ``simple`` is True, use a simple tokenizer that assumes that license
        symbols are all license keys that do not contain spaces.
        N)r   c              3   p   K   | ].  }|j                   s|j                   j                         s+| 0 y wr/   stringr   r<   ts     r)   r>   z%Licensing.tokenize.<locals>.<genexpr>S  s#     EqxxAHHNN4D!Es   666)r~   r   r   PARSE_EXPRESSION_NOT_UNICODEsimple_tokenizerget_advanced_tokenizerr   !build_symbols_from_unknown_tokens,replace_with_subexpression_by_license_symbolstartr   r1   r   r-   r   r   )r3   r   r   r   r   rf   tokenposr   token_value	token_objs              r)   r   zLicensing.tokenize1  s     $ *c*(DEE**:6F!%!<!<!>'00<F 36: FVE >ffM  	/E++C <<L++K+z2'	K1',,	 ,DEE\3..	/s   C,C.c                    | j                   | j                   S t               x| _         }|j                  }t        D ]  } ||j                  |        | j
                  j                         D ]M  \  }} |||       t        |dg       }|D ]-  }|sdj                  |j                               } |||       / O |j                          |S )a  
        Return an AdvancedTokenizer instance for this Licensing either cached or
        created as needed.

        If symbols were provided when this Licensing object was created, the
        tokenizer will recognize known symbol keys and aliases (ignoring case)
        when tokenizing expressions.

        A license symbol is any string separated by keywords and parens (and it
        can include spaces).
        aliases )rf   AdvancedTokenizeraddKEYWORDSr1   rc   rZ   getattrr   splitmake_automaton)r3   	tokenizeradd_itemkeywordrb   rn   r   aliass           r)   r   z Licensing.get_advanced_tokenizerg  s     "".***.?.AA)== 	-GW]]G,	-
  --335 		,KCS&!fi4G  , HHU[[]3EUF+,			, 	  "r(   c                 D    | j                         }|j                  |      S )zL
        Return an iterable of Token from an ``expression`` string.
        )r   r   )r3   r   r   s      r)   rf   zLicensing.advanced_tokenizer  s#     //1	!!*--r(   c              #   J  K   | j                   xs i }t        |      D ]   }|s|j                         \  }}|dz
  }|j                         j                  } |d      }|rt        |||d        |d      }|rt        |||t                |d      }	|	rt        |||	t                |d      }
|
s|
j                         }t        j	                  |      }|rt        |||
|       |j	                  |      }|st        |
      }t        |||
|        yw)a  
        Return an iterable of Token from an ``expression`` string.

        The split is done on spaces, keywords and parens. Anything else is a
        symbol token, e.g. a typically license key or license id (that contains
        no spaces or parens).

        If symbols were provided when this Licensing object was created, the
        tokenizer will recognize known symbol keys (ignoring case) when
        tokenizing expressions.
           spaceNlparrparsymoprb   )re   _simple_tokenizerspan	groupdictgetr   KW_LPARKW_RPARrd   	OPERATORSrY   )r3   r   rg   matchr   endmatch_getterr   r   r   	sym_or_opsym_or_op_loweroperatorsyms                 r)   r   zLicensing.simple_tokenizer  s     ..4"&z2 	<EJE3'C ??,00L )EE3t44'DE3g66'DE3g66$W-I"+//"3$==9sIx@@!++o6C+	:sIs;;?	<s   B5D#8A+D#c                    | j                  |      }g }|j                  D ]V  }t        || j                  | j                  f      r!|j                  | j                  |             F|j                  |       X t        |t              r|}|S t        || j                  | j                  f      r'|j                  j                  }t        ||d|       }|S t        d|      )a  
        Return a deduplicated LicenseExpression given a license ``expression``
        string or LicenseExpression object.

        The deduplication process is similar to simplification but is
        specialized for working with license expressions. Simplification is
        otherwise a generic boolean operation that is not aware of the specifics
        of license expressions.

        The deduplication:

        - Does not sort the licenses of sub-expression in an expression. They
          stay in the same order as in the original expression.

        - Choices (as in "MIT or GPL") are kept as-is and not treated as
          simplifiable. This avoids droping important choice options in complex
          expressions which is never desirable.

        T)relationr   	licensingzUnknown expression type: )r}   argsr~   rT   rU   appenddedupr   ro   r$   combine_expressionsr"   )r3   r   expexpressionsargdedupedr   s          r)   r   zLicensing.dedup  s    ( jj$88 	(CHHGG ""4::c?3""3'	( c:&G" ! 
 }}--H)!	G  "$=j^"LMMr(   c                 ^   t        t        |            }	 | j                  ||      }	 | j                  |       |j                  s|j                  st        |      |_        |S # t        $ rU}|j                  j                  t        |             |j                  j                  |j                         |cY d}~S d}~ww xY w# t        $ r\}|j                  j                  t        |             | j                  |      }|j                  j                  |       |cY d}~S d}~ww xY w)a  
        Return a ExpressionInfo object that contains information about
        the validation of an ``expression``  license expression string.

        If the syntax and license keys of ``expression`` is valid, then
        `ExpressionInfo.normalized_license_expression` is set.

        If an error was encountered when validating ``expression``,
        `ExpressionInfo.errors` will be populated with strings containing the
        error message that has occured. If an error has occured due to unknown
        license keys or an invalid license symbol, the offending keys or symbols
        will be present in `ExpressionInfo.invalid_symbols`

        If ``strict`` is True, validation error messages will be included if in
        a "WITH" expression such as "XXX with ZZZ" if the XXX symbol has
        `is_exception` set to True or the YYY symbol has `is_exception` set to
        False. This checks that exception symbols are used strictly as intended
        on the right side of a "WITH" statement.
        )rC   )r   N)r@   r   r}   r"   rE   r   rF   r   r   r   extendrD   )r3   r   r   rv   expression_infoparsed_expressionrm   r   s           r)   r   zLicensing.validate  s    ( )S_M	# $

:f
 E	#&&z2 %%o.M.M478I4JO1'  	#""))#a&1++221>>B""	#  	#""))#a&144Z@L++22<@""		#s<   A& C &	C/A
B?9C?C	D,AD'!D,'D,)TT)T)FFF)FF)r$   r%   r&   rJ   r]   rG   ry   r{   rr   r   r   r   r   r   r   r   r   r}   r   r   rf   r   r   r   __classcell__ro   s   @r)   rL   rL      sz    7r  %wd 5'n

%!F "+.J"+$'Sj4/l#J..<`6p,r(   rL   c                 *    t        t        |             S )z
    Return a Licensing object using ScanCode license keys loaded from a
    ``license_index_location`` location of a license db JSON index files
    See https://scancode-licensedb.aboutcode.org/index.json
    )build_licensingget_license_indexlicense_index_locations    r)   get_scancode_licensingr  *  s     ,-CDEEr(   c                 *    t        t        |             S )z
    Return a Licensing object using SPDX license keys loaded from a
    ``license_index_location`` location of a license db JSON index files
    See https://scancode-licensedb.aboutcode.org/index.json
    )build_spdx_licensingr   r   s    r)   get_spdx_licensingr  3  s       12H IJJr(   c                 n    t        |       5 }t        j                  |      cddd       S # 1 sw Y   yxY w)a  
    Return a list of mappings that contain license key information from
    ``license_index_location``

    The default value of `license_index_location` points to a vendored copy
    of the license index from https://scancode-licensedb.aboutcode.org/
    N)openjsonload)r  fs     r)   r   r   <  s/     
$	% yy|  s   +4c                 R    | D cg c]  }t        di | }}t        |      S c c}w )z
    Return a Licensing object that has been loaded with license keys and
    attributes from a ``license_index`` list of license mappings.
    r'   )rY   rL   )license_indexlsymss      r)   !load_licensing_from_license_indexr  H  s.    
 )661MA6D6T? 7s   $c           	          | D cg c]8  }|j                  dd      |j                  dd      |j                  dd      d: }}t        |      S c c}w )z
    Return a Licensing object that has been loaded with license keys and
    attributes from a ``license_index`` list of simple ScanCode license mappings.
    license_key is_deprecatedFis_exception)rb   r  r  r   r  r  r  licss      r)   r   r   Q  sa      	 55+UU?E:EE.%8	
D  -T22s   =Ac           
          | D cg c]Z  }|j                  d      rG|j                  dd      |j                  dg       |j                  dd      |j                  dd      d\ }}t        |      S c c}w )z
    Return a Licensing object that has been loaded with license keys and
    attributes from a ``license_index`` list of simple SPDX license mappings.
    spdx_license_keyr  other_spdx_license_keysr  Fr  )rb   r   r  r  r  r  s      r)   r  r  a  s~     	 55#$ 55+R0uu6;UU?E:EE.%8		
	D 	 -T22	s   AA1c              #     K   t        |       } t               fd}| D ]U  }|j                  r |       D ]  }|  | $s|j                  j	                         s| Ej                  |       W  |       D ]  }|  yw)z
    Yield Token given a ``token`` sequence of Token replacing unmatched
    contiguous tokens by a single token with a LicenseSymbol.
    c               3     K   syg } r\d   j                   j                         s?| j                  j                                rd   j                   j                         s?radj	                  d D              }d   j
                  }d   j                  }t        |      }j                          t        ||||       | D ]  }|  yw)zY
        Build and return a new Token from accumulated unmatched tokens or None.
        Nr   c              3   j   K   | ]+  }|j                   j                         s|j                    - y wr/   r   r   s     r)   r>   zUbuild_symbols_from_unknown_tokens.<locals>.build_token_with_symbol.<locals>.<genexpr>  s!     N1QXX^^=MahhNs   33r   )
r   r   r   popr   r   r   rY   clearr   )trailing_spacesr   r   r   toksymts	unmatcheds         r)   build_token_with_symbolzBbuild_symbols_from_unknown_tokens.<locals>.build_token_with_symbol}  s      	" 4 4 : : <""9==?3 	" 4 4 : : < XXN	NNFaL&&EB-##C"6*FOOsFF33! 	BH	s   A#C'A/CN)r   r   r1   r   r   r   )r   r%  toksymtokr$  s       @r)   r   r   t  s     
 &\FI,  
&9913 ISZZ%5%5%7	  %
& *+ s   BB	c              #     K   t        |       } d}t        |       |k  r| D ]  }|f 	 yt               }|j                  }|j                  }|j
                  }| D ]D  }t        |      |k(  r,t        |      rt        |        |        n |       }|f  ||       F |r4t        |      |k(  rt        |      rt        |       y|D ]  }|f 	 yyw)z
    Yield tuples of Token given a ``tokens`` sequence of Token such that:
     - all "XXX WITH YYY" sequences of 3 tokens are grouped in a three-tuple
     - single tokens are just wrapped in a tuple for consistency.
       N)r   r0   r   popleftr   r   is_with_subexpressionr]   )r   
triple_lenr&  tripletriple_poplefttriple_cleartripple_appendprev_toks           r)   )build_token_groups_for_with_subexpressionr2    s      &\F J 6{Z 	C&L	 WF^^N<<L]]N v;*$$V,Fm#)+k!s v;*$)>v)F- f	 s   CCc                     | \  }}}t        |j                  t              xr/ |j                  t        k(  xr t        |j                  t              S )zd
    Return True if a ``tokens_tripple`` Token tripple is a "WITH" license sub-
    expression.
    )r~   r1   rY   KW_WITH)tokens_tripplelicwitexcs       r)   r+  r+    sF    
 #MCc399m, 	1II 	1syy-0r(   c              #   p  K   t        |       }|D ]  }t        |      }|s|dk(  r|d   }|j                  }t        |t              r>|j
                  t        k(  rt        t        |j                  |j                  t              t        |t              r9|rE|j                  r9t        t        |j                  |j                  t              t        d|      | |dk7  rOdj!                  |D cg c]  }|j                   c}      }|d   j                  }	t        t        ||	t              |\  }
}}|
j                  }|j                  }|j                  j#                         }| d| d| }|
j                  }t        |t              s+t        t        |
j                  |
j                  t$              |r7|j                  r+t        t        |
j                  |
j                  t              |j                  }t        |t              s+t        t        |j                  |j                  t$              |r7|j                  s+t        t        |j                  |j                  t&              t)        |||      }t+        |
j                  |j,                  ||      }|  y	c c}w w)
a  
    Given a ``tokens`` iterable of Token, yield updated Token(s) replacing any
    "XXX WITH ZZZ" subexpression by a LicenseWithExceptionSymbol symbol.

    Check validity of WITH subexpessions and raise ParseError on errors.

    If ``strict`` is True also raise ParseError if the left hand side
    LicenseSymbol has `is_exception` True or if the right hand side
    LicenseSymbol has `is_exception` False.
    r   r   r   z.Licensing.tokenize is internally confused...: r)  r   )license_symbolexception_symbolr   )r   r   r   r1   N)r2  r0   r1   r~   r-   r   
TOKEN_WITHr   r   r   r   rY   r  r   PARSE_INVALID_EXCEPTION	Exceptionr   r   PARSE_INVALID_SYMBOL!PARSE_INVALID_SYMBOL_AS_EXCEPTIONr\   r   r   )r   r   token_groupstoken_group	len_groupr   tvalr&  r   r   	lic_tokenWITH	exc_tokenr6  r8  r   lic_symexc_symlic_exc_syms                      r)   r   r     s     =VDL# o$	>NE;;D$(99
* %#-%*\\!&#;	  D-0d//$#/%*\\!&#:	   "PQUPX YZZK>XX[AcszzABFN((E'#3	  &1"	4{{  "avQse, // '=1'&--"/	  g**'&--"2	  //'=1'$^^ /	  '..'&--"<	  1"$
 //	
 _oT Bs   C4J66J1
	F-J6c                        e Zd ZdZddZddZy)
Renderablez.
    An interface for renderable objects.
    c                     t         S )a  
        Return a formatted string rendering for this expression using the
        ``template`` format string to render each license symbol. The variables
        available are `symbol.key` and any other attribute attached to a
        LicenseSymbol-like instance; a custom ``template`` can be provided to
        handle custom rendering such as HTML.

        For symbols that hold multiple licenses (e.g. in a "XXX WITH YYY"
        statement) the template is applied to each symbol individually.

        Note that when render() is called the ``*args`` and ``**kwargs`` are
        passed down recursively to any Renderable object render() method.
        NotImplementedErrorr3   templater   rv   s       r)   renderzRenderable.renderc  s
     #"r(   c                 v    t        | t              r | j                  ||dd|S  | j                  ||dd|S )a,  
        Return a formatted string rendering for this expression using the
        ``template`` format string to render each symbol.  Add extra parenthesis
        around "WITH" sub-expressions such as in "(XXX WITH YYY)"for improved
        readbility. See ``render()`` for other arguments.
        F)rQ  wrap_with_in_parensT)r~   r\   rR  rP  s       r)   render_as_readablezRenderable.render_as_readables  sE     d674;;de]V\]]t{{H$XQWXXr(   N{symbol.key})r$   r%   r&   rJ   rR  rU  r'   r(   r)   rL  rL  ^  s    # 
Yr(   rL  c                       e Zd ZdZd Zd Zy)r   z'
    A base class for all symbols.
    c                     t         )z>
        Yield the underlying symbols of this symbol.
        rN  r2   s    r)   r   zBaseSymbol.decompose  s
     "!r(   c                 v    t        t              sy| k(  ryt        fd| j                         D              S )zK
        Test if the ``other`` symbol is contained in this symbol.
        FTc              3   (   K   | ]	  }|k(    y wr/   r'   )r<   mineothers     r)   r>   z*BaseSymbol.__contains__.<locals>.<genexpr>  s     >T45=>s   )r~   r   anyr   r3   r]  s    `r)   __contains__zBaseSymbol.__contains__  s4     %,5=>T^^-=>>>r(   N)r$   r%   r&   rJ   r   r`  r'   r(   r)   r   r     s    "
?r(   r   z^[-:\w\s\.\+]+$c                        e Zd ZdZ e       ddf fd	Zd Zd Zd Zd Z	d Z
d	 xZZdd
Zd Zd Zd Zd Zed        Z xZS )rY   ze
    A LicenseSymbol represents a license key or identifier as used in a license
    expression.
    Fc                    |st        d|      t        |t              s+t        |t              r	 t        |      }nt        d|      |j	                         }|st        d|      t        |      st        d|      dj                  |j                               }|j                         t        v rt        d|      || _
        |r1t        |t        t        f      st        d|dt        |       d	      |xr t        |      xs
 t               | _        || _        || _        t$        t&        | S  | j                         y #  t        d|      xY w)
NzA license key cannot be empty: z A license key must be a string: zA license key cannot be blank: zwInvalid license key: the valid characters are: letters and numbers, underscore, dot, colon or hyphen signs and spaces: r   zPInvalid license key: a key cannot be a reserved keyword: "or", "and" or "with": zLicense aliases: z must be a sequence and not: .)r"   r~   r   r   r   is_valid_license_keyr   r   rd   KEYWORDS_STRINGSrb   r   r]   r   r   r   r  r  rX   rY   rG   )r3   rb   r   r  r  r   rv   ro   s          r)   rG   zLicenseSymbol.__init__  s~    !$CC7"KLL#s##u%Vc(C &(H&PQQiik!$CC7"KLL $C(!'#  hhsyy{#99;**!%%(G- 
 :
 #G;.KDQXM?Z[\  15><UW*( 	mT+DHH5YV),LSG*TUUs   E Ec              #      K   |  yw)zW
        Return an iterable of the underlying license symbols for this symbol.
        Nr'   r2   s    r)   r   zLicenseSymbol.decompose  s      
s   c                 D    t        | j                  | j                  f      S r/   hashrb   r  r3   r   rv   s      r)   __hash__zLicenseSymbol.__hash__      TXXt00122r(   c                     | |u ryt        || j                        s| j                  |      sy| j                  |j                  k(  xr | j                  |j                  k(  S NTFr~   ro   symbol_likerb   r  r_  s     r)   __eq__zLicenseSymbol.__eq__  sS    5=5$..1T5E5Ee5Lxx599$P):):e>P>P)PPr(   c                     | |u ryt        || j                        s| j                  |      sy| j                  |j                  k7  xs | j                  |j                  k7  S NFTro  r_  s     r)   __ne__zLicenseSymbol.__ne__  sS    5=5$..1T5E5Ee5Lxx599$O(9(9U=O=O(OOr(   c                 r    t        |t        t        t        f      rt	        |       t	        |      k  S t
        S r/   r~   rY   r\   LicenseSymbolLiker   NotImplementedr_  s     r)   __lt__zLicenseSymbol.__lt__  s4    68IJ
 t9s5z))!!r(   c                      yNTr'   r   s    r)   r4   zLicenseSymbol.<lambda>       r(   c                 &    |j                  |       S )N)rn   )r   rP  s       r)   rR  zLicenseSymbol.render  s    d++r(   c                     | j                   S r/   r   r2   s    r)   __str__zLicenseSymbol.__str__  s    xxr(   c                 ,    t        | j                        S r/   )r0   rb   r2   s    r)   __len__zLicenseSymbol.__len__  s    488}r(   c                     | j                   j                  }| j                  }| j                  xr d| j                  dxs d}| j                  }| d|d| d|dS )Nzaliases=r   r  r6   zis_exception=r7   )ro   r$   rb   r   r  )r3   clsrb   r   r  s        r)   rI   zLicenseSymbol.__repr__  sf    nn%%hh,,@Xdll-=R#@FB((awb	|6FaHHr(   c                     t        | j                  | j                  xr t        | j                        xs
 t               | j                        S )N)rb   r   r  )rY   rb   r   r]   r  r2   s    r)   __copy__zLicenseSymbol.__copy__  s;    LL8U4<<%8CEG**
 	
r(   c                 6    t        |d      xr t        |d      S )zj
        Return True if ``symbol`` is a symbol-like object with its essential
        attributes.
        rb   r  )hasattr)r  rn   s     r)   rp  zLicenseSymbol.symbol_like  s     vu%I'&.*IIr(   rV  )r$   r%   r&   rJ   r]   rG   r   rk  rq  rt  ry  __nonzero____bool__rR  r  r  rI   r  classmethodrp  r   r   s   @r)   rY   rY     sp     !7%e66p3QP" ,+K(,I
 J Jr(   rY   c                   V     e Zd ZdZ fdZd Zd
 fd	Zd xZZd Z	d Z
d Zd	 Z xZS )rw  zj
    A LicenseSymbolLike object wraps a symbol-like object to expose it's
    LicenseSymbol behavior.
    c                 p   | j                  |      st        d|      || _        t        t        |   |d| j                  j                  i| | j                  j                  | _        t        | j                  dt                     | _
        d | _        t        |dd       }t        |      r|| _        y y )NzNot a symbol-like object: rb   r   rR  )rp  r"   wrappedrX   rw  rG   rb   r  r   r]   r   _rendercallable)r3   rp  r   rv   rendererro   s        r)   rG   zLicenseSymbolLike.__init__*  s    ,!$>{o"NOO"/tVDLL4D4DVvV LL55t||Y@ ;$7H#DL r(   c                 .    t        | j                        S )N)rp  )rw  r  r2   s    r)   r  zLicenseSymbolLike.__copy__;  s     T\\::r(   c                 v    | j                   r | j                   |g|i |S t        t        |   |g|i |S r/   )r  rX   rw  rR  )r3   rQ  r   rv   ro   s       r)   rR  zLicenseSymbolLike.render>  sB    <<4<<:4:6::&4XOOOOr(   c                      yr{  r'   r|  s    r)   r4   zLicenseSymbolLike.<lambda>D  r}  r(   c                 D    t        | j                  | j                  f      S r/   rh  rj  s      r)   rk  zLicenseSymbolLike.__hash__F  rl  r(   c                     | |u ryt        || j                        s| j                  |      sy| j                  |j                  k(  xr | j                  |j                  k(  S rn  ro  r_  s     r)   rq  zLicenseSymbolLike.__eq__I  sS    5=5$..1T5E5Ee5Lxx599$P):):e>P>P)PPr(   c                     | |u ryt        || j                        s| j                  |      sy| j                  |j                  k7  xs | j                  |j                  k7  S rs  ro  r_  s     r)   rt  zLicenseSymbolLike.__ne__P  sS    5=5$..1T5E5Ee5Lxx599$O(9(9U=O=O(OOr(   c                 r    t        |t        t        t        f      rt	        |       t	        |      k  S t
        S r/   rv  r_  s     r)   ry  zLicenseSymbolLike.__lt__W  .    em-GIZ[\t9s5z))!!r(   rV  )r$   r%   r&   rJ   rG   r  rR  r  r  rk  rq  rt  ry  r   r   s   @r)   rw  rw  #  s:    
$";P ,+K(3QP"r(   rw  c                   f     e Zd ZdZd fd	Zd Zd ZddZd Zd Z	d Z
d	 Zd
 xZZd Zd Z xZS )r\   a  
    A LicenseWithExceptionSymbol represents a license with a "WITH" keyword and
    a license exception such as the Classpath exception. When used in a license
    expression, this is treated as a single Symbol. It holds two LicenseSymbols
    objects: one for the left-hand side license proper and one for the right-
    hand side exception to the license and deals with the specifics of
    resolution, validation and representation.
    c                 V   t         j                  |      st        d|      |r|j                  rt        d|      t         j                  |      st        d|      |r|j                  st        d|      || _        || _        t        t        | #  t        |              y)aF  
        Initialize a new LicenseWithExceptionSymbol from a ``license_symbol``
        and a ``exception_symbol`` symbol-like objects.

        Raise a ExpressionError exception if ``strict`` is True and either:
        - ``license_symbol``.is_exception is True
        - ``exception_symbol``.is_exception is not True
        z4license_symbol must be a LicenseSymbol-like object: zTlicense_symbol cannot be an exception with the "is_exception" attribute set to True:z6exception_symbol must be a LicenseSymbol-like object: zGexception_symbol must be an exception with "is_exception" set to True: N)
rY   rp  r"   r  r:  r;  rX   r\   rG   r   )r3   r:  r;  r   r   rv   ro   s         r)   rG   z#LicenseWithExceptionSymbol.__init__j  s     ((8!F~FXY  n11!))7(:< 
 (()9:!HIYH\]  *77!  035 
 - 0($8TCr(   c                 h    t        t        | j                        t        | j                              S )Nr:  r;  )r\   r   r:  r;  r2   s    r)   r  z#LicenseWithExceptionSymbol.__copy__  s+    ) 3 34!$"7"78
 	
r(   c              #   D   K   | j                    | j                   y wr/   r  r2   s    r)   r   z$LicenseWithExceptionSymbol.decompose  s     !!!###s    c                      | j                   j                  |g|i |} | j                  j                  |g|i |}| d| }|rd| d}|S )z
        Return a formatted "WITH" expression. If ``wrap_with_in_parens``, wrap
        the expression in parens as in "(XXX WITH YYY)".
         WITH r6   r7   )r:  rR  r;  )r3   rQ  rT  r   rv   r6  r8  rends           r)   rR  z!LicenseWithExceptionSymbol.render  sm    
 )d!!((CDCFC*d##**8EdEfEfSE"tfA;Dr(   c                 D    t        | j                  | j                  f      S r/   )ri  r:  r;  rj  s      r)   rk  z#LicenseWithExceptionSymbol.__hash__  s&    ##%%
 	
r(   c                     | |u ryt        || j                        sy| j                  |j                  k(  xr | j                  |j                  k(  S rn  r~   ro   r:  r;  r_  s     r)   rq  z!LicenseWithExceptionSymbol.__eq__  sR    5=%0 5#7#77 @%%)?)??	
r(   c                     | |u ryt        || j                        sy| j                  |j                  k(  xr | j                  |j                  k(   S rs  r  r_  s     r)   rt  z!LicenseWithExceptionSymbol.__ne__  sW    5=%0 5#7#77 @%%)?)??
 	
r(   c                 r    t        |t        t        t        f      rt	        |       t	        |      k  S t
        S r/   rv  r_  s     r)   ry  z!LicenseWithExceptionSymbol.__lt__  r  r(   c                      yr{  r'   r|  s    r)   r4   z#LicenseWithExceptionSymbol.<lambda>  r}  r(   c                 `    | j                   j                   d| j                  j                   S )Nr  )r:  rb   r;  r2   s    r)   r  z"LicenseWithExceptionSymbol.__str__  s-    %%))*&1F1F1J1J0KLLr(   c                     | j                   j                  }t        | j                   j                        }|j                  | j                         | d| j
                  d| j                  dS )N)r  z(license_symbol=z, exception_symbol=r7   )ro   r$   dictupdate__dict__r:  r;  )r3   r  r   s      r)   rI   z#LicenseWithExceptionSymbol.__repr__  sh    nn%%//0DMM"e "114 5  $ 5 58;	
r(   F)rW  F)r$   r%   r&   rJ   rG   r  r   rR  rk  rq  rt  ry  r  r  r  rI   r   r   s   @r)   r\   r\   _  sI    "DH
$





" ,+K(M
r(   r\   c                       e Zd ZddZy)RenderableFunctionc                 H   | j                   }t        |      dk(  rw|d   }t        |t              r |j                  |g|i |}nt        d|       t        |      }| j                  r| j                   | }|S | j                   d| d}|S g }|j                  }|D ]d  }	t        |	t              r |	j                  |g|i |}nt        d|	d       t        |	      }|	j                  r	 ||       Y |d| d       f | j                  j                  |      S )z
        Render an expression as a string, recursively applying the string
        ``template`` to every symbols and operators.
        r   r   zFWARNING: symbol is not renderable: using plain string representation: r6   r7   z^WARNING: object in expression is not renderable: falling back to plain string representation: rc  )r   r0   r~   rL  rR  r`   r   	isliteralr   r   r   )
r3   rQ  r   rv   expression_argsr   renderedrendered_itemsrendered_items_appendr   s
             r)   rR  zRenderableFunction.render  sJ   
 ))1$!!$C#z* cjj;D;F; \]`\cd #h ~~"mm_SE2 O #mm_AcU!4O . 5 5" 	7C#z*%3::h@@@ DDG7!M s8}}%h/%(1o6!	7$ }}!!.11r(   NrV  )r$   r%   r&   rR  r'   r(   r)   r  r    s    .2r(   r  c                   "     e Zd ZdZ fdZ xZS )rT   zB
    Custom representation for the AND operator to uppercase.
    c                 f    t        |      dk  rt        d      t        t        |   |  d| _        y )N   z4AND requires two or more licenses as in: MIT AND BSDz AND )r0   r"   rX   rT   rG   r   r3   r   ro   s     r)   rG   zAND.__init__  s0    t9q=!"XYYc4!4(r(   r$   r%   r&   rJ   rG   r   r   s   @r)   rT   rT     s       r(   rT   c                   "     e Zd ZdZ fdZ xZS )rU   zA
    Custom representation for the OR operator to uppercase.
    c                 f    t        |      dk  rt        d      t        t        |   |  d| _        y )Nr  z2OR requires two or more licenses as in: MIT OR BSDz OR )r0   r"   rX   rU   rG   r   r  s     r)   rG   zOR.__init__  s0    t9q=!"VWWb$ $'r(   r  r   s   @r)   rU   rU     s     r(   rU   c                 L    | sg S g }| D ]  }||v r|j                  |        |S )zT
    Return unique items in a sequence ``seq`` preserving their original order.
    )r   )sequniquesitems      r)   r   r   &  s=     	G 7?t Nr(   c              #   l  K   | r| D ]  }|st        |t              r	 t        |      }t        |t              r|j	                         sCt        |       Qt        |t
              r| ft
        j                  |      rt        |       t        |d       yy#  t        |d      xY ww)az  
    Return an iterable of LicenseSymbol objects from a ``symbols`` sequence of
    strings or LicenseSymbol-like objects.

    If an item is a string, then create a new LicenseSymbol for it using the
    string as key.
    If this is not a string it must be a LicenseSymbol- like type. Raise a
    TypeError expection if an item is neither a string or LicenseSymbol- like.
    z is not a string.z, is neither a string nor LicenseSymbol-like.N)r~   r   r   r   r   rY   rp  rw  )rg   rn   s     r)   r^   r^   4  s       	[F&%(D [F &#&<<>'//FM2**62'//  6*,X YZZ)	[ D#vj0A$BCCs"   B4B! B4
AB4!B11B4c           
      
   t               }i }t               }g }t               }t               }t        t              }t               }	t        t              }
t               }| D ]  }t        |t              s|j                  |       &|j                  }|j                         }|j                         }||v r|j                  |       |t        v r|	j                  |       |j                  |       t        |dg       }t        |      }t        |D cg c]=  }dj                  |j                         j                         j                               ? c}      }t        d |D              }t        |      |k7  r|j                  |       |j                  |       |D ]O  }|j                  |      }|r||k7  r||   j                  |       |t        v r|
|   j                  |       |||<   Q |j                   s||v r|j                  |       |j                  |        g }t#        |      D ]  }|j                  d|d        t#        |      D ]  }|j                  d|d        t#        |j%                               D ].  \  }}dj                  |      }|j                  d| d	|d       0 t#        |
j%                               D ].  \  }}dj                  |      }|j                  d
|d| d       0 t#        |      D ]  }|j                  d| d        t#        |	      D ]  }|j                  d| d        g }t#        |      D ]  }|j                  d|d        ||fS c c}w )a  
    Return a tuple of (`warnings`, `errors`) given a sequence of ``symbols``
    LicenseSymbol-like objects.

    - `warnings` is a list of validation warnings messages (possibly empty if
      there were no warnings).
    - `errors` is a list of validation error messages (possibly empty if there
      were no errors).

    Keys and aliases are cleaned and validated for uniqueness.

    If ``validate_keys`` also validate that license keys are known keys.
    r   r   c              3   &   K   | ]	  }|s|  y wr/   r'   )r<   as     r)   r>   z#validate_symbols.<locals>.<genexpr>  s     .AAa.s   z*Invalid item: not a LicenseSymbol object: rc  z Invalid duplicated license key: r   z4Invalid duplicated alias pointing to multiple keys: z point to keys: z@Invalid aliases: an alias cannot be an expression keyword. key: z, aliases: z*Invalid duplicated license exception key: z4Invalid key: a key cannot be an expression keyword: z5Duplicated or empty aliases ignored for license key: )setr   r   r~   rY   r   rb   r   rd   r   re  r   r0   r   r   r   r  sortedrZ   )rg   validate_keys	seen_keysseen_aliasesseen_exceptionsnot_symbol_classes	dupe_keysdupe_exceptionsdupe_aliasesinvalid_keys_as_kwinvalid_alias_as_kwwarning_dupe_aliasesrn   rb   keylr   initial_alias_lenr   aliased_keyrE   inddupedaliasdkeysikeyialiasesikwwarnings
dupe_aliass                                r)   r_   r_   V  s     ILeO IeOt$L%d+ 5 8*&-0%%f-jjiikyy{ 9MM# ##""3' 	d &)R0L GT5sxx 3 3 5 ; ; =>TU ... w<,, $$S) 	D 	'E
 '**51K{d2U#**3/ ((#C(//6"&L	' &##D)##D)q8*v F() MB3'KLM y! D8BCD   2 2 45 
		% Bh&uiq2	

 !!4!:!:!<= 
h99X&8;xj3	

 ' LB4&JKL () ULSEQRSTU H\* _
Mj^[\]^_ VC Us   AN 
Tc                    | syt        | t        t        f      st        dt	        |              |r|j                         dvrt        d|       | D cg c]  }|j                  |d       } }|r1t        | D ci c]  }t        |      | c}j                               } t        |       dk(  r| d   S |j                  |j                  d|   } ||  S c c}w c c}w )	aC  
    Return a combined LicenseExpression object with the `relation`, given a list
    of license ``expressions`` strings or LicenseExpression objects. If
    ``unique`` is True remove duplicates before combining expressions.

    For example::
        >>> a = 'mit'
        >>> b = 'gpl'
        >>> str(combine_expressions([a, b]))
        'mit AND gpl'
        >>> assert 'mit' == str(combine_expressions([a]))
        >>> combine_expressions([])
        >>> combine_expressions(None)
        >>> str(combine_expressions(('gpl', 'mit', 'apache',)))
        'gpl AND mit AND apache'
        >>> str(combine_expressions(('gpl', 'mit', 'apache',), relation='OR'))
        'gpl OR mit OR apache'
        >>> str(combine_expressions(('gpl', 'mit', 'mit',)))
        'gpl AND mit'
        >>> str(combine_expressions(('mit WITH foo', 'gpl', 'mit',)))
        'mit WITH foo AND gpl AND mit'
        >>> str(combine_expressions(('gpl', 'mit', 'mit',), relation='OR', unique=False))
        'gpl OR mit OR mit'
        >>> str(combine_expressions(('mit', 'gpl', 'mit',)))
        'mit AND gpl'
    Nz/expressions should be a list or tuple and not: )rT   rU   z+relation should be one of AND, OR and not: T)r   r   r   )r~   r   r]   r   r   upperr}   r   valuesr0   rT   rU   )r   r   r   r   lexs         r)   r   r     s    @ kD%=1I${J[I\]^^x~~' 0  EhZPQQ ?JJ9??2d?3JKJ {;!CFAI;BBDE
;11~ }}ILL9(CH[!! K
 <s   C>Cr  )`rJ   r   r  rer   collectionsr   r   r   r   r   	functoolsr   os.pathr	   r
   r   booleanr   r   boolean.booleanr   r   r   r   r   r   r   r   r   r   r   r   r   !license_expression._pyahocorasickr   r   r   __file__curr_dirdata_dir*vendored_scancode_licensedb_index_locationr   r=  r@  r?  r>  r"   r,   r-   r  r<  r   r   KW_ANDKW_ORr4  r   r  re  r   compileVERBOSE	MULTILINEUNICODEfinditerr   r@   BooleanAlgebrarL   r  r  r   r  r   r  r   r2  r+  r   objectrL  rV   r   r   rd  rY   rw  r\   r  rT   rU   r   r^   r_   r   r'   r(   r)   <module>r     sM     	  #  "   $     3 ) 4 1 ; 9 ; / & ( % $ & & G 378$%&!-1#. *  # |31VL-. ,.	+ ()
 %( !$L8] 23  |+)ML%&	i 		: 	
 Y
-. 
 #z
"
#z
"			"h
&*
% 	 3(33  %9	BJJ JJ

* ( /
 /
dj	&& j	Z 3] F /Y K .X 	3 3&-`+\
|~Y YD?W^^ ?2 "rzz"4bjjAGG  AJJ AJ AJJ 7" 7" 7"v w
 w
 w
t12 12h	 
gkk 	 		WZZ 	[Dy| k	8"r(   