Repository: conda/conda-build

Issue:
conda skeleton pypi error (hdf5storage)
Tried to run `conda skeleton pypi hdf5storage` to get an initial recipe for the [hdf5storage]( https://pypi.python.org/pypi/hdf5storage ) package, but it seem to not work for some reason. Had the same issue when using Python 2 or Python 3 in the `root` environment.

Log:

<details>

```
$ conda skeleton pypi hdf5storage
Using url https://pypi.python.org/packages/cc/d5/ff101fb07d2cc1765517396dc937b69b8a19dc38e2bcb1d63de726c70466/hdf5storage-0.1.14.zip (115 KB) for hdf5storage.
Downloading hdf5storage
INFO:fetch.start:('hdf5storage-0.', 118087)
INFO:fetch.update:16384
INFO:fetch.update:32768
INFO:fetch.update:49152
INFO:fetch.update:65536
INFO:fetch.update:81920
INFO:fetch.update:98304
INFO:fetch.update:114688
INFO:fetch.update:118087
INFO:fetch.stop:None
Unpacking hdf5storage...
done
working in /var/folders/jj/pp1xwt1n4zdgy9zxbxc22t8w66tr7q/T/tmp_be1qvconda_skeleton_hdf5storage-0.1.14.zip

The following NEW packages will be INSTALLED:

    ca-certificates: 2017.4.17-0      conda-forge
    certifi:         2017.4.17-py27_0 conda-forge
    ncurses:         5.9-10           conda-forge
    openssl:         1.0.2k-0         conda-forge
    pip:             9.0.1-py27_0     conda-forge
    python:          2.7.13-1         conda-forge
    pyyaml:          3.12-py27_1      conda-forge
    readline:        6.2-0            conda-forge
    setuptools:      33.1.1-py27_0    conda-forge
    sqlite:          3.13.0-1         conda-forge
    tk:              8.5.19-1         conda-forge
    wheel:           0.29.0-py27_0    conda-forge
    yaml:            0.1.6-0          conda-forge
    zlib:            1.2.11-0         conda-forge

Applying patch: '/var/folders/jj/pp1xwt1n4zdgy9zxbxc22t8w66tr7q/T/tmp_be1qvconda_skeleton_hdf5storage-0.1.14.zip/pypi-distutils.patch'
patching file core.py
Hunk #1 succeeded at 169 with fuzz 2 (offset 2 lines).
Traceback (most recent call last):
  File "/zopt/conda2/bin/conda-skeleton", line 6, in <module>
    sys.exit(conda_build.cli.main_skeleton.main())
  File "/zopt/conda2/lib/python2.7/site-packages/conda_build/cli/main_skeleton.py", line 66, in main
    return execute(sys.argv[1:])
  File "/zopt/conda2/lib/python2.7/site-packages/conda_build/cli/main_skeleton.py", line 62, in execute
    version=args.version, config=config)
  File "/zopt/conda2/lib/python2.7/site-packages/conda_build/api.py", line 208, in skeletonize
    recursive=recursive, config=config, **kwargs)
  File "/zopt/conda2/lib/python2.7/site-packages/conda_build/skeletons/pypi.py", line 423, in skeletonize
    setup_options=setup_options)
  File "/zopt/conda2/lib/python2.7/site-packages/conda_build/skeletons/pypi.py", line 803, in get_package_metadata
    in pkginfo['tests_require']]))
TypeError: sequence item 0: expected string, NoneType found
```

</details>

<br>
Environment:
<br>
<br>

<details>

```yaml
name: root
channels:
- conda-forge
- defaults
dependencies:
- anaconda-client=1.6.3=py27_0
- anaconda-verify=1.2.0=py27_0
- appnope=0.1.0=py27_0
- backports.shutil_get_terminal_size=1.0.0=py27_1
- beautifulsoup4=4.5.3=py27_0
- ca-certificates=2017.4.17=0
- certifi=2017.4.17=py27_0
- cffi=1.10.0=py27_0
- chardet=3.0.2=py27_1
- clyent=1.2.1=py27_0
- conda=4.3.21=py27_1
- conda-build=2.1.15=py27_0
- conda-build-all=1.0.4=py27_0
- conda-env=2.6.0=0
- conda-execute=0.8.0=py27_1
- conda-verify=2.0.0=py27_0
- configparser=3.5.0=py27_0
- constructor=1.3.4=py27_0
- contextlib2=0.5.5=py27_0
- coverage=4.4.1=py27_0
- curl=7.52.1=0
- decorator=4.0.11=py27_0
- enum34=1.1.6=py27_1
- expat=2.1.0=2
- filelock=2.0.6=py27_0
- flake8=3.3.0=py27_0
- flake8-import-order=0.12=py27_0
- funcsigs=1.0.2=py27_0
- futures=3.0.5=py27_0
- gitdb=0.6.4=py27_1
- gitpython=2.1.1=py27_0
- idna=2.5=py27_0
- ipaddress=1.0.18=py27_0
- ipython=5.4.1=py27_0
- ipython_genutils=0.2.0=py27_0
- jinja2=2.9.5=py27_0
- libconda=4.0.0=py27_0
- libffi=3.2.1=3
- markupsafe=1.0=py27_0
- mccabe=0.6.1=py27_0
- mock=2.0.0=py27_0
- ncurses=5.9=10
- nose=1.3.7=py27_2
- openssl=1.0.2k=0
- packaging=16.8=py27_0
- pathlib2=2.3.0=py27_0
- pbr=3.0.1=py27_0
- pep8-naming=0.4.1=py27_0
- pexpect=4.2.1=py27_0
- pickleshare=0.7.3=py27_0
- pip=9.0.1=py27_0
- pkginfo=1.2.1=py27_0
- prompt_toolkit=1.0.14=py27_0
- psutil=5.2.1=py27_0
- ptyprocess=0.5.1=py27_0
- pyasn1=0.2.3=py27_0
- pycodestyle=2.3.1=py27_0
- pycosat=0.6.1=py27_0
- pycparser=2.17=py27_0
- pycrypto=2.6.1=py27_1
- pyflakes=1.5.0=py27_0
- pygithub=1.34=py27_0
- pygments=2.2.0=py27_0
- pyjwt=1.5.0=py27_0
- pyopenssl=16.2.0=py27_0
- pyparsing=2.2.0=py27_0
- pysocks=1.6.7=py27_0
- python=2.7.13=1
- python-dateutil=2.6.0=py27_0
- pytz=2017.2=py27_0
- pyyaml=3.12=py27_1
- readline=6.2=0
- requests=2.18.1=py27_0
- ruamel.ordereddict=0.4.6=py27_0
- ruamel.yaml=0.15.8=py27_0
- ruamel_yaml=0.11.14=py27_0
- scandir=1.5=py27_1
- setuptools=33.1.1=py27_0
- simplegeneric=0.8.1=py27_0
- six=1.10.0=py27_1
- smmap=2.0.1=py27_0
- sqlite=3.13.0=1
- tk=8.5.19=1
- traitlets=4.3.2=py27_0
- typing=3.6.1=py27_0
- urllib3=1.21.1=py27_1
- wcwidth=0.1.7=py27_0
- wheel=0.29.0=py27_0
- yaml=0.1.6=0
- zlib=1.2.11=0
- asn1crypto=0.22.0=py27_0
- cryptography=1.8.1=py27_0
- python.app=1.2=py27_4
- pip:
  - backports.shutil-get-terminal-size==1.0.0
  - conda-smithy (/Users/kirkhamj/Developer/Conda/conda-forge/conda-smithy)==2.0.2.dev4+fast.finish.cis
  - ipython-genutils==0.2.0
  - prompt-toolkit==1.0.14
  - ruamel-yaml==0.11.14
  - smmap2==2.0.1
```

</details>


Discussion:
Seems to be a problem in either how ``spec_from_line`` is parsing ``pkginfo['tests_require']``  or how the 0.1.x version of hdf5storage lists its test requirements. In 0.1.x, ``setup.py`` shows the test_requirements as ``'nose>=1.0'`` when ``spec_from_line`` expects a list in the form of ``['nose>=1.0']``. This is why ``pkginfo['tests_require']`` shows ``'nose>=1.0'`` as its value and fails. Changing this key's value to ``['nose >= 1.0']`` results in a proper recipe.

Resolving patch:
diff --git a/conda_build/skeletons/pypi.py b/conda_build/skeletons/pypi.py
--- a/conda_build/skeletons/pypi.py
+++ b/conda_build/skeletons/pypi.py
@@ -29,7 +29,7 @@
 from conda_build.conda_interface import human_bytes, hashsum_file
 from conda_build.conda_interface import default_python
 
-from conda_build.utils import tar_xf, unzip, rm_rf, check_call_env
+from conda_build.utils import tar_xf, unzip, rm_rf, check_call_env, ensure_list
 from conda_build.source import apply_patch
 from conda_build.build import create_env
 from conda_build.config import Config
@@ -800,7 +800,7 @@ def get_package_metadata(package, d, data, output_dir, python_version, all_extra
         d['import_comment'] = ''
 
         d['tests_require'] = INDENT.join(sorted([spec_from_line(pkg) for pkg
-                                                    in pkginfo['tests_require']]))
+                                                 in ensure_list(pkginfo['tests_require'])]))
 
     if pkginfo.get('homeurl'):
         d['homeurl'] = pkginfo['homeurl']


Test patch:
diff --git a/tests/test_api_skeleton.py b/tests/test_api_skeleton.py
--- a/tests/test_api_skeleton.py
+++ b/tests/test_api_skeleton.py
@@ -119,3 +119,12 @@ def test_pypi_with_version_inconsistency(testing_workdir):
     with open('mpi4py_test/meta.yaml') as f:
         actual = yaml.load(f)
         assert parse_version(actual['package']['version']) == parse_version("0.0.10")
+
+
+def test_setuptools_test_requirements(testing_workdir):
+    api.skeletonize(packages='hdf5storage', repo='pypi')
+
+    with open('hdf5storage/meta.yaml') as f:
+        actual = yaml.load(f)
+
+    assert actual['test']['requires'] == ['nose >=1.0']