Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plan: add typing #2235

Merged
merged 9 commits into from
Dec 17, 2024
Merged

Plan: add typing #2235

merged 9 commits into from
Dec 17, 2024

Conversation

myakove
Copy link
Collaborator

@myakove myakove commented Dec 16, 2024

Summary by CodeRabbit

  • New Features

    • Enhanced type hints for parameters in the Plan class constructor, improving clarity on expected input types.
    • Introduced hooks_array attribute to store hook specifications.
    • Added a new entry to .gitignore for ignoring the .local_dev/ directory.
  • Bug Fixes

    • Updated logic for adding hooks to virtual machines to ensure both hooks_array and virtual_machines_list are present before proceeding.
  • Changes

    • Modified return types of the __enter__ and deploy methods in the Resource class to Any, broadening expected return values.

Copy link

coderabbitai bot commented Dec 16, 2024

Walkthrough

The pull request introduces type annotations and structural modifications to the Plan class in the ocp_resources/plan.py file, enhancing type safety and clarity for method signatures, particularly in the constructor and the hook specification generation method. Additionally, the .gitignore file is updated to ignore the .local_dev/ directory, and the Resource class in ocp_resources/resource.py has its method return types changed to Any. The core functionalities remain consistent across all changes.

Changes

File Change Summary
ocp_resources/plan.py - Updated __init__ method with type hints for all parameters
- Added hooks_array attribute initialization
- Modified generate_hook_spec method with type hints
- Updated hook specification logic to ensure presence of hooks and virtual machines list
.gitignore - Added entry to ignore the .local_dev/ directory
ocp_resources/resource.py - Updated __enter__ and deploy methods to return Any instead of Resource
- Minor formatting and comment adjustments made

Possibly related issues

Suggested labels

size/XL, can-be-merged, approved-rnetser

Suggested reviewers

  • dbasunag
  • rnetser

📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 57a82c1 and 5e90de0.

📒 Files selected for processing (1)
  • ocp_resources/plan.py (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • ocp_resources/plan.py

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@redhat-qe-bot1
Copy link

Report bugs in Issues

The following are automatically added:

  • Add reviewers from OWNER file (in the root of the repository) under reviewers section.
  • Set PR size label.
  • New issue is created for the PR. (Closed when PR is merged/closed)
  • Run pre-commit if .pre-commit-config.yaml exists in the repo.

Available user actions:

  • To mark PR as WIP comment /wip to the PR, To remove it from the PR comment /wip cancel to the PR.
  • To block merging of PR comment /hold, To un-block merging of PR comment /hold cancel.
  • To mark PR as verified comment /verified to the PR, to un-verify comment /verified cancel to the PR.
    verified label removed on each new commit push.
  • To cherry pick a merged PR comment /cherry-pick <target branch to cherry-pick to> in the PR.
    • Multiple target branches can be cherry-picked, separated by spaces. (/cherry-pick branch1 branch2)
    • Cherry-pick will be started when PR is merged
  • To build and push container image command /build-and-push-container in the PR (tag will be the PR number).
    • You can add extra args to the Podman build command
      • Example: /build-and-push-container --build-arg OPENSHIFT_PYTHON_WRAPPER_COMMIT=<commit_hash>
  • To add a label by comment use /<label name>, to remove, use /<label name> cancel
  • To assign reviewers based on OWNERS file use /assign-reviewers
  • To check if PR can be merged use /check-can-merge
Supported /retest check runs
  • /retest tox: Retest tox
  • /retest python-module-install: Retest python-module-install
  • /retest all: Retest all
Supported labels
  • hold
  • verified
  • wip
  • lgtm

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🔭 Outside diff range comments (1)
ocp_resources/plan.py (1)

Type hints need improvement in to_dict method

The type hints are mostly complete and well-structured, but there are two specific issues:

  • The to_dict method is incorrectly typed as -> None when it should return a dictionary
  • The virtual_machines_list could use a more specific type than list[Any] since we know its structure from the docstring

Specific locations:

  • to_dict(self) -> None should be to_dict(self) -> dict[str, Any]
  • virtual_machines_list: list[Any] could be improved to list[dict[str, str]] based on the example [{"id": "vm-id-x"}, {"name": "vm-name-x"}]
🔗 Analysis chain

Line range hint 1-96: Verify typing coverage is complete

While the current type additions are good, let's verify we haven't missed any opportunities for typing.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for any remaining untyped function definitions or variables
rg "def [^(]+\([^:]+\)" ocp_resources/plan.py
# Check for any Any types that could be more specific
rg "Any" ocp_resources/plan.py
# Check for consistency in type hints
rg "-> None" ocp_resources/plan.py

Length of output: 770


Script:

#!/bin/bash
# Let's get more context around the function definitions and their return types
rg -A 2 "def " ocp_resources/plan.py

# Check for variable annotations
rg ":.+" ocp_resources/plan.py

# Get the full class definition to see all methods
ast-grep --pattern 'class Plan {
  $$$
}'

Length of output: 3234

🧹 Nitpick comments (3)
ocp_resources/plan.py (3)

29-45: Consider using a more specific type for virtual_machines_list

While the type hints are generally well-implemented, the list[Any] for virtual_machines_list could be more specific. The docstring indicates it should be a list of dicts with specific keys.

Consider using TypedDict to better type the VM entries:

from typing import TypedDict, Union

class VMEntry(TypedDict, total=False):
    id: str
    name: str
    hooks: list[dict[str, Any]]

# Then in __init__:
    virtual_machines_list: list[VMEntry] | None = None

Line range hint 64-74: Consider moving generate_hook_spec outside init

While the type hints are good, having generate_hook_spec nested inside __init__ reduces maintainability and testability. Consider making it a private class method.

@classmethod
def _generate_hook_spec(cls, hook_name: str, hook_namespace: str, hook_type: str) -> dict[str, Any]:
    return {
        "hook": {
            "name": hook_name,
            "namespace": hook_namespace,
        },
        "step": hook_type,
    }

94-96: Consider adding runtime type validation for VM entries

While the type hints help with static analysis, consider adding runtime validation for the VM dictionary structure before applying hooks.

def _validate_vm_entry(vm: dict) -> None:
    if not isinstance(vm, dict):
        raise TypeError("VM entry must be a dictionary")
    if not any(key in vm for key in ('id', 'name')):
        raise ValueError("VM entry must contain either 'id' or 'name'")

# Then in the loop:
for vm in self.virtual_machines_list:
    _validate_vm_entry(vm)
    vm["hooks"] = self.hooks_array
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dd9c016 and beccce1.

📒 Files selected for processing (1)
  • ocp_resources/plan.py (5 hunks)
🔇 Additional comments (1)
ocp_resources/plan.py (1)

1-1: LGTM: Appropriate typing import added

The Any type import is correctly added to support the new type hints in the code.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between beccce1 and b3fc1a5.

📒 Files selected for processing (2)
  • .gitignore (1 hunks)
  • ocp_resources/resource.py (4 hunks)
✅ Files skipped from review due to trivial changes (1)
  • .gitignore
🔇 Additional comments (1)
ocp_resources/resource.py (1)

Line range hint 617-635: Verify the impact of type changes

The type changes from "Resource" to Any in both __enter__ and deploy methods could affect code that depends on these methods. Let's verify the impact.

✅ Verification successful

Based on the search results, I can now generate the final response:

Type changes appear to be safe

The type changes from "Resource" to Any in both __enter__ and deploy methods are safe because:

  1. No explicit return type annotations were found in the codebase for these methods
  2. The actual usage patterns show these methods are used in simple deployment scenarios:
    • Basic deployment calls: ns.deploy()
    • Context manager usage that relies on the deploy result
  3. The return value is only used for assertions or stored in variables without type constraints

The change to Any actually makes the type more permissive and won't break existing code, as it allows for any return type from these methods.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find usages of these methods to assess the impact of type changes

# Search for method calls
echo "Searching for __enter__ method calls..."
rg -p ".__enter__\(\)" --type python

echo "Searching for deploy method calls..."
rg -p "\.deploy\(" --type python

# Search for type hints using Resource
echo "Searching for type hints using Resource..."
rg -p "-> .*Resource.*" --type python

Length of output: 847


Script:

#!/bin/bash
# Let's try a different approach without file type filtering

# Search for method calls
echo "Searching for __enter__ method calls..."
rg ".__enter__\(\)"

echo "Searching for deploy method calls..."
rg "\.deploy\("

# Search for type hints using Resource
echo "Searching for type hints using Resource..."
rg "-> .*Resource"

# Let's also look for imports and class inheritance
echo "Searching for Resource imports and inheritance..."
rg "from.*Resource|class.*\(.*Resource.*\)"

Length of output: 69173


Script:

#!/bin/bash
# Let's search for type annotations and return types in Python files
echo "Searching for return type annotations..."
rg -p "def (deploy|__enter__).* -> " --type-list=py

# Let's also look for direct usage of these methods
echo "Searching for method calls with context..."
rg -p "with.*\.__enter__" -A 2
rg -p "\.deploy\(" -A 2

Length of output: 1173

ocp_resources/resource.py Outdated Show resolved Hide resolved
ocp_resources/resource.py Show resolved Hide resolved
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
ocp_resources/plan.py (1)

29-45: Consider using a more specific type for virtual_machines_list

While the type hints are well-implemented, the list[Any] for virtual_machines_list could be more specific to better document the expected structure.

Consider creating a TypedDict for VM entries:

from typing import TypedDict

class VirtualMachine(TypedDict, total=False):
    id: str
    name: str
    hooks: list[dict[str, Any]]

Then update the parameter type:

-        virtual_machines_list: list[Any] | None = None,
+        virtual_machines_list: list[VirtualMachine] | None = None,
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b3fc1a5 and 8f9323e.

📒 Files selected for processing (2)
  • ocp_resources/plan.py (4 hunks)
  • ocp_resources/resource.py (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • ocp_resources/resource.py
🔇 Additional comments (3)
ocp_resources/plan.py (3)

1-1: LGTM: Appropriate typing import added

The addition of typing.Any import is necessary for the type hints being introduced.


119-127: LGTM: Well-structured hook specification generator

The _generate_hook_spec method is well-implemented with appropriate type hints and a clear, focused responsibility.


64-86: Consider edge case handling in hook assignment

The hook assignment logic looks good, but there's a potential edge case to verify.

The current implementation assumes that virtual_machines_list items are dictionaries that can accept a 'hooks' key. Let's verify this assumption across the codebase:

✅ Verification successful

Edge case handling in hook assignment is safe

The code is safe regarding the edge case concern. The docstring and type hints clearly document that virtual_machines_list is expected to be a list of dictionaries with a specific structure:

"""virtual_machines_list (list): A List of dicts, each contain
                              the Name Or Id of the source Virtual Machines to migrate.
                              Example: [ { "id": "vm-id-x" }, { "name": "vm-name-x" } ]"""

The implementation correctly:

  1. Checks for both hooks_array and virtual_machines_list being truthy before assignment
  2. Uses the documented dictionary structure, which is later serialized in to_dict() method under the "vms" key
  3. Follows the example format where each VM entry is already a dictionary
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for virtual_machines_list usage to verify the structure
rg -A 5 "virtual_machines_list" --type python

Length of output: 76


Script:

#!/bin/bash
# Search for virtual_machines_list usage without file type restriction
rg -A 5 "virtual_machines_list"

Length of output: 2213


Script:

#!/bin/bash
# Search for the class/file where virtual_machines_list is defined
ast-grep --pattern 'class $_ {
  $$$
  virtual_machines_list = $$$
  $$$
}'

Length of output: 77


Script:

#!/bin/bash
# Look for dictionary operations on virtual_machines_list items
rg "virtual_machines_list.*\[.*\].*\[.*\]|virtual_machines_list.*\[.*\].*\."

Length of output: 78

ocp_resources/plan.py Show resolved Hide resolved
ocp_resources/plan.py Outdated Show resolved Hide resolved
@myakove
Copy link
Collaborator Author

myakove commented Dec 16, 2024

/verified

@myakove
Copy link
Collaborator Author

myakove commented Dec 17, 2024

/verified

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
ocp_resources/plan.py (3)

Line range hint 7-22: Update docstring to reflect optional parameters

The docstring should indicate which parameters are optional since all parameters have None as default value.

Consider updating the parameter descriptions to include "(optional)" for each optional parameter, for example:

-        source_provider_name (str): MTV Source Provider CR name.
+        source_provider_name (str, optional): MTV Source Provider CR name.

64-64: Consider a more descriptive name for hooks_array

The variable name hooks_array could be more descriptive of its purpose.

Consider renaming to hook_specifications or vm_hooks to better reflect its content and usage.


84-86: Optimize hook application logic

The current implementation modifies each VM dictionary individually, which could be inefficient for large lists.

Consider setting hooks once in the VM template:

-        if self.hooks_array and self.virtual_machines_list:
-            for vm in self.virtual_machines_list:
-                vm["hooks"] = self.hooks_array
+        if self.hooks_array and self.virtual_machines_list:
+            vm_template = {"hooks": self.hooks_array}
+            self.virtual_machines_list = [
+                {**vm, **vm_template} for vm in self.virtual_machines_list
+            ]
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8f9323e and 57a82c1.

📒 Files selected for processing (1)
  • ocp_resources/plan.py (4 hunks)
🔇 Additional comments (3)
ocp_resources/plan.py (3)

1-1: LGTM: Import changes are appropriate

The addition of typing.Any import is necessary for the new type hints being introduced.


29-45: LGTM: Type hints are well-structured

The type hints follow modern Python typing practices:

  • Appropriate use of union types with None for optional parameters
  • Correct typing for heterogeneous list with Any
  • Proper return type annotation for the constructor

119-126: Consider using consistent dictionary format

As mentioned in the previous review, consider using the same format as the class generator for consistency.

The current implementation is functionally correct, but for consistency with the rest of the codebase, consider:

-    def _generate_hook_spec(self, hook_name: str, hook_namespace: str, hook_type: str) -> dict[str, Any]:
-        return {
-            "hook": {
-                "name": hook_name,
-                "namespace": hook_namespace,
-            },
-            "step": hook_type,
-        }
+    def _generate_hook_spec(self, hook_name: str, hook_namespace: str, hook_type: str) -> dict[str, Any]:
+        return {
+            "hook": {
+                "name": hook_name,
+                "namespace": hook_namespace,
+            },
+            "step": hook_type,
+        }

@myakove
Copy link
Collaborator Author

myakove commented Dec 17, 2024

/verified

@rnetser rnetser enabled auto-merge (squash) December 17, 2024 09:01
@rnetser rnetser merged commit 6bcfcbd into main Dec 17, 2024
6 checks passed
@rnetser rnetser deleted the Plan-add-typing branch December 17, 2024 09:29
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.

6 participants