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

Revert nullable schema generation for array slices #594

Closed
wants to merge 2 commits into from

Conversation

lsdch
Copy link
Contributor

@lsdch lsdch commented Oct 2, 2024

1961ef9 reverts #527 which seems to be causing more trouble than good (see #571 and comments on #527).

110fcaa introduces a configuration field in the schema registry, which allows specifying whether schemas for arrays/slices should be nullable by default. This is not ideal since it would rather belong in the huma.Config, but then it would not be accessible at the time of schema generation without major changes in the API. Let me know if you got ideas on how to improve this.

Summary by CodeRabbit

  • New Features

    • Introduced a new RegistryConfig struct to manage nullability of slices in OpenAPI schema generation.
    • Enhanced Config methods to provide direct access to registry configurations.
  • Bug Fixes

    • Improved handling of the Nullable property for array types, allowing dynamic control based on configuration settings.
  • Tests

    • Updated test cases to reflect the new NullSlices configuration, ensuring accurate schema generation for nullable arrays and slices.

Copy link

coderabbitai bot commented Oct 2, 2024

Walkthrough

This pull request introduces several enhancements to the schema configuration capabilities within the Huma framework. A new RegistryConfig struct is added, which includes a NullSlices boolean field for controlling the nullability of slices in OpenAPI specifications. The Config method is implemented in the Registry interface and the mapRegistry struct to provide access to this configuration. Additionally, modifications are made to the Schema struct to dynamically handle the Nullable property for arrays based on the new configuration, along with corresponding updates in the test cases.

Changes

File Change Summary
api.go Added method func (c *Config) RegistryConfig() *RegistryConfig to Config struct.
registry.go Introduced new struct RegistryConfig with field NullSlices. Added Config() method to Registry interface and updated mapRegistry to include a config field. Updated NewMapRegistry to initialize config.
schema.go Modified Schema struct to dynamically set Nullable for arrays based on registry configuration.
schema_test.go Updated test cases to reflect changes in handling nullable slices and arrays with new NullSlices configuration. Adjusted expected JSON schema outputs accordingly.

Possibly related issues

Possibly related PRs

  • fix: nullable schemas for arrays/slices #527: This PR is directly related as it modifies the schema.go file to enhance the handling of nullable array types, which aligns with the new configuration capabilities introduced in the main PR.

Suggested reviewers

  • danielgtaylor: Suggested as a reviewer due to their involvement in previous related changes and expertise in the Huma framework.

Poem

🐰 In the garden of code, changes bloom bright,
With NullSlices added, the future looks right.
Schemas now dance, with flexibility's grace,
Huma's new features, a sweet, happy place!
So hop on, dear friends, let’s celebrate cheer,
For every new change brings us closer, my dear! 🌼


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

codecov bot commented Oct 2, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 92.81%. Comparing base (6e119e8) to head (0f04456).
Report is 30 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #594      +/-   ##
==========================================
+ Coverage   92.80%   92.81%   +0.01%     
==========================================
  Files          22       22              
  Lines        3903     3910       +7     
==========================================
+ Hits         3622     3629       +7     
  Misses        236      236              
  Partials       45       45              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

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 and nitpick comments (6)
registry.go (5)

12-19: LGTM, but consider placement of configuration.

The RegistryConfig struct is well-defined and documented. However, as mentioned in the PR description, this configuration might be better suited within the huma.Config structure for better accessibility during schema generation.

Consider exploring ways to integrate this configuration with the existing huma.Config structure in future iterations to improve API consistency and accessibility.


32-32: LGTM. Consider returning a copy of the config.

The addition of the Config() method to the Registry interface is consistent with the new RegistryConfig struct. However, returning a pointer might allow unintended modifications to the configuration.

Consider returning a copy of the config instead of a pointer to prevent unexpected modifications:

Config() RegistryConfig

This change would ensure that the configuration remains immutable from the caller's perspective.


79-84: LGTM. Consider ensuring immutability of the config.

The addition of the config field to mapRegistry and the implementation of the Config() method are consistent with the Registry interface update. However, returning a pointer to the config field might allow external modification of the configuration.

Consider returning a copy of the config instead of a pointer to ensure immutability:

func (r *mapRegistry) Config() RegistryConfig {
	return r.config
}

This change would prevent unintended modifications to the registry's configuration from external code.


188-190: LGTM. Consider using a named RegistryConfig for clarity.

The initialization of the config field with default values is correct and consistent with the PR objectives.

For improved readability, consider using a named RegistryConfig:

config: RegistryConfig{
	NullSlices: false,
},

This change would make it clearer that we're initializing a RegistryConfig struct, especially if more fields are added in the future.


Line range hint 1-191: Overall implementation looks good, but reconsider configuration placement.

The changes successfully introduce the new configuration option for nullable slices while reverting the previous behavior. The implementation is consistent and well-documented. However, as mentioned in the PR description, the placement of this configuration in the Registry might not be ideal.

Consider exploring ways to integrate this configuration with the existing huma.Config structure in a future iteration. This would improve API consistency and make the configuration more accessible during schema generation without significant alterations to the API.

schema.go (1)

765-765: Consider updating documentation and test cases.

With the introduction of configurable slice nullability, it would be beneficial to:

  1. Update any relevant documentation to reflect this new configuration option.
  2. Add or modify test cases to cover different configuration settings for slice nullability.

This will ensure that users are aware of the new behavior and that it works correctly under various scenarios.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 6e119e8 and 110fcaa.

📒 Files selected for processing (4)
  • api.go (1 hunks)
  • registry.go (4 hunks)
  • schema.go (1 hunks)
  • schema_test.go (12 hunks)
🧰 Additional context used
🪛 GitHub Check: codecov/patch
api.go

[warning] 194-195: api.go#L194-L195
Added lines #L194 - L195 were not covered by tests

🔇 Additional comments (19)
api.go (1)

194-196: ⚠️ Potential issue

Consider refactoring the configuration structure and improve method implementation.

While the RegistryConfig() method provides access to the schema registry configuration, there are several points to consider:

  1. As mentioned in the PR description, the placement of this configuration option might not be ideal. Consider moving it to the huma.Config structure for easier access during schema generation.

  2. The method lacks null checks, which could lead to a null pointer dereference if c.Components or c.Components.Schemas is nil. Consider adding appropriate checks.

  3. The method is not documented. Adding a comment explaining its purpose and return value would improve usability.

To address these concerns, consider refactoring the method as follows:

+// RegistryConfig returns the configuration for the schema registry.
+// It returns nil if the Components or Schemas are not initialized.
 func (c *Config) RegistryConfig() *RegistryConfig {
+    if c.Components == nil || c.Components.Schemas == nil {
+        return nil
+    }
 	return c.Components.Schemas.Config()
 }

The lack of test coverage for this new method is concerning. Consider adding unit tests to ensure its functionality. Here's a script to check for existing tests:

If no tests are found, please add appropriate unit tests for this new method.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 194-195: api.go#L194-L195
Added lines #L194 - L195 were not covered by tests

schema.go (1)

765-765: LGTM! Verify impact on existing code.

The change to make slice nullability configurable is a good improvement. It allows for more flexibility in schema generation and aligns with the PR objectives.

To ensure this change doesn't unexpectedly affect existing code, let's check for any direct uses of the Nullable field for array types:

schema_test.go (17)

109-111: Initialization of nullSlicesCfg is Correct

The nullSlicesCfg variable is properly initialized with NullSlices: true, allowing tests to configure the registry to generate nullable slices and arrays.


118-118: Adding config Field Enhances Test Flexibility

Introducing the config huma.RegistryConfig field to the test cases enables each test to customize the registry configuration, which is beneficial for testing different scenarios.


1103-1108: New Test Case for Nullable Arrays with NullSlices Configuration

The "array-null-cfg" test case correctly verifies that arrays are nullable when NullSlices is set to true. The expected JSON schema reflects the nullable array type as ["array", "null"], ensuring accurate schema generation.


1110-1114: New Test Case for Nullable Slices with NullSlices Configuration

The "slice-null-cfg" test case appropriately tests that slices are nullable when NullSlices is true. The expected schema output correctly includes ["array", "null"] in the type field.


1116-1135: Test Case for Nullable Array Fields in Structs

The "field-array-null-cfg" test case effectively verifies that array fields within structs are correctly marked as nullable when the NullSlices configuration is enabled. The expected JSON schema accurately represents the nullable array type.


1142-1143: Proper Configuration of NullSlices for Each Test Case

Setting r.Config().NullSlices = c.config.NullSlices within the test loop ensures that each test case uses the intended NullSlices configuration. This approach maintains test independence and accuracy.


294-294: Consistency in Array Type Definition

The "type": "array" in the expected JSON schema for the "field-array" test case maintains consistency with the schema definitions, aligning with prior expectations.


352-352: Accurate Typing in Array Enum Schema

In the "field-array-enum" test case, the "type": "array" is correctly specified, ensuring the array of integers with enumerated values is accurately represented in the schema.


442-442: Correct Schema Representation for Default Array of Strings

The "type": "array" in the expected schema for "field-default-array-string" is properly defined, accurately reflecting the default value of ["foo", "bar"].


462-462: Proper Array Type Specification in Default Array of Integers

The expected schema for "field-default-array-int" includes the correct "type": "array", ensuring that the default integer array [1, 2] is properly represented.


761-761: Accurate Schema for Recursive Array Fields

In the "recursive-embedded-structure" test case, the "type":"array" definitions for the array and slice fields are correctly specified, ensuring the schema accurately captures the recursive nature of these fields.

Also applies to: 779-779


901-901: Consistent Array Typing in Custom Length String Slice

The "type":"array" in the expected schema for "field-custom-length-string-in-slice" test case accurately represents the slice of TypedStringWithCustomLength, maintaining consistency in array definitions.


1058-1058: Correct Array Schema with Custom Description

The schema for "field-custom-array" correctly specifies the "type":"array" and includes the custom description, ensuring the array of floats with a fixed length is properly documented.


1081-1081: Accurate Schema for Pointer to Custom Array

In the "field-ptr-to-custom-array" test case, the "type":"array" is correctly defined, and the custom description is preserved, accurately representing the pointer to a custom array type.


1103-1108: Validating Nullable Array Behavior in Schema Generation

The expected schema in the "array-null-cfg" test case correctly includes "type": ["array", "null"], validating that arrays are nullable when the configuration is enabled.


1110-1114: Ensuring Nullable Slice Behavior with Configuration

The "slice-null-cfg" test case's expected schema accurately reflects the nullable slice type, confirming that the NullSlices configuration is effective.


1116-1135: Testing Nullable Array Field within Structs

The expected schema in "field-array-null-cfg" precisely includes "type": ["array", "null"] for the value field, demonstrating that array fields within structs are correctly treated as nullable when configured.

@lsdch lsdch force-pushed the revert-null-slice-schema branch from 110fcaa to 1869d0e Compare October 2, 2024 10:27
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: 1

🧹 Outside diff range and nitpick comments (5)
api_test.go (2)

129-129: Consider adding documentation for the new configuration option

While the new test function effectively demonstrates the usage of the NullSlices configuration, it would be beneficial to add some documentation explaining the purpose and implications of this new option. This could be in the form of a comment above the test function or even a package-level comment if this is a significant change to the library's behavior.

Consider adding a comment like this before the test function:

// TestRegistryConfig verifies the behavior of the new NullSlices configuration option.
// This option allows users to specify whether schemas for arrays or slices should be nullable by default.
// Note: The placement of this configuration might change in future versions to be part of huma.Config.

This documentation will help other developers understand the purpose of this test and the new configuration option.


130-134: Address concerns about configuration placement

The implementation of the NullSlices configuration option in the schema registry is a step towards addressing the issue mentioned in #571. However, as noted in the PR objectives, there are concerns about its current placement.

  1. Consider documenting the current limitations of this approach in the code or README.
  2. Create an issue to track the potential future relocation of this configuration to huma.Config.
  3. Evaluate if there's a way to make this configuration accessible during schema generation without significant API changes.

While this implementation provides a solution to the immediate problem, it's important to consider the long-term maintainability and usability of the API. If possible, explore options to refactor the configuration structure in a way that doesn't break existing APIs but allows for more flexibility in the future.

Would you like assistance in drafting a plan for future improvements or creating an issue to track this technical debt?

schema_test.go (3)

1115-1135: LGTM: Comprehensive test case for nullable array field configuration.

This test case thoroughly verifies the behavior of the new nullable array field configuration. It ensures that when NullSlices is set to true, the generated schema includes "null" as a possible type for the array field while preserving other array constraints like minItems, maxItems, and uniqueItems.

Consider adding a test case for a nullable slice field as well, to ensure complete coverage of both array and slice scenarios with field-level constraints.


1142-1143: LGTM: Integration of new configuration in test function.

The changes correctly integrate the new NullSlices configuration into the existing test framework. This ensures that the new feature is properly tested alongside existing functionality.

Consider adding a comment explaining the purpose of the NullSlices configuration for better code readability and maintainability.


Line range hint 109-1143: Overall implementation of nullable slices configuration looks good.

The changes effectively implement and test the new nullable slices configuration as described in the PR objectives. The implementation is consistent, and the test coverage is comprehensive, including cases for arrays, slices, and fields with array types.

While the implementation is good, the PR author's concern about the placement of this configuration option is valid. Consider exploring ways to integrate this configuration into the huma.Config structure in a future iteration, which would make it more accessible during schema generation without significant API changes.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 110fcaa and 1869d0e.

📒 Files selected for processing (5)
  • api.go (1 hunks)
  • api_test.go (1 hunks)
  • registry.go (4 hunks)
  • schema.go (1 hunks)
  • schema_test.go (12 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • api.go
  • registry.go
  • schema.go
🔇 Additional comments (3)
schema_test.go (3)

109-111: LGTM: New configuration field for nullable slices.

The addition of the NullSlices field to the RegistryConfig struct is a good implementation of the new feature described in the PR objectives. This allows users to specify whether schemas for arrays or slices should be nullable by default.


1103-1108: LGTM: New test case for nullable array configuration.

This test case correctly verifies the behavior of the new nullable array configuration. It ensures that when NullSlices is set to true, the generated schema includes "null" as a possible type for the array.


1109-1114: LGTM: New test case for nullable slice configuration.

This test case correctly verifies the behavior of the new nullable slice configuration. It ensures that when NullSlices is set to true, the generated schema includes "null" as a possible type for the slice.

api_test.go Outdated
Comment on lines 130 to 138
func TestRegistryConfig(t *testing.T) {
cfg := huma.DefaultConfig("Test", "3.1")
cfg.RegistryConfig().NullSlices = true
assert.True(t, cfg.Components.Schemas.Config().NullSlices)
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance test coverage for the new NullSlices configuration

The test correctly verifies that the NullSlices configuration can be set. However, to ensure comprehensive coverage, consider the following improvements:

  1. Test the default value of NullSlices before setting it.
  2. Add a test case that demonstrates how this configuration affects schema generation for array/slice fields.
  3. Consider testing edge cases or interactions with other configuration options.

Here's a suggested expansion of the test:

func TestRegistryConfig(t *testing.T) {
	// Test default value
	cfg := huma.DefaultConfig("Test", "3.1")
	assert.False(t, cfg.Components.Schemas.Config().NullSlices, "Default value of NullSlices should be false")

	// Test setting the value
	cfg.RegistryConfig().NullSlices = true
	assert.True(t, cfg.Components.Schemas.Config().NullSlices, "NullSlices should be set to true")

	// Test effect on schema generation
	type TestStruct struct {
		SliceField []string `json:"sliceField"`
	}
	schema := cfg.Components.Schemas.Add(TestStruct{})
	sliceFieldSchema := schema.Properties["sliceField"]
	assert.True(t, sliceFieldSchema.Nullable, "Slice field should be nullable when NullSlices is true")

	// Test interaction with other options (if applicable)
	// ...
}

Additionally, given the concerns about the placement of this configuration option mentioned in the PR objectives, it might be worth adding a comment in the test file noting this limitation and potential future changes.

Consider adding a TODO comment about the potential relocation of this configuration option to huma.Config in the future, as mentioned in the PR objectives.

@lsdch lsdch force-pushed the revert-null-slice-schema branch from 1869d0e to 0f04456 Compare October 2, 2024 10:44
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 and nitpick comments (2)
schema_test.go (2)

1103-1135: LGTM: Comprehensive test cases for nullable slices.

The new test cases thoroughly cover the nullable slices feature for arrays, slices, and struct fields with array types. They correctly expect the type field to be ["array", "null"] when using the nullable slices configuration.

Consider adding a test case for a nested array or slice to ensure the feature works correctly with more complex data structures.


Line range hint 109-1143: Summary: Well-implemented nullable slices feature with comprehensive tests.

The changes successfully implement the nullable slices feature and provide thorough test coverage. The new NullSlices configuration option in huma.RegistryConfig is correctly utilized throughout the test cases. The implementation maintains compatibility with existing code while adding support for nullable arrays and slices in schema generation.

Consider documenting this new feature in the library's documentation and README, explaining its purpose and usage. This will help users understand and utilize the new nullable slices functionality effectively.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 1869d0e and 0f04456.

📒 Files selected for processing (5)
  • api.go (1 hunks)
  • api_test.go (1 hunks)
  • registry.go (4 hunks)
  • schema.go (1 hunks)
  • schema_test.go (12 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • api.go
  • api_test.go
  • registry.go
  • schema.go
🔇 Additional comments (2)
schema_test.go (2)

109-111: LGTM: New configuration for nullable slices.

The nullSlicesCfg variable is correctly defined with NullSlices set to true. This will be useful for testing the new nullable slices feature.


1142-1143: LGTM: Correct application of NullSlices configuration.

The NullSlices configuration is now correctly set in the registry before running each test case. This ensures that the nullable slices feature is properly tested with the provided configuration.

@danielgtaylor
Copy link
Owner

@lsdch I spent some time thinking about this one and have proposed an alternative in #612. Would you be willing to take a look and let me know what you think?

@lsdch
Copy link
Contributor Author

lsdch commented Oct 17, 2024

As commented on #612, I like the more straightforward alternative 👍 Closing !

@lsdch lsdch closed this Oct 17, 2024
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.

2 participants