Repository: dr-leo/pandaSDMX (python)

Issue:
Check tab-completion of Request convenience methods
As raised by @dr-leo via e-mail:
> In [9]: flows=ecb.dataflow()
> In [10]: flows
> Out[10]: <StructureMessage header=<Header error=None id='IDREF291392' prepared='
2019-07-21T16:00:17' receiver='no… footer=None response=<Response [200]> categor
y_scheme=DictLike() codelist=DictLike() concept_scheme=DictLike() constraint=Dic
tLike() dataflow=DictLike([('AME', <DataflowDefinition: 'AME'='AMECO'>), ('BKN',
 <DataflowDefini… structure=DictLike() organisation_scheme=DictLike() provisiona
greement=DictLike
>
> ---
> tab completion does not work on my box when I issue: 'ecb.datafl...'. Might be unrelated to your code. Should doublecheck with v0.9.

In 0.9, additional methods were added to Request using a helper class and method:
https://github.com/dr-leo/pandaSDMX/blob/16950d60fd7be933543cff2c26e8a11e1fd7433e/pandasdmx/api.py#L87-L93

In 1.0, these are handed by `__getattr__` and the `Resource` enum, which has the full list of members.
https://github.com/dr-leo/pandaSDMX/blob/28f6be45733e5cb7549c4c6dae215a28b6a0e676/pandasdmx/api.py#L67-L69

For tab-completion to work, the solution is to [override `__dir__`](https://docs.python.org/3/reference/datamodel.html#object.__dir__).

Pull request description:
Include Request convenience methods in interactive tab-completion
Closes #88.

Patch:
diff --git a/pandasdmx/api.py b/pandasdmx/api.py
index b2ce935..533f2b7 100644
--- a/pandasdmx/api.py
+++ b/pandasdmx/api.py
@@ -61,6 +61,10 @@ class Request:
         """Convenience methods."""
         return partial(self.get, Resource[name])
 
+    def __dir__(self):
+        """Include convenience methods in dir()."""
+        return sorted(super().__dir__() + [ep.name for ep in Resource])
+
     def clear_cache(self):
         self.cache.clear()
 


Test patch:
diff --git a/tests/test_api.py b/tests/test_api.py
index ba977df..a4cff49 100644
--- a/tests/test_api.py
+++ b/tests/test_api.py
@@ -34,12 +34,11 @@ def test_open_file(tmp_path):
         sdmx.open_file(bad_file)
 
 
-
 def test_request():
     # Constructor
     r = sdmx.Request(log_level=logging.ERROR)
 
-    # Invalid agency name (replaces former test_request.py)
+    # Invalid source name raise an exception
     with pytest.raises(ValueError):
         sdmx.Request('noagency')
 
@@ -49,6 +48,12 @@ def test_request():
     r.timeout = 300
     assert r.timeout == 300
 
+    # dir() includes convenience methods for resource endpoints
+    expected = {'cache', 'clear_cache', 'get', 'preview_data', 'series_keys',
+                'session', 'source', 'timeout'}
+    expected |= set(ep.name for ep in sdmx.Resource)
+    assert set(filter(lambda s: not s.startswith('_'), dir(r))) == expected
+
 
 def test_request_get_exceptions():
     """Tests of Request.get() that don't require remote data."""