Skip to content

Conversation

@aseembits93
Copy link
Contributor

@aseembits93 aseembits93 commented May 20, 2025

User description

Adding type hints tends to help with guiding the test generation process, only homogeneous test inputs are generated.


PR Type

Enhancement


Description

  • Replace cast(str, ...) with cast("str", ...) calls.

  • Add list[int]|list[float] hints to bubble_sort function.

  • Update project_name cast return annotation.

  • Standardize string-literal casting usage.


Changes walkthrough 📝

Relevant files
Enhancement
cmd_init.py
Standardize cast args and add type hints                                 

codeflash/cli_cmds/cmd_init.py

  • Swapped cast first argument to "str" in multiple statements
  • Added union type hints to bubble_sort_content signature
  • Updated cast for project_name return annotation
  • +6/-6     

    Need help?
  • Type /help how to ... in the comments thread for any questions about PR-Agent usage.
  • Check out the documentation for more information.
  • @aseembits93 aseembits93 changed the title Adding type hints to the dummy code for verify-setup Adding type hints to the dummy code for verify-setup (CF-647) May 20, 2025
    @github-actions
    Copy link

    PR Reviewer Guide 🔍

    Here are some key observations to aid the review process:

    ⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
    🧪 No relevant tests
    🔒 No security concerns identified
    ⚡ Recommended focus areas for review

    Incorrect cast usage

    The use of string literals in cast calls (e.g., cast("str", ...)) passes a string instead of a type object, which will raise a TypeError at runtime. cast expects actual type objects, not string names.

        tests_root = Path(curdir) / Path(cast("str", tests_root_answer))
    tests_root = tests_root.relative_to(curdir)
    ph("cli-tests-root-provided")
    
    # Autodiscover test framework
    autodetected_test_framework = detect_test_framework(curdir, tests_root)
    autodetected_suffix = (
        f" (seems to me you're using {autodetected_test_framework})" if autodetected_test_framework else ""
    )
    test_framework = inquirer_wrapper(
        inquirer.list_input,
        message="Which test framework do you use?" + autodetected_suffix,
        choices=["pytest", "unittest"],
        default=autodetected_test_framework or "pytest",
        carousel=True,
    )
    
    ph("cli-test-framework-provided", {"test_framework": test_framework})
    
    # Get benchmarks root directory
    default_benchmarks_subdir = "benchmarks"
    create_benchmarks_option = f"okay, create a {default_benchmarks_subdir}{os.path.sep} directory for me!"
    no_benchmarks_option = "I don't need benchmarks"
    
    # Check if benchmarks directory exists inside tests directory
    tests_subdirs = []
    if tests_root.exists():
        tests_subdirs = [d.name for d in tests_root.iterdir() if d.is_dir() and not d.name.startswith(".")]
    
    benchmarks_options = []
    benchmarks_options.append(no_benchmarks_option)
    if default_benchmarks_subdir in tests_subdirs:
        benchmarks_options.append(default_benchmarks_subdir)
    benchmarks_options.extend([d for d in tests_subdirs if d != default_benchmarks_subdir and d not in ignore_subdirs])
    benchmarks_options.append(create_benchmarks_option)
    benchmarks_options.append(custom_dir_option)
    
    benchmarks_answer = inquirer_wrapper(
        inquirer.list_input,
        message="Where are your performance benchmarks located? (benchmarks must be a sub directory of your tests root directory)",
        choices=benchmarks_options,
        default=(
            default_benchmarks_subdir if default_benchmarks_subdir in benchmarks_options else benchmarks_options[0]
        ),
    )
    
    if benchmarks_answer == create_benchmarks_option:
        benchmarks_root = tests_root / default_benchmarks_subdir
        benchmarks_root.mkdir(exist_ok=True)
        click.echo(f"✅ Created directory {benchmarks_root}{os.path.sep}{LF}")
    elif benchmarks_answer == custom_dir_option:
        custom_benchmarks_answer = inquirer_wrapper_path(
            "path",
            message=f"Enter the path to your benchmarks directory inside {tests_root}{os.path.sep} ",
            path_type=inquirer.Path.DIRECTORY,
        )
        if custom_benchmarks_answer:
            benchmarks_root = tests_root / Path(custom_benchmarks_answer["path"])
        else:
            apologize_and_exit()
    elif benchmarks_answer == no_benchmarks_option:
        benchmarks_root = None
    else:
        benchmarks_root = tests_root / Path(cast("str", benchmarks_answer))
    
    # TODO: Implement other benchmark framework options
    # if benchmarks_root:
    #     benchmarks_root = benchmarks_root.relative_to(curdir)
    #
    #     # Ask about benchmark framework
    #     benchmark_framework_options = ["pytest-benchmark", "asv (Airspeed Velocity)", "custom/other"]
    #     benchmark_framework = inquirer_wrapper(
    #         inquirer.list_input,
    #         message="Which benchmark framework do you use?",
    #         choices=benchmark_framework_options,
    #         default=benchmark_framework_options[0],
    #         carousel=True,
    #     )
    
    formatter = inquirer_wrapper(
        inquirer.list_input,
        message="Which code formatter do you use?",
        choices=["black", "ruff", "other", "don't use a formatter"],
        default="black",
        carousel=True,
    )
    
    git_remote = ""
    try:
        repo = Repo(str(module_root), search_parent_directories=True)
        git_remotes = get_git_remotes(repo)
        if git_remotes:  # Only proceed if there are remotes
            if len(git_remotes) > 1:
                git_remote = inquirer_wrapper(
                    inquirer.list_input,
                    message="What git remote do you want Codeflash to use for new Pull Requests? ",
                    choices=git_remotes,
                    default="origin",
                    carousel=True,
                )
            else:
                git_remote = git_remotes[0]
        else:
            click.echo(
                "No git remotes found. You can still use Codeflash locally, but you'll need to set up a remote "
                "repository to use GitHub features."
            )
    except InvalidGitRepositoryError:
        git_remote = ""
    
    ignore_paths: list[str] = []
    return SetupInfo(
        module_root=str(module_root),
        tests_root=str(tests_root),
        benchmarks_root=str(benchmarks_root) if benchmarks_root else None,
        test_framework=cast("str", test_framework),
        ignore_paths=ignore_paths,
        formatter=cast("str", formatter),
        git_remote=str(git_remote),
    Annotation compatibility

    The union type syntax list[int] | list[float] in the generated bubble_sort_content requires Python 3.10+. Verify that generated code targets a compatible Python version or adjust annotations for older versions.

    bubble_sort_content = """def sorter(arr: list[int] | list[float]) -> list[int] | list[float]:
    for i in range(len(arr)):

    @github-actions
    Copy link

    PR Code Suggestions ✨

    Explore these optional code suggestions:

    CategorySuggestion                                                                                                                                    Impact
    Possible issue
    Fix misuse of cast for tests_root

    The first argument to cast should be a type, not a string literal. Replace the
    quoted "str" with the actual str type to restore correct runtime behavior.

    codeflash/cli_cmds/cmd_init.py [242]

    -tests_root = Path(curdir) / Path(cast("str", tests_root_answer))
    +tests_root = Path(curdir) / Path(cast(str, tests_root_answer))
    Suggestion importance[1-10]: 6

    __

    Why: The cast call uses a string literal instead of the str type, which breaks static type checking; changing it to cast(str, ...) restores correct type hints.

    Low
    Correct cast usage for benchmarks

    cast expects a type object, not a string. Change "str" to str to correctly hint the
    type for benchmarks_answer.

    codeflash/cli_cmds/cmd_init.py [305]

    -benchmarks_root = tests_root / Path(cast("str", benchmarks_answer))
    +benchmarks_root = tests_root / Path(cast(str, benchmarks_answer))
    Suggestion importance[1-10]: 6

    __

    Why: Similar to the first change, cast("str", ...) should use the actual str type to satisfy static analysis without altering runtime behavior.

    Low
    Replace string literal in cast calls

    Both cast calls use a string instead of the str type. Update them to pass the actual
    type so static checks and runtime casts work properly.

    codeflash/cli_cmds/cmd_init.py [357-359]

    -test_framework=cast("str", test_framework),
    -formatter=cast("str", formatter),
    +test_framework=cast(str, test_framework),
    +formatter=cast(str, formatter),
    Suggestion importance[1-10]: 6

    __

    Why: Both test_framework and formatter casts use "str" instead of str, which is incorrect for type hinting; updating them ensures proper static type checking.

    Low
    Fix cast on project_name

    Change the quoted "str" to the str type in cast to ensure the return value is
    correctly interpreted.

    codeflash/cli_cmds/cmd_init.py [469]

    -return cast("str", project_name)
    +return cast(str, project_name)
    Suggestion importance[1-10]: 6

    __

    Why: The return value cast uses a string literal "str" rather than the str type, so replacing it corrects the type hint without impacting runtime.

    Low

    @aseembits93 aseembits93 enabled auto-merge May 20, 2025 20:35
    @aseembits93 aseembits93 merged commit 309ec58 into main May 20, 2025
    15 checks passed
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Projects

    None yet

    Development

    Successfully merging this pull request may close these issues.

    3 participants