#!/usr/bin/env python3 """Bundle exact resolved package licenses; no network or parent-project dependency.""" import json,pathlib,urllib.parse root=pathlib.Path(__file__).resolve().parents[1] config=root/'.dart_tool/package_config.json' packages=json.loads(config.read_text())['packages'] sections=[]; index=[] for package in sorted(packages,key=lambda p:p['name']): if package['name']=='sm_mobile': continue uri=urllib.parse.urljoin(config.as_uri(),package['rootUri']) path=pathlib.Path(urllib.parse.unquote(urllib.parse.urlparse(uri).path)) texts=[] for file in sorted(path.iterdir()): if file.is_file() and file.name.upper().split('.')[0] in ['LICENSE','LICENCE','COPYING','NOTICE']: texts.append(file.name+'\n'+file.read_text(errors='replace')) if not texts and package['name'] in ['flutter_driver','flutter_test','integration_test','flutter_localizations','flutter_web_plugins','flutter','fuchsia_remote_debug_protocol']: for parent in path.parents: license_file=parent/'LICENSE' if license_file.is_file(): texts.append('Flutter SDK LICENSE\n'+license_file.read_text());break if not texts: raise SystemExit('Missing license: '+package['name']) version='SDK' pubspec=path/'pubspec.yaml' if pubspec.exists(): import re m=re.search(r'^version:\s*([^\n]+)',pubspec.read_text(),re.M) if m: version=m.group(1) index.append(f"| {package['name']} | {version} |") sections.append('\n'+'='*72+'\n'+package['name']+' '+version+'\n'+'\n'.join(texts)) (root/'assets/legal/third_party_notices.txt').write_text('SM Mobile — licenses of resolved Dart/Flutter components\n'+''.join(sections)) (root/'docs/RESOLVED_COMPONENTS.md').write_text('# Resolved Dart and Flutter components\n\nGenerated from package_config.json and the exact package license files.\nFull texts: `assets/legal/third_party_notices.txt`. Flutter also embeds NOTICES.Z in each build.\n\n| Component | Version |\n| --- | --- |\n'+'\n'.join(index)+'\n') print(f'Collected {len(sections)} component license notices.')