Repository: rucio/rucio

Issue:
rucio list-dids -h should expose the list of available options
Motivation
----------
rucio list-dids -h
usage: rucio list-dids [-h] [--recursive] [--filter FILTER] [--short] did

List the Data IDentifiers matching certain pattern. Only the collections (i.e.
dataset or container) are returned by default. With the filter option, you can
specify a list of metadata that the Data IDentifier should match.

positional arguments:                                                                                                                                                                                                                                                          
  did              Data IDentifier pattern                                                                                                                                                                                                                                     
                                                                                                                                                                                                                                                                               
optional arguments:
  -h, --help       show this help message and exit
  --recursive      List data identifiers recursively.
  --filter FILTER  Filter arguments in form
                   `key=value,another_key=next_value`. Valid keys are name,
                   type.
  --short          Just dump the list of DIDs.

There is no list of available filter options

Modification
------------
rucio list-dids -h should expose the list of available options



Discussion:

Resolving patch:
diff --git a/lib/rucio/core/did.py b/lib/rucio/core/did.py
--- a/lib/rucio/core/did.py
+++ b/lib/rucio/core/did.py
@@ -22,6 +22,7 @@
 # - Thomas Beermann <thomas.beermann@cern.ch>, 2013-2018
 # - Joaquin Bogado <jbogado@linti.unlp.edu.ar>, 2014-2015
 # - Wen Guan <wguan.icedew@gmail.com>, 2015
+# - Hannes Hansen <hannes.jakob.hansen@cern.ch>, 2018
 
 import json
 import logging
@@ -1475,7 +1476,7 @@ def set_status(scope, name, session=None, **kwargs):
 @stream_session
 def list_dids(scope, filters, type='collection', ignore_case=False, limit=None,
               offset=None, long=False, session=None):
-    """0
+    """
     Search data identifiers
 
     :param scope: the scope name.
@@ -1517,7 +1518,7 @@ def list_dids(scope, filters, type='collection', ignore_case=False, limit=None,
 
     for (k, v) in filters.items():
 
-        if k not in ['created_before', 'created_after'] \
+        if k not in ['created_before', 'created_after', 'length.gt', 'length.lt', 'length.lte', 'length.gte', 'length'] \
            and not hasattr(models.DataIdentifier, k):
             raise exception.KeyNotFound(k)
 
@@ -1540,6 +1541,16 @@ def list_dids(scope, filters, type='collection', ignore_case=False, limit=None,
         elif k == 'guid':
             query = query.filter_by(guid=v).\
                 with_hint(models.ReplicaLock, "INDEX(DIDS_GUIDS_IDX)", 'oracle')
+        elif k == 'length.gt':
+            query = query.filter(models.DataIdentifier.length > v)
+        elif k == 'length.lt':
+            query = query.filter(models.DataIdentifier.length < v)
+        elif k == 'length.gte':
+            query = query.filter(models.DataIdentifier.length >= v)
+        elif k == 'length.lte':
+            query = query.filter(models.DataIdentifier.length <= v)
+        elif k == 'length':
+            query = query.filter(models.DataIdentifier.length == v)
         else:
             query = query.filter(getattr(models.DataIdentifier, k) == v)
 


Test patch:
diff --git a/lib/rucio/tests/test_did.py b/lib/rucio/tests/test_did.py
--- a/lib/rucio/tests/test_did.py
+++ b/lib/rucio/tests/test_did.py
@@ -21,6 +21,7 @@
 # - Yun-Pin Sun <winter0128@gmail.com>, 2013
 # - Thomas Beermann <thomas.beermann@cern.ch>, 2013-2018
 # - Joaquin Bogado <jbogado@linti.unlp.edu.ar>, 2018
+# - Hannes Hansen <hannes.jakob.hansen@cern.ch>, 2018
 
 from __future__ import print_function
 
@@ -243,6 +244,31 @@ def test_list_dids(self):
         with assert_raises(UnsupportedOperation):
             self.did_client.list_dids(tmp_scope, {'name': 'file*'}, type='whateverytype')
 
+    def test_list_by_length(self):
+        """ DATA IDENTIFIERS (CLIENT): List did with length """
+        tmp_scope = 'mock'
+
+        tmp_dsn3 = 'dsn_%s' % generate_uuid()
+        self.did_client.add_dataset(scope=tmp_scope, name=tmp_dsn3)
+
+        dids = self.did_client.list_dids(tmp_scope, {'length.gt': 0})
+        results = []
+        for d in dids:
+            results.append(d)
+        assert_not_equal(len(results), 0)
+
+        dids = self.did_client.list_dids(tmp_scope, {'length.gt': -1, 'length.lt': 1})
+        results = []
+        for d in dids:
+            results.append(d)
+        assert_equal(len(results), 0)
+
+        dids = self.did_client.list_dids(tmp_scope, {'length': 0})
+        results = []
+        for d in dids:
+            results.append(d)
+        assert_equal(len(results), 0)
+
     def test_list_by_metadata(self):
         """ DATA IDENTIFIERS (CLIENT): List did with metadata"""
         dsns = []