nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: theacodes/nox
Pull request #493 (2021-10-06 01:44:18)

Show error message when keywords expression contains a syntax error
Related to #492.

Currently, providing a `--keywords` argument that is not a valid expression causes Nox to crash with a SyntaxError.

```
$ nox -k 'foo:bar'
Traceback (most recent call last):
  ...
  File "<string>", line 1
    foo:bar
       ^
SyntaxError: invalid syntax
```

This change validates the keywords argument using [ast.parse](https://docs.python.org/3/library/ast.html#ast.parse) and prints an error message if it is not a valid expression.

```
$ nox -k 'foo:bar'
nox > Error while collecting sessions: keywords argument must be a Python expression.
```


Patch:
diff --git a/nox/tasks.py b/nox/tasks.py
index 5226332..918f3f1 100644
--- a/nox/tasks.py
+++ b/nox/tasks.py
@@ -12,6 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import ast
 import importlib.machinery
 import io
 import json
@@ -150,9 +151,17 @@ def filter_manifest(
         manifest.filter_by_python_interpreter(global_config.pythons)
 
     # Filter by keywords.
-    # This function never errors, but may cause an empty list of sessions
-    # (which is an error condition later).
     if global_config.keywords:
+        try:
+            ast.parse(global_config.keywords, mode="eval")
+        except SyntaxError:
+            logger.error(
+                "Error while collecting sessions: keywords argument must be a Python expression."
+            )
+            return 3
+
+        # This function never errors, but may cause an empty list of sessions
+        # (which is an error condition later).
         manifest.filter_by_keywords(global_config.keywords)
 
     # Return the modified manifest.


Test patch:
diff --git a/tests/test_tasks.py b/tests/test_tasks.py
index c8edb8a..6ce4e50 100644
--- a/tests/test_tasks.py
+++ b/tests/test_tasks.py
@@ -233,6 +233,15 @@ def test_filter_manifest_keywords():
     assert len(manifest) == 2
 
 
+def test_filter_manifest_keywords_syntax_error():
+    config = _options.options.namespace(
+        sessions=(), pythons=(), keywords="foo:bar", posargs=[]
+    )
+    manifest = Manifest({"foo_bar": session_func, "foo_baz": session_func}, config)
+    return_value = tasks.filter_manifest(manifest, config)
+    assert return_value == 3
+
+
 def test_honor_list_request_noop():
     config = _options.options.namespace(list_sessions=False)
     manifest = {"thing": mock.sentinel.THING}