Print a summary of `m` using a output text width of `n` chars

def model_summary(m:Learner, n:int=70):
    "Print a summary of `m` using a output text width of `n` chars"
    info = layers_info(m)
    header = ["Layer (type)", "Output Shape", "Param #", "Trainable"]
    res = "=" * n + "\n"
    res += f"{header[0]:<20} {header[1]:<20} {header[2]:<10} {header[3]:<10}\n"
    res += "=" * n + "\n"
    total_params = 0
    total_trainable_params = 0
    for layer, size, params, trainable in info:
        if size is None: continue
        total_params += int(params)
        total_trainable_params += int(params) * trainable
        size, trainable = str(list(size)), str(trainable)
        res += f"{layer:<20} {size:<20} {int(params):<10,} {trainable:<10}\n"
        res += "_" * n + "\n"
    res += f"\nTotal params: {total_params:,}\n"
    res += f"Total trainable params: {total_trainable_params:,}\n"
    res += f"Total non-trainable params: {total_params - total_trainable_params:,}\n"
    return PrettyString(res)