File size: 2,348 Bytes
be0c348 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | """Check syntax, imported local modules, file types and public package hashes."""
import ast
import hashlib
import importlib.util
import json
from pathlib import Path
root = Path(__file__).resolve().parents[1]
allowed = {'.py', '.sh', '.json', '.md', '.yaml', '.yml', '.txt', '.cff', '.sha256'}
files = [p for p in root.rglob('*') if p.is_file() and '__pycache__' not in p.parts]
modules = {}
for path in (root / 'src').rglob('*.py'):
parts = list(path.relative_to(root / 'src').with_suffix('').parts)
if parts[-1] == '__init__':
parts.pop()
modules['.'.join(parts)] = path
errors = []
for path in files:
rel = path.relative_to(root).as_posix()
if path.is_symlink() or path.suffix not in allowed or path.stat().st_size > 2 * 1024 * 1024:
errors.append(f'Unexpected file: {rel}')
continue
text = path.read_text(encoding='utf-8')
if path.suffix == '.py':
ast.parse(text, filename=rel)
if path.suffix == '.json':
json.loads(text)
for module, path in modules.items():
package = module if path.name == '__init__.py' else module.rpartition('.')[0]
for node in ast.walk(ast.parse(path.read_text())):
targets = []
if isinstance(node, ast.Import):
targets = [alias.name for alias in node.names]
elif isinstance(node, ast.ImportFrom):
targets = [importlib.util.resolve_name('.' * node.level + (node.module or ''), package)
if node.level else node.module or '']
for target in targets:
if target.startswith('llamafactory') and target not in modules:
errors.append(f'Missing local import: {module} -> {target}')
manifest = root / 'MANIFEST.sha256'
expected_paths = set()
for line in manifest.read_text().splitlines():
digest, relative = line.split(' ', 1)
expected_paths.add(relative)
path = root / relative
if not path.is_file() or hashlib.sha256(path.read_bytes()).hexdigest() != digest:
errors.append(f'Checksum mismatch: {relative}')
if expected_paths != {p.relative_to(root).as_posix() for p in files if p != manifest}:
errors.append('Checksum manifest and package file set differ')
if errors:
raise SystemExit('\n'.join(errors))
print(f'Passed: {len(files)} package files, {len(modules)} source modules, syntax, imports and hashes.')
|