Repository: spyder-ide/spyder

Issue:
Execute permission bits are set to 1 for newly created files
## Problem Description

Created files have POSIX execute permission bits set to 1. Usually, files should be created with "666 minus umask" permissions, for example 666-022=644 (cf. Note in https://wiki.archlinux.org/index.php/umask).

For python scripts it may be considered a feature to have them executable. However, it would be nice to be able to configure this behaviour, and for other file types it may be considered a bug to have the execute bits set.

The mask is computed here:
https://github.com/spyder-ide/spyder/blob/6bbd5b006aec95f612135d542ddb842012666f9a/spyder/utils/encoding.py#L265
but i do not know if changing it there would be appropriate or break other uses of the function.

### What steps reproduce the problem?

1. New file...
2. Save...

### What is the expected output? What do you see instead?

It should be at least configurable that the created file has the execute permission bits set to 0, preferably "666 minus umask". The created file has the execute permission bits set to 1, for me the permissions are 755.

## Versions
<!--- You can get this information from Help > About Spyder...
or (if Spyder won't launch) the "conda list" command
from the Anaconda Prompt/Terminal/command line. --->

* Spyder version: Spyder 5.0.0.dev0
* Python version: Python 3.8.5 64-bit
* Qt version: Qt 5.9.7
* PyQt version: PyQt5 5.9.2
* Operating System name/version: Linux 5.9.2-arch1-1

### Dependencies
```
# Mandatory:
atomicwrites >=1.2.0           :  1.4.0 (OK)
chardet >=2.0.0                :  3.0.4 (OK)
cloudpickle >=0.5.0            :  1.6.0 (OK)
diff_match_patch >=20181111    :  20200713 (OK)
intervaltree                   :  None (OK)
IPython >=4.0                  :  7.18.1 (OK)
jedi =0.17.1                   :  0.17.1 (OK)
keyring                        :  None (OK)
nbconvert >=4.0                :  6.0.7 (OK)
numpydoc >=0.6.0               :  1.1.0 (OK)
parso =0.7.0                   :  0.7.0 (OK)
pexpect >=4.4.0                :  4.8.0 (OK)
pickleshare >=0.4              :  0.7.5 (OK)
psutil >=5.3                   :  5.7.2 (OK)
pygments >=2.0                 :  2.7.2 (OK)
pylint >=1.0                   :  2.6.0 (OK)
pyls >=0.34.0;<1.0.0           :  0.35.1 (OK)
qdarkstyle >=2.8               :  2.8.1 (OK)
qtawesome >=0.5.7              :  1.0.1 (OK)
qtconsole >=4.6.0              :  4.7.7 (OK)
qtpy >=1.5.0                   :  1.9.0 (OK)
rtree >=0.8.3                  :  0.9.4 (OK)
sphinx >=0.6.6                 :  3.2.1 (OK)
spyder_kernels >=1.9.4;<1.10.0 :  1.9.4 (OK)
watchdog                       :  None (OK)
xdg >=0.26                     :  0.27 (OK)
zmq >=17                       :  19.0.2 (OK)

# Optional:
cython >=0.21                  :  None (OK)
matplotlib >=2.0.0             :  None (OK)
numpy >=1.7                    :  None (OK)
pandas >=0.13.1                :  None (OK)
scipy >=0.17.0                 :  None (OK)
sympy >=0.7.3                  :  None (OK)
```



Discussion:
Thanks for the report. I reproduced this with Spyder version 4. 

As a matter of fact, I had already noticed executable Python files appearing in my directories, but I did not realize Spyder created them. I'd prefer if we went back to the Spyder v3 behaviour and create non-executable files; I don't think making them executable was a conscious decision.
I also think we should avoid this. We'll take a look at it for 4.2.1, to be released just before Christmas.

Resolving patch:
diff --git a/spyder/utils/encoding.py b/spyder/utils/encoding.py
--- a/spyder/utils/encoding.py
+++ b/spyder/utils/encoding.py
@@ -262,7 +262,9 @@ def write(text, filename, encoding='utf-8', mode='wb'):
             # Creating a new file, emulate what os.open() does
             umask = os.umask(0)
             os.umask(umask)
-            original_mode = 0o777 & ~umask
+            # Set base permission of a file to standard permissions.
+            # See #spyder-ide/spyder#14112.
+            original_mode = 0o666 & ~umask
             creation = time.time()
         try:
             # fixes issues with scripts in Dropbox leaving


Test patch: