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

feat: Support passing arbitrary arguments/context to custom extensions (Issue #700) #814

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

Conversation

atharva-2001
Copy link
Contributor

Description

Related to #687 and #700.

Allowing custom **kwargs to custom extension classes.

e.g. This PR refactors the X submodule, applying Y's algorithm to improve Z by K percent.

Related Issues

Checklist

  • This PR has sufficient documentation.
  • This PR has sufficient test coverage.
  • This PR title satisfies semantic convention.

Additional Comments

No additional comments.

@atharva-2001 atharva-2001 changed the title Support passing arbitrary arguments/context to custom extensions (Issue #700) feat: Support passing arbitrary arguments/context to custom extensions (Issue #700) Sep 25, 2023
@atharva-2001
Copy link
Contributor Author

@noahnu I'm changing the classes which make up the AbstractSyrupyExtension class and also it's subclasses. Is this the right way to do this?

@@ -264,6 +264,7 @@ def __call__(
extension_class: Optional[Type["AbstractSyrupyExtension"]] = None,
matcher: Optional["PropertyMatcher"] = None,
name: Optional["SnapshotIndex"] = None,
**kwargs: Any,
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm a bit worried about name collisions by just forwarding arbitrary arguments, vs. something like:

assert "hi" == snapshot(extra={...})

I know it doesn't read as nicely, but you can always add syntactic sugar via a fixture:

@pytest.fixture
def snapshot(named_arg: str):
    return snapshot.with_defaults(extra={ "named_arg": named_arg })

def test_case(snapshot):
    assert "hi" == snapshot(named_arg="hi")

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added the argument to both __call__ and with_defaults method. I added it to the __call__ argument because I wanted it to work with cases when I want to change the snapshot behaviour but don't want it to persist.

@@ -280,6 +285,8 @@ def __call__(
self.__with_prop("_custom_index", name)
if diff is not None:
self.__with_prop("_snapshot_diff", diff)
if extra_args:
self._extra_args = extra_args
Copy link
Collaborator

Choose a reason for hiding this comment

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

Use self.__with_prop. It does seam auto-cleanup

src/syrupy/assertion.py Outdated Show resolved Hide resolved
Comment on lines 310 to 313
matcher_options = None
for key,value in self._extra_args.items():
if key == "matcher_options":
matcher_options = value
Copy link
Collaborator

Choose a reason for hiding this comment

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

This enforces a certain schema in the extra_args object which if we want to support arbitrary args we shouldn't do. Instead, we should propagate the "extra_args" to all relevant methods.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed this. I also forwaded extra_args to different functions. Could you please tell me what you think about this?

@noahnu
Copy link
Collaborator

noahnu commented Sep 26, 2023

We have built-in linters in the project via pyinvoke. You can run invoke lint and invoke test locally.

@noahnu
Copy link
Collaborator

noahnu commented Sep 27, 2023

Changing the signatures of all these functions will break any existing extensions in the wild, unless they were already using kwargs. Even then, I spent a couple hours trying to pass the context (or extra_args as you called it) to all relevant functions and the PR grew a bit out of control... I think we need to move back to instance-based extensions (which was something we moved away from in syrupy v4).

I've put up #816 to add "context", although context is only available in instance extension methods and there aren't many of those. Once that change is in, we'll have to start migrating from classmethods to instance methods. May need to do that in a syrupy v5 update since it'll be a breaking change to the API.

Going back to instance methods also plays nicely with some of the discussion in #754

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.

Support passing arbitrary arguments/context to custom extensions
2 participants