@@ -514,5 +514,168 @@ def test_real_project_optimization_benefits(self, temp_project):
514514 assert optimized_efficiency >= naive_efficiency or optimized_efficiency >= 0.3
515515
516516
517+ class TestDirectoryExclusion :
518+ """Test directory exclusion patterns in ContextOptimizer."""
519+
520+ def test_should_exclude_path_no_patterns (self ):
521+ """Test that no exclusions occur when no patterns are provided."""
522+ optimizer = ContextOptimizer (base_dir = "/test" , exclude_patterns = None )
523+ assert not optimizer ._should_exclude_path (Path ("/test/src" ))
524+ assert not optimizer ._should_exclude_path (Path ("/test/apm_modules" ))
525+
526+ def test_should_exclude_path_simple_directory (self ):
527+ """Test exclusion of simple directory patterns."""
528+ optimizer = ContextOptimizer (
529+ base_dir = "/test" ,
530+ exclude_patterns = ["apm_modules" , "tmp" ]
531+ )
532+ assert optimizer ._should_exclude_path (Path ("/test/apm_modules" ))
533+ assert optimizer ._should_exclude_path (Path ("/test/tmp" ))
534+ assert not optimizer ._should_exclude_path (Path ("/test/src" ))
535+
536+ def test_should_exclude_path_with_trailing_slash (self ):
537+ """Test exclusion patterns with trailing slashes."""
538+ optimizer = ContextOptimizer (
539+ base_dir = "/test" ,
540+ exclude_patterns = ["apm_modules/" , "tmp/" ]
541+ )
542+ assert optimizer ._should_exclude_path (Path ("/test/apm_modules" ))
543+ assert optimizer ._should_exclude_path (Path ("/test/apm_modules/package" ))
544+ assert optimizer ._should_exclude_path (Path ("/test/tmp" ))
545+ assert not optimizer ._should_exclude_path (Path ("/test/src" ))
546+
547+ def test_should_exclude_path_nested_directories (self ):
548+ """Test exclusion of nested directory patterns."""
549+ optimizer = ContextOptimizer (
550+ base_dir = "/test" ,
551+ exclude_patterns = ["projects/packages/apm" ]
552+ )
553+ assert optimizer ._should_exclude_path (Path ("/test/projects/packages/apm" ))
554+ assert optimizer ._should_exclude_path (Path ("/test/projects/packages/apm/src" ))
555+ assert not optimizer ._should_exclude_path (Path ("/test/projects/packages/other" ))
556+
557+ def test_should_exclude_path_glob_patterns (self ):
558+ """Test exclusion using glob patterns."""
559+ optimizer = ContextOptimizer (
560+ base_dir = "/test" ,
561+ exclude_patterns = ["**/test-fixtures" , "coverage/**" ]
562+ )
563+ assert optimizer ._should_exclude_path (Path ("/test/test-fixtures" ))
564+ assert optimizer ._should_exclude_path (Path ("/test/src/test-fixtures" ))
565+ assert optimizer ._should_exclude_path (Path ("/test/coverage" ))
566+ assert optimizer ._should_exclude_path (Path ("/test/coverage/report" ))
567+ assert not optimizer ._should_exclude_path (Path ("/test/src" ))
568+
569+ def test_should_exclude_path_wildcard_patterns (self ):
570+ """Test exclusion using wildcard patterns."""
571+ optimizer = ContextOptimizer (
572+ base_dir = "/test" ,
573+ exclude_patterns = ["tmp*" , "*cache*" ]
574+ )
575+ assert optimizer ._should_exclude_path (Path ("/test/tmp" ))
576+ assert optimizer ._should_exclude_path (Path ("/test/tmp123" ))
577+ assert optimizer ._should_exclude_path (Path ("/test/cache" ))
578+ assert optimizer ._should_exclude_path (Path ("/test/mycache" ))
579+ assert not optimizer ._should_exclude_path (Path ("/test/src" ))
580+
581+ def test_should_exclude_path_complex_glob (self ):
582+ """Test complex glob patterns."""
583+ optimizer = ContextOptimizer (
584+ base_dir = "/test" ,
585+ exclude_patterns = ["projects/**/apm/**" , "**/node_modules/**" ]
586+ )
587+ assert optimizer ._should_exclude_path (Path ("/test/projects/packages/apm" ))
588+ assert optimizer ._should_exclude_path (Path ("/test/projects/packages/apm/src" ))
589+ assert optimizer ._should_exclude_path (Path ("/test/node_modules" ))
590+ assert optimizer ._should_exclude_path (Path ("/test/src/node_modules" ))
591+ assert not optimizer ._should_exclude_path (Path ("/test/projects/other" ))
592+
593+ def test_should_exclude_path_path_outside_base_dir (self ):
594+ """Test that paths outside base_dir are not excluded."""
595+ optimizer = ContextOptimizer (
596+ base_dir = "/test" ,
597+ exclude_patterns = ["apm_modules" ]
598+ )
599+ # Path that's not relative to base_dir should not be excluded
600+ assert not optimizer ._should_exclude_path (Path ("/other/apm_modules" ))
601+
602+ def test_analyze_project_structure_with_exclusions (self ):
603+ """Test that _analyze_project_structure respects exclusion patterns."""
604+ with tempfile .TemporaryDirectory () as tmpdir :
605+ base_path = Path (tmpdir )
606+
607+ # Create directory structure
608+ (base_path / "src" ).mkdir ()
609+ (base_path / "src" / "file.py" ).touch ()
610+ (base_path / "apm_modules" ).mkdir ()
611+ (base_path / "apm_modules" / "file.py" ).touch ()
612+ (base_path / "tmp" ).mkdir ()
613+ (base_path / "tmp" / "file.py" ).touch ()
614+
615+ # Create optimizer with exclusions
616+ optimizer = ContextOptimizer (
617+ base_dir = str (base_path ),
618+ exclude_patterns = ["apm_modules" , "tmp" ]
619+ )
620+ optimizer ._analyze_project_structure ()
621+
622+ # Check that excluded directories are not in cache
623+ cached_dirs = set (optimizer ._directory_cache .keys ())
624+ assert base_path / "src" in cached_dirs
625+ assert base_path / "apm_modules" not in cached_dirs
626+ assert base_path / "tmp" not in cached_dirs
627+
628+ def test_analyze_project_structure_with_nested_exclusions (self ):
629+ """Test that nested exclusions work correctly."""
630+ with tempfile .TemporaryDirectory () as tmpdir :
631+ base_path = Path (tmpdir )
632+
633+ # Create nested directory structure
634+ (base_path / "projects" / "packages" / "apm" / "src" ).mkdir (parents = True )
635+ (base_path / "projects" / "packages" / "apm" / "src" / "file.py" ).touch ()
636+ (base_path / "projects" / "packages" / "other" / "src" ).mkdir (parents = True )
637+ (base_path / "projects" / "packages" / "other" / "src" / "file.py" ).touch ()
638+
639+ # Create optimizer with nested exclusion
640+ optimizer = ContextOptimizer (
641+ base_dir = str (base_path ),
642+ exclude_patterns = ["projects/packages/apm/**" ]
643+ )
644+ optimizer ._analyze_project_structure ()
645+
646+ # Check that excluded directories are not in cache
647+ cached_dirs = set (optimizer ._directory_cache .keys ())
648+ assert base_path / "projects" / "packages" / "apm" not in cached_dirs
649+ assert base_path / "projects" / "packages" / "apm" / "src" not in cached_dirs
650+ # Other directories should be present
651+ assert base_path / "projects" / "packages" / "other" / "src" in cached_dirs
652+
653+ def test_default_exclusions_still_work (self ):
654+ """Test that default hardcoded exclusions still work alongside custom patterns."""
655+ with tempfile .TemporaryDirectory () as tmpdir :
656+ base_path = Path (tmpdir )
657+
658+ # Create directories including default exclusions
659+ (base_path / "src" ).mkdir ()
660+ (base_path / "src" / "file.py" ).touch ()
661+ (base_path / "node_modules" ).mkdir ()
662+ (base_path / "node_modules" / "file.js" ).touch ()
663+ (base_path / "custom_exclude" ).mkdir ()
664+ (base_path / "custom_exclude" / "file.py" ).touch ()
665+
666+ # Create optimizer with custom exclusion only
667+ optimizer = ContextOptimizer (
668+ base_dir = str (base_path ),
669+ exclude_patterns = ["custom_exclude" ]
670+ )
671+ optimizer ._analyze_project_structure ()
672+
673+ # Check that both default and custom exclusions work
674+ cached_dirs = set (optimizer ._directory_cache .keys ())
675+ assert base_path / "src" in cached_dirs
676+ assert base_path / "node_modules" not in cached_dirs # Default exclusion
677+ assert base_path / "custom_exclude" not in cached_dirs # Custom exclusion
678+
679+
517680if __name__ == "__main__" :
518681 pytest .main ([__file__ ])
0 commit comments