#!/usr/bin/env python3 """ Analyze column widths from YAML specs. Usage: python3 analyze_column_widths.py [stand] stand: test (default), dev, prod """ import os, sys, yaml STAND = sys.argv[1] if len(sys.argv) > 1 else 'test' REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) YAML_DIR = f'{REPO}/generated/{STAND}/resources_yaml' if not os.path.isdir(YAML_DIR): print(f'Error: {YAML_DIR} not found') sys.exit(1) all_params = [] nested_count = 0 def extract_params(svc, op, params_list, depth=0): global nested_count for p in params_list: if not isinstance(p, dict): continue all_params.append((svc, op, p, depth)) sub = p.get('sub_params', []) if sub: nested_count += len(sub) extract_params(svc, op, sub, depth + 1) for fname in sorted(os.listdir(YAML_DIR)): if not fname.endswith('.yaml'): continue with open(os.path.join(YAML_DIR, fname)) as f: data = yaml.safe_load(f) svc = data.get('name', fname) for op in data.get('operations', []): if op.get('action') not in ('create', 'modify'): continue extract_params(svc, op.get('name', '?'), op.get('params', [])) print(f'Stand: {STAND} | Files: {len(os.listdir(YAML_DIR))}') print(f'Total params: {len(all_params)} | Nested subparams: {nested_count}') def stats(items, label): if not items: return lens = [len(str(t[2])) for t in items] n = len(lens) mx, avg = max(lens), sum(lens)/n print(f'\n--- {label} (n={n}) ---') print(f' MAX: {mx} | AVG: {avg:.0f}') print(f' >30: {sum(l in (l>30 for l in lens))/n*100:.0f}% >50: {sum(1 for l in lens if l>50)/n*100:.0f}% >100: {sum(1 for l in lens if l>100)/n*100:.0f}% >200: {sum(1 for l in lens if l>200)/n*100:.0f}% >500: {sum(1 for l in lens if l>500)/n*100:.0f}%') codes = [(s,o,p.get('code','')) for s,o,p,d in all_params] dtypes = [(s,o,p.get('data_type', p.get('type',''))) for s,o,p,d in all_params] defs = [(s,o,str(p['default'])) for s,o,p,d in all_params if 'default' in p] descrs = [(s,o,p.get('descr','') or p.get('man','')) for s,o,p,d in all_params if p.get('descr') or p.get('man')] constraint_keys = ['min_value','max_value','regex','value_list','max_length','min_length','func','ref_svc_id','unique'] constraints = [] for s,o,p,d in all_params: parts = [] for k in constraint_keys: v = p.get(k) if v is not None: parts.append(f'{k}={v}') if parts: constraints.append((s,o,' | '.join(parts))) stats(codes, 'Code'); stats(dtypes, 'Type'); stats(defs, 'Default') stats(descrs, 'Description'); stats(constraints, 'Constraints') for name, arr in [('Code', codes), ('Type', dtypes), ('Default', defs), ('Description', descrs), ('Constraints', constraints)]: top = sorted(arr, key=lambda x: len(str(x[2])), reverse=True)[:3] print(f'\nTop-3 longest {name}:') for s, o, v in top: print(f' [{s}/{o}] len={len(str(v))}: {str(v)[:120]}')