Repository: planetlabs/planet-client-python

Issue:
Don't require a filter for a quick search.
To solve the issues below, do the following:
1. In quick search, make filter a named option (`--filter` for CLI, `search_filter` for api), if not supplied then no filtering will take place
2. Change `planet data filter` to output an empty filter (no filtering) by default so that `planet data filter | planet search PSScene --filter -` has the same behavior as `planet search PSScene` - this resolves #704 

---

If I try to do a quick search with no filter I get:

```
% planet data search-quick PSScene                                                              

Usage: planet data search-quick [OPTIONS] ITEM_TYPES FILTER

Try 'planet data search-quick --help' for help.

Error: Missing argument 'FILTER'.
```

In v1 doing a search without a filter would just show you the latest data. 

Right now you can do `planet data filter | planet data search-quick SkysatCollect -`, since filter outputs `{"type": "PermissionFilter", "config": ["assets:download"]}` by default.

But then if you didn't want to only search downloadable assets you could do:

`planet data filter --permission false | planet data search-quick SkysatCollect -` and then you get a failure, since the latter doesn't actually output a filter, it emits nothing.



Discussion:

Patch:
diff --git a/planet/cli/data.py b/planet/cli/data.py
index 5f13850..d2cea4c 100644
--- a/planet/cli/data.py
+++ b/planet/cli/data.py
@@ -218,12 +218,8 @@ def filter(ctx,
             else:
                 filters.append(f)
 
-    if filters:
-        if len(filters) > 1:
-            filt = data_filter.and_filter(filters)
-        else:
-            filt = filters[0]
-        echo_json(filt, pretty)
+    filt = data_filter.and_filter(filters)
+    echo_json(filt, pretty)
 
 
 @data.command()
diff --git a/planet/clients/data.py b/planet/clients/data.py
index 471f2f4..94266c0 100644
--- a/planet/clients/data.py
+++ b/planet/clients/data.py
@@ -109,6 +109,21 @@ class DataClient:
         `name` parameter of the search defaults to the id of the generated
         search id if `name` is not specified.
 
+        To filter to items you have access to download which are of standard
+        (aka not test) quality, use the following:
+
+        ```python
+        >>> from planet import data_filter
+        >>> data_filter.and_filter([
+        ...     data_filter.permission_filter(),
+        ...     data_filter.std_quality_filter()
+        >>> ])
+
+        ```
+
+        To avoid filtering out any imagery, supply a blank AndFilter, which can
+        be created with `data_filter.and_filter([])`.
+
         Example:
 
         ```python
@@ -176,6 +191,22 @@ class DataClient:
                             enable_email: bool = False) -> dict:
         """Create a new saved structured item search.
 
+        To filter to items you have access to download which are of standard
+        (aka not test) quality, use the following:
+
+        ```python
+        >>> from planet import data_filter
+        >>> data_filter.and_filter([
+        ...     data_filter.permission_filter(),
+        ...     data_filter.std_quality_filter()
+        >>> ])
+
+        ```
+
+        To avoid filtering out any imagery, supply a blank AndFilter, which can
+        be created with `data_filter.and_filter([])`.
+
+
         Parameters:
             name: The name of the saved search.
             item_types: The item types to include in the search.


Test patch:
diff --git a/tests/integration/test_data_cli.py b/tests/integration/test_data_cli.py
index 60a1a64..62eabf1 100644
--- a/tests/integration/test_data_cli.py
+++ b/tests/integration/test_data_cli.py
@@ -105,13 +105,8 @@ def test_data_filter_defaults(permission,
     assert result.exit_code == 0
 
     [default_filters.remove(rem) for rem in [p_remove, s_remove] if rem]
-    if len(default_filters) > 1:
-        expected_filt = {"type": "AndFilter", "config": default_filters}
-        assert_and_filters_equal(json.loads(result.output), expected_filt)
-    elif len(default_filters) == 1:
-        assert json.loads(result.output) == default_filters[0]
-    else:
-        assert result.output == ''
+    expected_filt = {"type": "AndFilter", "config": default_filters}
+    assert_and_filters_equal(json.loads(result.output), expected_filt)
 
 
 @respx.mock