nvidia-nat-test 1.3.0a20250930__py3-none-any.whl → 1.3.0a20251001__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.
nat/test/plugin.py CHANGED
@@ -14,7 +14,9 @@
14
14
  # limitations under the License.
15
15
 
16
16
  import os
17
+ import subprocess
17
18
  import typing
19
+ from pathlib import Path
18
20
 
19
21
  import pytest
20
22
 
@@ -235,3 +237,98 @@ def restore_environ_fixture():
235
237
  for key in list(os.environ.keys()):
236
238
  if key not in orig_vars:
237
239
  del (os.environ[key])
240
+
241
+
242
+ @pytest.fixture(name="root_repo_dir", scope='session')
243
+ def root_repo_dir_fixture() -> Path:
244
+ from nat.test.utils import locate_repo_root
245
+ return locate_repo_root()
246
+
247
+
248
+ @pytest.fixture(name="require_etcd", scope="session")
249
+ def require_etcd_fixture(fail_missing: bool = False) -> bool:
250
+ """
251
+ To run these tests, an etcd server must be running
252
+ """
253
+ import requests
254
+
255
+ host = os.getenv("NAT_CI_ETCD_HOST", "localhost")
256
+ port = os.getenv("NAT_CI_ETCD_PORT", "2379")
257
+ health_url = f"http://{host}:{port}/health"
258
+
259
+ try:
260
+ response = requests.get(health_url, timeout=5)
261
+ response.raise_for_status()
262
+ return True
263
+ except: # noqa: E722
264
+ failure_reason = f"Unable to connect to etcd server at {health_url}"
265
+ if fail_missing:
266
+ raise RuntimeError(failure_reason)
267
+ pytest.skip(reason=failure_reason)
268
+
269
+
270
+ @pytest.fixture(name="milvus_uri", scope="session")
271
+ def milvus_uri_fixture(require_etcd: bool, fail_missing: bool = False) -> str:
272
+ """
273
+ To run these tests, a Milvus server must be running
274
+ """
275
+ host = os.getenv("NAT_CI_MILVUS_HOST", "localhost")
276
+ port = os.getenv("NAT_CI_MILVUS_PORT", "19530")
277
+ uri = f"http://{host}:{port}"
278
+ try:
279
+ from pymilvus import MilvusClient
280
+ MilvusClient(uri=uri)
281
+
282
+ return uri
283
+ except: # noqa: E722
284
+ reason = f"Unable to connect to Milvus server at {uri}"
285
+ if fail_missing:
286
+ raise RuntimeError(reason)
287
+ pytest.skip(reason=reason)
288
+
289
+
290
+ @pytest.fixture(name="populate_milvus", scope="session")
291
+ def populate_milvus_fixture(milvus_uri: str, root_repo_dir: Path):
292
+ """
293
+ Populate Milvus with some test data.
294
+ """
295
+ populate_script = root_repo_dir / "scripts/langchain_web_ingest.py"
296
+
297
+ # Ingest default cuda docs
298
+ subprocess.run(["python", str(populate_script), "--milvus_uri", milvus_uri], check=True)
299
+
300
+ # Ingest MCP docs
301
+ subprocess.run([
302
+ "python",
303
+ str(populate_script),
304
+ "--milvus_uri",
305
+ milvus_uri,
306
+ "--urls",
307
+ "https://github.com/modelcontextprotocol/python-sdk",
308
+ "--urls",
309
+ "https://modelcontextprotocol.io/introduction",
310
+ "--urls",
311
+ "https://modelcontextprotocol.io/quickstart/server",
312
+ "--urls",
313
+ "https://modelcontextprotocol.io/quickstart/client",
314
+ "--urls",
315
+ "https://modelcontextprotocol.io/examples",
316
+ "--urls",
317
+ "https://modelcontextprotocol.io/docs/concepts/architecture",
318
+ "--collection_name",
319
+ "mcp_docs"
320
+ ],
321
+ check=True)
322
+
323
+ # Ingest some wikipedia docs
324
+ subprocess.run([
325
+ "python",
326
+ str(populate_script),
327
+ "--milvus_uri",
328
+ milvus_uri,
329
+ "--urls",
330
+ "https://en.wikipedia.org/wiki/Aardvark",
331
+ "--collection_name",
332
+ "wikipedia_docs"
333
+ ],
334
+ check=True)
nat/test/register.py CHANGED
@@ -22,3 +22,4 @@ from . import embedder
22
22
  from . import functions
23
23
  from . import memory
24
24
  from . import llm
25
+ from . import utils
nat/test/utils.py ADDED
@@ -0,0 +1,87 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ import importlib.resources
17
+ import inspect
18
+ import subprocess
19
+ import typing
20
+ from pathlib import Path
21
+
22
+ if typing.TYPE_CHECKING:
23
+ from nat.data_models.config import Config
24
+ from nat.utils.type_utils import StrPath
25
+
26
+
27
+ def locate_repo_root() -> Path:
28
+ result = subprocess.run(["git", "rev-parse", "--show-toplevel"], check=False, capture_output=True, text=True)
29
+ assert result.returncode == 0, f"Failed to get git root: {result.stderr}"
30
+ return Path(result.stdout.strip())
31
+
32
+
33
+ def locate_example_src_dir(example_config_class: type) -> Path:
34
+ """
35
+ Locate the example src directory for an example's config class.
36
+ """
37
+ package_name = inspect.getmodule(example_config_class).__package__
38
+ return importlib.resources.files(package_name)
39
+
40
+
41
+ def locate_example_dir(example_config_class: type) -> Path:
42
+ """
43
+ Locate the example directory for an example's config class.
44
+ """
45
+ src_dir = locate_example_src_dir(example_config_class)
46
+ example_dir = src_dir.parent.parent
47
+ return example_dir
48
+
49
+
50
+ def locate_example_config(example_config_class: type,
51
+ config_file: str = "config.yml",
52
+ assert_exists: bool = True) -> Path:
53
+ """
54
+ Locate the example config file for an example's config class, assumes the example contains a 'configs' directory
55
+ """
56
+ example_dir = locate_example_src_dir(example_config_class)
57
+ config_path = example_dir.joinpath("configs", config_file).absolute()
58
+ if assert_exists:
59
+ assert config_path.exists(), f"Config file {config_path} does not exist"
60
+
61
+ return config_path
62
+
63
+
64
+ async def run_workflow(
65
+ config_file: "StrPath | None",
66
+ question: str,
67
+ expected_answer: str,
68
+ assert_expected_answer: bool = True,
69
+ config: "Config | None" = None,
70
+ ) -> str:
71
+ from nat.builder.workflow_builder import WorkflowBuilder
72
+ from nat.runtime.loader import load_config
73
+ from nat.runtime.session import SessionManager
74
+
75
+ if config is None:
76
+ assert config_file is not None, "Either config_file or config must be provided"
77
+ config = load_config(config_file)
78
+
79
+ async with WorkflowBuilder.from_config(config=config) as workflow_builder:
80
+ workflow = SessionManager(await workflow_builder.build())
81
+ async with workflow.run(question) as runner:
82
+ result = await runner.result(to_type=str)
83
+
84
+ if assert_expected_answer:
85
+ assert expected_answer.lower() in result.lower(), f"Expected '{expected_answer}' in '{result}'"
86
+
87
+ return result
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nvidia-nat-test
3
- Version: 1.3.0a20250930
3
+ Version: 1.3.0a20251001
4
4
  Summary: Testing utilities for NeMo Agent toolkit
5
5
  Keywords: ai,rag,agents
6
6
  Classifier: Programming Language :: Python
@@ -9,7 +9,7 @@ Classifier: Programming Language :: Python :: 3.12
9
9
  Classifier: Programming Language :: Python :: 3.13
10
10
  Requires-Python: <3.14,>=3.11
11
11
  Description-Content-Type: text/markdown
12
- Requires-Dist: nvidia-nat==v1.3.0a20250930
12
+ Requires-Dist: nvidia-nat==v1.3.0a20251001
13
13
  Requires-Dist: langchain-community~=0.3
14
14
  Requires-Dist: pytest~=8.3
15
15
 
@@ -5,11 +5,12 @@ nat/test/functions.py,sha256=0ScrdsjcxCsPRLnyb5gfwukmvZxFi_ptCswLSIG0DVY,3095
5
5
  nat/test/llm.py,sha256=osJWGsJN7x-JGOaitueKeSwuJPVmnIFqJUCz28ngSRg,8215
6
6
  nat/test/memory.py,sha256=xki_A2yiMhEZuQk60K7t04QRqf32nQqnfzD5Iv7fkvw,1456
7
7
  nat/test/object_store_tests.py,sha256=PyJioOtoSzILPq6LuD-sOZ_89PIcgXWZweoHBQpK2zQ,4281
8
- nat/test/plugin.py,sha256=WgBTKdV77j5ANlhiFlR6DrEG1H2R1r5yqJFEqkvG9mI,8315
9
- nat/test/register.py,sha256=FZLjc3-G1lniSUJ3qVOr0aQ-aoH1F493JMFtKbZG56w,877
8
+ nat/test/plugin.py,sha256=P6awHPN-iVmb8VIzLX_pd9rMnR4PD8Of3H_ypPPFr8Q,11246
9
+ nat/test/register.py,sha256=o1BEA5fyxyFyCxXhQ6ArmtuNpgRyTEfvw6HdBgECPLI,897
10
10
  nat/test/tool_test_runner.py,sha256=SxavwXHkvCQDl_PUiiiqgvGfexKJJTeBdI5i1qk6AzI,21712
11
- nvidia_nat_test-1.3.0a20250930.dist-info/METADATA,sha256=q5WrFJW9cQzA6zV4LCZgjOe7MR-HXRaHvg2QHWuXK84,1619
12
- nvidia_nat_test-1.3.0a20250930.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
13
- nvidia_nat_test-1.3.0a20250930.dist-info/entry_points.txt,sha256=7dOP9XB6iMDqvav3gYx9VWUwA8RrFzhbAa8nGeC8e4Y,99
14
- nvidia_nat_test-1.3.0a20250930.dist-info/top_level.txt,sha256=8-CJ2cP6-f0ZReXe5Hzqp-5pvzzHz-5Ds5H2bGqh1-U,4
15
- nvidia_nat_test-1.3.0a20250930.dist-info/RECORD,,
11
+ nat/test/utils.py,sha256=y77p5uVpRPSQqVOnetBLvJVsSRgS4_fEgcuRoHwvRKE,3187
12
+ nvidia_nat_test-1.3.0a20251001.dist-info/METADATA,sha256=2MOKvNLYaMHIBKK7nZd4lIHO0qL6P2As1KRbTcYMhy4,1619
13
+ nvidia_nat_test-1.3.0a20251001.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
14
+ nvidia_nat_test-1.3.0a20251001.dist-info/entry_points.txt,sha256=7dOP9XB6iMDqvav3gYx9VWUwA8RrFzhbAa8nGeC8e4Y,99
15
+ nvidia_nat_test-1.3.0a20251001.dist-info/top_level.txt,sha256=8-CJ2cP6-f0ZReXe5Hzqp-5pvzzHz-5Ds5H2bGqh1-U,4
16
+ nvidia_nat_test-1.3.0a20251001.dist-info/RECORD,,