Repository: scipy/scipy

Issue:
BUG: pavement.py glitch
`paver release` command in standard release workflow fails locally with:

```
Traceback (most recent call last):
  File "/mnt/c/Users/treddy/venv_py38/lib/python3.8/site-packages/paver/tasks.py", line 201, in _run_task
    return do_task()
  File "/mnt/c/Users/treddy/venv_py38/lib/python3.8/site-packages/paver/tasks.py", line 198, in do_task
    return func(**kw)
  File "pavement.py", line 199, in release
    write_release_and_log()
  File "/mnt/c/Users/treddy/venv_py38/lib/python3.8/site-packages/paver/tasks.py", line 333, in __call__
    retval = environment._run_task(self.name, self.needs, self.func)
  File "/mnt/c/Users/treddy/venv_py38/lib/python3.8/site-packages/paver/tasks.py", line 219, in _run_task
    return do_task()
  File "/mnt/c/Users/treddy/venv_py38/lib/python3.8/site-packages/paver/tasks.py", line 198, in do_task
    return func(**kw)
  File "pavement.py", line 287, in write_release_and_log
    write_release_task(options, os.path.join(options.installers.releasedir, 'README'))
  File "pavement.py", line 247, in write_release_task
    ftarget.writelines(['%s\n' % c for c in compute_md5(idirs)])
  File "pavement.py", line 212, in compute_md5
    checksums.append('%s  %s' % (m.hexdigest(), os.path.basename(f)))
  File "/mnt/c/Users/treddy/venv_py38/lib/python3.8/posixpath.py", line 142, in basename
    p = os.fspath(p)
TypeError: expected str, bytes or os.PathLike object, not _io.BufferedReader
```

It appears related to this commit:

```
commit aa2a3c6685fb4f3090d003f62100f3f5c84e5c23
Author: Seth Troisi <sethtroisi@google.com>
Date:   Tue Aug 4 15:31:52 2020 -0700

    MAINT: Fixes from static analysis
```

This local fix circumvents the issue for now by restoring the previous code in a few parts of the module--should likely be patched on `master` and backported for one of the rcs:

```diff
diff --git a/pavement.py b/pavement.py
index c29687462..bcd0d6daf 100644
--- a/pavement.py
+++ b/pavement.py
@@ -206,9 +206,8 @@ def release(options):
 def compute_md5(idirs):
     released = paver.path.path(idirs).listdir()
     checksums = []
-    for fn in sorted(released):
-        with open(fn, 'rb') as f:
-            m = md5(f.read())
+    for f in sorted(released):
+        m = md5(open(f, 'rb').read())
         checksums.append('%s  %s' % (m.hexdigest(), os.path.basename(f)))

     return checksums
@@ -218,9 +217,8 @@ def compute_sha256(idirs):
     # to verify the binaries instead of signing all binaries
     released = paver.path.path(idirs).listdir()
     checksums = []
-    for fn in sorted(released):
-        with open(fn, 'rb') as f:
-            m = sha256(f.read())
+    for f in sorted(released):
+        m = sha256(open(f, 'rb').read())
         checksums.append('%s  %s' % (m.hexdigest(), os.path.basename(f)))

     return checksums
```

We may also want to think carefully about applying static analyzer changes to parts of the code that are not routinely tested without strong justifications.

There is probably a cleaner fix that retains the new context managers, but does someone really want to guarantee that their replacement fix is going to work when CI won't catch it otherwise.


Discussion:
I'm proceeding with the `1.6.0rc1` wheel build attempts since the above only affects release management proper.

Resolving patch:
diff --git a/pavement.py b/pavement.py
--- a/pavement.py
+++ b/pavement.py
@@ -209,7 +209,7 @@ def compute_md5(idirs):
     for fn in sorted(released):
         with open(fn, 'rb') as f:
             m = md5(f.read())
-        checksums.append('%s  %s' % (m.hexdigest(), os.path.basename(f)))
+        checksums.append('%s  %s' % (m.hexdigest(), os.path.basename(fn)))
 
     return checksums
 
@@ -221,7 +221,7 @@ def compute_sha256(idirs):
     for fn in sorted(released):
         with open(fn, 'rb') as f:
             m = sha256(f.read())
-        checksums.append('%s  %s' % (m.hexdigest(), os.path.basename(f)))
+        checksums.append('%s  %s' % (m.hexdigest(), os.path.basename(fn)))
 
     return checksums
 


Test patch: