33import pytest
44import click
55from pathlib import Path
6- from unittest import mock
7- from unittest .mock import patch , MagicMock , ANY
8- import sys
6+ from unittest .mock import patch , ANY
97import os
108
119# Mock generate_output_paths before importing construct_paths if it's needed globally
1816def resolve_path (relative_path_str , base_dir ):
1917 return str (Path (base_dir ) / relative_path_str )
2018
19+
2120def test_construct_paths_load_input_files (tmpdir ):
2221 """
2322 Test that construct_paths properly loads input files into input_strings,
@@ -2906,4 +2905,133 @@ def test_construct_paths_sync_basename_paths_pattern_context(self, tmp_path, mon
29062905
29072906 assert resolved_config ["_matched_context" ] == "frontend-components"
29082907 assert resolved_config ["prompts_dir" ] == "prompts"
2909- assert Path (resolved_config ["code_dir" ]).as_posix ().endswith ("frontend/src/components" )
2908+ assert Path (resolved_config ["code_dir" ]).as_posix ().endswith ("frontend/src/components" )
2909+
2910+
2911+ def test_resolve_config_hierarchy_env_prompts_dir (monkeypatch ):
2912+ """PDD_PROMPTS_DIR environment variable should be respected."""
2913+ monkeypatch .setenv ("PDD_PROMPTS_DIR" , "/tmp/custom_prompts" )
2914+
2915+ resolved = _resolve_config_hierarchy (
2916+ cli_options = {},
2917+ context_config = {},
2918+ env_vars = {
2919+ "PDD_PROMPTS_DIR" : os .environ .get ("PDD_PROMPTS_DIR" ),
2920+ },
2921+ )
2922+
2923+ assert "prompts_dir" in resolved
2924+ assert resolved ["prompts_dir" ] == "/tmp/custom_prompts"
2925+
2926+
2927+ def test_resolve_config_hierarchy_pddrc_prompts_dir (monkeypatch ):
2928+ """The .pddrc key `prompts_dir` should be respected."""
2929+ monkeypatch .delenv ("PDD_PROMPTS_DIR" , raising = False )
2930+
2931+ context_config = {
2932+ "prompts_dir" : "my_prompts" ,
2933+ }
2934+
2935+ resolved = _resolve_config_hierarchy (
2936+ cli_options = {},
2937+ context_config = context_config ,
2938+ env_vars = {},
2939+ )
2940+
2941+ assert "prompts_dir" in resolved
2942+ assert resolved ["prompts_dir" ] == "my_prompts"
2943+
2944+
2945+ def test_resolve_config_hierarchy_cli_prompts_dir_wins (monkeypatch ):
2946+ """CLI prompts_dir should take precedence over .pddrc and env vars."""
2947+ monkeypatch .setenv ("PDD_PROMPTS_DIR" , "/tmp/env_prompts" )
2948+
2949+ resolved = _resolve_config_hierarchy (
2950+ cli_options = {
2951+ "prompts_dir" : "cli_prompts" ,
2952+ },
2953+ context_config = {
2954+ "prompts_dir" : "pddrc_prompts" ,
2955+ },
2956+ env_vars = {
2957+ "PDD_PROMPTS_DIR" : os .environ .get ("PDD_PROMPTS_DIR" ),
2958+ },
2959+ )
2960+
2961+ assert "prompts_dir" in resolved
2962+ assert resolved ["prompts_dir" ] == "cli_prompts"
2963+
2964+
2965+ def test_construct_paths_regular_mode_respects_env_prompts_dir (tmp_path , monkeypatch ):
2966+ """
2967+ Integration test: PDD_PROMPTS_DIR should be respected in regular mode (e.g., pdd generate).
2968+
2969+ This verifies the environment variable works through the full construct_paths flow,
2970+ not just in _resolve_config_hierarchy isolation.
2971+ """
2972+ monkeypatch .chdir (tmp_path )
2973+ monkeypatch .setenv ("PDD_PROMPTS_DIR" , "/custom/prompts" )
2974+
2975+ # Create minimal test files
2976+ prompts_dir = tmp_path / "custom_prompts_location"
2977+ prompts_dir .mkdir ()
2978+ prompt_file = prompts_dir / "test_python.prompt"
2979+ prompt_file .write_text ("% Test prompt" , encoding = "utf-8" )
2980+
2981+ input_file_paths = {"prompt_file" : str (prompt_file )}
2982+ command_options = {"output" : "test.py" }
2983+
2984+ resolved_config , _ , output_paths , _ = construct_paths (
2985+ input_file_paths = input_file_paths ,
2986+ force = True ,
2987+ quiet = True ,
2988+ command = "generate" ,
2989+ command_options = command_options ,
2990+ )
2991+
2992+ # The environment variable should be in resolved_config
2993+ assert "prompts_dir" in resolved_config
2994+ assert resolved_config ["prompts_dir" ] == "/custom/prompts" , \
2995+ f"Expected prompts_dir='/custom/prompts' from PDD_PROMPTS_DIR, got '{ resolved_config ['prompts_dir' ]} '"
2996+
2997+
2998+ def test_construct_paths_sync_mode_respects_env_prompts_dir (tmp_path , monkeypatch ):
2999+ """
3000+ Integration test: PDD_PROMPTS_DIR should be respected in sync discovery mode.
3001+
3002+ Verifies the fix for the bug where sync mode would unconditionally overwrite
3003+ prompts_dir (lines 794, 807, 812) even when PDD_PROMPTS_DIR was set.
3004+ """
3005+ monkeypatch .chdir (tmp_path )
3006+ monkeypatch .setenv ("PDD_PROMPTS_DIR" , "/custom/sync/prompts" )
3007+
3008+ # Create minimal structure for sync mode
3009+ (tmp_path / "src" ).mkdir ()
3010+ (tmp_path / "tests" ).mkdir ()
3011+ (tmp_path / "context" ).mkdir ()
3012+
3013+ command_options = {"basename" : "calculator" }
3014+
3015+ # Mock generate_output_paths to return predictable paths
3016+ mock_output_paths = {
3017+ "generate_output_path" : str (tmp_path / "src" / "calculator.py" ),
3018+ "test_output_path" : str (tmp_path / "tests" / "test_calculator.py" ),
3019+ "example_output_path" : str (tmp_path / "context" / "calculator_example.py" ),
3020+ }
3021+
3022+ with patch ('pdd.construct_paths.generate_output_paths' , return_value = mock_output_paths ), \
3023+ patch ('pdd.construct_paths._get_context_config' , return_value = {}):
3024+
3025+ resolved_config , _ , _ , _ = construct_paths (
3026+ input_file_paths = {},
3027+ force = True ,
3028+ quiet = True ,
3029+ command = "sync" ,
3030+ command_options = command_options ,
3031+ )
3032+
3033+ # The environment variable should take precedence over sync discovery inference
3034+ assert "prompts_dir" in resolved_config
3035+ assert resolved_config ["prompts_dir" ] == "/custom/sync/prompts" , \
3036+ f"Expected prompts_dir='/custom/sync/prompts' from PDD_PROMPTS_DIR in sync mode, got '{ resolved_config ['prompts_dir' ]} '"
3037+
0 commit comments