From c492d96602f623ba7a6e8862c342ca926912ccae Mon Sep 17 00:00:00 2001 From: danielhrisca Date: Thu, 16 May 2019 14:38:53 +0300 Subject: [PATCH 1/7] fix calling local references with keyword arguments in query --- pandas/core/computation/expr.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pandas/core/computation/expr.py b/pandas/core/computation/expr.py index cb9d537e61ebc..0e5372fa1b755 100644 --- a/pandas/core/computation/expr.py +++ b/pandas/core/computation/expr.py @@ -633,9 +633,7 @@ def visit_Call(self, node, side=None, **kwargs): "'{func}'".format(func=node.func.id)) if key.arg: - # TODO: bug? - kwargs.append(ast.keyword( - keyword.arg, self.visit(keyword.value))) # noqa + kwargs[key.arg] = self.visit(key.value).value return self.const_type(res(*new_args, **kwargs), self.env) From 634dc0609c789ad8f4a563d3925e67eaf317b399 Mon Sep 17 00:00:00 2001 From: danielhrisca Date: Thu, 16 May 2019 15:21:36 +0300 Subject: [PATCH 2/7] add test --- pandas/tests/computation/test_eval.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/pandas/tests/computation/test_eval.py b/pandas/tests/computation/test_eval.py index 69c05ccfe9818..9d329b3607945 100644 --- a/pandas/tests/computation/test_eval.py +++ b/pandas/tests/computation/test_eval.py @@ -1345,6 +1345,33 @@ def test_multi_line_expression_local_variable(self): assert_frame_equal(expected, df) assert ans is None + def test_multi_line_expression_callable_local_variable(self): + # GH 15342 + df = pd.DataFrame({'a': [1, 2, 3], 'b': [4, 5, 6]}) + + def local_func(a, b): + return b + + expected = df.copy() + expected['c'] = expected['a'] * local_func(1, 7) + expected['d'] = expected['c'] + local_func(1, 7) + ans = df.eval(""" + c = a * @local_func(1, 7) + d = c + @local_func(1, 7) + """, inplace=True) + assert_frame_equal(expected, df) + assert ans is None + + expected = df.copy() + expected['c'] = expected['a'] * local_func(b=7, a=1) + expected['d'] = expected['c'] + local_func(b=7, a=1) + ans = df.eval(""" + c = a * @local_func(b=7, a=1) + d = c + @local_func(b=7, a=1) + """, inplace=True) + assert_frame_equal(expected, df) + assert ans is None + def test_assignment_in_query(self): # GH 8664 df = pd.DataFrame({'a': [1, 2, 3], 'b': [4, 5, 6]}) From 49dae52a671e22a1b8270536ee34dd91b48e8582 Mon Sep 17 00:00:00 2001 From: danielhrisca Date: Sat, 18 May 2019 13:32:30 +0300 Subject: [PATCH 3/7] split test into separate functions --- pandas/tests/computation/test_eval.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pandas/tests/computation/test_eval.py b/pandas/tests/computation/test_eval.py index 9d329b3607945..190030b05e4aa 100644 --- a/pandas/tests/computation/test_eval.py +++ b/pandas/tests/computation/test_eval.py @@ -1346,7 +1346,6 @@ def test_multi_line_expression_local_variable(self): assert ans is None def test_multi_line_expression_callable_local_variable(self): - # GH 15342 df = pd.DataFrame({'a': [1, 2, 3], 'b': [4, 5, 6]}) def local_func(a, b): @@ -1362,6 +1361,12 @@ def local_func(a, b): assert_frame_equal(expected, df) assert ans is None + def test_multi_line_expression_callable_local_variable_with_kwargs(self): + df = pd.DataFrame({'a': [1, 2, 3], 'b': [4, 5, 6]}) + + def local_func(a, b): + return b + expected = df.copy() expected['c'] = expected['a'] * local_func(b=7, a=1) expected['d'] = expected['c'] + local_func(b=7, a=1) From 9e497df409e6d5198f33eebf39afebea87852bac Mon Sep 17 00:00:00 2001 From: danielhrisca Date: Sat, 18 May 2019 19:42:29 +0300 Subject: [PATCH 4/7] add whatsnew entry --- doc/source/whatsnew/v0.25.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v0.25.0.rst b/doc/source/whatsnew/v0.25.0.rst index d38ee7b8b589a..cf27186cb0d2a 100644 --- a/doc/source/whatsnew/v0.25.0.rst +++ b/doc/source/whatsnew/v0.25.0.rst @@ -295,7 +295,6 @@ Bug Fixes ~~~~~~~~~ - Categorical ^^^^^^^^^^^ @@ -475,6 +474,7 @@ Other - Removed unused C functions from vendored UltraJSON implementation (:issue:`26198`) - Bug in :func:`factorize` when passing an ``ExtensionArray`` with a custom ``na_sentinel`` (:issue:`25696`). - Allow :class:`Index` and :class:`RangeIndex` to be passed to numpy ``min`` and ``max`` functions. +- Allow keyword arguments for callable local reference used in the ``DataFrame.query`` string .. _whatsnew_0.250.contributors: From 169729a607028b9f036b031ec2944384fbff7ad7 Mon Sep 17 00:00:00 2001 From: Daniel Hrisca Date: Sun, 19 May 2019 21:40:48 +0300 Subject: [PATCH 5/7] Update v0.25.0.rst --- doc/source/whatsnew/v0.25.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v0.25.0.rst b/doc/source/whatsnew/v0.25.0.rst index cf27186cb0d2a..1ac7ad8deda5a 100644 --- a/doc/source/whatsnew/v0.25.0.rst +++ b/doc/source/whatsnew/v0.25.0.rst @@ -375,6 +375,7 @@ Indexing - Bug in :meth:`DataFrame.loc` and :meth:`Series.loc` where ``KeyError`` was not raised for a ``MultiIndex`` when the key was less than or equal to the number of levels in the :class:`MultiIndex` (:issue:`14885`). - Bug in which :meth:`DataFrame.append` produced an erroneous warning indicating that a ``KeyError`` will be thrown in the future when the data to be appended contains new columns (:issue:`22252`). - Bug in which :meth:`DataFrame.to_csv` caused a segfault for a reindexed data frame, when the indices were single-level :class:`MultiIndex` (:issue:`26303`). +- Allow keyword arguments for callable local reference used in the :method:`DataFrame.query` string (PR 26426) Missing @@ -474,7 +475,6 @@ Other - Removed unused C functions from vendored UltraJSON implementation (:issue:`26198`) - Bug in :func:`factorize` when passing an ``ExtensionArray`` with a custom ``na_sentinel`` (:issue:`25696`). - Allow :class:`Index` and :class:`RangeIndex` to be passed to numpy ``min`` and ``max`` functions. -- Allow keyword arguments for callable local reference used in the ``DataFrame.query`` string .. _whatsnew_0.250.contributors: From b31ff8bd8afec89acab5bf611e975fbad18cfeb3 Mon Sep 17 00:00:00 2001 From: danielhrisca Date: Sun, 19 May 2019 21:49:36 +0300 Subject: [PATCH 6/7] add PR reference in the tests --- pandas/tests/computation/test_eval.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pandas/tests/computation/test_eval.py b/pandas/tests/computation/test_eval.py index 190030b05e4aa..ca78e2e40ec74 100644 --- a/pandas/tests/computation/test_eval.py +++ b/pandas/tests/computation/test_eval.py @@ -1346,6 +1346,7 @@ def test_multi_line_expression_local_variable(self): assert ans is None def test_multi_line_expression_callable_local_variable(self): + # 26426 df = pd.DataFrame({'a': [1, 2, 3], 'b': [4, 5, 6]}) def local_func(a, b): @@ -1362,6 +1363,7 @@ def local_func(a, b): assert ans is None def test_multi_line_expression_callable_local_variable_with_kwargs(self): + # 26426 df = pd.DataFrame({'a': [1, 2, 3], 'b': [4, 5, 6]}) def local_func(a, b): From c7d58af040527fff845a44ff6dac30ac0d7af6b7 Mon Sep 17 00:00:00 2001 From: Daniel Hrisca Date: Sun, 19 May 2019 22:32:07 +0300 Subject: [PATCH 7/7] Update v0.25.0.rst --- doc/source/whatsnew/v0.25.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v0.25.0.rst b/doc/source/whatsnew/v0.25.0.rst index ea43d2b89e7e1..84f9fd8906dbf 100644 --- a/doc/source/whatsnew/v0.25.0.rst +++ b/doc/source/whatsnew/v0.25.0.rst @@ -379,7 +379,7 @@ Indexing - Bug in which :meth:`DataFrame.append` produced an erroneous warning indicating that a ``KeyError`` will be thrown in the future when the data to be appended contains new columns (:issue:`22252`). - Bug in which :meth:`DataFrame.to_csv` caused a segfault for a reindexed data frame, when the indices were single-level :class:`MultiIndex` (:issue:`26303`). - Fixed bug where assigning a :class:`arrays.PandasArray` to a :class:`pandas.core.frame.DataFrame` would raise error (:issue:`26390`) -- Allow keyword arguments for callable local reference used in the :method:`DataFrame.query` string (PR 26426) +- Allow keyword arguments for callable local reference used in the :method:`DataFrame.query` string (:issue:`26426`) Missing