mirror of
https://github.com/MervinPraison/PraisonAI.git
synced 2026-11-09 17:31:52 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5d67f0fdcf | ||
|
|
fb93b7d6d5 |
No files matched your search
@@ -148,6 +148,10 @@ Methods:
|
||||
* <code title="cli">praisonai agents info <a href="./src/praisonai/praisonai/cli/commands/agents.py">--help</a></code>
|
||||
* <code title="cli">praisonai agents list <a href="./src/praisonai/praisonai/cli/commands/agents.py">--help</a></code>
|
||||
* <code title="cli">praisonai audit agent-centric <a href="./src/praisonai/praisonai/cli/commands/audit.py">--help</a></code>
|
||||
* <code title="cli">praisonai batch batch-run <a href="./src/praisonai/praisonai/cli/commands/batch.py">--help</a></code>
|
||||
* <code title="cli">praisonai batch list <a href="./src/praisonai/praisonai/cli/commands/batch.py">--help</a></code>
|
||||
* <code title="cli">praisonai batch report <a href="./src/praisonai/praisonai/cli/commands/batch.py">--help</a></code>
|
||||
* <code title="cli">praisonai batch stats <a href="./src/praisonai/praisonai/cli/commands/batch.py">--help</a></code>
|
||||
* <code title="cli">praisonai benchmark agent <a href="./src/praisonai/praisonai/cli/commands/benchmark.py">--help</a></code>
|
||||
* <code title="cli">praisonai benchmark benchmark-callback <a href="./src/praisonai/praisonai/cli/commands/benchmark.py">--help</a></code>
|
||||
* <code title="cli">praisonai benchmark cli <a href="./src/praisonai/praisonai/cli/commands/benchmark.py">--help</a></code>
|
||||
|
||||
@@ -16,7 +16,7 @@ RUN mkdir -p /root/.praison
|
||||
# Install Python packages (using latest versions)
|
||||
RUN pip install --no-cache-dir \
|
||||
praisonai_tools \
|
||||
"praisonai>=3.9.2" \
|
||||
"praisonai>=3.9.3" \
|
||||
"praisonai[chat]" \
|
||||
"embedchain[github,youtube]"
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ RUN mkdir -p /root/.praison
|
||||
# Install Python packages (using latest versions)
|
||||
RUN pip install --no-cache-dir \
|
||||
praisonai_tools \
|
||||
"praisonai>=3.9.2" \
|
||||
"praisonai>=3.9.3" \
|
||||
"praisonai[ui]" \
|
||||
"praisonai[chat]" \
|
||||
"praisonai[realtime]" \
|
||||
|
||||
@@ -16,7 +16,7 @@ RUN mkdir -p /root/.praison
|
||||
# Install Python packages (using latest versions)
|
||||
RUN pip install --no-cache-dir \
|
||||
praisonai_tools \
|
||||
"praisonai>=3.9.2" \
|
||||
"praisonai>=3.9.3" \
|
||||
"praisonai[ui]" \
|
||||
"praisonai[crewai]"
|
||||
|
||||
|
||||
@@ -1,155 +1,155 @@
|
||||
{
|
||||
"timestamp": "2025-12-31T18:45:38.187539Z",
|
||||
"timestamp": "2026-01-16T05:23:04.919943Z",
|
||||
"metadata": {
|
||||
"python_version": "3.12.11",
|
||||
"platform": "macOS-15.7.4-arm64-arm-64bit",
|
||||
"praisonai_version": "2.9.2",
|
||||
"timestamp": "2025-12-31T18:45:38.226558Z"
|
||||
"platform": "macOS-26.3-arm64-arm-64bit",
|
||||
"praisonai_version": "3.9.2",
|
||||
"timestamp": "2026-01-16T05:23:04.932474Z"
|
||||
},
|
||||
"startup": {
|
||||
"cold_ms": 80.9305000002496,
|
||||
"warm_ms": 55.266541996388696
|
||||
"cold_ms": 27.866583000104583,
|
||||
"warm_ms": 27.75670800019725
|
||||
},
|
||||
"import_analysis": [
|
||||
{
|
||||
"module": "praisonaiagents",
|
||||
"self_us": 2419,
|
||||
"cumulative_us": 1645390,
|
||||
"self_ms": 2.419,
|
||||
"cumulative_ms": 1645.39
|
||||
"self_us": 403,
|
||||
"cumulative_us": 188329,
|
||||
"self_ms": 0.403,
|
||||
"cumulative_ms": 188.329
|
||||
},
|
||||
{
|
||||
"module": "praisonaiagents.workflows",
|
||||
"self_us": 670,
|
||||
"cumulative_us": 1375919,
|
||||
"self_ms": 0.67,
|
||||
"cumulative_ms": 1375.919
|
||||
"self_us": 106,
|
||||
"cumulative_us": 112180,
|
||||
"self_ms": 0.106,
|
||||
"cumulative_ms": 112.18
|
||||
},
|
||||
{
|
||||
"module": "praisonaiagents.workflows.yaml_parser",
|
||||
"self_us": 775,
|
||||
"cumulative_us": 1369435,
|
||||
"self_ms": 0.775,
|
||||
"cumulative_ms": 1369.435
|
||||
"self_us": 217,
|
||||
"cumulative_us": 107210,
|
||||
"self_ms": 0.217,
|
||||
"cumulative_ms": 107.21
|
||||
},
|
||||
{
|
||||
"module": "praisonaiagents.agent.agent",
|
||||
"self_us": 19,
|
||||
"cumulative_us": 1349174,
|
||||
"self_ms": 0.019,
|
||||
"cumulative_ms": 1349.174
|
||||
"self_us": 15,
|
||||
"cumulative_us": 98811,
|
||||
"self_ms": 0.015,
|
||||
"cumulative_ms": 98.811
|
||||
},
|
||||
{
|
||||
"module": "praisonaiagents.agent",
|
||||
"self_us": 537,
|
||||
"cumulative_us": 1349155,
|
||||
"self_ms": 0.537,
|
||||
"cumulative_ms": 1349.155
|
||||
"self_us": 146,
|
||||
"cumulative_us": 98796,
|
||||
"self_ms": 0.146,
|
||||
"cumulative_ms": 98.796
|
||||
},
|
||||
{
|
||||
"module": "praisonaiagents.agent.agent",
|
||||
"self_us": 1453,
|
||||
"cumulative_us": 1285299,
|
||||
"self_ms": 1.453,
|
||||
"cumulative_ms": 1285.299
|
||||
},
|
||||
{
|
||||
"module": "praisonaiagents.llm.openai_client",
|
||||
"self_us": 7887,
|
||||
"cumulative_us": 1123578,
|
||||
"self_ms": 7.887,
|
||||
"cumulative_ms": 1123.578
|
||||
},
|
||||
{
|
||||
"module": "openai",
|
||||
"self_us": 1083,
|
||||
"cumulative_us": 1115692,
|
||||
"self_ms": 1.083,
|
||||
"cumulative_ms": 1115.692
|
||||
},
|
||||
{
|
||||
"module": "openai.types",
|
||||
"self_us": 2606,
|
||||
"cumulative_us": 957990,
|
||||
"self_ms": 2.606,
|
||||
"cumulative_ms": 957.99
|
||||
},
|
||||
{
|
||||
"module": "openai.types.batch",
|
||||
"self_us": 1787,
|
||||
"cumulative_us": 485667,
|
||||
"self_ms": 1.787,
|
||||
"cumulative_ms": 485.667
|
||||
},
|
||||
{
|
||||
"module": "openai._models",
|
||||
"self_us": 13423,
|
||||
"cumulative_us": 450798,
|
||||
"self_ms": 13.423,
|
||||
"cumulative_ms": 450.798
|
||||
},
|
||||
{
|
||||
"module": "openai.types.eval_create_params",
|
||||
"self_us": 644,
|
||||
"cumulative_us": 393275,
|
||||
"self_ms": 0.644,
|
||||
"cumulative_ms": 393.275
|
||||
},
|
||||
{
|
||||
"module": "openai.types.graders.grader_inputs_param",
|
||||
"self_us": 17,
|
||||
"cumulative_us": 359515,
|
||||
"self_ms": 0.017,
|
||||
"cumulative_ms": 359.515
|
||||
},
|
||||
{
|
||||
"module": "openai.types.graders",
|
||||
"self_us": 392,
|
||||
"cumulative_us": 359498,
|
||||
"self_ms": 0.392,
|
||||
"cumulative_ms": 359.498
|
||||
},
|
||||
{
|
||||
"module": "openai.types.graders.multi_grader",
|
||||
"self_us": 3847,
|
||||
"cumulative_us": 351251,
|
||||
"self_ms": 3.847,
|
||||
"cumulative_ms": 351.251
|
||||
},
|
||||
{
|
||||
"module": "openai.types.graders.label_model_grader",
|
||||
"self_us": 5450,
|
||||
"cumulative_us": 337291,
|
||||
"self_ms": 5.45,
|
||||
"cumulative_ms": 337.291
|
||||
},
|
||||
{
|
||||
"module": "openai.types.graders.grader_inputs",
|
||||
"self_us": 545,
|
||||
"cumulative_us": 331841,
|
||||
"self_ms": 0.545,
|
||||
"cumulative_ms": 331.841
|
||||
},
|
||||
{
|
||||
"module": "openai.types.responses.response_input_text",
|
||||
"self_us": 21,
|
||||
"cumulative_us": 331297,
|
||||
"self_ms": 0.021,
|
||||
"cumulative_ms": 331.297
|
||||
},
|
||||
{
|
||||
"module": "openai.types.responses",
|
||||
"self_us": 1301,
|
||||
"cumulative_us": 331277,
|
||||
"self_ms": 1.301,
|
||||
"cumulative_ms": 331.277
|
||||
"self_us": 1027,
|
||||
"cumulative_us": 86223,
|
||||
"self_ms": 1.027,
|
||||
"cumulative_ms": 86.223
|
||||
},
|
||||
{
|
||||
"module": "rich.logging",
|
||||
"self_us": 1066,
|
||||
"cumulative_us": 238256,
|
||||
"self_ms": 1.066,
|
||||
"cumulative_ms": 238.256
|
||||
"self_us": 282,
|
||||
"cumulative_us": 53009,
|
||||
"self_ms": 0.282,
|
||||
"cumulative_ms": 53.009
|
||||
},
|
||||
{
|
||||
"module": "praisonaiagents.main",
|
||||
"self_us": 18784,
|
||||
"cumulative_us": 45759,
|
||||
"self_ms": 18.784,
|
||||
"cumulative_ms": 45.759
|
||||
},
|
||||
{
|
||||
"module": "praisonaiagents.llm.openai_client",
|
||||
"self_us": 2470,
|
||||
"cumulative_us": 28251,
|
||||
"self_ms": 2.47,
|
||||
"cumulative_ms": 28.251
|
||||
},
|
||||
{
|
||||
"module": "rich.traceback",
|
||||
"self_us": 1478,
|
||||
"cumulative_us": 18788,
|
||||
"self_ms": 1.478,
|
||||
"cumulative_ms": 18.788
|
||||
},
|
||||
{
|
||||
"module": "rich.console",
|
||||
"self_us": 1737,
|
||||
"cumulative_us": 18587,
|
||||
"self_ms": 1.737,
|
||||
"cumulative_ms": 18.587
|
||||
},
|
||||
{
|
||||
"module": "pygments.lexers",
|
||||
"self_us": 242,
|
||||
"cumulative_us": 15427,
|
||||
"self_ms": 0.242,
|
||||
"cumulative_ms": 15.427
|
||||
},
|
||||
{
|
||||
"module": "rich.markdown",
|
||||
"self_us": 409,
|
||||
"cumulative_us": 13987,
|
||||
"self_ms": 0.409,
|
||||
"cumulative_ms": 13.987
|
||||
},
|
||||
{
|
||||
"module": "pygments.plugin",
|
||||
"self_us": 85,
|
||||
"cumulative_us": 13503,
|
||||
"self_ms": 0.085,
|
||||
"cumulative_ms": 13.503
|
||||
},
|
||||
{
|
||||
"module": "importlib.metadata",
|
||||
"self_us": 637,
|
||||
"cumulative_us": 13419,
|
||||
"self_ms": 0.637,
|
||||
"cumulative_ms": 13.419
|
||||
},
|
||||
{
|
||||
"module": "rich._log_render",
|
||||
"self_us": 145,
|
||||
"cumulative_us": 13380,
|
||||
"self_ms": 0.145,
|
||||
"cumulative_ms": 13.38
|
||||
},
|
||||
{
|
||||
"module": "markdown_it",
|
||||
"self_us": 172,
|
||||
"cumulative_us": 13339,
|
||||
"self_ms": 0.172,
|
||||
"cumulative_ms": 13.339
|
||||
},
|
||||
{
|
||||
"module": "rich.text",
|
||||
"self_us": 582,
|
||||
"cumulative_us": 13236,
|
||||
"self_ms": 0.582,
|
||||
"cumulative_ms": 13.236
|
||||
},
|
||||
{
|
||||
"module": "markdown_it.main",
|
||||
"self_us": 298,
|
||||
"cumulative_us": 13168,
|
||||
"self_ms": 0.298,
|
||||
"cumulative_ms": 13.168
|
||||
},
|
||||
{
|
||||
"module": "pydantic",
|
||||
"self_us": 223,
|
||||
"cumulative_us": 11119,
|
||||
"self_ms": 0.223,
|
||||
"cumulative_ms": 11.119
|
||||
}
|
||||
],
|
||||
"scenarios": [
|
||||
@@ -162,28 +162,22 @@
|
||||
"iterations": 2
|
||||
},
|
||||
"import_time_stats": {
|
||||
"mean": 0.008833496394800022,
|
||||
"min": 0.005916997906751931,
|
||||
"max": 0.011749994882848114,
|
||||
"stdev": 0.0041245517164382375,
|
||||
"median": 0.008833496394800022
|
||||
"mean": 0,
|
||||
"min": 0,
|
||||
"max": 0,
|
||||
"stdev": 0,
|
||||
"median": 0
|
||||
},
|
||||
"total_time_stats": {
|
||||
"mean": 1727.4090415012324,
|
||||
"min": 1367.2264170018025,
|
||||
"max": 2087.5916660006624,
|
||||
"stdev": 509.3751524982296,
|
||||
"median": 1727.4090415012324
|
||||
"mean": 0,
|
||||
"min": 0,
|
||||
"max": 0,
|
||||
"stdev": 0,
|
||||
"median": 0
|
||||
},
|
||||
"first_token_stats": null,
|
||||
"raw_import_times_ms": [
|
||||
0.011749994882848114,
|
||||
0.005916997906751931
|
||||
],
|
||||
"raw_total_times_ms": [
|
||||
1367.2264170018025,
|
||||
2087.5916660006624
|
||||
]
|
||||
"raw_import_times_ms": [],
|
||||
"raw_total_times_ms": []
|
||||
},
|
||||
{
|
||||
"name": "simple_stream",
|
||||
@@ -194,34 +188,22 @@
|
||||
"iterations": 2
|
||||
},
|
||||
"import_time_stats": {
|
||||
"mean": 0.008792001608526334,
|
||||
"min": 0.006375004886649549,
|
||||
"max": 0.01120899833040312,
|
||||
"stdev": 0.0034181495442894613,
|
||||
"median": 0.008792001608526334
|
||||
"mean": 0,
|
||||
"min": 0,
|
||||
"max": 0,
|
||||
"stdev": 0,
|
||||
"median": 0
|
||||
},
|
||||
"total_time_stats": {
|
||||
"mean": 2321.0982290001994,
|
||||
"min": 1697.1089580038097,
|
||||
"max": 2945.087499996589,
|
||||
"stdev": 882.4540898183949,
|
||||
"median": 2321.0982290001994
|
||||
"mean": 0,
|
||||
"min": 0,
|
||||
"max": 0,
|
||||
"stdev": 0,
|
||||
"median": 0
|
||||
},
|
||||
"first_token_stats": {
|
||||
"mean": 2312.8511880022415,
|
||||
"min": 1681.2440420035273,
|
||||
"max": 2944.458334000956,
|
||||
"stdev": 893.2273919631452,
|
||||
"median": 2312.8511880022415
|
||||
},
|
||||
"raw_import_times_ms": [
|
||||
0.01120899833040312,
|
||||
0.006375004886649549
|
||||
],
|
||||
"raw_total_times_ms": [
|
||||
2945.087499996589,
|
||||
1697.1089580038097
|
||||
]
|
||||
"first_token_stats": null,
|
||||
"raw_import_times_ms": [],
|
||||
"raw_total_times_ms": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -3,8 +3,8 @@ class Praisonai < Formula
|
||||
|
||||
desc "AI tools for various AI applications"
|
||||
homepage "https://github.com/MervinPraison/PraisonAI"
|
||||
url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v3.9.2.tar.gz"
|
||||
sha256 `curl -sL https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v3.9.2.tar.gz | shasum -a 256`.split.first
|
||||
url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v3.9.3.tar.gz"
|
||||
sha256 `curl -sL https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v3.9.3.tar.gz | shasum -a 256`.split.first
|
||||
license "MIT"
|
||||
|
||||
depends_on "[email protected]"
|
||||
|
||||
@@ -482,6 +482,11 @@ def docs_run_all(
|
||||
"--quiet", "-q",
|
||||
help="Minimal output",
|
||||
),
|
||||
ci: bool = typer.Option(
|
||||
False,
|
||||
"--ci",
|
||||
help="CI-friendly output (no colors, proper exit codes)",
|
||||
),
|
||||
):
|
||||
"""
|
||||
Run all documentation code blocks group-by-group.
|
||||
@@ -495,7 +500,7 @@ def docs_run_all(
|
||||
praisonai docs run-all --workers 8 --timeout 120
|
||||
"""
|
||||
import json
|
||||
from concurrent.futures import ProcessPoolExecutor, as_completed
|
||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||
from praisonai.suite_runner import DocsSource, SuiteExecutor, RunResult
|
||||
|
||||
docs = docs_path or _get_default_docs_path()
|
||||
@@ -509,9 +514,16 @@ def docs_run_all(
|
||||
source = DocsSource(root=docs)
|
||||
all_groups = sorted(source.get_groups())
|
||||
|
||||
typer.echo(f"Found {len(all_groups)} groups to process")
|
||||
typer.echo(f"Mode: {'parallel' if parallel else 'sequential'}")
|
||||
typer.echo("=" * 60)
|
||||
if ci:
|
||||
print(f"Found {len(all_groups)} groups to process")
|
||||
print(f"Mode: {'parallel' if parallel else 'sequential'}")
|
||||
print(f"Workers: {max_workers}")
|
||||
print(f"Timeout: {timeout}s")
|
||||
print("=" * 60)
|
||||
else:
|
||||
typer.echo(f"Found {len(all_groups)} groups to process")
|
||||
typer.echo(f"Mode: {'parallel' if parallel else 'sequential'}")
|
||||
typer.echo("=" * 60)
|
||||
|
||||
# Track overall results
|
||||
overall_results = {
|
||||
@@ -556,8 +568,8 @@ def docs_run_all(
|
||||
}
|
||||
|
||||
if parallel and len(all_groups) > 1:
|
||||
# Parallel execution
|
||||
with ProcessPoolExecutor(max_workers=min(max_workers, len(all_groups))) as pool:
|
||||
# Parallel execution using ThreadPoolExecutor (ProcessPoolExecutor cannot pickle nested functions)
|
||||
with ThreadPoolExecutor(max_workers=min(max_workers, len(all_groups))) as pool:
|
||||
futures = {pool.submit(run_group, g): g for g in all_groups}
|
||||
|
||||
for future in as_completed(futures):
|
||||
@@ -572,13 +584,23 @@ def docs_run_all(
|
||||
overall_results[key] += summary[key]
|
||||
|
||||
if not quiet:
|
||||
typer.echo(
|
||||
f"✅ {group_name}: "
|
||||
f"✅{summary['passed']} ❌{summary['failed']} "
|
||||
f"⏭️{summary['skipped']} ⏱️{summary['timeout']} 📝{summary['not_run']}"
|
||||
)
|
||||
if ci:
|
||||
print(
|
||||
f"PASS {group_name}: "
|
||||
f"PASS:{summary['passed']} FAIL:{summary['failed']} "
|
||||
f"SKIP:{summary['skipped']} TIMEOUT:{summary['timeout']} NOT_RUN:{summary['not_run']}"
|
||||
)
|
||||
else:
|
||||
typer.echo(
|
||||
f"✅ {group_name}: "
|
||||
f"✅{summary['passed']} ❌{summary['failed']} "
|
||||
f"⏭️{summary['skipped']} ⏱️{summary['timeout']} 📝{summary['not_run']}"
|
||||
)
|
||||
except Exception as e:
|
||||
typer.echo(f"❌ {group_name}: Error - {e}")
|
||||
if ci:
|
||||
print(f"FAIL {group_name}: Error - {e}")
|
||||
else:
|
||||
typer.echo(f"❌ {group_name}: Error - {e}")
|
||||
else:
|
||||
# Sequential execution with real-time output
|
||||
for group_name in all_groups:
|
||||
@@ -642,25 +664,41 @@ def docs_run_all(
|
||||
)
|
||||
|
||||
# Final report
|
||||
typer.echo("\n" + "=" * 80)
|
||||
typer.echo("FINAL REPORT - ALL GROUPS")
|
||||
typer.echo("=" * 80)
|
||||
|
||||
typer.echo(f"\n{'Group':<20} {'Total':>8} {'Passed':>8} {'Failed':>8} {'Skip':>8} {'Timeout':>8} {'NotRun':>8}")
|
||||
typer.echo("-" * 80)
|
||||
|
||||
for gs in sorted(group_summaries, key=lambda x: x['group']):
|
||||
if ci:
|
||||
print("")
|
||||
print("=" * 80)
|
||||
print("FINAL REPORT - ALL GROUPS")
|
||||
print("=" * 80)
|
||||
print(f"{'Group':<20} {'Total':>8} {'Passed':>8} {'Failed':>8} {'Skip':>8} {'Timeout':>8} {'NotRun':>8}")
|
||||
print("-" * 80)
|
||||
for gs in sorted(group_summaries, key=lambda x: x['group']):
|
||||
print(
|
||||
f"{gs['group']:<20} {gs['total']:>8} {gs['passed']:>8} {gs['failed']:>8} "
|
||||
f"{gs['skipped']:>8} {gs['timeout']:>8} {gs['not_run']:>8}"
|
||||
)
|
||||
print("-" * 80)
|
||||
print(
|
||||
f"{'TOTAL':<20} {overall_results['total']:>8} {overall_results['passed']:>8} "
|
||||
f"{overall_results['failed']:>8} {overall_results['skipped']:>8} "
|
||||
f"{overall_results['timeout']:>8} {overall_results['not_run']:>8}"
|
||||
)
|
||||
else:
|
||||
typer.echo("\n" + "=" * 80)
|
||||
typer.echo("FINAL REPORT - ALL GROUPS")
|
||||
typer.echo("=" * 80)
|
||||
typer.echo(f"\n{'Group':<20} {'Total':>8} {'Passed':>8} {'Failed':>8} {'Skip':>8} {'Timeout':>8} {'NotRun':>8}")
|
||||
typer.echo("-" * 80)
|
||||
for gs in sorted(group_summaries, key=lambda x: x['group']):
|
||||
typer.echo(
|
||||
f"{gs['group']:<20} {gs['total']:>8} {gs['passed']:>8} {gs['failed']:>8} "
|
||||
f"{gs['skipped']:>8} {gs['timeout']:>8} {gs['not_run']:>8}"
|
||||
)
|
||||
typer.echo("-" * 80)
|
||||
typer.echo(
|
||||
f"{gs['group']:<20} {gs['total']:>8} {gs['passed']:>8} {gs['failed']:>8} "
|
||||
f"{gs['skipped']:>8} {gs['timeout']:>8} {gs['not_run']:>8}"
|
||||
f"{'TOTAL':<20} {overall_results['total']:>8} {overall_results['passed']:>8} "
|
||||
f"{overall_results['failed']:>8} {overall_results['skipped']:>8} "
|
||||
f"{overall_results['timeout']:>8} {overall_results['not_run']:>8}"
|
||||
)
|
||||
|
||||
typer.echo("-" * 80)
|
||||
typer.echo(
|
||||
f"{'TOTAL':<20} {overall_results['total']:>8} {overall_results['passed']:>8} "
|
||||
f"{overall_results['failed']:>8} {overall_results['skipped']:>8} "
|
||||
f"{overall_results['timeout']:>8} {overall_results['not_run']:>8}"
|
||||
)
|
||||
|
||||
# Save final summary
|
||||
output_dir.mkdir(parents=True, exist_ok=True)
|
||||
@@ -672,8 +710,12 @@ def docs_run_all(
|
||||
'groups': group_summaries,
|
||||
}, f, indent=2)
|
||||
|
||||
typer.echo(f"\n📁 Final summary saved to: {summary_path}")
|
||||
typer.echo(f"📁 Individual group reports in: {output_dir}")
|
||||
if ci:
|
||||
print(f"Final summary: {summary_path}")
|
||||
print(f"Group reports: {output_dir}")
|
||||
else:
|
||||
typer.echo(f"\n📁 Final summary saved to: {summary_path}")
|
||||
typer.echo(f"📁 Individual group reports in: {output_dir}")
|
||||
|
||||
# Exit code
|
||||
if overall_results['failed'] > 0 or overall_results['timeout'] > 0:
|
||||
|
||||
@@ -492,6 +492,11 @@ def examples_run_all(
|
||||
"--quiet", "-q",
|
||||
help="Minimal output",
|
||||
),
|
||||
ci: bool = typer.Option(
|
||||
False,
|
||||
"--ci",
|
||||
help="CI-friendly output (no colors, proper exit codes)",
|
||||
),
|
||||
):
|
||||
"""
|
||||
Run all examples group-by-group.
|
||||
@@ -505,7 +510,7 @@ def examples_run_all(
|
||||
praisonai examples run-all --workers 8 --timeout 120
|
||||
"""
|
||||
import json
|
||||
from concurrent.futures import ProcessPoolExecutor, as_completed
|
||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||
from praisonai.suite_runner import ExamplesSource, SuiteExecutor, RunResult
|
||||
|
||||
examples_path = path or _get_default_examples_path()
|
||||
@@ -519,9 +524,16 @@ def examples_run_all(
|
||||
source = ExamplesSource(root=examples_path)
|
||||
all_groups = sorted(source.get_groups())
|
||||
|
||||
typer.echo(f"Found {len(all_groups)} groups to process")
|
||||
typer.echo(f"Mode: {'parallel' if parallel else 'sequential'}")
|
||||
typer.echo("=" * 60)
|
||||
if ci:
|
||||
print(f"Found {len(all_groups)} groups to process")
|
||||
print(f"Mode: {'parallel' if parallel else 'sequential'}")
|
||||
print(f"Workers: {max_workers}")
|
||||
print(f"Timeout: {timeout}s")
|
||||
print("=" * 60)
|
||||
else:
|
||||
typer.echo(f"Found {len(all_groups)} groups to process")
|
||||
typer.echo(f"Mode: {'parallel' if parallel else 'sequential'}")
|
||||
typer.echo("=" * 60)
|
||||
|
||||
# Track overall results
|
||||
overall_results = {
|
||||
@@ -566,8 +578,8 @@ def examples_run_all(
|
||||
}
|
||||
|
||||
if parallel and len(all_groups) > 1:
|
||||
# Parallel execution
|
||||
with ProcessPoolExecutor(max_workers=min(max_workers, len(all_groups))) as pool:
|
||||
# Parallel execution using ThreadPoolExecutor (ProcessPoolExecutor cannot pickle nested functions)
|
||||
with ThreadPoolExecutor(max_workers=min(max_workers, len(all_groups))) as pool:
|
||||
futures = {pool.submit(run_group, g): g for g in all_groups}
|
||||
|
||||
for future in as_completed(futures):
|
||||
@@ -582,13 +594,23 @@ def examples_run_all(
|
||||
overall_results[key] += summary[key]
|
||||
|
||||
if not quiet:
|
||||
typer.echo(
|
||||
f"✅ {group_name}: "
|
||||
f"✅{summary['passed']} ❌{summary['failed']} "
|
||||
f"⏭️{summary['skipped']} ⏱️{summary['timeout']} ⚠️{summary.get('xfail', 0)}"
|
||||
)
|
||||
if ci:
|
||||
print(
|
||||
f"PASS {group_name}: "
|
||||
f"PASS:{summary['passed']} FAIL:{summary['failed']} "
|
||||
f"SKIP:{summary['skipped']} TIMEOUT:{summary['timeout']} XFAIL:{summary.get('xfail', 0)}"
|
||||
)
|
||||
else:
|
||||
typer.echo(
|
||||
f"✅ {group_name}: "
|
||||
f"✅{summary['passed']} ❌{summary['failed']} "
|
||||
f"⏭️{summary['skipped']} ⏱️{summary['timeout']} ⚠️{summary.get('xfail', 0)}"
|
||||
)
|
||||
except Exception as e:
|
||||
typer.echo(f"❌ {group_name}: Error - {e}")
|
||||
if ci:
|
||||
print(f"FAIL {group_name}: Error - {e}")
|
||||
else:
|
||||
typer.echo(f"❌ {group_name}: Error - {e}")
|
||||
else:
|
||||
# Sequential execution with real-time output
|
||||
for group_name in all_groups:
|
||||
@@ -652,25 +674,41 @@ def examples_run_all(
|
||||
)
|
||||
|
||||
# Final report
|
||||
typer.echo("\n" + "=" * 80)
|
||||
typer.echo("FINAL REPORT - ALL GROUPS")
|
||||
typer.echo("=" * 80)
|
||||
|
||||
typer.echo(f"\n{'Group':<20} {'Total':>8} {'Passed':>8} {'Failed':>8} {'Skip':>8} {'Timeout':>8} {'XFail':>8}")
|
||||
typer.echo("-" * 80)
|
||||
|
||||
for gs in sorted(group_summaries, key=lambda x: x['group']):
|
||||
if ci:
|
||||
print("")
|
||||
print("=" * 80)
|
||||
print("FINAL REPORT - ALL GROUPS")
|
||||
print("=" * 80)
|
||||
print(f"{'Group':<20} {'Total':>8} {'Passed':>8} {'Failed':>8} {'Skip':>8} {'Timeout':>8} {'XFail':>8}")
|
||||
print("-" * 80)
|
||||
for gs in sorted(group_summaries, key=lambda x: x['group']):
|
||||
print(
|
||||
f"{gs['group']:<20} {gs['total']:>8} {gs['passed']:>8} {gs['failed']:>8} "
|
||||
f"{gs['skipped']:>8} {gs['timeout']:>8} {gs.get('xfail', 0):>8}"
|
||||
)
|
||||
print("-" * 80)
|
||||
print(
|
||||
f"{'TOTAL':<20} {overall_results['total']:>8} {overall_results['passed']:>8} "
|
||||
f"{overall_results['failed']:>8} {overall_results['skipped']:>8} "
|
||||
f"{overall_results['timeout']:>8} {overall_results.get('xfail', 0):>8}"
|
||||
)
|
||||
else:
|
||||
typer.echo("\n" + "=" * 80)
|
||||
typer.echo("FINAL REPORT - ALL GROUPS")
|
||||
typer.echo("=" * 80)
|
||||
typer.echo(f"\n{'Group':<20} {'Total':>8} {'Passed':>8} {'Failed':>8} {'Skip':>8} {'Timeout':>8} {'XFail':>8}")
|
||||
typer.echo("-" * 80)
|
||||
for gs in sorted(group_summaries, key=lambda x: x['group']):
|
||||
typer.echo(
|
||||
f"{gs['group']:<20} {gs['total']:>8} {gs['passed']:>8} {gs['failed']:>8} "
|
||||
f"{gs['skipped']:>8} {gs['timeout']:>8} {gs.get('xfail', 0):>8}"
|
||||
)
|
||||
typer.echo("-" * 80)
|
||||
typer.echo(
|
||||
f"{gs['group']:<20} {gs['total']:>8} {gs['passed']:>8} {gs['failed']:>8} "
|
||||
f"{gs['skipped']:>8} {gs['timeout']:>8} {gs.get('xfail', 0):>8}"
|
||||
f"{'TOTAL':<20} {overall_results['total']:>8} {overall_results['passed']:>8} "
|
||||
f"{overall_results['failed']:>8} {overall_results['skipped']:>8} "
|
||||
f"{overall_results['timeout']:>8} {overall_results.get('xfail', 0):>8}"
|
||||
)
|
||||
|
||||
typer.echo("-" * 80)
|
||||
typer.echo(
|
||||
f"{'TOTAL':<20} {overall_results['total']:>8} {overall_results['passed']:>8} "
|
||||
f"{overall_results['failed']:>8} {overall_results['skipped']:>8} "
|
||||
f"{overall_results['timeout']:>8} {overall_results.get('xfail', 0):>8}"
|
||||
)
|
||||
|
||||
# Save final summary
|
||||
output_dir.mkdir(parents=True, exist_ok=True)
|
||||
@@ -682,8 +720,12 @@ def examples_run_all(
|
||||
'groups': group_summaries,
|
||||
}, f, indent=2)
|
||||
|
||||
typer.echo(f"\n📁 Final summary saved to: {summary_path}")
|
||||
typer.echo(f"📁 Individual group reports in: {output_dir}")
|
||||
if ci:
|
||||
print(f"Final summary: {summary_path}")
|
||||
print(f"Group reports: {output_dir}")
|
||||
else:
|
||||
typer.echo(f"\n📁 Final summary saved to: {summary_path}")
|
||||
typer.echo(f"📁 Individual group reports in: {output_dir}")
|
||||
|
||||
# Exit code
|
||||
if overall_results['failed'] > 0 or overall_results['timeout'] > 0:
|
||||
|
||||
@@ -57,7 +57,7 @@ class CloudDeployer:
|
||||
file.write("FROM python:3.11-slim\n")
|
||||
file.write("WORKDIR /app\n")
|
||||
file.write("COPY . .\n")
|
||||
file.write("RUN pip install flask praisonai==3.9.2 gunicorn markdown\n")
|
||||
file.write("RUN pip install flask praisonai==3.9.3 gunicorn markdown\n")
|
||||
file.write("EXPOSE 8080\n")
|
||||
file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n')
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
__version__ = "3.9.2"
|
||||
__version__ = "3.9.3"
|
||||
Reference in new issue
Block a user