Thanks to visit codestin.com
Credit goes to github.com

Skip to content

MNT/TST: generalize check_figures_equal to work with pytest.marks #15199

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

Merged

Conversation

tacaswell
Copy link
Member

PR Summary

Generalize (at the cost of reaching a little bit into pytest
internals) the check_figures_equal decorator so it works as
expected with pytest.mark.paramatarize

PR Checklist

  • Has Pytest style unit tests
  • Code is Flake 8 compliant

Generalize (at the cost of reaching a little bit into pytest
internals) the check_figures_equal decorator so it works as
expected with `pytest.mark.paramatarize`
@tacaswell tacaswell added this to the v3.3.0 milestone Sep 6, 2019
@QuLogic QuLogic requested a review from anntzer September 7, 2019 00:36

wrapper.pytestmark = get_unpacked_marks(
wrapper
) + get_unpacked_marks(func)
Copy link
Member

Choose a reason for hiding this comment

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

Is this not something you can add together from wrapper.pytestmark and func.pytestmark?

Copy link
Member Author

Choose a reason for hiding this comment

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

Is that actually part of the public API?

Internally, pytest uses these three functions to do the mark manipulation:

def get_unpacked_marks(obj):
    """
    obtain the unpacked marks that are stored on an object
    """
    mark_list = getattr(obj, "pytestmark", [])
    if not isinstance(mark_list, list):
        mark_list = [mark_list]
    return normalize_mark_list(mark_list)


def normalize_mark_list(mark_list):
    """
    normalizes marker decorating helpers to mark objects

    :type mark_list: List[Union[Mark, Markdecorator]]
    :rtype: List[Mark]
    """
    extracted = [
        getattr(mark, "mark", mark) for mark in mark_list
    ]  # unpack MarkDecorator
    for mark in extracted:
        if not isinstance(mark, Mark):
            raise TypeError("got {!r} instead of Mark".format(mark))
    return [x for x in extracted if isinstance(x, Mark)]


def store_mark(obj, mark):
    """store a Mark on an object
    this is used to implement the Mark declarations/decorators correctly
    """
    assert isinstance(mark, Mark), mark
    # always reassign name to avoid updating pytestmark
    # in a reference that was only borrowed
    obj.pytestmark = get_unpacked_marks(obj) + [mark]

I was between just vendoring them all, doing the semi-private import, or adding the obj.pytestmark list together. I took the middle route, I'll change it to just adding the pytestmark lists together.

sig = inspect.signature(func)
new_sig = sig.replace(
parameters=(
[
Copy link
Member

Choose a reason for hiding this comment

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

As a side note, I find your code formatting style extremely hard to read.

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree this just looks like the worst of black, things like

wrapper.pytestmark = get_unpacked_marks(
    wrapper
) + get_unpacked_marks(func)

just completely obfuscate the structure of the code -- compare with

wrapper.pytestmark = (get_unpacked_marks(wrapper)
                      + get_unpacked_marks(func))

(or with an additional newline after the opening parenthesis).

Copy link
Member Author

Choose a reason for hiding this comment

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

This is indeed black's doing.

Ironically, the biggest selling point of black for me is avoiding exactly these conversations.

Copy link
Contributor

Choose a reason for hiding this comment

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

The fact that it's automated doesn't absolve it from completely violating basic esthetics.

Copy link
Contributor

Choose a reason for hiding this comment

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

fwiw @NelleV and I have been trying to come up with a better automated scheme and it's certainly not trivial... Nevertheless, since afaict matplotlib hasn't added black as a dependency, it's a bit weird to add badly black-formatted code...

Copy link
Contributor

Choose a reason for hiding this comment

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

(And @tacaswell it looks like you've set it to 71c wide? Which is unconventional to say the least...)

Copy link
Contributor

Choose a reason for hiding this comment

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

(I personally just don't buy into the idea that code can be properly formatted without understanding the underlying semantics.)

Copy link
Member

Choose a reason for hiding this comment

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

(Juan is considering doing constrained reinforcement learning to learn the rules…)

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 thought I set it to 80c (to keep our pyflakes happy). Black does a slightly better job if you give it a bit more width to work with.

@NelleV
Copy link
Member

NelleV commented Sep 7, 2019

I'm having a hard time understanding whether this is worth it. There's a chance this gets broken without warning between two pytests version.

@anntzer
Copy link
Contributor

anntzer commented Sep 7, 2019

The idea looks fine to me, but I agree both with @QuLogic's query about whether this can be done with public API and with @NelleV's point about style.

@anntzer anntzer removed their request for review September 7, 2019 09:55
@tacaswell
Copy link
Member Author

I compressed the code a bit. I'm not convinced it is actually more readable.....

@anntzer anntzer merged commit 45b9201 into matplotlib:master Oct 4, 2019
@tacaswell tacaswell deleted the check_figures_equal_with_parametrize branch October 8, 2019 21:34
@tacaswell tacaswell modified the milestones: v3.3.0, v3.2.1 Mar 16, 2020
@tacaswell
Copy link
Member Author

@meeseeksdev backport to v3.2.x

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants