Repository: conda/conda-build

Issue:
conda-build tries to expand real files as glob patterns and fails
**Update**:  See the second post for a minimal reproducible example.

~~The recipe which can be used to reproduce this issue can be found here: https://github.com/conda-forge/staged-recipes/pull/2260.~~

`glob` returns the following error message ([full backtrace](https://travis-ci.org/conda-forge/staged-recipes/builds/193919568#L765)) even tough there are no glob patterns in `meta.yaml`:
```
sre_constants.error: bad character range e-b at position 16
```

As far as I can tell, this is caused by a real file named `expected[graphene-bilayer].pbz` which is part of the source PyPI package. For some reason, conda-build considers this filename as a glob pattern and tries to expand it. `glob` tries to interpret the `[]`, but complains about the bad range around `-`, hence the error message above. But the real problem is that `glob` should not have gotten the name of a real file in the first place.

This was working as expected a few months ago (~ November), so I assume it's a recent bug. Let me know if you need any more information.


Discussion:
I've put together a minimal example which reproduces the error: [recipe.tar.gz](https://github.com/conda/conda-build/files/732381/recipe.tar.gz)

The example recipe includes a file named `file[with-a-strange-name].dat` which triggers the error, as explained in the original post.
```
$ conda build recipe
BUILD START: example-0.0.1-py35_0
updating index in: /home/dean/miniconda3/conda-bld/linux-64
updating index in: /home/dean/miniconda3/conda-bld/noarch

The following NEW packages will be INSTALLED:

    openssl:    1.0.2j-0     
    pip:        9.0.1-py35_1 
    python:     3.5.2-0      
    readline:   6.2-2        
    setuptools: 27.2.0-py35_0
    sqlite:     3.13.0-0     
    tk:         8.5.18-0     
    wheel:      0.29.0-py35_0
    xz:         5.2.2-1      
    zlib:       1.2.8-3      

Copying /home/dean/Code/conda-test/recipe/src to /home/dean/miniconda3/conda-bld/recipe_1485437356789/work
Package: example-0.0.1-py35_0
source tree in: /home/dean/miniconda3/conda-bld/recipe_1485437356789/work
+ source /home/dean/miniconda3/bin/activate /home/dean/miniconda3/conda-bld/recipe_1485437356789/_b_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_place
+ python setup.py install --single-version-externally-managed --record record.txt
running install
running build
running build_py
creating build
creating build/lib
creating build/lib/example
copying example/__init__.py -> build/lib/example
running egg_info
creating example.egg-info
writing example.egg-info/PKG-INFO
writing top-level names to example.egg-info/top_level.txt
writing dependency_links to example.egg-info/dependency_links.txt
writing manifest file 'example.egg-info/SOURCES.txt'
reading manifest file 'example.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file 'example.egg-info/SOURCES.txt'
copying example/file[with-a-strange-name].dat -> build/lib/example
running install_lib
creating /home/dean/miniconda3/conda-bld/recipe_1485437356789/_b_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_place/lib/python3.5/site-packages/example
copying build/lib/example/__init__.py -> /home/dean/miniconda3/conda-bld/recipe_1485437356789/_b_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_place/lib/python3.5/site-packages/example
copying build/lib/example/file[with-a-strange-name].dat -> /home/dean/miniconda3/conda-bld/recipe_1485437356789/_b_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_place/lib/python3.5/site-packages/example
byte-compiling /home/dean/miniconda3/conda-bld/recipe_1485437356789/_b_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_place/lib/python3.5/site-packages/example/__init__.py to __init__.cpython-35.pyc
running install_egg_info
Copying example.egg-info to /home/dean/miniconda3/conda-bld/recipe_1485437356789/_b_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_place/lib/python3.5/site-packages/example-0.0.1-py3.5.egg-info
running install_scripts
writing list of installed files to 'record.txt'
compiling .pyc files...
number of files: 8
Fixing permissions
Fixing permissions
Traceback (most recent call last):
  File "/home/dean/miniconda3/bin/conda-build", line 6, in <module>
    sys.exit(conda_build.cli.main_build.main())
  File "/home/dean/miniconda3/lib/python3.5/site-packages/conda_build/cli/main_build.py", line 322, in main
    execute(sys.argv[1:])
  File "/home/dean/miniconda3/lib/python3.5/site-packages/conda_build/cli/main_build.py", line 313, in execute
    noverify=args.no_verify)
  File "/home/dean/miniconda3/lib/python3.5/site-packages/conda_build/api.py", line 97, in build
    need_source_download=need_source_download, config=config)
  File "/home/dean/miniconda3/lib/python3.5/site-packages/conda_build/build.py", line 1478, in build_tree
    config=config)
  File "/home/dean/miniconda3/lib/python3.5/site-packages/conda_build/build.py", line 1130, in build
    built_package = bundlers[output.get('type', 'conda')](output, m, config, env)
  File "/home/dean/miniconda3/lib/python3.5/site-packages/conda_build/build.py", line 823, in bundle_conda
    files = list(set(utils.expand_globs(files, config.build_prefix)))
  File "/home/dean/miniconda3/lib/python3.5/site-packages/conda_build/utils.py", line 668, in expand_globs
    files.extend(f.replace(root_dir + os.path.sep, '') for f in glob(path))
  File "/home/dean/miniconda3/lib/python3.5/glob.py", line 20, in glob
    return list(iglob(pathname, recursive=recursive))
  File "/home/dean/miniconda3/lib/python3.5/glob.py", line 71, in _iglob
    for name in glob_in_dir(dirname, basename):
  File "/home/dean/miniconda3/lib/python3.5/glob.py", line 90, in glob1
    return fnmatch.filter(names, pattern)
  File "/home/dean/miniconda3/lib/python3.5/fnmatch.py", line 52, in filter
    match = _compile_pattern(pat)
  File "/home/dean/miniconda3/lib/python3.5/fnmatch.py", line 46, in _compile_pattern
    return re.compile(res).match
  File "/home/dean/miniconda3/lib/python3.5/re.py", line 224, in compile
    return _compile(pattern, flags)
  File "/home/dean/miniconda3/lib/python3.5/re.py", line 293, in _compile
    p = sre_compile.compile(pattern, flags)
  File "/home/dean/miniconda3/lib/python3.5/sre_compile.py", line 536, in compile
    p = sre_parse.parse(p, flags)
  File "/home/dean/miniconda3/lib/python3.5/sre_parse.py", line 829, in parse
    p = _parse_sub(source, pattern, 0)
  File "/home/dean/miniconda3/lib/python3.5/sre_parse.py", line 437, in _parse_sub
    itemsappend(_parse(source, state))
  File "/home/dean/miniconda3/lib/python3.5/sre_parse.py", line 575, in _parse
    raise source.error(msg, len(this) + 1 + len(that))
sre_constants.error: bad character range h-a at position 8
```
Thanks for the report and the reproducible example.  This is a pretty extreme corner case.  I'll be happy to fix it at some point, but unfortunately it is not high on my priority list.  PRs welcome.

Resolving patch:
diff --git a/conda_build/utils.py b/conda_build/utils.py
--- a/conda_build/utils.py
+++ b/conda_build/utils.py
@@ -664,6 +664,8 @@ def expand_globs(path_list, root_dir):
         if os.path.isdir(path):
             files.extend(os.path.join(root, f).replace(root_dir + os.path.sep, '')
                             for root, _, fs in os.walk(path) for f in fs)
+        elif os.path.isfile(path):
+            files.append(path.replace(root_dir + os.path.sep, ''))
         else:
             files.extend(f.replace(root_dir + os.path.sep, '') for f in glob(path))
     return files


Test patch: