# ubelt.util_io module

Functions for reading and writing files on disk.

`writeto()` and `readfrom()` wrap `open().write()` and `open().read()` and primarily serve to indicate that the type of data being written and read is unicode text.

`delete()` wraps `os.unlink()` and `shutil.rmtree()` and does not throw an error if the file or directory does not exist. It also contains workarounds for win32 issues with `shutil`.

ubelt.util_io.readfrom(fpath, aslines=False, errors='replace', verbose=None)

  Reads (utf8) text from a file.

  Note

  You probably should use `ub.Path(<fpath>).read_text()` instead. This function exists as a convenience for writing in Python2. After 2020-01-01, we may consider deprecating the function.

  Parameters:

    - fpath (str | PathLike) – file path

    - aslines (bool) – if True returns list of lines

    - errors (str) – how to handle decoding errors

    - verbose (int | None) – verbosity flag

  Returns:

    text from fpath (this is unicode)

  Return type:

    str

ubelt.util_io.writeto(fpath, to_write, aslines=False, verbose=None)

  Writes (utf8) text to a file.

  Parameters:

    - fpath (str | PathLike) – file path

    - to_write (str) – text to write (must be unicode text)

    - aslines (bool) – if True to_write is assumed to be a list of lines

    - verbose (int | None) – verbosity flag

  Note

  In CPython you may want to use `open(<fpath>).write(<to_write>)` instead. This function exists as a convenience for writing in Python2. After 2020-01-01, we may consider deprecating the function.

  NOTE: In PyPy `open(<fpath>).write(<to_write>)` does not work. See https://pypy.org/compat.html. This is an argument for keeping this function.

  NOTE: With modern versions of Python, it is generally recommend to use `pathlib.Path.write_text()` instead. Although there does seem to be some corner case this handles better on win32, so maybe useful?

  Example

      >>> import ubelt as ub
      >>> import os
      >>> from os.path import exists
      >>> dpath = ub.Path.appdir('ubelt').ensuredir()
      >>> fpath = dpath + '/' + 'testwrite.txt'
      >>> if exists(fpath):
      >>>     os.remove(fpath)
      >>> to_write = 'utf-8 symbols Δ, Й, ק, م, ๗, あ, 叶, 葉, and 말.'
      >>> ub.writeto(fpath, to_write)
      >>> read_ = ub.readfrom(fpath)
      >>> print('read_    = ' + read_)
      >>> print('to_write = ' + to_write)
      >>> assert read_ == to_write

  Example

      >>> import ubelt as ub
      >>> import os
      >>> from os.path import exists
      >>> dpath = ub.Path.appdir('ubelt').ensuredir()
      >>> fpath = dpath + '/' + 'testwrite2.txt'
      >>> if exists(fpath):
      >>>     os.remove(fpath)
      >>> to_write = ['a\n', 'b\n', 'c\n', 'd\n']
      >>> ub.writeto(fpath, to_write, aslines=True)
      >>> read_ = ub.readfrom(fpath, aslines=True)
      >>> print('read_    = {}'.format(read_))
      >>> print('to_write = {}'.format(to_write))
      >>> assert read_ == to_write

  Example

      >>> # With modern Python, use pathlib.Path (or ub.Path) instead
      >>> import ubelt as ub
      >>> dpath = ub.Path.appdir('ubelt/tests/io').ensuredir()
      >>> fpath = (dpath / 'test_file.txt').delete()
      >>> to_write = 'utf-8 symbols Δ, Й, ק, م, ๗, あ, 叶, 葉, and 말.'
      >>> ub.writeto(fpath, to_write)
      >>> fpath.write_bytes(to_write.encode('utf8'))
      >>> assert fpath.read_bytes().decode('utf8') == to_write

ubelt.util_io.touch(fpath, mode=438, dir_fd=None, verbose=0, **kwargs)

  change file timestamps

  Works like the touch unix utility

  Parameters:

    - fpath (str | PathLike) – name of the file

    - mode (int) – file permissions (python3 and unix only)

    - dir_fd (io.IOBase | None) – optional directory file descriptor. If specified, fpath is interpreted as relative to this descriptor (python 3 only).

    - verbose (int) – verbosity

    - **kwargs – extra args passed to `os.utime()` (python 3 only).

  Returns:

    path to the file

  Return type:

    str

  References

  [SO_1158076]

  https://stackoverflow.com/questions/1158076/implement-touch-using-python

  Example

      >>> import ubelt as ub
      >>> from os.path import join
      >>> dpath = ub.Path.appdir('ubelt').ensuredir()
      >>> fpath = join(dpath, 'touch_file')
      >>> assert not exists(fpath)
      >>> ub.touch(fpath)
      >>> assert exists(fpath)
      >>> os.unlink(fpath)

ubelt.util_io.delete(path, verbose=False)

  Removes a file or recursively removes a directory. If a path does not exist, then this is does nothing.

  Parameters:

    - path (str | PathLike) – file or directory to remove

    - verbose (bool) – if True prints what is being done

  SeeAlso:
    send2trash -

      A cross-platform Python package for sending files to the trash instead of irreversibly deleting them.

    `ubelt.util_path.Path.delete()`

  Notes

  This can call `os.unlink()`, `os.rmdir()`, or `shutil.rmtree()`, depending on what `path` references on the filesystem. (On windows may also call a custom `ubelt._win32_links._win32_rmtree()`).

  Example

      >>> import ubelt as ub
      >>> from os.path import join
      >>> base = ub.Path.appdir('ubelt', 'delete_test').ensuredir()
      >>> dpath1 = ub.ensuredir(join(base, 'dir'))
      >>> ub.ensuredir(join(base, 'dir', 'subdir'))
      >>> ub.touch(join(base, 'dir', 'to_remove1.txt'))
      >>> fpath1 = join(base, 'dir', 'subdir', 'to_remove3.txt')
      >>> fpath2 = join(base, 'dir', 'subdir', 'to_remove2.txt')
      >>> ub.touch(fpath1)
      >>> ub.touch(fpath2)
      >>> assert all(map(exists, (dpath1, fpath1, fpath2)))
      >>> ub.delete(fpath1)
      >>> assert all(map(exists, (dpath1, fpath2)))
      >>> assert not exists(fpath1)
      >>> ub.delete(dpath1)
      >>> assert not any(map(exists, (dpath1, fpath1, fpath2)))

  Example

      >>> import ubelt as ub
      >>> from os.path import exists, join
      >>> dpath = ub.Path.appdir('ubelt', 'delete_test2').ensuredir()
      >>> dpath1 = ub.ensuredir(join(dpath, 'dir'))
      >>> fpath1 = ub.touch(join(dpath1, 'to_remove.txt'))
      >>> assert exists(fpath1)
      >>> ub.delete(dpath)
      >>> assert not exists(fpath1)