forked from pyjanitor-devs/pyjanitor
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[ENH] Add
.also()
inspired by Kotlin (pyjanitor-devs#735)
* add basic implementation with wip docs * add also to general_functions page * add tests for also * add tests for args and kwargs * workshop docstring * workshop func explanation * add contribution artifacts * fix docstring codeblock rendering * fix typo * silence accepted flake8 errors * Add docstrings for tests * Update tests/functions/test_also.py * make tests pass in python 3.6 * remove tuple unpacking Co-authored-by: Eric Ma <[email protected]>
- Loading branch information
Showing
5 changed files
with
124 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -80,6 +80,7 @@ Other | |
:toctree: janitor.functions/ | ||
|
||
then | ||
also | ||
shuffle | ||
count_cumulative_unique | ||
sort_naturally | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
"""Unit tests for `.also()`.""" | ||
from unittest.mock import Mock | ||
import pytest | ||
|
||
|
||
def remove_first_two_letters_from_col_names(df): | ||
"""Helper function to mutate dataframe by changing column names.""" | ||
col_names = df.columns | ||
col_names = [name[2:] for name in col_names] | ||
df.columns = col_names | ||
return df | ||
|
||
|
||
def remove_rows_3_and_4(df): | ||
"""Helper function to mutate dataframe by removing rows.""" | ||
df = df.drop(3, axis=0) | ||
df = df.drop(4, axis=0) | ||
return df | ||
|
||
|
||
def drop_inplace(df): | ||
""" | ||
Helper function to mutate dataframe by dropping a column. | ||
We usually would not use `inplace=True` in a block, | ||
but the intent here is to test that | ||
the in-place modification of a dataframe | ||
doesn't get passed through in the `.also()` function. | ||
Hence, we tell Flake8 to skip checking `PD002` on that line. | ||
""" | ||
df.drop(columns=[df.columns[0]], inplace=True) # noqa: PD002 | ||
|
||
|
||
@pytest.mark.functions | ||
def test_also_column_manipulation_no_change(dataframe): | ||
"""Test that changed dataframe inside `.also()` doesn't get returned.""" | ||
cols = tuple(dataframe.columns) | ||
df = dataframe.also(remove_first_two_letters_from_col_names) | ||
assert dataframe is df | ||
assert cols == tuple(df.columns) | ||
|
||
|
||
@pytest.mark.functions | ||
def test_also_remove_rows_no_change(dataframe): | ||
"""Test that changed dataframe inside `.also()` doesn't get returned.""" | ||
df = dataframe.also(remove_rows_3_and_4) | ||
rows = tuple(df.index) | ||
assert rows == (0, 1, 2, 3, 4, 5, 6, 7, 8) | ||
|
||
|
||
@pytest.mark.functions | ||
def test_also_runs_function(dataframe): | ||
"""Test that `.also()` executes the function.""" | ||
method = Mock(return_value=None) | ||
df = dataframe.also(method) | ||
assert id(df) == id(dataframe) | ||
assert method.call_count == 1 | ||
|
||
|
||
@pytest.mark.functions | ||
def test_also_args(dataframe): | ||
"""Test that the args are passed through to the function.""" | ||
method = Mock(return_value=None) | ||
_ = dataframe.also(method, 5) | ||
|
||
assert method.call_args[0][1] == 5 | ||
|
||
|
||
@pytest.mark.functions | ||
def test_also_kwargs(dataframe): | ||
"""Test that the kwargs are passed through to the function.""" | ||
method = Mock(return_value=None) | ||
_ = dataframe.also(method, n=5) | ||
|
||
assert method.call_args[1] == {"n": 5} | ||
|
||
|
||
@pytest.mark.functions | ||
def test_also_drop_inplace(dataframe): | ||
"""Test that in-place modification of dataframe does not pass through.""" | ||
cols = tuple(dataframe.columns) | ||
df = dataframe.also(drop_inplace) | ||
assert tuple(df.columns) == cols |