22# requires-python = ">=3.11"
33# dependencies = [
44# "scancode-toolkit",
5- # "requests",
65# ]
76# ///
87
98import json
109import subprocess
1110import sys
12- import os
13- from datetime import datetime
11+ from pathlib import Path
1412
15- # A more robust mapping of license text templates
16- # In a production org, you'd pull these from https://opensource.org/licenses/
17- LICENSE_MAP = {
18- "MIT" : "https://opensource.org/licenses/MIT" ,
19- "Apache-2.0" : "https://opensource.org/licenses/Apache-2.0" ,
20- "GPL-3.0" : "https://opensource.org/licenses/GPL-3.0" ,
21- "AGPL-3.0" : "https://opensource.org/licenses/AGPL-3.0" ,
22- }
23-
24- def get_full_license_text (license_id , holder ):
13+ def evaluate_compliance (detected_licenses ):
2514 """
26- In a real scenario, you'd have these files in your 'compliance-toolkit' repo.
27- For this script, we generate a placeholder header.
15+ Pure logic: Takes a list of licenses and returns (recommendation, commercial_allowed, blockers).
2816 """
29- year = datetime .now ().year
30- return f"FULL LICENSE TEXT FOR { license_id } \n Copyright (c) { year } { holder } \n \n [Standard { license_id } terms apply...]"
17+ recommendation = "Apache-2.0"
18+ commercial_allowed = True
19+ blockers = []
3120
32- def run_scan (target ):
33- print ("🚀 Scanning dependencies..." )
34- subprocess .run (["scancode" , "-l" , "--json-pp" , "results.json" , target ], check = True , capture_output = True )
21+ # Normalize to lowercase for easier matching
22+ normalized = [l .lower () for l in detected_licenses ]
3523
36- def analyze ():
37- with open ("results.json" ) as f :
38- data = json .load (f )
24+ # Check for Viral/Strong Copyleft (AGPL/GPL)
25+ if any ("agpl" in l for l in normalized ):
26+ recommendation = "AGPL-3.0"
27+ commercial_allowed = False
28+ elif any ("gpl" in l for l in normalized ):
29+ recommendation = "GPL-3.0"
30+ commercial_allowed = False
31+
32+ # Collect blockers for commercial release
33+ if not commercial_allowed :
34+ blockers = [l for l in detected_licenses if any (v in l .lower () for v in ["gpl" , "agpl" ])]
3935
40- detected = set ()
41- hindering_commercial = []
42-
43- for file in data .get ('files' , []):
44- for entry in file .get ('license_expressions' , []):
45- lic = entry .lower ()
46- detected .add (entry )
47- # Check for commercial blockers
48- if any (viral in lic for viral in ["gpl" , "osl" , "cpal" ]):
49- hindering_commercial .append (f"{ file ['path' ]} ({ entry } )" )
36+ return recommendation , commercial_allowed , blockers
5037
51- return detected , hindering_commercial
38+ def run_scancode (target_path ):
39+ """Runs the actual shell command to scan the project."""
40+ output_file = "results.json"
41+ subprocess .run (
42+ ["scancode" , "-l" , "--json-pp" , output_file , target_path ],
43+ check = True , capture_output = True
44+ )
45+ return output_file
5246
5347def main ():
5448 target = sys .argv [1 ] if len (sys .argv ) > 1 else "."
5549 apply_fix = "--apply" in sys .argv
56- org_name = "Your Organization Name"
5750
58- run_scan (target )
59- detected , blockers = analyze ()
51+ # 1. Scan
52+ results_path = run_scancode (target )
53+
54+ # 2. Parse
55+ with open (results_path ) as f :
56+ data = json .load (f )
57+
58+ detected = set ()
59+ for file in data .get ('files' , []):
60+ for entry in file .get ('license_expressions' , []):
61+ detected .add (entry )
6062
61- print ("\n " + "=" * 50 )
62- print ("⚖️ OPEN SOURCE COMPLIANCE ANALYSIS" )
63- print ("=" * 50 )
63+ # 3. Evaluate
64+ rec , comm_ok , blockers = evaluate_compliance (list (detected ))
6465
65- # 1. Commercial Viability Check
66+ # 4. Output (simplified for brevity)
67+ print (f"Recommended License: { rec } " )
68+ print (f"Commercial Release Possible: { comm_ok } " )
6669 if blockers :
67- print ("\n ❌ COMMERCIAL RELEASE: NOT RECOMMENDED" )
68- print ("The following dependencies have 'Viral' licenses that require your code to be Open Source:" )
69- for b in set (blockers [:5 ]): # Show first 5
70- print (f" - { b } " )
71- else :
72- print ("\n ✅ COMMERCIAL RELEASE: POSSIBLE" )
73- print ("All dependencies are permissive. You can release this commercially." )
74-
75- # 2. Recommendation Logic
76- recommendation = "Apache-2.0" # Default
77- if any ("agpl" in l .lower () for l in detected ):
78- recommendation = "AGPL-3.0"
79- elif any ("gpl" in l .lower () for l in detected ):
80- recommendation = "GPL-3.0"
81-
82- print (f"\n 💡 RECOMMENDED OPEN SOURCE LICENSE: { recommendation } " )
83-
84- # 3. Apply the license file
85- if apply_fix :
86- text = get_full_license_text (recommendation , org_name )
87- with open ("LICENSE" , "w" ) as f :
88- f .write (text )
89- print (f"\n 💾 SUCCESS: Created LICENSE file ({ recommendation } )" )
90- else :
91- print ("\n 👉 Run with '--apply' to automatically create the LICENSE file." )
70+ print (f"Blockers: { ', ' .join (blockers )} " )
9271
9372if __name__ == "__main__" :
9473 main ()
0 commit comments