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

Improve ListArtifact #1093

Closed
wants to merge 2 commits into from
Closed

Improve ListArtifact #1093

wants to merge 2 commits into from

Conversation

collindutter
Copy link
Member

Describe your changes

Added

  • Generic type support to ListArtifact.
  • Iteration support to ListArtifact.

Issue ticket number and link

NA

Copy link

codecov bot commented Aug 21, 2024

Codecov Report

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

Files with missing lines Patch % Lines
griptape/tasks/tool_task.py 50.00% 1 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

@collindutter collindutter force-pushed the feature/list-artifact branch from 1d189b8 to bd93052 Compare August 21, 2024 17:47
@collindutter collindutter force-pushed the feature/list-artifact branch from bd93052 to 00b780e Compare August 21, 2024 17:52
@collindutter collindutter force-pushed the feature/list-artifact branch 2 times, most recently from 410587d to 7fe622c Compare August 21, 2024 18:14
@collindutter
Copy link
Member Author

I thought the type check was dependency related but there's something else going on. Looking into it.

@collindutter collindutter force-pushed the feature/list-artifact branch 2 times, most recently from ba1a0d1 to 982f708 Compare August 21, 2024 18:47
@collindutter collindutter requested a review from vachillo August 21, 2024 18:48
Comment on lines +22 to 23
def validate_value(self, _: Attribute, value: list[T]) -> None:
if self.validate_uniform_types and len(value) > 0:
Copy link
Member

@vachillo vachillo Aug 21, 2024

Choose a reason for hiding this comment

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

is validate_uniform_types still applicable here?
what would happen with:

ListArtifact[BlobArtifact]([TextArtifact("foo")], validate_uniform_types=False)

?

Copy link
Member Author

Choose a reason for hiding this comment

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

I think validate_uniform_types is still useful as a runtime check (although we don't actually use it anywhere lol). In your example, it would fail type check but succeed at runtime.

@collindutter collindutter requested a review from vachillo August 21, 2024 22:35
Copy link
Contributor

@dylanholmes dylanholmes left a comment

Choose a reason for hiding this comment

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

Awesome!

CHANGELOG.md Show resolved Hide resolved
from collections.abc import Sequence
from collections.abc import Iterator, Sequence

T = TypeVar("T", bound=BaseArtifact)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this should set covariant=True.

This will allow for example, passing ListArtifact[TextArtifact] where a ListArtifact[BaseTextArtifact] is required.

Relating it to the definition of a covariant type, if ListArtifact[T] is covariant in T if ListArtifact[S] is considered a subtype of ListArtifact[T] whenever S is a subtype of T. Kind of like the bounds=, but where the value of bounds is determined by a particular usage rather than all usages.

Copy link
Member Author

Choose a reason for hiding this comment

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

Great suggestion! Will update.

Comment on lines +16 to +17
class ListArtifact(BaseArtifact, Generic[T]):
value: Sequence[T] = field(factory=list, metadata={"serializable": True})
Copy link
Contributor

@dylanholmes dylanholmes Aug 22, 2024

Choose a reason for hiding this comment

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

Could you remind me why value is Sequence instead of list? If you wanted ListArtifact to subclass a collection, would you pick Sequence or list? (I expect the choice to be based on whether or not ListArtifact should be mutable or not)

We currently implement the interface of at least Sequence (required methods are __getitem__, __len__, __contains__), but we just don't have the base class.

Copy link
Member Author

Choose a reason for hiding this comment

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

list is not covariant, Sequence is. Here is an example pyright error:

    Return type mismatch: base method returns type "BaseArtifact | list[BaseArtifact]", override returns type "list[CsvRowArtifact]"
      Type "list[CsvRowArtifact]" is incompatible with type "BaseArtifact | list[BaseArtifact]"
        "list[CsvRowArtifact]" is incompatible with "BaseArtifact"
        "list[CsvRowArtifact]" is incompatible with "list[BaseArtifact]"
          Type parameter "_T@list" is invariant, but "CsvRowArtifact" is not the same as "BaseArtifact"
          Consider switching from "list" to "Sequence" which is covariant (reportIncompatibleMethodOverride)

Copy link
Contributor

@dylanholmes dylanholmes Aug 22, 2024

Choose a reason for hiding this comment

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

TIL!

After looking into why list is not covariant and why Sequence is, its because list is mutable!

example:

class Animal:
    pass

class Dog(Animal):
    pass

dogs: list[Dog] = [Dog(), Dog()]
animals: list[Animal] = dogs  # This would be allowed if lists were covariant

animals.append(Animal())  # Adding an Animal (not necessarily a Dog!) to a list of Dogs

So this leads me to the question, ListArtifact is not intended to be mutable, is it?

Copy link
Member Author

Choose a reason for hiding this comment

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

ListArtifact is not intended to be mutable, is it?

Good question, probably not. I can investigate changing back to list, but it will have implications throughout the codebase so I think it should be done in a separate PR.

@collindutter
Copy link
Member Author

Many Artifact refactors incoming

@collindutter collindutter deleted the feature/list-artifact branch December 10, 2024 18:41
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.

3 participants