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

Include generics in discriminated union schemas #157

Merged
merged 5 commits into from
Feb 7, 2025

Conversation

tpoliaw
Copy link
Contributor

@tpoliaw tpoliaw commented Jan 31, 2025

  • Restrict subclasses of typed unions
  • Allow arbitrary types to be included in 'StrictConfig' types

Fixes #156

Instructions to reviewer on how to test:

  1. Create set of subclasses of a decorated base class:
@discriminated_union_of_subclasses
class Base(Generic[T]):
    pass

@dataclass
class Child(Base[T]):
    foo: T
  1. Try and deserialise a serialised Child as a Base:
one = TypeAdapter(Base[int]).validate_python({"type": "Child", "foo": "42"})
assert one.foo == 42 # <== 42 instead of "42" as type should be converted

Checks for reviewer

  • Would the PR title make sense to a user on a set of release notes

Copy link
Contributor

@coretl coretl left a comment

Choose a reason for hiding this comment

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

From a skim this looks fine to me

Copy link
Contributor

@DiamondJoseph DiamondJoseph left a comment

Choose a reason for hiding this comment

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

A nit and a possible edge case

src/scanspec/core.py Outdated Show resolved Hide resolved
Comment on lines 231 to 237
def _compatible_types(left: TypeVar, right: TypeVar) -> bool:
return (
left.__bound__ == right.__bound__
and left.__constraints__ == right.__constraints__
and left.__covariant__ == right.__covariant__
and left.__contravariant__ == right.__contravariant__
)
Copy link
Contributor

Choose a reason for hiding this comment

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

Could left.__ be a subset of right.__?

class Super:
class Sub(Super):

@discriminated...
class Parent(Generic[Super]):
class Child(Parent[Sub], Generic[Sub])

e.g. for class ReadableMovable(Movable)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You can't pass concrete types to Generic as in this example but yes, this is definitely restricting the supported cases beyond what is possible in theory. It turns out to be difficult to determine what should be passed without re-implementing an entire type-checker. There are a couple of examples in #156 and a few in a previous version of this commit where I tried to support a wider range of options but until we have a use case for them I'd prefer a well defined restriction instead of an array of unsupported edge-cases.

@tpoliaw tpoliaw force-pushed the restrict_discriminated_subclasses branch from 06e7542 to 08e4d1a Compare February 4, 2025 16:08
Copy link

codecov bot commented Feb 4, 2025

Codecov Report

Attention: Patch coverage is 95.00000% with 2 lines in your changes missing coverage. Please review.

Project coverage is 95.70%. Comparing base (b75ff5d) to head (216f797).

Files with missing lines Patch % Lines
src/scanspec/core.py 95.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #157      +/-   ##
==========================================
- Coverage   95.74%   95.70%   -0.05%     
==========================================
  Files           9        9              
  Lines         940      977      +37     
==========================================
+ Hits          900      935      +35     
- Misses         40       42       +2     

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

@callumforrester
Copy link
Contributor

Delete uncovered lines as discussed

@callumforrester
Copy link
Contributor

Should consider adding a codecov config like ophyd-async's for consistency

@DiamondJoseph DiamondJoseph mentioned this pull request Feb 7, 2025
@DiamondJoseph DiamondJoseph force-pushed the restrict_discriminated_subclasses branch from 216f797 to c8c4494 Compare February 7, 2025 15:50
@DiamondJoseph
Copy link
Contributor

Rebased to pick up codecov changes

@DiamondJoseph DiamondJoseph merged commit 96f5982 into main Feb 7, 2025
21 checks passed
@DiamondJoseph DiamondJoseph deleted the restrict_discriminated_subclasses branch February 7, 2025 15:54
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.

discriminated_union_of_subclasses loses type information when deserialising
4 participants