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

use result #191

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

use result #191

wants to merge 2 commits into from

Conversation

expobrain
Copy link
Owner

@expobrain expobrain commented Oct 12, 2024

Summary by CodeRabbit

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a new dependency, result, enhancing error handling across multiple components.
    • Updated various methods to return structured results, allowing for better error management.
  • Bug Fixes

    • Improved error handling in decision-making processes and schema transformations, ensuring clearer outcomes.
  • Tests

    • Updated test assertions to validate results wrapped in Ok and Err objects, enhancing clarity and robustness of test cases.
    • Streamlined test logic by verifying success before accessing result data and improved error handling in tests.

@expobrain expobrain marked this pull request as ready for review October 12, 2024 22:54
Copy link

coderabbitai bot commented Oct 12, 2024

Walkthrough

The pull request introduces significant changes across multiple files, primarily focusing on enhancing error handling and result management through the introduction of a new dependency, result. Key modifications include updates to method return types, allowing structured results to encapsulate success and error states. The pyproject.toml file has been updated to include the new dependency, while various classes and methods have been refactored to utilize this result-handling pattern. Additionally, test cases have been adjusted to reflect these changes, ensuring that assertions align with the new result structures.

Changes

File Change Summary
pyproject.toml Added dependency: result = "^0.17.0" in [tool.poetry.dependencies].
sqlalchemy_to_json_schema/command/driver.py Updated method signatures in Driver class to return Result types instead of plain types. Enhanced error handling in run method.
sqlalchemy_to_json_schema/command/transformer.py Updated transform methods in multiple transformer classes to return Result[Schema, str] instead of Schema. Enhanced error handling.
sqlalchemy_to_json_schema/decisions.py Changed return types of decision methods in decision classes to Iterator[Result[DecisionResult, MapperProperty]].
sqlalchemy_to_json_schema/schema_factory.py Updated type annotations, error handling, and method signatures to utilize Result types.
tests/command/test_transformer.py Updated assertions to check against Ok objects instead of plain dictionaries.
tests/regression/test_generate_schema_with_type_decorator.py Changed return type of _callFUT function to Result[Schema, str] and updated assertions.
tests/test_it.py Added .unwrap() method to schema generation calls in multiple tests.
tests/test_it_reflection.py Updated assertions to compare against Ok(expected) instead of expected.
tests/test_relation.py Modified assertions to check for success using is_ok and updated comparison methods.
tests/test_schema_factory.py Updated assertions to compare against Ok objects in multiple test methods.
tests/test_walker.py Enhanced result handling in assertions, checking for success before accessing properties.

Poem

🐇 In the garden of code, a new path we tread,
With result in hand, no more worries or dread.
Errors now wrapped in a cozy embrace,
Our tests dance with joy, in this structured space.
So hop along, friends, let’s celebrate bright,
For our code is now clearer, and everything's right! 🌼


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 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.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

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.

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: 7

🧹 Outside diff range and nitpick comments (24)
sqlalchemy_to_json_schema/command/main.py (2)

7-7: Approved: Direct import of Driver class.

The change to directly import the Driver class simplifies the code and aligns with the new implementation in the main function. However, note that this reduces the flexibility of loading different drivers at runtime. Ensure this change aligns with the project's requirements for extensibility.


Line range hint 1-52: Summary of changes and potential impact

The changes in this file align with the PR objectives of code simplification and optimization. Key improvements include:

  1. Enhanced type safety with the use of Final for constants.
  2. Simplified driver instantiation, removing dynamic loading.
  3. Streamlined main function signature.

These changes generally improve code clarity and maintainability. However, they also reduce some flexibility (e.g., in driver loading) which may impact extensibility.

Points to consider:

  1. Verify that removing the ability to load different drivers aligns with project requirements.
  2. Ensure the removal of the depth parameter doesn't break any existing functionality.
  3. The adoption of using results instead of exceptions (mentioned in PR objectives) is not directly visible in this file. Ensure this change is implemented consistently across the codebase.
tests/test_it_reflection.py (1)

Line range hint 1-70: Overall impact: Improved result handling in tests.

The changes in this file successfully implement the new result handling pattern using the Ok type from the result module. This approach enhances error handling and aligns the tests with the modifications in the main code. The core expectations about the schema structure remain intact, ensuring that existing functionality is still properly tested.

To further improve the tests:

  1. Consider adding test cases that specifically check for error conditions, using the counterpart to Ok (likely an Err type) to ensure comprehensive coverage of the new result handling pattern.
  2. Update the docstrings or comments in the test functions to reflect the new result-based assertions, which would help maintain clear documentation of the test strategy.

Would you like assistance in implementing these suggestions or creating additional test cases to cover error scenarios?

tests/test_it.py (2)

45-45: Approve change and suggest fixing typo in function name

The addition of .unwrap() is correct and aligns with the PR objectives of using results instead of exceptions. This change improves error handling and result management.

Consider fixing the typo in the function name:

-def test_it_create_schema__and__valid_params__sucess() -> None:
+def test_it_create_schema__and__valid_params__success() -> None:

Line range hint 45-70: Summary of changes and suggestions for improvement

The changes in this file consistently add .unwrap() to all schema generation calls, which aligns with the PR objectives of improving error handling and result management. This systematic update enhances the codebase's consistency in handling results.

Consider creating a separate issue to address the following pre-existing typos, as they may affect test reliability:

  1. Function name typo: "sucess" instead of "success" in test_it_create_schema__and__valid_params__sucess.
  2. Parameter typo: "uesrs.pk" instead of "users.pk" in the excludes list of test_it_create_schema__and__invalid_params__failure.

Fixing these typos will improve the overall quality and reliability of the test suite.

tests/regression/test_generate_schema_with_type_decorator.py (1)

68-70: LGTM: Test case updated to handle Result type, but consider consistency.

The changes in the test_it__impl_is_not_callable function correctly adapt the test case to the new result-based approach. The use of is_ok to check for a successful result before accessing its value is appropriate.

However, note that this test uses unwrap() to access the result value, while the previous test used value. For consistency, consider using the same method in both tests, preferably unwrap() as it's more explicit about error handling.

tests/command/test_main.py (2)

24-24: LGTM: Function signature simplified correctly

The removal of the mock_load_module_or_symbol parameter from the function signature is consistent with the PR objectives and the removal of the corresponding fixture. This change simplifies the test function without affecting its functionality.

Consider updating the function's docstring to reflect the removal of the mock_load_module_or_symbol parameter, ensuring that the documentation remains in sync with the code changes.


Line range hint 1-93: Overall assessment: Changes improve test simplicity and maintainability

The modifications in this file successfully simplify the test code by removing the mock_load_module_or_symbol fixture and updating the test function signatures accordingly. These changes align well with the PR objectives of code simplification and removal of the ability to load different drivers.

The updates maintain the functionality of the tests while reducing complexity, which should improve maintainability. The changes are consistent throughout the file and don't introduce any apparent issues.

Consider reviewing other test files in the project to ensure consistent application of these simplifications, if applicable. This will help maintain a uniform testing approach across the codebase.

tests/test_walker.py (4)

52-54: LGTM: Improved result handling and order-independent assertion

The changes in this test function effectively implement the new result-handling pattern and introduce order-independent assertion for property keys. This aligns well with the PR objectives and improves the robustness of the test.

Consider using set instead of list for a more concise representation:

assert set(result.unwrap()["properties"].keys()) == set(["color", "name", "pk"])

This achieves the same order-independent comparison without the need for the unordered function.


79-80: LGTM: Consistent implementation of result handling

The changes in this test function correctly implement the new result-handling pattern, maintaining consistency with other test functions.

Consider renaming the test function to something more descriptive and following Python naming conventions. For example:

def test_properties_contain_all_expected_fields():

This name more clearly describes the purpose of the test and follows the snake_case convention for Python function names.


97-99: LGTM: Improved result handling and order-independent assertions

The changes in these test functions effectively implement the new result-handling pattern and introduce order-independent assertions for property keys. This aligns well with the PR objectives and improves the robustness of the tests.

Consider using set instead of list for a more concise representation in both functions:

assert set(result.unwrap()["properties"].keys()) == {"pk"}

and

assert set(result.unwrap()["properties"].keys()) == {"color", "name"}

This achieves the same order-independent comparison without the need for the unordered function and is more idiomatic Python.

Also applies to: 105-107


142-145: LGTM: Improved error handling using Result pattern

The changes in this test function effectively implement the new result-handling pattern for error cases. Instead of expecting an exception, the test now checks for an Err result, which aligns well with the PR objectives of using results instead of exceptions.

Consider using a more specific error message assertion:

expected_error = f"invalid overrides: {set(overrides.keys())}"
assert actual == Err(expected_error)

This approach makes the expected error message more explicit and easier to update if needed.

tests/test_relation.py (2)

60-62: LGTM: Improved test robustness and flexibility.

The changes enhance the test by:

  1. Using is_ok to ensure the result is successful before accessing its value.
  2. Using unordered for a more flexible comparison of property keys.

These modifications improve the test's reliability and reduce its sensitivity to the order of properties.

Consider adding an assertion for the required field, similar to other tests in this file:

assert "required" in result.value

Line range hint 1-237: Overall improvements in test suite robustness and flexibility

The changes made to tests/test_relation.py consistently enhance the test suite's reliability and maintainability:

  1. Introduction of is_ok checks ensures proper error handling and result validation.
  2. Use of unordered comparisons allows for more flexible assertions, reducing test brittleness.
  3. Updated assertions reflect changes in the schema generation logic, particularly in areas such as nested relationships and handling of potential infinite loops.

These modifications align well with the PR objectives of code simplification and optimization. They contribute to a more robust test suite that is less prone to false negatives due to ordering issues or minor schema changes.

Consider adding a helper function to encapsulate the common pattern of checking is_ok(result) and accessing result.value. This could further reduce code duplication and improve readability across the test suite.

tests/command/test_transformer.py (1)

Line range hint 88-114: Consider updating collect_models for consistency.

While the changes to use the Result type are appropriately applied to the transformer tests, the collect_models function and its tests remain unchanged. For consistency across the codebase, it might be worth considering whether collect_models should also return a Result type (e.g., Ok(list_of_models) or Err(error_message)). This would align all parts of the code with the new error-handling approach.

Would you like me to propose a specific implementation for updating collect_models to use the Result type?

tests/test_schema_factory.py (6)

130-140: LGTM: Assertion updated to use Ok wrapper.

The change to wrap the expected result in Ok is consistent with the new approach of using a Result type. This modification enhances the test by explicitly checking for a successful outcome.

Consider extracting the expected result into a separate variable before the assertion. This can improve readability, especially for larger dictionaries:

expected_result = {
    "properties": {
        "pk": {"type": "integer"},
        "concatenable": {"type": "array", "items": {"type": expected_type}},
    },
    "required": ["pk"],
    "title": "Model",
    "type": "object",
}
assert actual == Ok(expected_result)

153-160: LGTM: Assertion updated to use Ok wrapper.

The change to wrap the expected result in Ok is consistent with the new approach of using a Result type. This modification enhances the test by explicitly checking for a successful outcome.

As suggested earlier, consider extracting the expected result into a separate variable before the assertion to improve readability:

expected_result = {
    "properties": {"id": {"type": "string", "format": "uuid"}},
    "required": ["id"],
    "title": "Model",
    "type": "object",
}
assert actual == Ok(expected_result)

174-184: LGTM: Assertion updated to use Ok wrapper.

The change to wrap the expected result in Ok is consistent with the new approach of using a Result type. This modification enhances the test by explicitly checking for a successful outcome.

As suggested earlier, consider extracting the expected result into a separate variable before the assertion to improve readability:

expected_result = {
    "properties": {
        "id": {"type": "integer"},
        "data": {"type": "object"},
    },
    "required": ["id"],
    "title": "Model",
    "type": "object",
}
assert actual == Ok(expected_result)

205-212: LGTM: Assertions updated to use Ok wrapper in multiple test methods.

The changes to wrap the expected results in Ok in both test_hybrid_property and test_hybrid_property_with_mixin methods are consistent with the new approach of using a Result type. These modifications enhance the tests by explicitly checking for successful outcomes.

As suggested earlier, consider extracting the expected results into separate variables before the assertions in both methods to improve readability:

# In test_hybrid_property
expected_result = {
    "properties": {"id": {"type": "integer"}},
    "required": ["id"],
    "title": "Model",
    "type": "object",
}
assert actual == Ok(expected_result)

# In test_hybrid_property_with_mixin
expected_result = {
    "properties": {"id": {"type": "integer"}},
    "required": ["id"],
    "title": "Model",
    "type": "object",
}
assert actual == Ok(expected_result)

Also applies to: 234-241


319-319: LGTM: Assertions updated to use Ok wrapper in remaining test methods.

The changes to wrap the expected results in Ok in both test_hybrid_property_with_relationship and test_column_custom_column methods are consistent with the new approach of using a Result type. These modifications enhance the tests by explicitly checking for successful outcomes.

For the test_column_custom_column method, consider extracting the expected result into a separate variable before the assertion to improve readability:

expected_result = {
    "properties": {"pk": {"type": expected_type}},
    "required": ["pk"],
    "title": "Model",
    "type": "object",
}
assert actual == Ok(expected_result)

Also applies to: 365-372


Line range hint 1-372: Overall LGTM: Consistent implementation of Result type in test assertions.

The changes made to this test file demonstrate a systematic approach to incorporating the Result type (Ok) in test assertions. This modification enhances the test suite by explicitly checking for successful outcomes and aligns with a larger refactoring effort to use the Result type throughout the codebase.

Key points:

  1. The Ok import has been added to support the new assertion style.
  2. All test methods have been updated consistently to use the Ok wrapper in their assertions.
  3. The actual content of the expected results remains unchanged, preserving the original test logic.

These changes improve error handling and make success/failure states more explicit in the tests. They also prepare the test suite for potential future enhancements, such as handling error cases with a corresponding Err type.

Consider the following to further improve the test suite:

  1. Update the docstrings of the test methods to reflect the new assertion style.
  2. If not already done, ensure that the main codebase (outside of tests) is also using this Result type consistently.
  3. Consider adding test cases that check for error conditions, using a corresponding Err type if available.
sqlalchemy_to_json_schema/schema_factory.py (2)

334-335: Clarify error message for unused overrides

When there are unused keys in overrides_manager.not_used_keys, consider enhancing the error message to provide more context. For example, specify which override keys are invalid or suggest valid keys. This will aid in debugging.


423-427: Improve error message for unsupported mapped properties

In _build_properties, when an unsupported mapped property is encountered, the error message could include more details about the property causing the issue. Providing the property name or type can help in troubleshooting.

sqlalchemy_to_json_schema/command/transformer.py (1)

85-86: Provide a more descriptive error message

The error message Err(f"Expected a class or module, got {target}") could include the type of target for clearer debugging.

Consider refining the error message:

-    return Err(f"Expected a class or module, got {target}")
+    return Err(f"Expected a class or module, got {type(target).__name__}: {target}")
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 78f2857 and 308c726.

⛔ Files ignored due to path filters (1)
  • poetry.lock is excluded by !**/*.lock
📒 Files selected for processing (14)
  • pyproject.toml (1 hunks)
  • sqlalchemy_to_json_schema/command/driver.py (4 hunks)
  • sqlalchemy_to_json_schema/command/main.py (2 hunks)
  • sqlalchemy_to_json_schema/command/transformer.py (6 hunks)
  • sqlalchemy_to_json_schema/decisions.py (4 hunks)
  • sqlalchemy_to_json_schema/schema_factory.py (13 hunks)
  • tests/command/test_main.py (1 hunks)
  • tests/command/test_transformer.py (5 hunks)
  • tests/regression/test_generate_schema_with_type_decorator.py (4 hunks)
  • tests/test_it.py (3 hunks)
  • tests/test_it_reflection.py (3 hunks)
  • tests/test_relation.py (4 hunks)
  • tests/test_schema_factory.py (8 hunks)
  • tests/test_walker.py (5 hunks)
🧰 Additional context used
🔇 Additional comments (47)
sqlalchemy_to_json_schema/command/main.py (2)

3-3: LGTM: Import of Final added.

The addition of Final from the typing module is appropriate for the subsequent use in constant declarations. This change enhances type hinting and code clarity.


10-12: LGTM: Constants declared as Final.

The addition of Final type hints to DEFAULT_WALKER, DEFAULT_DECISION, and DEFAULT_LAYOUT is a good practice. It ensures these values are immutable and improves type safety.

tests/test_it_reflection.py (3)

4-4: LGTM: Import of Ok from result module.

This import aligns with the PR objective of using results instead of exceptions. It introduces a more structured way of handling successful outcomes, which is a good practice for error handling and result management.


47-47: LGTM: Updated assertion to use Ok result type.

The modification to wrap the expected result in Ok() is consistent with the new result handling pattern. This change ensures that the test not only checks the correctness of the schema content but also verifies that it's properly encapsulated in a successful result type.


70-70: LGTM: Consistent use of Ok result type in assertions.

The change in test_it2 mirrors the modification in test_it, demonstrating consistent adoption of the new result handling pattern across test cases. This uniformity in approach is commendable and helps maintain clarity in the testing strategy.

tests/test_it.py (1)

70-70: Approve change

The addition of .unwrap() is correct and consistent with the changes in other functions. This change aligns with the PR objectives of using results instead of exceptions.

tests/regression/test_generate_schema_with_type_decorator.py (4)

5-5: LGTM: New import aligns with PR objectives.

The addition of Result and is_ok from the result library is consistent with the PR's goal of using results instead of exceptions for error handling.


15-15: LGTM: Function signature updated to use Result type.

The change in the _callFUT function signature from returning Schema to Result[Schema, str] is a good implementation of the result-based error handling approach. This allows for more structured and explicit error management.


19-21: LGTM: Internal changes in _callFUT align with new signature.

The changes within the _callFUT function, including the variable rename to schema_result and the direct return of this result, are consistent with the new function signature. These modifications improve code clarity and maintain the new error handling approach.


52-54: LGTM: Test case updated to handle Result type.

The changes in the test_it function appropriately adapt the test case to the new result-based approach. The use of is_ok to check for a successful result before accessing its value ensures that the test correctly handles the new Result type. The added blank line improves readability.

tests/command/test_main.py (2)

20-20: LGTM: Mock driver path updated correctly

The change to mock "sqlalchemy_to_json_schema.command.main.Driver" directly aligns with the PR objectives of simplifying the code and removing the ability to load a different driver. This modification is consistent with the removal of the mock_load_module_or_symbol fixture and maintains the test's functionality while reducing complexity.


Line range hint 52-60: LGTM: Function signature simplified correctly

The removal of the mock_load_module_or_symbol parameter from the function signature is consistent with the PR objectives and the removal of the corresponding fixture. This change simplifies the test function without affecting its functionality, aligning well with the overall goal of code simplification.

tests/test_walker.py (5)

4-5: LGTM: New imports align with PR objectives

The addition of unordered from pytest_unordered and Err, is_ok from result aligns well with the PR objectives. These imports support the transition to using results instead of exceptions and enable order-independent assertions in tests.


43-45: LGTM: Improved result handling in test_type__is_object

The changes in this test function effectively implement the new result-handling pattern. By first checking is_ok(result) and then using result.unwrap(), the test becomes more robust and aligns with the PR objectives of using results instead of exceptions.


61-63: LGTM: Consistent implementation of result handling

The changes in this test function consistently apply the new result-handling pattern. By first checking is_ok(result) and then using result.unwrap(), the test becomes more robust and maintains consistency with other test functions.


70-72: LGTM: Consistent implementation of result handling

The changes in this test function maintain consistency with the new result-handling pattern. The addition of is_ok(result) check and the use of result.unwrap() improve the robustness of the test and align with the changes in other test functions.


Line range hint 1-145: Overall assessment: Well-implemented result handling pattern

The changes in this file consistently implement the new result-handling pattern across all test functions. This aligns well with the PR objectives of using results instead of exceptions. The use of is_ok() checks and result.unwrap() improves the robustness of the tests.

Some minor improvements have been suggested:

  1. Using set instead of list with unordered for property key comparisons.
  2. Renaming the test_properties__all__this_is_slackoff_little_bit__all_is_all function to something more descriptive.
  3. Making the error message assertion more explicit in the test__overrides__wrong_column function.

These suggestions, if implemented, would further enhance the code quality and readability.

tests/test_relation.py (8)

8-9: LGTM: New imports enhance test functionality.

The addition of unordered from pytest_unordered and is_ok from result aligns well with the changes made in the test functions. These imports support more flexible assertions and improved error handling.


69-72: LGTM: Enhanced test reliability and flexibility.

The modifications improve the test by:

  1. Using is_ok to verify the result's success before accessing its value.
  2. Employing unordered for a more flexible comparison of property keys.

These changes align well with the improvements made in other test functions and contribute to more robust and maintainable tests.


79-82: LGTM: Consistent improvement in test robustness.

The changes in this test function maintain consistency with the improvements made in previous tests:

  1. Utilizing is_ok to ensure the result's success before accessing its value.
  2. Applying unordered for a more flexible comparison of property keys.

These modifications contribute to a more reliable and maintainable test suite.


172-175: LGTM: Consistent improvements in test reliability.

The modifications in this test function align with the enhancements made in previous tests:

  1. Using is_ok to verify the result's success.
  2. Applying unordered for flexible property key comparison.

These changes contribute to a more robust and maintainable test suite.


183-187: LGTM: Consistent enhancements in test robustness.

The changes in this test function maintain consistency with the improvements made in previous tests:

  1. Utilizing is_ok to ensure the result's success before accessing its value.
  2. Applying unordered for a more flexible comparison of property keys.

These modifications contribute to a more reliable and maintainable test suite.


157-164: LGTM: Consistent improvements and updated nested assertions.

The changes in this test function maintain consistency with previous improvements:

  1. Utilizing is_ok to ensure the result's success.
  2. Applying unordered for flexible property key comparison.

The updated assertions for nested children reflect changes in the schema generation logic.

Please verify that the changes in the nested children assertions accurately reflect the intended modifications in the schema generation logic. Run the following script to check the relevant models and schema generation code:

#!/bin/bash
# Description: Verify the nested model definitions and schema generation logic

# Test: Search for the A0 to A5 model definitions
rg --type python -A 10 'class A[0-5]\('

# Test: Search for the schema generation logic related to nested relationships
rg --type python -A 15 'def (get_schema|generate_schema).*depth'

89-96: LGTM: Consistent improvements and updated schema assertion.

The changes in this test function align with the improvements made in previous tests:

  1. Using is_ok to verify the result's success.
  2. Applying unordered for flexible property key comparison.

The updated assertion for the User definition reflects changes in the schema generation logic.

Please verify that the changes in the User definition assertion accurately reflect the intended modifications in the schema generation logic. Run the following script to check the User model definition and ensure it matches the expected output:


219-226: LGTM: Consistent improvements and updated assertions for infinite loop tests.

The changes in both test_properties__infinite_loop and test_properties__infinite_loop2 align with the enhancements made in previous tests:

  1. Using is_ok to verify the result's success.
  2. Applying unordered for flexible property key comparison.

The updated assertions reflect changes in the schema generation logic, particularly in handling potential infinite loops in relationships.

Please verify that the changes in the assertions for both infinite loop tests accurately reflect the intended modifications in the schema generation logic. Run the following script to check the relevant models and schema generation code:

Also applies to: 234-237

tests/command/test_transformer.py (4)

7-7: LGTM: New import aligns with PR objectives.

The addition of from result import Ok is consistent with the PR's goal of using results instead of exceptions. This import introduces the Ok class, which is typically used in Result types to represent successful outcomes.


37-51: LGTM: Test assertions updated to use Result type.

The changes in both test_transform_model and test_transform_module methods of TestJSONSchemaTransformer are consistent with the new result-handling pattern. The expected outputs are now wrapped in Ok() objects, which represents successful outcomes in the Result type pattern. This modification enhances error handling and aligns with the PR's objective of using results instead of exceptions.

Also applies to: 61-84


119-161: LGTM: AsyncAPI2Transformer tests updated to use Result type.

The changes in both test_transform_model and test_transform_module methods of TestAsyncAPI2Transformer are consistent with the new result-handling pattern. Similar to the changes in TestJSONSchemaTransformer, the expected outputs are now wrapped in Ok() objects. This modification maintains consistency across the test suite and aligns with the PR's objective of using results instead of exceptions.

Also applies to: 171-223


Line range hint 1-223: Summary: Successful implementation of Result type in transformer tests.

The changes in this file successfully implement the new result-handling pattern using the Ok type from the result module. The modifications are consistently applied across both JSONSchemaTransformer and AsyncAPI2Transformer tests, maintaining the existing test coverage while enhancing error handling. These changes align well with the PR objectives and contribute to a more robust and predictable codebase.

Key points:

  1. New import added for Ok from result module.
  2. Test assertions in both transformer classes updated to use Ok().
  3. Overall structure and logic of the tests remain intact.
  4. Consistency in applying the new pattern across different transformer types.

The only potential improvement would be to consider updating the collect_models function and its tests to also use the Result type for complete consistency across the codebase.

tests/test_schema_factory.py (1)

7-7: LGTM: Import of Ok aligns with new assertion style.

The addition of from result import Ok is consistent with the changes made in the test assertions. This import indicates a shift towards using a Result type for handling outcomes, which can improve error handling and make success/failure states more explicit.

sqlalchemy_to_json_schema/command/driver.py (3)

61-63: Verify all usages of build_transformer handle the new Result type

The return type of build_transformer has been updated to Callable[..., Result[Schema, str]]. Ensure that all callers of this method are updated to handle the Result type appropriately.

Run the following script to find all usages of build_transformer:

#!/bin/bash
# Description: Find all calls to 'build_transformer' and check for proper handling.

rg --type python 'build_transformer\(' -A 5

79-79: Ensure callers of run handle the new Result return type

The run method now returns a Result[None, str]. Verify that any code invoking this method is updated to handle the Result type.

Run the following script to locate all calls to the run method:

#!/bin/bash
# Description: Search for invocations of 'run' in the codebase.

rg --type python 'Driver\(.*\)\.run\(' -A 3

10-10: Ensure the result package is included in project dependencies

With the addition of from result import Err, Ok, Result, please verify that the result package is included in your project's dependencies to prevent import errors at runtime.

Run the following script to check if result is listed in your dependency files:

✅ Verification successful

result package is included in project dependencies

The result package was found in pyproject.toml, confirming that it is included in the project dependencies.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if 'result' is specified in pyproject.toml or requirements.txt

# Search in pyproject.toml
if rg '^\s*result\s*=' pyproject.toml; then
  echo "'result' found in pyproject.toml"
else
  echo "'result' not found in pyproject.toml"
fi

# Search in requirements.txt
if [ -f requirements.txt ]; then
  if rg '^result' requirements.txt; then
    echo "'result' found in requirements.txt"
  else
    echo "'result' not found in requirements.txt"
  fi
fi

Length of output: 243


Script:

#!/bin/bash
# Description: Check if 'result' is specified in pyproject.toml or requirements.txt

# Search in pyproject.toml
if rg '^\s*result\s*=' pyproject.toml; then
  echo "'result' found in pyproject.toml"
else
  echo "'result' not found in pyproject.toml"
fi

# Search in requirements.txt
if [ -f requirements.txt ]; then
  if rg '^result' requirements.txt; then
    echo "'result' found in requirements.txt"
  else
    echo "'result' not found in requirements.txt"
  fi
fi

Length of output: 166

sqlalchemy_to_json_schema/schema_factory.py (5)

29-29: Ensure 'result' dependency is declared

Since the code introduces a new dependency on the result package, please verify that this dependency is added to your project's configuration files (e.g., pyproject.toml or requirements.txt) to prevent any missing dependency issues.


Line range hint 124-137: LGTM: Updated method signature and error handling

The updated method signature in Classifier.__getitem__ correctly reflects the return types. Raising a KeyError when a mapping is not found aligns with standard Python practices.


273-290: Proper error handling in child_schema method

The child_schema method correctly utilizes the Result type for error handling, returning Ok and Err where appropriate. The logic for constructing subschemas and managing different relationship directions is sound.


Line range hint 488-494: LGTM: Accurate detection of required fields

The _detect_required method appropriately identifies required properties based on column nullability and applies adjustments through the adjust_required callback when provided.


245-250: ⚠️ Potential issue

Type inconsistency when calling get_children

In the child_walker method, walker.includes and walker.excludes are passed to get_children as params. Ensure that the types of walker.includes and walker.excludes are consistent with the expected parameter type of get_children. Adjust type annotations or data structures accordingly to maintain type consistency.

sqlalchemy_to_json_schema/command/transformer.py (9)

8-8: Good job importing the 'result' module for structured error handling

The addition of from result import Err, Ok, Result enables the use of the Result type for more robust error handling. This is a positive change that improves the code's reliability.


22-22: Update method signatures in subclasses to match the new return type

The abstract method transform now returns Result[Schema, str]. Ensure all subclasses correctly override this method with the updated return type to maintain consistency and adhere to the new error handling pattern.


28-28: Consistent use of 'Result' in 'JSONSchemaTransformer.transform'

The transform method in JSONSchemaTransformer correctly returns Result[Schema, str], aligning with the updated abstract method. This consistent use of Result enhances error handling across the codebase.


37-37: Improved error handling by returning 'Err' instead of raising exceptions

Replacing the exception with return Err(f"Expected a class or module, got {item}") provides a consistent error handling approach using the Result type. This avoids interrupting the flow with exceptions and makes error management more predictable.


39-44: Correctly checking for errors and unwrapping results

The code properly checks if partial_definitions.is_err() and returns the error if present. On success, it unpacks the result with partial_definitions.unwrap(). This pattern ensures that errors are handled gracefully and that only valid data is processed.


Line range hint 76-92: Consistent error handling in 'OpenAPI2Transformer.transform'

The method now returns Result[Schema, str] and utilizes Err and Ok for error management. This aligns with the overall error handling strategy and improves code reliability.


135-135: Verify the structure of the returned definitions in 'OpenAPI2Transformer'

In transform_by_module, return Ok(definitions) is used. Ensure that this return value matches the expected OpenAPI 2 schema structure and that consumers of this method can handle it correctly.

To confirm, you might run tests or review the code that consumes this output to ensure compatibility.


152-168: Effective adaptation to OpenAPI 3 schema requirements

The OpenAPI3Transformer properly overrides the transform method, handling errors with Result and adjusting references to match OpenAPI 3 standards. The use of replace_ref to update $ref pointers is appropriate and helps maintain compatibility with the OpenAPI 3 specification.


162-166: Ensure 'components' and 'schemas' keys are correctly initialized

The code checks and initializes the 'components' and 'schemas' keys in the definitions. This is essential for conforming to the OpenAPI 3 schema structure. Good attention to detail.

sqlalchemy_to_json_schema/command/main.py Outdated Show resolved Hide resolved
@@ -32,6 +32,7 @@ pyyaml = ">=5.4"
loguru = ">=0.7"
typing-extensions = ">=4.6"
greenlet = ">=3"
result = "^0.17.0"
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

Exception-based error handling still present.

The 'result' dependency has been integrated and used in several areas. However, multiple instances of exception-based error handling (raise, except, try:) remain in the codebase. Please ensure that all error handling aligns with the PR objective of using results instead of exceptions.

🔗 Analysis chain

LGTM! Verify integration of the new 'result' dependency.

The addition of the 'result' dependency (version ^0.17.0) aligns with the PR objective of using results instead of exceptions for error handling. This is a good practice for more structured error handling.

To ensure smooth integration, please run the following script to check for any potential conflicts or issues:

This script will help identify where and how the new 'result' dependency is being used, and if there are any remaining exception-based error handling that might need to be updated.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the integration of the 'result' dependency

# Test: Check if 'result' is imported in the project files
echo "Checking for 'result' imports:"
rg --type python 'from result import' || echo "No imports found"

# Test: Look for usage of Result type or functions
echo "Checking for 'Result' usage:"
rg --type python '\bResult\b' || echo "No direct usage of 'Result' found"

# Test: Check for any remaining exception-based error handling
echo "Checking for exception-based error handling:"
rg --type python '(raise|except|try:)' || echo "No exception-based error handling found"

# Note: These checks provide an overview. Manual review of the results is recommended.

Length of output: 669


Script:

#!/bin/bash
# Description: Verify the integration of the 'result' dependency without specifying file type

# Test: Check if 'result' is imported in the project files
echo "Checking for 'result' imports:"
rg 'from result import' || echo "No imports found"

# Test: Look for usage of Result type or functions
echo "Checking for 'Result' usage:"
rg '\bResult\b' || echo "No direct usage of 'Result' found"

# Test: Check for any remaining exception-based error handling
echo "Checking for exception-based error handling:"
rg '(raise|except|try:)' || echo "No exception-based error handling found"

# Note: These checks provide an overview. Manual review of the results is recommended.

Length of output: 5369

@@ -54,7 +54,7 @@ def test_it_create_schema__and__valid_params__sucess() -> None:

def test_it_create_schema__and__invalid_params__failure() -> None:
target = _makeOne()
schema = target(Group, excludes=["pk", "uesrs.pk"])
schema = target(Group, excludes=["pk", "uesrs.pk"]).unwrap()
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Approve change and suggest fixing typo in excludes parameter

The addition of .unwrap() is correct and consistent with the changes in other functions.

There's a typo in the excludes parameter that might affect the test's effectiveness:

-    schema = target(Group, excludes=["pk", "uesrs.pk"]).unwrap()
+    schema = target(Group, excludes=["pk", "users.pk"]).unwrap()

This typo is pre-existing but should be fixed to ensure the test is excluding the intended field.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
schema = target(Group, excludes=["pk", "uesrs.pk"]).unwrap()
schema = target(Group, excludes=["pk", "users.pk"]).unwrap()

Comment on lines +83 to +88
yield Ok(
( # type: ignore[arg-type]
{"type": "array", "items": {"type": "string"}},
prop,
{},
)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix type inconsistency in yield statement for MANYTOMANY relationship

In the UseForeignKeyIfPossibleDecision.decision method, within the elif prop.direction == MANYTOMANY block, the yield statement returns a tuple where the first element is a dictionary ({"type": "array", "items": {"type": "string"}}). However, the DecisionResult expects the first element to be of type ColumnPropertyType. This inconsistency necessitates the # type: ignore[arg-type] comment.

Consider defining a new member in ColumnPropertyType to represent this case (e.g., ColumnPropertyType.ARRAY) and adjust the yield statement accordingly. This will ensure type consistency and eliminate the need for the type ignore comment.

Apply this diff to correct the issue:

-                    yield Ok(
-                        (  # type: ignore[arg-type]
-                            {"type": "array", "items": {"type": "string"}},
-                            prop,
-                            {},
-                        )
-                    )
+                    yield Ok(
+                        (
+                            ColumnPropertyType.ARRAY,
+                            prop,
+                            {"type": "array", "items": {"type": "string"}},
+                        )
+                    )

Committable suggestion was skipped due to low confidence.

Comment on lines +90 to +97
schema = self.transformer(modules_and_models, depth)

if schema.is_err():
return Err(schema.unwrap_err())

self.dump(schema.unwrap(), filename=filename, format=format)

return Ok(None)
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider handling potential exceptions from the dump method

While the run method now handles errors from self.transformer, consider that self.dump might raise exceptions (e.g., file I/O errors). To maintain consistent error handling, you could modify dump to return a Result type or handle exceptions within run.

Proposed Change to dump:

Modify the dump method to return a Result[None, str]:

 def dump(
     self,
     data: dict[str, Any],
     /,
     *,
     filename: Optional[Path] = None,
     format: Optional[Format] = None,
- ) -> None:
+ ) -> Result[None, str]:
     try:
         dump_function = yaml.dump if format == Format.YAML else json.dump

         if filename is None:
             output_stream = sys.stdout
         else:
             output_stream = filename.open("w")

         dump_function(data, output_stream)  # type: ignore[operator]
+        return Ok(None)
     except Exception as e:
+        return Err(str(e))

Update run to Handle the Result from dump:

 schema = self.transformer(modules_and_models, depth)

 if schema.is_err():
     return Err(schema.unwrap_err())

- self.dump(schema.unwrap(), filename=filename, format=format)
+ dump_result = self.dump(schema.unwrap(), filename=filename, format=format)
+ if dump_result.is_err():
+     return Err(dump_result.unwrap_err())

 return Ok(None)

This ensures that any errors from dump are captured and propagated correctly.

Committable suggestion was skipped due to low confidence.

Comment on lines 178 to 185
params: Sequence[str] | None,
/,
*,
splitter: str = ".",
default: Optional[Union[list[str], dict[str, Any]]] = None,
) -> Union[list[str], dict[str, Any], None]:
default: list[str] | None = None,
) -> list[str] | None:
prefix = name + splitter
if hasattr(params, "items"):
if params is None:
raise RuntimeError("params is None")
if isinstance(params, dict):
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Inconsistent type annotations in get_children function

The get_children function specifies params as Sequence[str] | None, but the code checks if isinstance(params, dict):, which is inconsistent with the annotated type. Please update the type annotation of params to include Mapping[str, Any] | None if dictionaries are expected, or adjust the conditional checks to align with the annotated types.

if "definitions" in schema:
subdefinitions.update(schema.pop("definitions"))
definitions[schema["title"]] = schema
d = {}
d.update(subdefinitions)
d.update(definitions)
return {"definitions": definitions}
return Ok({"definitions": definitions})
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Inconsistent wrapping of 'definitions' in the return statement

In transform_by_module, you're returning Ok({"definitions": definitions}), which wraps the definitions inside another definitions key. However, in other transformers, you return Ok(definitions) directly. This inconsistency could lead to confusion or errors when the output is used elsewhere. Consider standardizing the return structure across all transformers.

Apply this diff to align the return statement with other methods:

-    return Ok({"definitions": definitions})
+    return Ok(definitions)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return Ok({"definitions": definitions})
return Ok(definitions)

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: 4

🧹 Outside diff range and nitpick comments (8)
tests/regression/test_generate_schema_with_type_decorator.py (2)

15-15: Function signature updated correctly.

The change to return Result[Schema, str] aligns well with the new error handling approach. This clearly indicates that the function can return either a Schema or an error message.

Consider adding or updating the function's docstring to reflect this change in return type and behavior.


52-54: Test case updated correctly for new Result type.

The changes appropriately adapt the test case to the new Result-based approach:

  1. Checking for success using is_ok(result) before accessing the value.
  2. Accessing the schema properties via result.value.

These changes ensure that the test case correctly handles the new error handling mechanism.

Consider adding an additional test case to verify the behavior when an error occurs (i.e., when is_ok(result) would return False).

sqlalchemy_to_json_schema/schema_factory.py (5)

Line range hint 124-137: Improved type safety and standard exception handling

The changes to the __getitem__ method are beneficial:

  1. The return type is now more specific, enhancing type safety.
  2. Using KeyError instead of a custom exception aligns with Python's standard practices for dictionary-like objects.

These improvements make the code more predictable and easier to use.

Consider adding a type annotation to the mapped variable for even better type clarity:

mapped: TypeFormatFn | None = None

272-290: Robust error handling with Result type

The changes to child_schema method significantly improve error handling:

  1. The return type Result[dict[str, Any], str] allows for explicit error cases.
  2. The new error handling logic (lines 282-285) properly propagates errors from subschema creation.
  3. Successful results are now wrapped in Ok(...), adhering to the Result pattern.

These changes make the method more robust and easier to use safely.

Consider adding a comment explaining the meaning of the error string in the Err case:

if subschema_result.is_err():
    # Propagate the error message from subschema creation
    return subschema_result

Line range hint 322-345: Enhanced error handling and configuration validation

The updates to SchemaFactory.__call__ method bring several improvements:

  1. The return type Result[Schema, str] allows for explicit error reporting.
  2. New error handling for the properties creation process (lines 329-330) ensures that errors are properly propagated.
  3. The additional check for unused overrides (line 335) helps catch potential misconfigurations.

These changes make the method more robust and help prevent silent errors.

Consider adding more context to the error message for unused overrides:

if overrides_manager.not_used_keys:
    return Err(f"Invalid overrides: {overrides_manager.not_used_keys}. These keys were not used in schema generation.")

Line range hint 411-478: Comprehensive error handling in property building

The updates to SchemaFactory._build_properties method significantly enhance error handling:

  1. The return type Result[dict[str, Any], str] allows for explicit success and failure cases.
  2. New error handling in the decision loop (lines 424-427) provides specific error messages for unsupported properties.
  3. Consistent use of Ok(...) and Err(...) for return statements improves code clarity.

These changes make the method more robust and easier to debug when issues arise.

Consider adding more context to the error message for unsupported column types:

return Err(f"Unsupported column type: {type(column.type)}. Please ensure all column types are supported.")

Line range hint 1-501: Overall improvements in error handling and type safety

The changes made to this file represent a significant improvement in error handling and type safety:

  1. Consistent use of the Result type for error handling throughout the file.
  2. More precise type annotations, especially in function return types.
  3. Better alignment with Python standards (e.g., using KeyError instead of custom exceptions).

These changes will make the code more robust, easier to debug, and less prone to runtime errors. The consistent error handling pattern will also make it easier for users of this library to handle potential issues.

Consider adding documentation or comments explaining the new error handling pattern, especially if this is a public-facing library. This will help users understand how to properly handle potential errors when using the schema factory.

sqlalchemy_to_json_schema/command/transformer.py (1)

37-37: Standardize error messages for consistency

The error messages in lines 37 and 85 use different variable names ({item} vs. {target}):

  • Line 37: return Err(f"Expected a class or module, got {item}")
  • Line 85: return Err(f"Expected a class or module, got {target}")

Consider standardizing the variable names in the error messages to maintain consistency across the transformers.

Also applies to: 85-85

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 308c726 and 6352810.

⛔ Files ignored due to path filters (1)
  • poetry.lock is excluded by !**/*.lock
📒 Files selected for processing (12)
  • pyproject.toml (1 hunks)
  • sqlalchemy_to_json_schema/command/driver.py (4 hunks)
  • sqlalchemy_to_json_schema/command/transformer.py (7 hunks)
  • sqlalchemy_to_json_schema/decisions.py (4 hunks)
  • sqlalchemy_to_json_schema/schema_factory.py (9 hunks)
  • tests/command/test_transformer.py (5 hunks)
  • tests/regression/test_generate_schema_with_type_decorator.py (4 hunks)
  • tests/test_it.py (3 hunks)
  • tests/test_it_reflection.py (3 hunks)
  • tests/test_relation.py (4 hunks)
  • tests/test_schema_factory.py (8 hunks)
  • tests/test_walker.py (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (8)
  • pyproject.toml
  • sqlalchemy_to_json_schema/decisions.py
  • tests/command/test_transformer.py
  • tests/test_it.py
  • tests/test_it_reflection.py
  • tests/test_relation.py
  • tests/test_schema_factory.py
  • tests/test_walker.py
🧰 Additional context used
🔇 Additional comments (10)
tests/regression/test_generate_schema_with_type_decorator.py (2)

5-5: LGTM: New import added correctly.

The new import from result import Result, is_ok is correctly placed and necessary for the changes made in this file.


19-21: LGTM: Internal changes to _callFUT are correct.

The variable name change to schema_result and the direct return of this value are appropriate given the new Result-based approach. These changes correctly implement the new error handling strategy.

sqlalchemy_to_json_schema/command/driver.py (3)

10-10: LGTM: Importing Result types for improved error handling

The addition of Err, Ok, and Result imports from the result module is a good step towards implementing structured error handling in the Driver class.


61-63: LGTM: Updated return type for build_transformer

The return type of build_transformer has been updated to reflect that it now returns a Callable that produces a Result[Schema, str]. This change is consistent with the introduction of structured error handling and provides better type information.


Line range hint 1-116: Overall improvement in error handling, with room for further enhancement

The changes in this file represent a significant improvement in error handling for the Driver class. The introduction of the Result type and its usage in the build_transformer and run methods enhance the robustness and type safety of the code.

To fully realize the benefits of this new error handling pattern, consider extending it to the dump method as suggested in the previous comment. This would provide a consistent approach to error management throughout the class.

Great work on improving the code quality! These changes will make the library more reliable and easier to use.

sqlalchemy_to_json_schema/schema_factory.py (2)

29-29: Improved error handling with Result type

The addition of Err, Ok, Result from the result library is a positive change. This will enable more explicit and type-safe error handling throughout the codebase, making it easier to manage and propagate errors.


Line range hint 145-145: Enhanced type precision in return annotation

The updated return type tuple[DeclarativeMeta | None, TypeFormatFn | None] is more precise and explicit. This change improves type safety and makes the function's behavior clearer, especially when dealing with cases where no mapping is found.

sqlalchemy_to_json_schema/command/transformer.py (3)

8-8: Use of result module enhances error handling

Importing Err, Ok, and Result from the result module introduces functional error handling, which improves the robustness and readability of the code.


22-22: Update method signatures to return Result[Schema, str]

The method signatures for transform in AbstractTransformer, JSONSchemaTransformer, OpenAPI2Transformer, and OpenAPI3Transformer have been updated to return Result[Schema, str]. This change allows for more structured error handling throughout the transformer classes.

Also applies to: 28-28, 76-76, 152-152


39-42: Consistent error propagation using is_err() and unwrap()

In both JSONSchemaTransformer.transform and OpenAPI2Transformer.transform, you've effectively used is_err() to check for errors and unwrap() to access successful results. This consistent pattern improves error handling and code clarity.

Also applies to: 87-90

Comment on lines +68 to +70

assert is_ok(result)
assert result.unwrap()["properties"]["color"] == {"type": "string", "maxLength": 1}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Test case updated for new Result type, but with inconsistent value access.

The changes correctly adapt the test case to the new Result-based approach:

  1. Checking for success using is_ok(result) before accessing the value.
  2. Accessing the schema properties via result.unwrap().

While these changes ensure that the test case handles the new error handling mechanism, there's an inconsistency in how the result value is accessed compared to the previous test case.

The result.unwrap() usage here is inconsistent with result.value used in the previous test case. For consistency, consider using result.value here as well:

-    assert result.unwrap()["properties"]["color"] == {"type": "string", "maxLength": 1}
+    assert result.value["properties"]["color"] == {"type": "string", "maxLength": 1}

Alternatively, if unwrap() is preferred, update the previous test case to use it as well for consistency across the file.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
assert is_ok(result)
assert result.unwrap()["properties"]["color"] == {"type": "string", "maxLength": 1}
assert is_ok(result)
assert result.value["properties"]["color"] == {"type": "string", "maxLength": 1}

@@ -73,7 +76,7 @@ def run(
filename: Optional[Path] = None,
format: Optional[Format] = None,
depth: Optional[int] = None,
) -> None:
) -> Result[None, str]:
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

LGTM: Improved error handling in run method

The run method has been updated to return a Result[None, str] and now includes proper error handling for the self.transformer call. This is a significant improvement in error management.

However, there's still room for improvement in handling potential errors from self.dump:

Consider updating the dump method to return a Result type and handle its potential errors in the run method. This would provide consistent error handling throughout the class. Here's a suggested implementation:

def dump(self, ...) -> Result[None, str]:
    try:
        # Existing implementation
        return Ok(None)
    except Exception as e:
        return Err(str(e))

def run(self, ...):
    # Existing implementation
    dump_result = self.dump(schema.unwrap(), filename=filename, format=format)
    if dump_result.is_err():
        return Err(dump_result.unwrap_err())
    return Ok(None)

This change would ensure that any errors occurring during the dump process are also captured and propagated correctly.

Also applies to: 90-97

Comment on lines +58 to +63

if schema_result.is_err():
return schema_result

schema = schema_result.unwrap()

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Refactor duplicated code into a shared method

The code handling schema_result in transform_by_module methods of JSONSchemaTransformer and OpenAPI2Transformer is duplicated:

schema_result = self.schema_factory(basemodel, depth=depth)

if schema_result.is_err():
    return schema_result

schema = schema_result.unwrap()

Consider refactoring this logic into a shared helper method or moving it to the AbstractTransformer class to reduce duplication and enhance maintainability.

Also applies to: 119-124

Comment on lines +155 to +156
if definitions_result.is_err():
return Err(definitions_result.unwrap_err())
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Simplify error propagation in transform method

In OpenAPI3Transformer.transform, you unwrap the error only to wrap it again:

if definitions_result.is_err():
    return Err(definitions_result.unwrap_err())

You can simplify this by returning the definitions_result directly when an error occurs:

if definitions_result.is_err():
    return definitions_result

This approach maintains consistency with other methods and reduces unnecessary code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant