Skip to content

Please support os.PathLike #11579

Closed

Description

@olebole

Description

When I try to open a FITS file with a path like object which is not dircetly a pathlib.Path, I get a failure:

import os

class DummyPath(os.Pathlike):
    def __init__(self, path):
        self.path = path

    def __fspath__(self):
        return str(self.path)

With the normal open, this works fine:

>>> p = DummyPath('foo.txt')
>>> fp = open(p)
>>> print(fp.read()
A big brown fox

But it does not work with astropy.io.fits:

>>> from astropy.io import fits
>>> f = DummyPath('foo.fits')
>>> fits.open(f)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3/dist-packages/astropy/io/fits/hdu/hdulist.py", line 164, in fitsopen
    return HDUList.fromfile(name, mode, memmap, save_backup, cache,
  File "/usr/lib/python3/dist-packages/astropy/io/fits/hdu/hdulist.py", line 401, in fromfile
    return cls._readfrom(fileobj=fileobj, mode=mode, memmap=memmap,
  File "/usr/lib/python3/dist-packages/astropy/io/fits/hdu/hdulist.py", line 1052, in _readfrom
    fileobj = _File(fileobj, mode=mode, memmap=memmap, cache=cache)
  File "/usr/lib/python3/dist-packages/astropy/utils/decorators.py", line 535, in wrapper
    return function(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/astropy/io/fits/file.py", line 177, in __init__
    self._open_filelike(fileobj, mode, overwrite)
  File "/usr/lib/python3/dist-packages/astropy/io/fits/file.py", line 541, in _open_filelike
    raise OSError("File-like object does not have a 'write' "
OSError: File-like object does not have a 'write' method, required for mode 'ostream'.

Having os.PathLike supported would make it easy to implement f.e. a cache, where __fspath__() could handle the creation or download of a requested file before opening.

For fits, I would guess that the problem is that pathlib.Path is hardcoded:

# If fileobj is of type pathlib.Path
if isinstance(fileobj, pathlib.Path):
fileobj = str(fileobj)

This could be replaced with checking for os.PathLike, and accessing the string with __fspath__() instead, but there may be other places as well. A simple grep shows that isinstance(…, pathlib.Path) is used here:

  • io/registry.py
  • io/fits/util.py
  • io/fits/convenience.py
  • io/fits/file.py (this is the one shown above)
  • io/fits/diff.py
  • config/configuration.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions