waldiez 0.1.11__py3-none-any.whl → 0.1.13__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of waldiez might be problematic. Click here for more details.

waldiez/__main__.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """Waldiez entrypoint when called as a module."""
2
2
 
3
- from .cli import main
3
+ from .cli import app
4
4
 
5
5
  if __name__ == "__main__":
6
- main()
6
+ app()
waldiez/_version.py CHANGED
@@ -1,3 +1,3 @@
1
1
  """Version information for Waldiez."""
2
2
 
3
- __version__ = "0.1.11"
3
+ __version__ = "0.1.13"
waldiez/cli.py CHANGED
@@ -1,12 +1,15 @@
1
1
  """Command line interface to convert or run a waldiez file."""
2
2
 
3
- import argparse
3
+ # pylint: disable=missing-function-docstring,missing-param-doc,missing-raises-doc
4
4
  import json
5
5
  import logging
6
6
  import os
7
7
  import sys
8
8
  from pathlib import Path
9
- from typing import TYPE_CHECKING, Any, Dict, Optional
9
+ from typing import TYPE_CHECKING, Optional
10
+
11
+ import typer
12
+ from typing_extensions import Annotated
10
13
 
11
14
  from . import Waldiez, __version__
12
15
  from .exporter import WaldiezExporter
@@ -16,121 +19,169 @@ if TYPE_CHECKING:
16
19
  from autogen import ChatResult # type: ignore[import-untyped]
17
20
 
18
21
 
19
- def get_parser() -> argparse.ArgumentParser:
20
- """Get the argument parser for the Waldiez package.
21
-
22
- Returns
23
- -------
24
- argparse.ArgumentParser
25
- The argument parser.
26
- """
27
- parser = argparse.ArgumentParser(
28
- description="Run or export a Waldiez flow.",
29
- prog="waldiez",
30
- )
31
- parser.add_argument(
32
- "file",
33
- type=str,
34
- help="Path to the Waldiez flow (*.waldiez) file.",
35
- )
36
- parser.add_argument(
37
- "-e",
38
- "--export",
39
- action="store_true",
40
- help=(
41
- "Export the Waldiez flow to a Python script or a jupyter notebook."
22
+ app = typer.Typer(
23
+ name="waldiez",
24
+ help="Handle Waldiez flows.",
25
+ context_settings={
26
+ "help_option_names": ["-h", "--help"],
27
+ "allow_extra_args": True,
28
+ },
29
+ add_completion=False,
30
+ no_args_is_help=True,
31
+ invoke_without_command=True,
32
+ add_help_option=True,
33
+ pretty_exceptions_enable=False,
34
+ epilog=("Use `waldiez [COMMAND] --help` for command-specific help. "),
35
+ )
36
+
37
+
38
+ @app.callback()
39
+ def show_version(
40
+ version: bool = typer.Option(
41
+ False,
42
+ "--version",
43
+ "-v",
44
+ help="Show the version of the Waldiez package.",
45
+ ),
46
+ ) -> None:
47
+ """Show the version of the Waldiez package and exit."""
48
+ if version:
49
+ typer.echo(f"waldiez version: {__version__}")
50
+ raise typer.Exit()
51
+
52
+
53
+ @app.command()
54
+ def run(
55
+ file: Annotated[
56
+ Path,
57
+ typer.Option(
58
+ ...,
59
+ help="Path to the Waldiez flow (*.waldiez) file.",
60
+ exists=True,
61
+ file_okay=True,
62
+ dir_okay=False,
63
+ readable=True,
64
+ resolve_path=True,
42
65
  ),
43
- )
44
- parser.add_argument(
45
- "-o",
46
- "--output",
47
- type=str,
66
+ ],
67
+ output: Optional[Path] = typer.Option(
68
+ None,
48
69
  help=(
49
- "Path to the output file. "
50
- "If exporting, the file extension determines the output format. "
51
- "If running, the output's directory will contain "
70
+ "Path to the output (.py) file. "
71
+ "The output's directory will contain "
52
72
  "the generated flow (.py) and any additional generated files."
53
73
  ),
54
- )
55
- parser.add_argument(
56
- "-f",
57
- "--force",
58
- action="store_true",
59
- help=("Override the output file if it already exists. "),
60
- )
61
- parser.add_argument(
62
- "-v",
63
- "--version",
64
- action="version",
65
- version=f"waldiez version: {__version__}",
66
- )
67
- return parser
68
-
69
-
70
- def _log_result(result: "ChatResult") -> None:
71
- """Log the result of the Waldiez flow."""
72
- logger = logging.getLogger("waldiez::cli")
73
- logger.info("Chat History:\n")
74
- logger.info(result.chat_history)
75
- logger.info("Summary:\n")
76
- logger.info(result.summary)
77
- logger.info("Cost:\n")
78
- logger.info(result.cost)
79
-
80
-
81
- def _run(data: Dict[str, Any], output_path: Optional[str]) -> None:
82
- """Run the Waldiez flow."""
74
+ dir_okay=False,
75
+ resolve_path=True,
76
+ ),
77
+ force: bool = typer.Option(
78
+ False,
79
+ help="Override the output file if it already exists.",
80
+ ),
81
+ ) -> None:
82
+ """Run a Waldiez flow."""
83
+ output_path = _get_output_path(output, force)
84
+ with file.open("r", encoding="utf-8") as _file:
85
+ try:
86
+ data = json.load(_file)
87
+ except json.decoder.JSONDecodeError as error:
88
+ typer.echo("Invalid .waldiez file. Not a valid json?")
89
+ raise typer.Exit(code=1) from error
83
90
  waldiez = Waldiez.from_dict(data)
84
91
  runner = WaldiezRunner(waldiez)
85
92
  results = runner.run(stream=None, output_path=output_path)
93
+ logger = _get_logger()
86
94
  if isinstance(results, list):
95
+ logger.info("Results:")
87
96
  for result in results:
88
- _log_result(result)
97
+ _log_result(result, logger)
89
98
  sep = "-" * 80
90
99
  print(f"\n{sep}\n")
91
100
  else:
92
- _log_result(results)
93
-
94
-
95
- def main() -> None:
96
- """Parse the command line arguments and run the Waldiez flow."""
97
- parser = get_parser()
98
- if len(sys.argv) == 1:
99
- parser.print_help()
100
- sys.exit(0)
101
- args = parser.parse_args()
102
- logger = _get_logger()
103
- waldiez_file: str = args.file
104
- if not os.path.exists(waldiez_file):
105
- logger.error("File not found: %s", waldiez_file)
106
- sys.exit(1)
107
- if not waldiez_file.endswith((".json", ".waldiez")):
108
- logger.error("Only .json or .waldiez files are supported.")
109
- sys.exit(1)
110
- with open(waldiez_file, "r", encoding="utf-8") as file:
101
+ _log_result(results, logger)
102
+
103
+
104
+ @app.command()
105
+ def convert(
106
+ file: Annotated[
107
+ Path,
108
+ typer.Option(
109
+ ...,
110
+ help="Path to the Waldiez flow (*.waldiez) file.",
111
+ exists=True,
112
+ file_okay=True,
113
+ dir_okay=False,
114
+ readable=True,
115
+ resolve_path=True,
116
+ ),
117
+ ],
118
+ output: Annotated[
119
+ Path,
120
+ typer.Option(
121
+ ...,
122
+ help=(
123
+ "Path to the output file. "
124
+ "The file extension determines the output format: "
125
+ "`.py` for Python script, `.ipynb` for Jupyter notebook."
126
+ ),
127
+ file_okay=True,
128
+ dir_okay=False,
129
+ resolve_path=True,
130
+ ),
131
+ ],
132
+ force: bool = typer.Option(
133
+ False,
134
+ help="Override the output file if it already exists.",
135
+ ),
136
+ ) -> None:
137
+ """Convert a Waldiez flow to a Python script or a Jupyter notebook."""
138
+ _get_output_path(output, force)
139
+ with file.open("r", encoding="utf-8") as _file:
111
140
  try:
112
- data = json.load(file)
113
- except json.decoder.JSONDecodeError:
114
- logger.error("Invalid .waldiez file: %s. Not a valid json?", file)
115
- return
116
- if args.export is True:
117
- if args.output is None:
118
- logger.error("Please provide an output file.")
119
- sys.exit(1)
120
- if not args.output.endswith((".py", ".ipynb", ".json", ".waldiez")):
121
- logger.error(
122
- "Only Python scripts, Jupyter notebooks "
123
- "and JSON/Waldiez files are supported."
124
- )
125
- sys.exit(1)
126
- output_file = Path(args.output).resolve()
127
- waldiez = Waldiez.from_dict(data)
128
- exporter = WaldiezExporter(waldiez)
129
- exporter.export(output_file, force=args.force)
130
- generated = str(output_file).replace(os.getcwd(), ".")
131
- logger.info("Generated: %s", generated)
132
- else:
133
- _run(data, args.output)
141
+ data = json.load(_file)
142
+ except json.decoder.JSONDecodeError as error:
143
+ typer.echo("Invalid .waldiez file. Not a valid json?")
144
+ raise typer.Exit(code=1) from error
145
+ waldiez = Waldiez.from_dict(data)
146
+ exporter = WaldiezExporter(waldiez)
147
+ exporter.export(output, force=force)
148
+ generated = str(output).replace(os.getcwd(), ".")
149
+ typer.echo(f"Generated: {generated}")
150
+
151
+
152
+ @app.command()
153
+ def check(
154
+ file: Annotated[
155
+ Path,
156
+ typer.Option(
157
+ ...,
158
+ help="Path to the Waldiez flow (*.waldiez) file.",
159
+ exists=True,
160
+ file_okay=True,
161
+ dir_okay=False,
162
+ readable=True,
163
+ resolve_path=True,
164
+ ),
165
+ ],
166
+ ) -> None:
167
+ """Validate a Waldiez flow."""
168
+ with file.open("r", encoding="utf-8") as _file:
169
+ data = json.load(_file)
170
+ Waldiez.from_dict(data)
171
+ typer.echo("Waldiez flow is valid.")
172
+
173
+
174
+ def _get_output_path(output: Optional[Path], force: bool) -> Optional[Path]:
175
+ if output is not None:
176
+ output = Path(output).resolve()
177
+ if output is not None and not output.parent.exists():
178
+ output.parent.mkdir(parents=True)
179
+ if output is not None and output.exists():
180
+ if force is False:
181
+ typer.echo("Output file already exists.")
182
+ raise typer.Exit(code=1)
183
+ output.unlink()
184
+ return output
134
185
 
135
186
 
136
187
  def _get_logger(level: int = logging.INFO) -> logging.Logger:
@@ -162,5 +213,16 @@ def _get_logger(level: int = logging.INFO) -> logging.Logger:
162
213
  return logger
163
214
 
164
215
 
216
+ def _log_result(result: "ChatResult", logger: logging.Logger) -> None:
217
+ """Log the result of the Waldiez flow."""
218
+ logger.info("Chat History:\n")
219
+ logger.info(result.chat_history)
220
+ logger.info("Summary:\n")
221
+ logger.info(result.summary)
222
+ logger.info("Cost:\n")
223
+ logger.info(result.cost)
224
+
225
+
165
226
  if __name__ == "__main__":
166
- main()
227
+ _get_logger()
228
+ app()
waldiez/runner.py CHANGED
@@ -169,8 +169,12 @@ class WaldiezRunner:
169
169
  print_function(
170
170
  f"Installing requirements: {', '.join(extra_requirements)}"
171
171
  )
172
+ pip_install = [sys.executable, "-m", "pip", "install"]
173
+ if not in_virtualenv():
174
+ pip_install.append("--user")
175
+ pip_install.extend(extra_requirements)
172
176
  with subprocess.Popen(
173
- [sys.executable, "-m", "pip", "install", *extra_requirements],
177
+ pip_install,
174
178
  stdout=subprocess.PIPE,
175
179
  stderr=subprocess.PIPE,
176
180
  ) as proc:
@@ -341,3 +345,16 @@ class WaldiezRunner:
341
345
  self._running = False
342
346
  self._stream.reset(token)
343
347
  del token
348
+
349
+
350
+ def in_virtualenv() -> bool:
351
+ """Check if we are inside a virtualenv.
352
+
353
+ Returns
354
+ -------
355
+ bool
356
+ True if inside a virtualenv, False otherwise.
357
+ """
358
+ return hasattr(sys, "real_prefix") or (
359
+ hasattr(sys, "base_prefix") and sys.base_prefix != sys.prefix
360
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: waldiez
3
- Version: 0.1.11
3
+ Version: 0.1.13
4
4
  Summary: waldiez
5
5
  Project-URL: homepage, https://waldiez.github.io/waldiez/
6
6
  Project-URL: repository, https://github.com/waldiez/waldiez.git
@@ -18,6 +18,7 @@ Classifier: Programming Language :: Python :: 3.12
18
18
  Requires-Python: <3.13,>=3.10
19
19
  Requires-Dist: ag2==0.4.1
20
20
  Requires-Dist: jupytext
21
+ Requires-Dist: typer<0.13,>=0.9
21
22
  Provides-Extra: ag2-extras
22
23
  Requires-Dist: ag2[anthropic]==0.4.1; extra == 'ag2-extras'
23
24
  Requires-Dist: ag2[bedrock]==0.4.1; extra == 'ag2-extras'
@@ -46,7 +47,7 @@ Requires-Dist: isort==5.13.2; extra == 'dev'
46
47
  Requires-Dist: mypy==1.13.0; extra == 'dev'
47
48
  Requires-Dist: pre-commit==4.0.1; extra == 'dev'
48
49
  Requires-Dist: pydocstyle==6.3.0; extra == 'dev'
49
- Requires-Dist: pylint==3.3.1; extra == 'dev'
50
+ Requires-Dist: pylint==3.3.2; extra == 'dev'
50
51
  Requires-Dist: python-dotenv==1.0.1; extra == 'dev'
51
52
  Requires-Dist: ruff==0.8.1; extra == 'dev'
52
53
  Requires-Dist: types-pyyaml==6.0.12.20240917; extra == 'dev'
@@ -56,7 +57,7 @@ Requires-Dist: mdx-include==1.4.2; extra == 'docs'
56
57
  Requires-Dist: mdx-truly-sane-lists==1.3; extra == 'docs'
57
58
  Requires-Dist: mkdocs-jupyter==0.25.1; extra == 'docs'
58
59
  Requires-Dist: mkdocs-macros-plugin==1.3.7; extra == 'docs'
59
- Requires-Dist: mkdocs-material==9.5.46; extra == 'docs'
60
+ Requires-Dist: mkdocs-material==9.5.47; extra == 'docs'
60
61
  Requires-Dist: mkdocs-minify-html-plugin==0.2.3; extra == 'docs'
61
62
  Requires-Dist: mkdocs==1.6.1; extra == 'docs'
62
63
  Requires-Dist: mkdocstrings-python==1.12.2; extra == 'docs'
@@ -67,7 +68,7 @@ Requires-Dist: pytest-html==4.1.1; extra == 'test'
67
68
  Requires-Dist: pytest-sugar==1.0.0; extra == 'test'
68
69
  Requires-Dist: pytest-timeout==2.3.1; extra == 'test'
69
70
  Requires-Dist: pytest-xdist==3.6.1; extra == 'test'
70
- Requires-Dist: pytest==8.3.3; extra == 'test'
71
+ Requires-Dist: pytest==8.3.4; extra == 'test'
71
72
  Description-Content-Type: text/markdown
72
73
 
73
74
  # Waldiez
@@ -82,9 +83,8 @@ To a python script or a jupyter notebook with the corresponding [ag2](https://gi
82
83
 
83
84
  ## Features
84
85
 
85
- - Export .waldiez flows to .py or .ipynb
86
+ - Convert .waldiez flows to .py or .ipynb
86
87
  - Run a .waldiez flow
87
- - Include a `logs` folder with the logs of the flow in csv format
88
88
  - Provide a custom [IOSStream](https://ag2ai.github.io/ag2/docs/reference/io/base#iostream) to handle input and output.
89
89
 
90
90
  ## Installation
@@ -106,10 +106,10 @@ python -m pip install git+https://github.com/waldiez/waldiez.git
106
106
  ### CLI
107
107
 
108
108
  ```bash
109
- # Export a Waldiez flow to a python script or a jupyter notebook
110
- waldiez --export /path/to/a/flow.waldiez --output /path/to/an/output/flow[.py|.ipynb]
111
- # Export and run the script, optionally force generation if the output file already exists
112
- waldiez /path/to/a/flow.waldiez --output /path/to/an/output/flow[.py] [--force]
109
+ # Convert a Waldiez flow to a python script or a jupyter notebook
110
+ waldiez convert --file /path/to/a/flow.waldiez --output /path/to/an/output/flow[.py|.ipynb]
111
+ # Convert and run the script, optionally force generation if the output file already exists
112
+ waldiez run --file /path/to/a/flow.waldiez --output /path/to/an/output/flow[.py] [--force]
113
113
  ```
114
114
 
115
115
  ### Using docker/podman
@@ -118,7 +118,7 @@ waldiez /path/to/a/flow.waldiez --output /path/to/an/output/flow[.py] [--force]
118
118
  CONTAINER_COMMAND=docker # or podman
119
119
  # pull the image
120
120
  $CONTAINER_COMMAND pull waldiez/waldiez
121
- # Export a Waldiez flow to a python script or a jupyter notebook
121
+ # Convert a Waldiez flow to a python script or a jupyter notebook
122
122
  $CONTAINER_COMMAND run \
123
123
  --rm \
124
124
  -v /path/to/a/flow.waldiez:/flow.waldiez \
@@ -132,12 +132,16 @@ $CONTAINER_COMMAND run \
132
132
  -v /path/to/an/output:/output \
133
133
  --userns=keep-id \
134
134
  --security-opt label=disable \
135
- waldiez/waldiez --export /flow.waldiez --output /output/flow[.py|.ipynb]
135
+ waldiez/waldiez convert --file /flow.waldiez --output /output/flow[.py|.ipynb]
136
136
  ```
137
137
 
138
138
  ```shell
139
- # Export and run the script
140
- $CONTAINER_COMMAND run --rm -v /path/to/a/flow.waldiez:/flow.waldiez -v /path/to/an/output:/output waldiez/waldiez /flow.waldiez --output /output/output[.py]
139
+ # Convert and run the script
140
+ $CONTAINER_COMMAND run \
141
+ --rm \
142
+ -v /path/to/a/flow.waldiez:/flow.waldiez \
143
+ -v /path/to/an/output:/output \
144
+ waldiez/waldiez run --file /flow.waldiez --output /output/output[.py]
141
145
  ```
142
146
 
143
147
  ### As a library
@@ -236,6 +240,7 @@ with WaldiezIOStream.set_default(io_stream):
236
240
  - [ag2 (formerly AutoGen)](https://github.com/ag2ai/ag2)
237
241
  - [juptytext](https://github.com/mwouts/jupytext)
238
242
  - [pydantic](https://github.com/pydantic/pydantic)
243
+ - [typer](https://github.com/fastapi/typer)
239
244
 
240
245
  ## Known Conflicts
241
246
 
@@ -1,11 +1,11 @@
1
1
  waldiez/__init__.py,sha256=ASGmxP3JcASIv89_tMYhYxvW0FlHK1jM0Nfb1hMN-z0,722
2
- waldiez/__main__.py,sha256=9xR-F2ohZcRPDG6KrM7cJpXciKX-u6WdL221ckyJ04k,112
3
- waldiez/_version.py,sha256=sJthgAdM_fnhfUw7CJUqaPJliLLYbXnDEyzn7i1rA9U,63
4
- waldiez/cli.py,sha256=wStRkt056Y-F2CcuD6Zlov-ooUpWndyNesV9s_MjyHU,4798
2
+ waldiez/__main__.py,sha256=mUQWu4CF03Jbbscvcfb_9EFTnIMliJJJmAuWf0sRRZU,110
3
+ waldiez/_version.py,sha256=N8g2SvYhwFeB_7w5OlUWgVZ5b8OUXI3arJvloUBkg9U,63
4
+ waldiez/cli.py,sha256=6BefTHXqib-L_FTdYOAaUkv4DLYYpjBePdlCn2BEYi0,6307
5
5
  waldiez/conflict_checker.py,sha256=T5FA7hsxpuW0Byb4YyZQ3-uVxzNnoTQV199YRBKjvmE,707
6
6
  waldiez/exporter.py,sha256=iKe-l_Me8NRWsXHIdBcrOrnLT9XIyp4iYi4HLuuj2jA,9342
7
7
  waldiez/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- waldiez/runner.py,sha256=hBHgtfxcV7LlGMAwGEf7xbNp3_qEvFsnbTTnKfe-Y1g,11097
8
+ waldiez/runner.py,sha256=v4A4NHdSnh96TQ5Vx1vs8UrTsshc2oAwDZrEHmq4RkU,11537
9
9
  waldiez/exporting/__init__.py,sha256=GMY7qTRpNmc7tpaCFNGLT5wX9eu26NvoNPuYX8MzP50,344
10
10
  waldiez/exporting/agents/__init__.py,sha256=v5KA112W_EFYwXE2TSBKYyO8rRKUOUAOpFS5CMSnfRs,110
11
11
  waldiez/exporting/agents/agent.py,sha256=d2ut2B90-aG4uBRhPWS7B4MKIvSJqQva6DjlXiqleVQ,7513
@@ -85,8 +85,8 @@ waldiez/models/model/model_data.py,sha256=pDPKUbltaXWjCuDArgwTOEHw_igfk_DkxzFzdn
85
85
  waldiez/models/skill/__init__.py,sha256=rU88bajKOGMYoHFcE8MP0jW9H0MswbQmvz5wxS35BYE,169
86
86
  waldiez/models/skill/skill.py,sha256=fhsAI413an2_d4DBIkf7dzEuWk6rGs2t4sl97a4dj20,3473
87
87
  waldiez/models/skill/skill_data.py,sha256=RTWn8Od6w7g-nRIpsS29sqZ8sPm5dCPiK7-qXmU-KD4,815
88
- waldiez-0.1.11.dist-info/METADATA,sha256=hzcUFwIJ4SXtYWeEbhfTNy8A7fkVupJFm5GJhfCbuOg,9288
89
- waldiez-0.1.11.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
90
- waldiez-0.1.11.dist-info/entry_points.txt,sha256=5Po4yQXPa_QEdtTevpEBgr3rGoIvDMeQuJR2zqwBLBo,45
91
- waldiez-0.1.11.dist-info/licenses/LICENSE,sha256=VQEHM6WMQLRu1qaGl3GWsoOknDwro-69eGo4NLIJPIM,1064
92
- waldiez-0.1.11.dist-info/RECORD,,
88
+ waldiez-0.1.13.dist-info/METADATA,sha256=opCfL797TnrS7AqpTvdz_YreuVRhKte5sA03NIzCrOg,9353
89
+ waldiez-0.1.13.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
90
+ waldiez-0.1.13.dist-info/entry_points.txt,sha256=9MQ8Y1rD19CU7UwjNPwoyTRpQsPs2QimjrtwTD0bD6k,44
91
+ waldiez-0.1.13.dist-info/licenses/LICENSE,sha256=VQEHM6WMQLRu1qaGl3GWsoOknDwro-69eGo4NLIJPIM,1064
92
+ waldiez-0.1.13.dist-info/RECORD,,
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ waldiez = waldiez.cli:app
@@ -1,2 +0,0 @@
1
- [console_scripts]
2
- waldiez = waldiez.cli:main