waldiez 0.4.4__py3-none-any.whl → 0.4.6__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/__init__.py +18 -10
- waldiez/_version.py +5 -2
- waldiez/cli.py +19 -4
- waldiez/exporter.py +8 -4
- waldiez/exporting/agent/utils/captain_agent.py +4 -1
- waldiez/exporting/agent/utils/group_manager.py +0 -1
- waldiez/exporting/agent/utils/rag_user/rag_user.py +1 -0
- waldiez/exporting/agent/utils/swarm_agent.py +1 -0
- waldiez/exporting/base/base_exporter.py +2 -2
- waldiez/exporting/base/mixin.py +3 -0
- waldiez/exporting/base/utils/comments.py +2 -0
- waldiez/exporting/chats/utils/sequential.py +1 -1
- waldiez/exporting/chats/utils/single_chat.py +3 -0
- waldiez/exporting/chats/utils/swarm.py +3 -0
- waldiez/exporting/flow/flow_exporter.py +2 -0
- waldiez/exporting/flow/utils/def_main.py +1 -0
- waldiez/exporting/flow/utils/flow_content.py +3 -0
- waldiez/exporting/flow/utils/flow_names.py +1 -0
- waldiez/exporting/flow/utils/importing_utils.py +1 -0
- waldiez/exporting/flow/utils/logging_utils.py +8 -8
- waldiez/exporting/skills/skills_exporter.py +1 -1
- waldiez/exporting/skills/utils.py +5 -3
- waldiez/models/__init__.py +1 -0
- waldiez/models/agents/agent/agent.py +1 -1
- waldiez/models/agents/agent/termination_message.py +1 -0
- waldiez/models/agents/group_manager/speakers.py +1 -1
- waldiez/models/agents/rag_user/retrieve_config.py +1 -0
- waldiez/models/agents/swarm_agent/after_work.py +0 -1
- waldiez/models/agents/swarm_agent/on_condition.py +1 -0
- waldiez/models/agents/swarm_agent/on_condition_available.py +1 -0
- waldiez/models/chat/chat.py +2 -0
- waldiez/models/chat/chat_message.py +1 -0
- waldiez/models/common/ag2_version.py +2 -2
- waldiez/models/common/method_utils.py +11 -2
- waldiez/models/flow/flow.py +1 -0
- waldiez/models/model/extra_requirements.py +2 -2
- waldiez/models/skill/extra_requirements.py +3 -6
- waldiez/models/waldiez.py +9 -8
- waldiez/runner.py +4 -2
- waldiez/running/__init__.py +2 -0
- waldiez/running/environment.py +21 -1
- waldiez/running/gen_seq_diagram.py +3 -2
- waldiez/running/running.py +3 -2
- waldiez/utils/__init__.py +2 -0
- waldiez/utils/conflict_checker.py +3 -3
- waldiez/utils/pysqlite3_checker.py +63 -21
- waldiez/utils/rdps_checker.py +122 -0
- {waldiez-0.4.4.dist-info → waldiez-0.4.6.dist-info}/METADATA +109 -41
- {waldiez-0.4.4.dist-info → waldiez-0.4.6.dist-info}/RECORD +53 -52
- {waldiez-0.4.4.dist-info → waldiez-0.4.6.dist-info}/licenses/LICENSE +2 -2
- waldiez-0.4.6.dist-info/licenses/NOTICE.md +14 -0
- waldiez-0.4.4.dist-info/licenses/NOTICE.md +0 -5
- {waldiez-0.4.4.dist-info → waldiez-0.4.6.dist-info}/WHEEL +0 -0
- {waldiez-0.4.4.dist-info → waldiez-0.4.6.dist-info}/entry_points.txt +0 -0
|
@@ -39,11 +39,11 @@ def get_models_extra_requirements(
|
|
|
39
39
|
for requirement in model.requirements:
|
|
40
40
|
model_requirements.add(requirement)
|
|
41
41
|
if model.data.api_type == "google":
|
|
42
|
-
model_requirements.add(f"
|
|
42
|
+
model_requirements.add(f"ag2[gemini]=={autogen_version}")
|
|
43
43
|
continue
|
|
44
44
|
if model.data.api_type in models_with_additional_requirements:
|
|
45
45
|
model_requirements.add(
|
|
46
|
-
f"
|
|
46
|
+
f"ag2[{model.data.api_type}]=={autogen_version}"
|
|
47
47
|
)
|
|
48
48
|
return model_requirements
|
|
49
49
|
|
|
@@ -19,6 +19,7 @@ def get_skills_extra_requirements(
|
|
|
19
19
|
The skills.
|
|
20
20
|
autogen_version : str
|
|
21
21
|
The ag2 version.
|
|
22
|
+
|
|
22
23
|
Returns
|
|
23
24
|
-------
|
|
24
25
|
List[str]
|
|
@@ -27,13 +28,9 @@ def get_skills_extra_requirements(
|
|
|
27
28
|
skill_requirements: Set[str] = set()
|
|
28
29
|
for skill in skills:
|
|
29
30
|
if skill.skill_type == "langchain":
|
|
30
|
-
skill_requirements.add(
|
|
31
|
-
f"pyautogen[interop-langchain]=={autogen_version}"
|
|
32
|
-
)
|
|
31
|
+
skill_requirements.add(f"ag2[interop-langchain]=={autogen_version}")
|
|
33
32
|
if skill.skill_type == "crewai":
|
|
34
|
-
skill_requirements.add(
|
|
35
|
-
f"pyautogen[interop-crewai]=={autogen_version}"
|
|
36
|
-
)
|
|
33
|
+
skill_requirements.add(f"ag2[interop-crewai]=={autogen_version}")
|
|
37
34
|
for requirement in skill.requirements:
|
|
38
35
|
skill_requirements.add(requirement)
|
|
39
36
|
return skill_requirements
|
waldiez/models/waldiez.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# SPDX-License-Identifier: Apache-2.0.
|
|
2
2
|
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
3
|
-
"""Waldiez
|
|
3
|
+
"""Waldiez data class.
|
|
4
4
|
|
|
5
5
|
A Waldiez class contains all the information that is needed to generate
|
|
6
6
|
and run an autogen workflow. It has the model/LLM configurations, the agent
|
|
@@ -167,7 +167,7 @@ class Waldiez:
|
|
|
167
167
|
"""Get the agents.
|
|
168
168
|
|
|
169
169
|
Yields
|
|
170
|
-
|
|
170
|
+
------
|
|
171
171
|
WaldiezAgent
|
|
172
172
|
The flow agents.
|
|
173
173
|
"""
|
|
@@ -178,7 +178,7 @@ class Waldiez:
|
|
|
178
178
|
"""Get the flow skills.
|
|
179
179
|
|
|
180
180
|
Yields
|
|
181
|
-
|
|
181
|
+
------
|
|
182
182
|
WaldiezSkill
|
|
183
183
|
The skills.
|
|
184
184
|
"""
|
|
@@ -189,7 +189,7 @@ class Waldiez:
|
|
|
189
189
|
"""Get the models.
|
|
190
190
|
|
|
191
191
|
Yields
|
|
192
|
-
|
|
192
|
+
------
|
|
193
193
|
WaldiezModel
|
|
194
194
|
The flow models.
|
|
195
195
|
"""
|
|
@@ -230,8 +230,9 @@ class Waldiez:
|
|
|
230
230
|
"""Get the flow requirements."""
|
|
231
231
|
autogen_version = get_autogen_version()
|
|
232
232
|
requirements_list = filter(
|
|
233
|
-
# we use the fixed "
|
|
233
|
+
# we use the fixed "ag2=={autogen_version}" below
|
|
234
234
|
lambda requirement: not (
|
|
235
|
+
# cspell:disable-next-line
|
|
235
236
|
requirement.startswith("pyautogen")
|
|
236
237
|
or requirement.startswith("ag2")
|
|
237
238
|
or requirement.startswith("autogen")
|
|
@@ -239,12 +240,12 @@ class Waldiez:
|
|
|
239
240
|
self.flow.requirements,
|
|
240
241
|
)
|
|
241
242
|
requirements = set(requirements_list)
|
|
242
|
-
requirements.add(f"
|
|
243
|
+
requirements.add(f"ag2[openai]=={autogen_version}")
|
|
243
244
|
if self.has_rag_agents:
|
|
244
245
|
rag_extras = get_retrievechat_extra_requirements(self.agents)
|
|
245
246
|
requirements.update(rag_extras)
|
|
246
247
|
if self.has_multimodal_agents:
|
|
247
|
-
requirements.add(f"
|
|
248
|
+
requirements.add(f"ag2[lmm]=={autogen_version}")
|
|
248
249
|
if self.has_captain_agents:
|
|
249
250
|
# pysqlite3-binary might not get installed on windows
|
|
250
251
|
captain_extras = [
|
|
@@ -276,7 +277,7 @@ class Waldiez:
|
|
|
276
277
|
autogen_version=autogen_version,
|
|
277
278
|
)
|
|
278
279
|
)
|
|
279
|
-
return sorted(
|
|
280
|
+
return sorted(requirements)
|
|
280
281
|
|
|
281
282
|
def get_flow_env_vars(self) -> List[Tuple[str, str]]:
|
|
282
283
|
"""Get the flow environment variables.
|
waldiez/runner.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# SPDX-License-Identifier: Apache-2.0.
|
|
2
2
|
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
3
3
|
"""Run a waldiez flow.
|
|
4
|
+
|
|
4
5
|
The flow is first converted to an autogen flow with agents, chats and skills.
|
|
5
6
|
We then chown to temporary directory, call the flow's `main()` and
|
|
6
7
|
return the results. Before running the flow, any additional environment
|
|
@@ -144,9 +145,9 @@ class WaldiezRunner:
|
|
|
144
145
|
Set[str]
|
|
145
146
|
The extra requirements.
|
|
146
147
|
"""
|
|
147
|
-
extra_requirements =
|
|
148
|
+
extra_requirements = {
|
|
148
149
|
req for req in self.waldiez.requirements if req not in sys.modules
|
|
149
|
-
|
|
150
|
+
}
|
|
150
151
|
if self.waldiez.has_captain_agents:
|
|
151
152
|
check_pysqlite3()
|
|
152
153
|
return extra_requirements
|
|
@@ -185,6 +186,7 @@ class WaldiezRunner:
|
|
|
185
186
|
The runtime uploads root.
|
|
186
187
|
skip_mmd : bool
|
|
187
188
|
Whether to skip the Mermaid diagram generation.
|
|
189
|
+
|
|
188
190
|
Returns
|
|
189
191
|
-------
|
|
190
192
|
Union[ChatResult, List[ChatResult]]
|
waldiez/running/__init__.py
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
from .environment import (
|
|
6
6
|
in_virtualenv,
|
|
7
|
+
is_root,
|
|
7
8
|
refresh_environment,
|
|
8
9
|
reset_env_vars,
|
|
9
10
|
set_env_vars,
|
|
@@ -26,6 +27,7 @@ __all__ = [
|
|
|
26
27
|
"chdir",
|
|
27
28
|
"get_printer",
|
|
28
29
|
"in_virtualenv",
|
|
30
|
+
"is_root",
|
|
29
31
|
"install_requirements",
|
|
30
32
|
"refresh_environment",
|
|
31
33
|
"reset_env_vars",
|
waldiez/running/environment.py
CHANGED
|
@@ -25,6 +25,26 @@ def in_virtualenv() -> bool:
|
|
|
25
25
|
)
|
|
26
26
|
|
|
27
27
|
|
|
28
|
+
def is_root() -> bool:
|
|
29
|
+
"""Check if the script is running as root/administrator.
|
|
30
|
+
|
|
31
|
+
Returns
|
|
32
|
+
-------
|
|
33
|
+
bool
|
|
34
|
+
True if running as root/administrator, False otherwise.
|
|
35
|
+
"""
|
|
36
|
+
# pylint: disable=import-outside-toplevel,line-too-long
|
|
37
|
+
if os.name == "nt":
|
|
38
|
+
try:
|
|
39
|
+
import ctypes
|
|
40
|
+
|
|
41
|
+
return ctypes.windll.shell32.IsUserAnAdmin() != 0 # type: ignore[unused-ignore,attr-defined] # noqa: E501
|
|
42
|
+
except Exception: # pylint: disable=broad-exception-caught
|
|
43
|
+
return False
|
|
44
|
+
else:
|
|
45
|
+
return os.getuid() == 0
|
|
46
|
+
|
|
47
|
+
|
|
28
48
|
def refresh_environment() -> None:
|
|
29
49
|
"""Refresh the environment."""
|
|
30
50
|
with warnings.catch_warnings():
|
|
@@ -70,7 +90,7 @@ def refresh_environment() -> None:
|
|
|
70
90
|
|
|
71
91
|
@contextlib.contextmanager
|
|
72
92
|
def _np_no_nep50_warning() -> Generator[None, None, None]:
|
|
73
|
-
"""
|
|
93
|
+
"""Avoid no_nep50 warning.
|
|
74
94
|
|
|
75
95
|
Yields
|
|
76
96
|
------
|
|
@@ -69,12 +69,12 @@ def process_events(df_events: pd.DataFrame) -> str:
|
|
|
69
69
|
----------
|
|
70
70
|
df_events : pd.DataFrame
|
|
71
71
|
The DataFrame containing the events data.
|
|
72
|
+
|
|
72
73
|
Returns
|
|
73
74
|
-------
|
|
74
75
|
str
|
|
75
76
|
The Mermaid sequence diagram text.
|
|
76
77
|
"""
|
|
77
|
-
|
|
78
78
|
# Set to store participants (senders and recipients)
|
|
79
79
|
participants: Set[str] = set()
|
|
80
80
|
recipient: str
|
|
@@ -150,7 +150,7 @@ def save_diagram(mermaid_text: str, output_path: Union[str, Path]) -> None:
|
|
|
150
150
|
def generate_sequence_diagram(
|
|
151
151
|
file_path: Union[str, Path], output_path: Union[str, Path]
|
|
152
152
|
) -> None:
|
|
153
|
-
"""
|
|
153
|
+
"""Generate the Mermaid diagram.
|
|
154
154
|
|
|
155
155
|
Parameters
|
|
156
156
|
----------
|
|
@@ -163,6 +163,7 @@ def generate_sequence_diagram(
|
|
|
163
163
|
------
|
|
164
164
|
FileNotFoundError
|
|
165
165
|
If the input file is not found.
|
|
166
|
+
|
|
166
167
|
ValueError
|
|
167
168
|
If the input file is not a JSON or CSV file.
|
|
168
169
|
"""
|
waldiez/running/running.py
CHANGED
|
@@ -23,7 +23,7 @@ from typing import (
|
|
|
23
23
|
Union,
|
|
24
24
|
)
|
|
25
25
|
|
|
26
|
-
from .environment import in_virtualenv
|
|
26
|
+
from .environment import in_virtualenv, is_root
|
|
27
27
|
from .gen_seq_diagram import generate_sequence_diagram
|
|
28
28
|
|
|
29
29
|
# pylint: disable=import-outside-toplevel
|
|
@@ -126,7 +126,8 @@ def install_requirements(
|
|
|
126
126
|
# but it might fail if we don't
|
|
127
127
|
break_system_packages = os.environ.get("PIP_BREAK_SYSTEM_PACKAGES", "")
|
|
128
128
|
os.environ["PIP_BREAK_SYSTEM_PACKAGES"] = "1"
|
|
129
|
-
|
|
129
|
+
if not is_root():
|
|
130
|
+
pip_install.append("--user")
|
|
130
131
|
pip_install.extend(extra_requirements)
|
|
131
132
|
# pylint: disable=too-many-try-statements
|
|
132
133
|
try:
|
waldiez/utils/__init__.py
CHANGED
|
@@ -6,10 +6,12 @@ from .cli_extras import add_cli_extras
|
|
|
6
6
|
from .conflict_checker import check_conflicts
|
|
7
7
|
from .flaml_warnings import check_flaml_warnings
|
|
8
8
|
from .pysqlite3_checker import check_pysqlite3
|
|
9
|
+
from .rdps_checker import check_rpds_py
|
|
9
10
|
|
|
10
11
|
__all__ = [
|
|
11
12
|
"check_conflicts",
|
|
12
13
|
"check_flaml_warnings",
|
|
13
14
|
"add_cli_extras",
|
|
14
15
|
"check_pysqlite3",
|
|
16
|
+
"check_rpds_py",
|
|
15
17
|
]
|
|
@@ -17,11 +17,11 @@ def _check_conflicts() -> None: # pragma: no cover
|
|
|
17
17
|
print(
|
|
18
18
|
"Conflict detected: 'autogen-agentchat' is installed "
|
|
19
19
|
"in the current environment, \n"
|
|
20
|
-
"which conflicts with 'ag2'
|
|
20
|
+
"which conflicts with 'ag2'.\n"
|
|
21
21
|
"Please uninstall 'autogen-agentchat': \n"
|
|
22
22
|
f"{sys.executable} -m pip uninstall -y autogen-agentchat" + "\n"
|
|
23
|
-
"And install '
|
|
24
|
-
f"{sys.executable} -m pip install --force
|
|
23
|
+
"And install 'ag2' (and/or 'waldiez') again: \n"
|
|
24
|
+
f"{sys.executable} -m pip install --force ag2 waldiez",
|
|
25
25
|
file=sys.stderr,
|
|
26
26
|
)
|
|
27
27
|
sys.exit(1)
|
|
@@ -8,6 +8,7 @@ Highly recommended to be run in a virtual environment.
|
|
|
8
8
|
'setuptools' and 'wheel' will also be installed if not already installed.
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
|
+
import contextlib
|
|
11
12
|
import os
|
|
12
13
|
import platform
|
|
13
14
|
import shutil
|
|
@@ -22,10 +23,10 @@ PYSQLITE3_VERSION = "0.5.4"
|
|
|
22
23
|
SQLITE_URL = "https://www.sqlite.org/2025/sqlite-amalgamation-3480000.zip"
|
|
23
24
|
PYSQLITE3_URL = f"https://github.com/coleifer/pysqlite3/archive/refs/tags/{PYSQLITE3_VERSION}.zip" # pylint: disable=line-too-long
|
|
24
25
|
|
|
25
|
-
PIP =
|
|
26
|
+
PIP = [sys.executable, "-m", "pip"]
|
|
26
27
|
|
|
27
28
|
|
|
28
|
-
def run_command(command: str, cwd: str = ".") -> None:
|
|
29
|
+
def run_command(command: list[str], cwd: str = ".") -> None:
|
|
29
30
|
"""Run a command.
|
|
30
31
|
|
|
31
32
|
Parameters
|
|
@@ -35,12 +36,11 @@ def run_command(command: str, cwd: str = ".") -> None:
|
|
|
35
36
|
cwd : str
|
|
36
37
|
The current working directory.
|
|
37
38
|
"""
|
|
38
|
-
cmd_parts = command.split(" ")
|
|
39
39
|
if cwd == ".":
|
|
40
40
|
cwd = os.getcwd()
|
|
41
41
|
try:
|
|
42
42
|
subprocess.run( # nosemgrep # nosec
|
|
43
|
-
|
|
43
|
+
command,
|
|
44
44
|
check=True,
|
|
45
45
|
cwd=cwd,
|
|
46
46
|
env=os.environ,
|
|
@@ -64,6 +64,26 @@ def in_virtualenv() -> bool:
|
|
|
64
64
|
)
|
|
65
65
|
|
|
66
66
|
|
|
67
|
+
def is_root() -> bool:
|
|
68
|
+
"""Check if the script is running as root/administrator.
|
|
69
|
+
|
|
70
|
+
Returns
|
|
71
|
+
-------
|
|
72
|
+
bool
|
|
73
|
+
True if running as root/administrator, False otherwise.
|
|
74
|
+
"""
|
|
75
|
+
# pylint: disable=import-outside-toplevel,line-too-long
|
|
76
|
+
if os.name == "nt":
|
|
77
|
+
try:
|
|
78
|
+
import ctypes
|
|
79
|
+
|
|
80
|
+
return ctypes.windll.shell32.IsUserAnAdmin() != 0 # type: ignore[unused-ignore,attr-defined] # noqa: E501
|
|
81
|
+
except Exception: # pylint: disable=broad-exception-caught
|
|
82
|
+
return False
|
|
83
|
+
else:
|
|
84
|
+
return os.getuid() == 0
|
|
85
|
+
|
|
86
|
+
|
|
67
87
|
def pip_install(*package_names: str, cwd: str = ".") -> None:
|
|
68
88
|
"""Install packages using pip.
|
|
69
89
|
|
|
@@ -74,11 +94,19 @@ def pip_install(*package_names: str, cwd: str = ".") -> None:
|
|
|
74
94
|
cwd : str
|
|
75
95
|
The current working directory.
|
|
76
96
|
"""
|
|
77
|
-
args = "-qq"
|
|
97
|
+
args = ["install", "-qq"]
|
|
98
|
+
break_system_packages = ""
|
|
99
|
+
if not in_virtualenv():
|
|
100
|
+
break_system_packages = os.environ.get("PIP_BREAK_SYSTEM_PACKAGES", "")
|
|
101
|
+
os.environ["PIP_BREAK_SYSTEM_PACKAGES"] = "1"
|
|
102
|
+
if not is_root():
|
|
103
|
+
args.append("--user")
|
|
104
|
+
run_command(PIP + args + list(package_names), cwd)
|
|
78
105
|
if not in_virtualenv():
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
106
|
+
if break_system_packages:
|
|
107
|
+
os.environ["PIP_BREAK_SYSTEM_PACKAGES"] = break_system_packages
|
|
108
|
+
else:
|
|
109
|
+
os.environ.pop("PIP_BREAK_SYSTEM_PACKAGES", None)
|
|
82
110
|
|
|
83
111
|
|
|
84
112
|
def pip_uninstall(*package_names: str, cwd: str = ".") -> None:
|
|
@@ -91,11 +119,17 @@ def pip_uninstall(*package_names: str, cwd: str = ".") -> None:
|
|
|
91
119
|
cwd : str
|
|
92
120
|
The current working directory.
|
|
93
121
|
"""
|
|
94
|
-
args = "-qq --yes"
|
|
122
|
+
args = ["uninstall", "-qq", "--yes"]
|
|
123
|
+
break_system_packages = ""
|
|
95
124
|
if not in_virtualenv():
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
run_command(
|
|
125
|
+
break_system_packages = os.environ.get("PIP_BREAK_SYSTEM_PACKAGES", "")
|
|
126
|
+
os.environ["PIP_BREAK_SYSTEM_PACKAGES"] = "1"
|
|
127
|
+
run_command(PIP + args + list(package_names), cwd)
|
|
128
|
+
if not in_virtualenv():
|
|
129
|
+
if break_system_packages:
|
|
130
|
+
os.environ["PIP_BREAK_SYSTEM_PACKAGES"] = break_system_packages
|
|
131
|
+
else:
|
|
132
|
+
os.environ.pop("PIP_BREAK_SYSTEM_PACKAGES", None)
|
|
99
133
|
|
|
100
134
|
|
|
101
135
|
def download_sqlite_amalgamation() -> str:
|
|
@@ -187,15 +221,23 @@ def install_pysqlite3(sqlite_amalgamation_path: str) -> None:
|
|
|
187
221
|
try:
|
|
188
222
|
pysqlite3_dir = prepare_pysqlite3(sqlite_amalgamation_path)
|
|
189
223
|
pip_install("setuptools")
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
224
|
+
# let's suppress logs
|
|
225
|
+
with open(os.devnull, "w", encoding="utf-8") as devnull:
|
|
226
|
+
with (
|
|
227
|
+
contextlib.redirect_stdout(devnull),
|
|
228
|
+
contextlib.redirect_stderr(devnull),
|
|
229
|
+
):
|
|
230
|
+
run_command(
|
|
231
|
+
[sys.executable, "setup.py", "build_static"], pysqlite3_dir
|
|
232
|
+
)
|
|
233
|
+
pip_install("wheel")
|
|
234
|
+
run_command(
|
|
235
|
+
PIP + ["wheel", ".", "-w", "dist"],
|
|
236
|
+
pysqlite3_dir,
|
|
237
|
+
)
|
|
238
|
+
wheel_file = os.listdir(os.path.join(pysqlite3_dir, "dist"))[0]
|
|
239
|
+
wheel_path = os.path.join("dist", wheel_file)
|
|
240
|
+
pip_install(wheel_path, cwd=pysqlite3_dir)
|
|
199
241
|
except BaseException as e: # pylint: disable=broad-except
|
|
200
242
|
print(f"Failed to install pysqlite3: {e}")
|
|
201
243
|
sys.exit(1)
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0.
|
|
2
|
+
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
3
|
+
"""
|
|
4
|
+
Check for rpds-py on Windows ARM64.
|
|
5
|
+
|
|
6
|
+
Since we cannot use direct git dependency for `rpds-py` in `pyproject.toml`,
|
|
7
|
+
let's check it here.
|
|
8
|
+
|
|
9
|
+
NOTE: We should regularly check if this is still needed.
|
|
10
|
+
"""
|
|
11
|
+
# pylint: disable=import-outside-toplevel,unused-import
|
|
12
|
+
|
|
13
|
+
# "rpds-py @ git+https://github.com/crate-py/rpds.git@v0.24.0 ;
|
|
14
|
+
# sys_platform == "win32" and platform_machine == "AARCH64"",
|
|
15
|
+
|
|
16
|
+
import os
|
|
17
|
+
import platform
|
|
18
|
+
import subprocess
|
|
19
|
+
import sys
|
|
20
|
+
|
|
21
|
+
PIP = [sys.executable, "-m", "pip"]
|
|
22
|
+
RDPS_PY_VERSION = "0.24.0"
|
|
23
|
+
RDPS_PY_URL = f"git+https://github.com/crate-py/rpds.git@{RDPS_PY_VERSION}"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def is_windows_arm64() -> bool:
|
|
27
|
+
"""Check if the current platform is Windows ARM64.
|
|
28
|
+
|
|
29
|
+
Returns
|
|
30
|
+
-------
|
|
31
|
+
bool
|
|
32
|
+
True if the platform is Windows ARM64, False otherwise.
|
|
33
|
+
"""
|
|
34
|
+
return sys.platform == "win32" and platform.machine().lower() in [
|
|
35
|
+
"arm64",
|
|
36
|
+
"aarch64",
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def is_rpds_py_installed() -> bool:
|
|
41
|
+
"""Check if `rpds-py` is installed.
|
|
42
|
+
|
|
43
|
+
Returns
|
|
44
|
+
-------
|
|
45
|
+
bool
|
|
46
|
+
True if `rpds-py` is installed, False otherwise.
|
|
47
|
+
"""
|
|
48
|
+
try:
|
|
49
|
+
import rpds # noqa: F401
|
|
50
|
+
|
|
51
|
+
return True
|
|
52
|
+
except ImportError:
|
|
53
|
+
return False
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def is_root() -> bool:
|
|
57
|
+
"""Check if the script is running as root/administrator.
|
|
58
|
+
|
|
59
|
+
Returns
|
|
60
|
+
-------
|
|
61
|
+
bool
|
|
62
|
+
True if running as root/administrator, False otherwise.
|
|
63
|
+
"""
|
|
64
|
+
# pylint: disable=import-outside-toplevel,line-too-long
|
|
65
|
+
if os.name == "nt":
|
|
66
|
+
try:
|
|
67
|
+
import ctypes
|
|
68
|
+
|
|
69
|
+
return ctypes.windll.shell32.IsUserAnAdmin() != 0 # type: ignore[unused-ignore,attr-defined] # noqa: E501
|
|
70
|
+
except Exception: # pylint: disable=broad-exception-caught
|
|
71
|
+
return False
|
|
72
|
+
else:
|
|
73
|
+
return os.getuid() == 0
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def in_virtualenv() -> bool:
|
|
77
|
+
"""Check if the current environment is a virtual environment.
|
|
78
|
+
|
|
79
|
+
Returns
|
|
80
|
+
-------
|
|
81
|
+
bool
|
|
82
|
+
True if in a virtual environment, False otherwise.
|
|
83
|
+
"""
|
|
84
|
+
return hasattr(sys, "real_prefix") or (
|
|
85
|
+
hasattr(sys, "base_prefix")
|
|
86
|
+
and os.path.realpath(sys.base_prefix) != os.path.realpath(sys.prefix)
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def install_rpds_py() -> None:
|
|
91
|
+
"""Install `rpds-py`."""
|
|
92
|
+
command = PIP + ["install", "-qq"]
|
|
93
|
+
if not in_virtualenv():
|
|
94
|
+
break_system_packages = os.environ.get("PIP_BREAK_SYSTEM_PACKAGES", "")
|
|
95
|
+
os.environ["PIP_BREAK_SYSTEM_PACKAGES"] = "1"
|
|
96
|
+
if not is_root():
|
|
97
|
+
command.append("--user")
|
|
98
|
+
command.append(RDPS_PY_URL)
|
|
99
|
+
try:
|
|
100
|
+
subprocess.check_call(command)
|
|
101
|
+
except subprocess.CalledProcessError as e:
|
|
102
|
+
print(f"Failed to install rpds-py: {e}")
|
|
103
|
+
finally:
|
|
104
|
+
if not in_virtualenv():
|
|
105
|
+
# restore the old env var
|
|
106
|
+
if break_system_packages:
|
|
107
|
+
os.environ["PIP_BREAK_SYSTEM_PACKAGES"] = break_system_packages
|
|
108
|
+
else:
|
|
109
|
+
del os.environ["PIP_BREAK_SYSTEM_PACKAGES"]
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def check_rpds_py() -> None:
|
|
113
|
+
"""Check if `rpds-py` is installed on Windows ARM64."""
|
|
114
|
+
if not is_windows_arm64():
|
|
115
|
+
return
|
|
116
|
+
if is_rpds_py_installed():
|
|
117
|
+
return
|
|
118
|
+
install_rpds_py()
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
if __name__ == "__main__":
|
|
122
|
+
check_rpds_py()
|