Repository: bids-standard/pybids

Issue:
Warn or error on misspecified (or changed due to pybids changes) target value
Going through the tutorial I saw that 
```python
# See all modality labels in this dataset
layout.get(return_type='id', target='modality')
```
is no longer producing any output (well - returns an empty list) although before was reporting `['anat', 'fmap', 'func']`.  Even though I know now -- CHANGELOG helps, it is `datatype` which is actually nothing -- I think it is an overall usability aspect. If I am asking to return some specific target, I can assume that there must be one defined/known, and then if nothing is actually returned, I would have appreciated to list what are the available "targets" here.  So, by default, I would have even appreciated an exception like `TargetNotFound` which ideally would have a list of available targets in its message or str; and may be optionally have a mode to just skip unknown targets. Not sure if that is something to be done on pybids or grabbit level, and not sure if I am missing some "flexibility" issue here that targets could be some arbitrary thing?

Discussion:

Patch:
diff --git a/bids/layout/layout.py b/bids/layout/layout.py
index c7624631..0e4874b7 100644
--- a/bids/layout/layout.py
+++ b/bids/layout/layout.py
@@ -397,6 +397,18 @@ class BIDSLayout(Layout):
             else:
                 md_kwargs[k] = v
 
+        # Provide some suggestions if target is specified and invalid.
+        if target is not None and target not in all_ents:
+            import difflib
+            potential = list(all_ents.keys())
+            suggestions = difflib.get_close_matches(target, potential)
+            if suggestions:
+                message = "Did you mean one of: {}?".format(suggestions)
+            else:
+                message = "Valid targets are: {}".format(potential)
+            raise ValueError(("Unknown target '{}'. " + message)
+                             .format(target))
+
         all_results = []
 
         # Get entity-based search results using the superclass's get()


Test patch:
diff --git a/bids/layout/tests/test_layout.py b/bids/layout/tests/test_layout.py
index f6ccc122..57733f52 100644
--- a/bids/layout/tests/test_layout.py
+++ b/bids/layout/tests/test_layout.py
@@ -135,6 +135,17 @@ def test_get_metadata_via_bidsfile(layout_7t_trt):
     assert 'subject' not in result
 
 
+def test_get_with_bad_target(layout_7t_trt):
+    with pytest.raises(ValueError) as exc:
+        layout_7t_trt.get(target='unicorn')
+        msg = exc.value.message
+        assert 'subject' in msg and 'reconstruction' in msg and 'proc' in msg
+    with pytest.raises(ValueError) as exc:
+        layout_7t_trt.get(target='sub')
+        msg = exc.value.message
+        assert 'subject' in msg and 'reconstruction' not in msg
+
+
 def test_get_bvals_bvecs(layout_ds005):
     dwifile = layout_ds005.get(subject="01", datatype="dwi")[0]
     result = layout_ds005.get_bval(dwifile.path)