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

Propose ADR 0002: Remove special handling of Optional and Union #154

Merged
merged 4 commits into from
Apr 15, 2024

Conversation

SimonHeybrock
Copy link
Member

Please comment!

@jokasimr
Copy link
Contributor

Very nice!

Sciline builds a data dependency graph based on type hints of callables.
Some callables may have optional inputs, which are commonly represented by `Optional[T]` in the type hint, for some type `T`.
Therefore, in [#50](https://github.com/scipp/sciline/pull/50) we have added special handling for `Optional` and [#89](https://github.com/scipp/sciline/pull/89) extended this for `Union`.
In the case of `Optional`, they way this works is that `sciline.Pipeline` prunes branches at the node where the optional input used, if any ancestor node has unsatisfied dependencies.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
In the case of `Optional`, they way this works is that `sciline.Pipeline` prunes branches at the node where the optional input used, if any ancestor node has unsatisfied dependencies.
In the case of `Optional`, the way this works is that `sciline.Pipeline` prunes branches at the node where the optional input is used if any ancestor node has unsatisfied dependencies.

There are a couple of possible workarounds:

- Add an explicit `Optional` provider that wraps (or depends on) the non-optional provider.
- Modify the graph structure (which we plan to support in the redesign of Sciline) using something like `pipeline[Optional[MyParam]] = pipeline[MyParam]`.
Copy link
Member

Choose a reason for hiding this comment

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

3rd option:
Since with the proposed approach, certain T basically always occur as Optional[T], we could adapt the domain types to include Optional directly, e.g.

MyParam = NewType('MyParam', Optional[float])

in the case above.

Copy link
Member Author

Choose a reason for hiding this comment

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

Isn't that a sub case of the first option (just syntactic sugar)?

Copy link
Member

Choose a reason for hiding this comment

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

Sort of. It forces the use of Optional[T] everywhere. With point 1, you could still mix Optional[T] and T.

It makes it tricky to represent the internals of `sciline.Pipeline` as a simple data dependency graph.
The special handling of `Optional` and `Union` seems to require pervasive changes to the code, which is a sign that it is not a good fit for the design.

### Counter arguments
Copy link
Member

Choose a reason for hiding this comment

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

Another counter argument: See ess.reduce.nexus.load_sample. The file_path arg supports multiple different types. They cannot be handled via duck typing as they require special handling within the provider. So #153 would not be a solution. So if we didn't support Union, we would need to restrict providers to accept either a single concrete type or an implementation of a protocol as argument.

Copy link
Member Author

Choose a reason for hiding this comment

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

Not sure I follow. load_sample would not need to change with the proposal?

Copy link
Member

Choose a reason for hiding this comment

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

Did I misunderstand it? Are you saying you want to keep support for Union but remove the branch-pruning behaviour of Optional?

Copy link
Member Author

Choose a reason for hiding this comment

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

The user can still use Union and Optional, but Sciline would not longer handle them in any special manner. A provider could then return Union[int, float], and another provider could depend on this.

What would be removed is the logic to hook up int or float to Union[int, float].

Copy link
Member

Choose a reason for hiding this comment

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

And that is exactly why I said it is bad for the example. It would require specifying the parameter as

params = {
  Union[FilePath, NeXusFile, NeXusGroup]: Path("...")
}

which is unwieldy. The best way to improve this I could think of is

FileSpec = NewType("FileSpec", Union[FilePath, NeXusFile, NeXusGroup])
params = {
  FileSpec: Path("...")
}

but this is odd because it requires two explicit types (key and value) but those are not the same.

Base automatically changed from adr-0001-remove-param-type-checks to main April 15, 2024 11:19
@SimonHeybrock SimonHeybrock merged commit de59da7 into main Apr 15, 2024
5 checks passed
@SimonHeybrock SimonHeybrock deleted the adr-0002-remove-optional-union-handling branch April 15, 2024 11:20
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.

5 participants