@@ -399,6 +399,11 @@ def register_operations(self) -> Dict[str, List[str]]:
399
399
_TEST_STREAM_QUERY_SCHEMAS = [
400
400
_TEST_AGENT_ENGINE_STREAM_QUERY_SCHEMA ,
401
401
]
402
+ _TEST_PACKAGE_DISTRIBUTIONS = {
403
+ "requests" : ["requests" ],
404
+ "cloudpickle" : ["cloudpickle" ],
405
+ "pydantic" : ["pydantic" ],
406
+ }
402
407
403
408
404
409
def _create_empty_fake_package (package_name : str ) -> str :
@@ -507,6 +512,16 @@ def importlib_metadata_version_mock():
507
512
with mock .patch .object (
508
513
importlib .metadata , "version"
509
514
) as importlib_metadata_version_mock :
515
+
516
+ def get_version (pkg ):
517
+ versions = {
518
+ "requests" : "2.0.0" ,
519
+ "cloudpickle" : "3.0.0" ,
520
+ "pydantic" : "1.11.1" ,
521
+ }
522
+ return versions .get (pkg , "unknown" )
523
+
524
+ importlib_metadata_version_mock .side_effect = get_version
510
525
yield importlib_metadata_version_mock
511
526
512
527
@@ -616,6 +631,14 @@ def unregister_api_methods_mock():
616
631
yield unregister_api_methods_mock
617
632
618
633
634
+ def create_fake_object_with_module (module_name ):
635
+ class FakeObject :
636
+ pass
637
+
638
+ FakeObject .__module__ = module_name
639
+ return FakeObject ()
640
+
641
+
619
642
class InvalidCapitalizeEngineWithoutQuerySelf :
620
643
"""A sample Agent Engine with an invalid query method."""
621
644
@@ -2519,3 +2542,69 @@ def test_compare_requirements_with_required_packages(self):
2519
2542
"missing" : set (),
2520
2543
},
2521
2544
}
2545
+
2546
+ @pytest .mark .usefixtures ("importlib_metadata_version_mock" )
2547
+ def test_scan_simple_object (self ):
2548
+ """Test scanning an object importing a known third-party package."""
2549
+ fake_obj = create_fake_object_with_module ("requests" )
2550
+ requirements = _utils .scan_requirements (
2551
+ fake_obj ,
2552
+ package_distributions = _TEST_PACKAGE_DISTRIBUTIONS ,
2553
+ )
2554
+ assert requirements == {
2555
+ "cloudpickle" : "3.0.0" ,
2556
+ "pydantic" : "1.11.1" ,
2557
+ "requests" : "2.0.0" ,
2558
+ }
2559
+
2560
+ @pytest .mark .usefixtures ("importlib_metadata_version_mock" )
2561
+ def test_scan_object_with_stdlib_module (self ):
2562
+ """Test that stdlib modules are ignored by default."""
2563
+ fake_obj_stdlib = create_fake_object_with_module ("json" )
2564
+ requirements = _utils .scan_requirements (
2565
+ fake_obj_stdlib ,
2566
+ package_distributions = _TEST_PACKAGE_DISTRIBUTIONS ,
2567
+ )
2568
+ # Requirements should not contain 'json',
2569
+ # because 'json' is a stdlib module.
2570
+ assert requirements == {
2571
+ "cloudpickle" : "3.0.0" ,
2572
+ "pydantic" : "1.11.1" ,
2573
+ }
2574
+
2575
+ @pytest .mark .usefixtures ("importlib_metadata_version_mock" )
2576
+ def test_scan_with_default_ignore_modules (self , monkeypatch ):
2577
+ """Test implicitly ignoring a module."""
2578
+ fake_obj = create_fake_object_with_module ("requests" )
2579
+ original_base = _utils ._BASE_MODULES
2580
+ monkeypatch .setattr (
2581
+ _utils ,
2582
+ "_BASE_MODULES" ,
2583
+ set (original_base ) | {"requests" },
2584
+ )
2585
+ requirements = _utils .scan_requirements (
2586
+ fake_obj ,
2587
+ package_distributions = _TEST_PACKAGE_DISTRIBUTIONS ,
2588
+ )
2589
+ # Requirements should not contain 'requests',
2590
+ # because 'requests' is implicitly ignored in `_BASE_MODULES`.
2591
+ assert requirements == {
2592
+ "cloudpickle" : "3.0.0" ,
2593
+ "pydantic" : "1.11.1" ,
2594
+ }
2595
+
2596
+ @pytest .mark .usefixtures ("importlib_metadata_version_mock" )
2597
+ def test_scan_with_explicit_ignore_modules (self ):
2598
+ """Test explicitly ignoring a module."""
2599
+ fake_obj = create_fake_object_with_module ("requests" )
2600
+ requirements = _utils .scan_requirements (
2601
+ fake_obj ,
2602
+ ignore_modules = ["requests" ],
2603
+ package_distributions = _TEST_PACKAGE_DISTRIBUTIONS ,
2604
+ )
2605
+ # Requirements should not contain 'requests',
2606
+ # because 'requests' is explicitly ignored in `ignore_modules`.
2607
+ assert requirements == {
2608
+ "cloudpickle" : "3.0.0" ,
2609
+ "pydantic" : "1.11.1" ,
2610
+ }
0 commit comments