Repository: Picterra/picterra-python

Issue:
Add list detectors endpoint

Discussion:

Patch:
diff --git a/examples/detectors_management.py b/examples/detectors_management.py
new file mode 100644
index 0000000..56ff82f
--- /dev/null
+++ b/examples/detectors_management.py
@@ -0,0 +1,14 @@
+import json
+from picterra import APIClient
+
+# Set the PICTERRA_API_KEY environment variable to define your API key
+client = APIClient()
+
+# Create a new detector (its type is 'count' by default)
+detector_id = client.create_detector('My first detector')
+
+
+# List existing detectors
+for d in client.list_detectors():
+    print('detector id=%s, name=%s, detection_type=%s, output_type=%s, training_steps=%d' % (
+        d['id'], d['name'], d['detection_type'], d['output_type'], d['training_steps']))
\ No newline at end of file
diff --git a/src/picterra/client.py b/src/picterra/client.py
index 45d8adf..50b68bc 100644
--- a/src/picterra/client.py
+++ b/src/picterra/client.py
@@ -58,6 +58,19 @@ class APIClient():
                 raise APIError('Operation %s failed' % operation_id)
             time.sleep(poll_interval)
 
+    def _paginate_through_list(self, resource_endpoint: str):
+        url = self._api_url('%s/?page_number=1' % resource_endpoint)
+        data = []
+        while url:
+            logger.debug('Paginating through %s list at page %s' % (resource_endpoint, url))
+            resp = self.sess.get(url)
+            r = resp.json()
+            url = r['next']
+            count = r['count']
+            data += r['results']
+        assert len(data) == count
+        return data
+
     def upload_raster(self, filename, name, folder_id=None):
         """
         Upload a raster to picterra.
@@ -122,17 +135,7 @@ class APIClient():
                 }
 
         """
-        url = self._api_url('rasters/?page_number=1')
-        data = []
-        while url:
-            logger.debug('Paginating through rasters list at page %s' % url)
-            resp = self.sess.get(url)
-            r = resp.json()
-            url = r['next']
-            count = r['count']
-            data += r['results']
-        assert len(data) == count
-        return data
+        return self._paginate_through_list('rasters')
 
     def delete_raster(self, raster_id):
         """
@@ -238,6 +241,33 @@ class APIClient():
             raise APIError(resp.text)
         return resp.json()['id']
 
+    def list_detectors(self):
+        """
+        Returns:
+            A list of detectors dictionaries
+
+        Example:
+
+            ::
+
+                {
+                    'id': '42',
+                    'detection_type': 'count',
+                    'name': 'cow detector',
+                    'output_type': 'bbox',
+                    'training_steps': 787
+                },
+                {
+                    'id': '43',
+                    'detection_type': 'segmentation',
+                    'name': 'test5',
+                    'output_type': 'polygon',
+                    'training_steps': 500
+                }
+
+        """
+        return self._paginate_through_list('detectors')
+
     def run_detector(self, detector_id, raster_id):
         """
         Runs a detector on a raster


Test patch:
diff --git a/tests/test_client.py b/tests/test_client.py
index bb7145e..89d5f51 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -38,6 +38,25 @@ def add_mock_rasters_list_response():
     responses.add(responses.GET, api_url('rasters/?page_number=2'), json=data2, status=200)
 
 
+def add_mock_detectors_list_response():
+    data1 = {
+        "count": 4, "next": api_url('detectors/?page_number=2'), "previous": None, "page_size": 2,
+        "results": [
+            {"id": "40", "type": "count", "name": "detector1"},
+            {"id": "41", "type": "count", "name": "detector2"}
+        ]
+    }
+    data2 = {
+        "count": 4, "next": None, "previous": api_url('detectors/?page_number=1'), "page_size": 2,
+        "results": [
+            {"id": "42", "type": "count", "name": "detector3"},
+            {"id": "43", "type": "count", "name": "detector4"}
+        ]
+    }
+    responses.add(responses.GET, api_url('detectors/?page_number=1'), json=data1, status=200)
+    responses.add(responses.GET, api_url('detectors/?page_number=2'), json=data2, status=200)
+
+
 def add_mock_detector_creation_response():
     responses.add(responses.POST, api_url('detectors/'), json={'id': 'foobar'}, status=201)
 
@@ -270,6 +289,15 @@ def test_detector_creation():
     assert detector == 'foobar'
 
 
+@responses.activate
+def test_list_detectors():
+    client = _client()
+    add_mock_detectors_list_response()
+    detectors = client.list_detectors()
+    assert detectors[0]['name'] == 'detector1'
+    assert detectors[1]['name'] == 'detector2'
+
+
 @responses.activate
 def test_set_raster_detection_areas_from_file():
     add_mock_detection_areas_upload_responses(1)