Repository: ros-infrastructure/rosdep

Issue:
`rosdep resolve` on version 0.16.2 yields `TypeError`
I installed `rosdep` from PyPI. `rosdep resolve` yields the failing the stack trace below:
```
acarrillo ~ $ rosdep resolve

ERROR: Rosdep experienced an error: argument of type 'NoneType' is not iterable
Please go to the rosdep page [1] and file a bug report with the stack trace below.
[1] : http://www.ros.org/wiki/rosdep

rosdep version: 0.16.2

Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/rosdep2/main.py", line 144, in rosdep_main
    exit_code = _rosdep_main(args)
  File "/usr/local/lib/python2.7/dist-packages/rosdep2/main.py", line 406, in _rosdep_main
    if os.environ['ROS_DISTRO'] in python_versions:
TypeError: argument of type 'NoneType' is not iterable
```

Discussion:
acarrillo: @sloretz yup looks good thanks for the quick fix! :+1: Performed an editable `rosdep` install from source and was able to `rosdep update`
```
acarrillo $ rosdep update
reading in sources list data from /etc/ros/rosdep/sources.list.d
Hit file:///etc/ros/rosdep/farmwise.yaml
Hit https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/osx-homebrew.yaml
Hit https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/base.yaml
Hit https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/python.yaml
Hit https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/ruby.yaml
Hit https://raw.githubusercontent.com/ros/rosdistro/master/releases/fuerte.yaml
Query rosdistro index https://raw.githubusercontent.com/ros/rosdistro/master/index-v4.yaml
Skip end-of-life distro "ardent"
Skip end-of-life distro "bouncy"
Add distro "crystal"
Add distro "dashing"
Add distro "eloquent"
Skip end-of-life distro "groovy"
Skip end-of-life distro "hydro"
Skip end-of-life distro "indigo"
Skip end-of-life distro "jade"
Add distro "kinetic"
Skip end-of-life distro "lunar"
Add distro "melodic"
Add distro "noetic"
updated cache in /home/acarrillo/.ros/rosdep/sources.cache

```
codecov-io: # [Codecov](https://codecov.io/gh/ros-infrastructure/rosdep/pull/721?src=pr&el=h1) Report
> Merging [#721](https://codecov.io/gh/ros-infrastructure/rosdep/pull/721?src=pr&el=desc) into [master](https://codecov.io/gh/ros-infrastructure/rosdep/commit/d812436fd7c0716280818f5ca8ae7d2a7166ae3f?src=pr&el=desc) will **increase** coverage by `<.01%`.
> The diff coverage is `66.66%`.

[![Impacted file tree graph](https://codecov.io/gh/ros-infrastructure/rosdep/pull/721/graphs/tree.svg?width=650&token=YdnUPit6vO&height=150&src=pr)](https://codecov.io/gh/ros-infrastructure/rosdep/pull/721?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #721      +/-   ##
==========================================
+ Coverage   76.03%   76.04%   +<.01%     
==========================================
  Files          40       40              
  Lines        3126     3127       +1     
==========================================
+ Hits         2377     2378       +1     
  Misses        749      749
```


| [Impacted Files](https://codecov.io/gh/ros-infrastructure/rosdep/pull/721?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [src/rosdep2/main.py](https://codecov.io/gh/ros-infrastructure/rosdep/pull/721/diff?src=pr&el=tree#diff-c3JjL3Jvc2RlcDIvbWFpbi5weQ==) | `49.36% <0%> (ø)` | :arrow_up: |
| [src/rosdep2/meta.py](https://codecov.io/gh/ros-infrastructure/rosdep/pull/721/diff?src=pr&el=tree#diff-c3JjL3Jvc2RlcDIvbWV0YS5weQ==) | `100% <100%> (ø)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/ros-infrastructure/rosdep/pull/721?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/ros-infrastructure/rosdep/pull/721?src=pr&el=footer). Last update [d812436...e91b931](https://codecov.io/gh/ros-infrastructure/rosdep/pull/721?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/src/rosdep2/main.py b/src/rosdep2/main.py
index 1b6b816..764ddad 100644
--- a/src/rosdep2/main.py
+++ b/src/rosdep2/main.py
@@ -402,7 +402,7 @@ def _rosdep_main(args):
 
     if 'ROS_PYTHON_VERSION' not in os.environ and 'ROS_DISTRO' in os.environ:
         # Set python version to version used by ROS distro
-        python_versions = MetaDatabase().get('ROS_PYTHON_VERSION')
+        python_versions = MetaDatabase().get('ROS_PYTHON_VERSION', default=[])
         if os.environ['ROS_DISTRO'] in python_versions:
             os.environ['ROS_PYTHON_VERSION'] = str(python_versions[os.environ['ROS_DISTRO']])
 
diff --git a/src/rosdep2/meta.py b/src/rosdep2/meta.py
index 29bd317..b8cd900 100644
--- a/src/rosdep2/meta.py
+++ b/src/rosdep2/meta.py
@@ -102,7 +102,7 @@ class MetaDatabase:
         write_cache_file(self._cache_dir, category, wrapper)
         self._loaded[category] = wrapper
 
-    def get(self, category):
+    def get(self, category, default=None):
         """Return metadata in the cache, or None if there is no cache entry."""
         if category not in self._loaded:
             self._load_from_cache(category, self._cache_dir)
@@ -110,6 +110,8 @@ class MetaDatabase:
         if category in self._loaded:
             return self._loaded[category].data
 
+        return default
+
     def _load_from_cache(self, category, cache_dir):
         filename = compute_filename_hash(category) + PICKLE_CACHE_EXT
         try:


Test patch:
diff --git a/test/test_metadata.py b/test/test_metadata.py
index 0caf844..424a5ac 100644
--- a/test/test_metadata.py
+++ b/test/test_metadata.py
@@ -65,6 +65,14 @@ def test_metadatabase_get_none():
         assert db.get('fruit') is None
 
 
+def test_metadatabase_get_default():
+    with TemporaryDirectory() as tmpdir:
+        db = MetaDatabase(cache_dir=tmpdir)
+        assert db.get('fruit', default='foo') == 'foo'
+        db.set('fruit', 'tomato')
+        assert db.get('fruit', default='foo') != 'foo'
+
+
 def test_metadatabase_get_mutate_get():
     with TemporaryDirectory() as tmpdir:
         db = MetaDatabase(cache_dir=tmpdir)