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

Add default filters #184

Merged
merged 9 commits into from
Feb 26, 2021
Merged

Add default filters #184

merged 9 commits into from
Feb 26, 2021

Conversation

saroad2
Copy link
Contributor

@saroad2 saroad2 commented Feb 20, 2021

Fixes #131

Now, pytest-cases have a bunch of default filter functions to use in order to filter cases.
Those filters can use "and" "or" and "invert" operations in order to create various complex filters.

@smarie
Copy link
Owner

smarie commented Feb 22, 2021

Thanks @saroad2 for this nice PR. In order to ease the review process would you mind creating a very small PR with just the migration of _CaseInfo and _tags_matches_query to pytest_cases/case_info.py first ? Or (faster for your) to revert this part, and propose the file migration later ? That way we'll be able to directly see what has changed in those symbols.

The test is very explicative, thanks.

I'm wondering how this can be documented in the file docs/index.md in addition to the other options. Can you propose some modification in the PR to this section: https://smarie.github.io/python-pytest-cases/#filters-and-tags ? Also finally, since this introduces some API change, you'll have to modify docs/api_reference.md too. Sorry, this is not generated automatically as I find this almost as fast to copy this manually, than to try to find a no-too-bad configuration of sphinx :D

Finally note that #147 has also suggested some evolution of the regex engine (in dedicated ticket #153). I do not think that these are contradictory, that will make one more way to perform the same thing, and developers will choose whatever style they prefer.

@saroad2
Copy link
Contributor Author

saroad2 commented Feb 23, 2021

Hey @smarie ,

As you requested, I moved the _CaseInfo module change to PR #185 .

Also, I added the changes to docs/index.md in this PR.

Unfortunately, I wasn't sure where to add the new API into docs/api_reference.md. I would appreciate it if you would make that change instead.

Let me know if you want me to change anything else!

@smarie
Copy link
Owner

smarie commented Feb 23, 2021

It looks perfect. Ok I'll make the change to api reference myself once merged. Let's merge #185 first

# Conflicts:
#	pytest_cases/case_funcs_new.py
#	pytest_cases/case_info.py
@saroad2
Copy link
Contributor Author

saroad2 commented Feb 24, 2021

Hey @smarie , I merged master into this PR and updated CaseInfo after renaming.

Just add the new API to the documentation and this PR can be merged :)

Would you mind release a new version soon so I could use those new filters?

pytest_cases/filters.py Outdated Show resolved Hide resolved


@parametrize_with_cases(
argnames="value", cases=".", filter=filters.has_prefix("case_t")
Copy link
Owner

Choose a reason for hiding this comment

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

See above: if you had written "data_t" here you would not be able to retrieve anythin, because prefix="case_" and is applied before filters are executed. We should change this to has_id_prefix as suggested above.



@parametrize_with_cases(
argnames="value", cases=".", filter=filters.has_suffix("e")
Copy link
Owner

Choose a reason for hiding this comment

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

Same comment as for prefix: rename id suffix

Comment on lines 49 to 50
def has_prefix(prefix):
return CaseFilter(lambda case: case.__name__.startswith(prefix))
Copy link
Owner

@smarie smarie Feb 24, 2021

Choose a reason for hiding this comment

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

The issue here is that parametrize_with_cases already has a prefix argument, and this is always used. Besides, it is used before the filters are called. Finally it does not take into account overridden ids.

So I suggest that we modify this so that it acts on the case id - that will complement nicely the prefix argument in order to work on the case id, not on the case function name.

Suggested change
def has_prefix(prefix):
return CaseFilter(lambda case: case.__name__.startswith(prefix))
def id_has_prefix(prefix):
"""Select cases that have a case id prefix `prefix`.
Note that this is not the prefix of the whole case function name, but the case id, possibly overridden with `@case(id=)`"""
return CaseFilter(lambda case: CaseInfo.get_from(case).id.startswith(prefix))

Note that tests should be updated accordingly, and the "suffix" filter too.

Comment on lines 53 to 54
def has_suffix(suffix):
return CaseFilter(lambda case: case.__name__.endswith(suffix))
Copy link
Owner

@smarie smarie Feb 24, 2021

Choose a reason for hiding this comment

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

Suggested change
def has_suffix(suffix):
return CaseFilter(lambda case: case.__name__.endswith(suffix))
def id_has_suffix(suffix):
"""Select cases that have a case id suffix `suffix`.
Note that this is not the suffix of the whole case function name, but the case id, possibly overridden with `@case(id=)`
"""
return CaseFilter(lambda case: CaseInfo.get_from(case).id.endswith(prefix))

Comment on lines 57 to 58
def match_regex(regex):
return CaseFilter(lambda case: re.match(regex, case.__name__))
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
def match_regex(regex):
return CaseFilter(lambda case: re.match(regex, case.__name__))
def id_match_regex(regex):
"""Select cases that have a case id matching `regex`.
Note that this is not a match of the whole case function name, but the case id, possibly overridden with `@case(id=)`
"""
return CaseFilter(lambda case: re.match(regex, CaseInfo.get_from(case).id))

@smarie
Copy link
Owner

smarie commented Feb 24, 2021

Thanks @saroad2 , I am deeply sorry to not have spotted this earlier but there are a few issues with the filters you propose: indeed the prefix argument or parametrize_with_cases is always applied at cases collection step, before filters are even applied. So I proposed a few changes where the filters apply always on the case id, not the case function name in order to not bring confusion/impossible filtering.

I am sorry that this takes longer than expected, I understand that this "back and forth" probably extremely frustrating for you... But I am busy most of my time with my employers' duties, and there is a big customer delivery these days.

Unfortunately I received a very bad news today: my travis.com credits are now zero, I made a request for OSS credits but no build (no release) can be done until further notice.

I was planning to migrate all my travis script to nox, so this may force me to do it earlier than expected... Then once it is nox-ified I'll be independent on the build system and therefore be able to integrate in github actions, migrate back to travis, move to circleci... more freely as needed.

Of course I can always do the release manually in the meantime using mkdocs deploy and twine.

@saroad2
Copy link
Contributor Author

saroad2 commented Feb 24, 2021

@smarie , you shouldn't be sorry at all! we are all busy people and we have previous commitments, me too. This is an open source project, and as so everyone knows that it takes time for everything to get in motion. We are not in a hurry, so take your time!

As for the fixes you suggested, I totally agree. You don't need to apologise. I'll shortly make a commit with those changes.

As for Travis, in my experience, I had a lot of troubles with 3rd party CI/CD tools such as CircleCI/Travis/etc.
My suggestion is to migrate everything to Github Actions workflow and avoid using those 3rd parties tools.
Once I made that migration myself on my projects, I started to have a much better experience in my CI/CD process.

@codecov-io
Copy link

codecov-io commented Feb 24, 2021

Codecov Report

Merging #184 (dcc2115) into master (dc1d4ad) will increase coverage by 0.02%.
The diff coverage is 90.32%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #184      +/-   ##
==========================================
+ Coverage   87.59%   87.62%   +0.02%     
==========================================
  Files         147      150       +3     
  Lines        5691     5745      +54     
==========================================
+ Hits         4985     5034      +49     
- Misses        706      711       +5     
Impacted Files Coverage Δ
pytest_cases/case_info.py 86.04% <86.04%> (ø)
pytest_cases/filters.py 88.00% <88.00%> (ø)
pytest_cases/case_funcs_new.py 90.54% <100.00%> (+0.36%) ⬆️
...s/pytest_extension/parametrize_plus/test_filter.py 100.00% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update c95ce37...b6c3837. Read the comment docs.

argnames="value", cases=".", filter=filters.has_tag(B)
)
def test_filter_with_tag(value):
print(value)
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
print(value)
pass

argnames="value", cases=".", filter=~filters.has_tag(B)
)
def test_filter_without_tag(value):
print(value)
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
print(value)
pass

argnames="value", cases=".", filter=filters.has_tag(B) & filters.has_tag(C)
)
def test_filter_with_and_relation(value):
print(value)
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
print(value)
pass

argnames="value", cases=".", filter=filters.has_tag(B) | filters.has_tag(C)
)
def test_filter_with_or_relation(value):
print(value)
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
print(value)
pass

argnames="value", cases=".", filter=filters.id_has_prefix("t")
)
def test_filter_with_prefix(value):
print(value)
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
print(value)
pass

argnames="value", cases=".", filter=filters.id_has_suffix("m")
)
def test_filter_with_suffix(value):
print(value)
Copy link
Owner

@smarie smarie Feb 25, 2021

Choose a reason for hiding this comment

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

Suggested change
print(value)
pass
def test_synthesis(module_results_dct):
assert list(modeul_results_dct) == [
"test_filter_with_tag[tim]",
"test_filter_with_tag[toni]",
"test_filter_without_tag[tom]",
"test_filter_without_tag[dom]",
"test_filter_with_and_relation[toni]",
"test_filter_with_or_relation[tim]",
"test_filter_with_or_relation[toni]",
"test_filter_with_or_relation[dom]",
"test_filter_with_prefix[tom]",
"test_filter_with_prefix[tim]",
"test_filter_with_prefix[toni]",
"test_filter_with_suffix[tom]",
"test_filter_with_suffix[tim]",
"test_filter_with_suffix[dom]",
]

Comment on lines +23 to +24
@case(tags=[A, C], id="dom")
def case_four():
Copy link
Owner

@smarie smarie Feb 25, 2021

Choose a reason for hiding this comment

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

At least one of the examples should have the default id extracted from the function name

Suggested change
@case(tags=[A, C], id="dom")
def case_four():
@case(tags=[A, C])
def case_dom():

@smarie
Copy link
Owner

smarie commented Feb 25, 2021

Thanks for your understanding @saroad2 .

Final round of review: the test should be a meta-test as all others, in other words we should use pytest-harvest to collect the list of test ids in the module and test that this list is correct. The prints can be discarded.

I suggested this in the comments, as you'll see. Can you make sure that it passes ? Indeed I did not try locally, I did it directly in github web page :)

@saroad2
Copy link
Contributor Author

saroad2 commented Feb 26, 2021

Hey @smarie .

I made the final change and all tests passed locally. The only thing I didn't manage to do is to change case_four to case_dom. The id of that case was changed and I don't know why.

Other than this, everything looks great :)

@smarie
Copy link
Owner

smarie commented Feb 26, 2021

Perfect, thanks @saroad2 ! Merging now

@smarie smarie merged commit d8cb440 into smarie:master Feb 26, 2021
@smarie smarie mentioned this pull request Feb 26, 2021
@saroad2 saroad2 deleted the add_default_filters branch February 28, 2021 16:07
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.

Run all case *without* a tag
3 participants