Repository: conda/conda-build

Issue:
Permission denied when testing a python tool.
Hi,

I am getting an unexpected permission denied error when trying to test a conda build for a tool I wish to include in bioconda.
The error:
```
dotknot.py sample.fasta
~/miniconda2/conda-bld/dotknot_1499267085047/test_tmp/run_test.sh: line 3: ~/miniconda2/conda-bld/dotknot_1499267085047/_t_env/bin/dotknot.py: Permission denied
TESTS FAILED: dotknot-1.3.2-py_0.tar.bz2
```


The following are my `meta.yaml` and `build.sh` (can also be found at https://github.com/HassanAmr/bioconda-recipes/tree/dotknot/recipes/dotknot):
`meta.yaml`
```
package:
  name: dotknot
  version: 1.3.2

build:
  number: 0
  noarch: python

source:
  url: http://dotknot.csse.uwa.edu.au/DotKnot_1.3.2.tar.gz
  md5: caf6dbf3559c699d98b5289983f43b2d
  patches:
    - dotknot.patch

requirements:
  build:
    - python
    - setuptools

  run:
    - python
    - viennarna ==1.8.5

test:
  commands:
    - printf '>sample\nacgtcgttgtgt\n' > sample.fasta && dotknot.py sample.fasta

about:
  home: http://dotknot.csse.uwa.edu.au/
  license: GNU GPL v3
  license_file: COPYING.FILE
  summary: DotKnot is a heuristic method for pseudoknot prediction in a given RNA sequence.
```

`build.sh`
```
#!/bin/bash
cp src/*.py $PREFIX/bin
cp src/stacking_only.par $PREFIX/bin

chmod +x $PREFIX/bin/BPs_to_CT.py
chmod +x $PREFIX/bin/cc06.py
chmod +x $PREFIX/bin/cc09.py
chmod +x $PREFIX/bin/dotknot.py
chmod +x $PREFIX/bin/functions.py
chmod +x $PREFIX/bin/kissing_hairpins.py
chmod +x $PREFIX/bin/longPK.py
chmod +x $PREFIX/bin/mwis_2d.py
chmod +x $PREFIX/bin/mwis.py
chmod +x $PREFIX/bin/pk_construction.py
chmod +x $PREFIX/bin/pk_energy.py
chmod +x $PREFIX/bin/pk_interrupted.py
chmod +x $PREFIX/bin/pk_recursive.py
chmod +x $PREFIX/bin/pk_tools.py
chmod +x $PREFIX/bin/secondary_elements.py
chmod +x $PREFIX/bin/stems.py
chmod +x $PREFIX/bin/user.py
```

Any help regarding this matter is greatly appreciated.
Thanks.



Discussion:
Hi @HassanAmr, could you show me the output of `conda info`?
`conda info`
```
Current conda install:

               platform : linux-64
          conda version : 4.3.22
       conda is private : False
      conda-env version : 4.3.22
    conda-build version : 2.1.15
         python version : 2.7.13.final.0
       requests version : 2.14.2
       root environment : /home/hassan/miniconda2  (writable)
    default environment : /home/hassan/miniconda2
       envs directories : /home/hassan/miniconda2/envs
                          /home/hassan/.conda/envs
          package cache : /home/hassan/miniconda2/pkgs
                          /home/hassan/.conda/pkgs
           channel URLs : https://conda.anaconda.org/bioconda/linux-64
                          https://conda.anaconda.org/bioconda/noarch
                          https://conda.anaconda.org/conda-forge/linux-64
                          https://conda.anaconda.org/conda-forge/noarch
                          https://repo.continuum.io/pkgs/free/linux-64
                          https://repo.continuum.io/pkgs/free/noarch
                          https://repo.continuum.io/pkgs/r/linux-64
                          https://repo.continuum.io/pkgs/r/noarch
                          https://repo.continuum.io/pkgs/pro/linux-64
                          https://repo.continuum.io/pkgs/pro/noarch
            config file : /home/hassan/.condarc
             netrc file : None
           offline mode : False
             user-agent : conda/4.3.22 requests/2.14.2 CPython/2.7.13 Linux/4.8.0-58-generic debian/stretch/sid glibc/2.23    
                UID:GID : 1000:1000
```
Does your test script work if you run it manually? On first glance it would seem that `dotknot.py sample.fasta` would work as `python dotknot.py sample.fasta`
Yes, it appears that you do not have the execute bit set.  Generally, it's better to do as @mandeep says, anyway, and explicitly run the script with python.
Yes, it does work with `python dotknot.py`. But I wish that it can also work using `dotknot.py`, since I am trying to include it in Bioconda. 
Sorry, I don't see why being explicit with python would preclude your package's inclusion in bioconda.  If you want to get one of the bioconda admins to comment here, we can talk with them.
The purpose is to hide from the end-user the technicalities under which the tools run as much as possible. 
It is the same I did with `reago` https://github.com/bioconda/bioconda-recipes/tree/master/recipes/reago
`conda install -c bioconda reago`
Sure, I will ask someone from Bioconda to join our conversation here, thanks :)
I've run into this same issue.  It appears as if all files in `noarch: python` packages have their permissions changed to remove the execute bit.  A minimal example is as follows:

meta.yaml
``` yaml
package:
  name: foobar
  version: 1.0
build:
  noarch: python

requirements:
  build:
    - python
  run: 
    - python

test:
  commands:
    - say_hello
```

build.sh
```
mkdir -p $PREFIX/bin
cp $RECIPE_DIR/say_hello $PREFIX/bin/
chmod +x $PREFIX/bin/say_hello
```

say_hello
```
#! /usr/bin/env python
print("Hello world")
```

A real world example where this would causes issue is the `sympy` package which copies the `isympy` script directly from the source code tree [within the setup function](https://github.com/sympy/sympy/blob/master/setup.py#L345).  Removing the execution bit from this file in the post build phase renders this script non-operational.

Resolving patch:
diff --git a/conda_build/noarch_python.py b/conda_build/noarch_python.py
--- a/conda_build/noarch_python.py
+++ b/conda_build/noarch_python.py
@@ -21,7 +21,8 @@ def _error_exit(exit_message):
 
 def rewrite_script(fn, prefix):
     """Take a file from the bin directory and rewrite it into the python-scripts
-    directory after it passes some sanity checks for noarch pacakges"""
+    directory with the same permissions after it passes some sanity checks for
+    noarch pacakges"""
 
     # Load and check the source file for not being a binary
     src = join(prefix, 'Scripts' if ISWIN else 'bin', fn)
@@ -30,6 +31,7 @@ def rewrite_script(fn, prefix):
             data = fi.read()
         except UnicodeDecodeError:  # file is binary
             _error_exit("Noarch package contains binary script: %s" % fn)
+    src_mode = os.stat(src).st_mode
     os.unlink(src)
 
     # Get rid of '-script.py' suffix on Windows
@@ -39,8 +41,10 @@ def rewrite_script(fn, prefix):
     # Rewrite the file to the python-scripts directory
     dst_dir = join(prefix, 'python-scripts')
     _force_dir(dst_dir)
-    with open(join(dst_dir, fn), 'w') as fo:
+    dst = join(dst_dir, fn)
+    with open(dst, 'w') as fo:
         fo.write(data)
+    os.chmod(dst, src_mode)
     return fn
 
 


Test patch: