Repository: ipython/ipython

Issue:
Pathlib, Pathlib everywhere.
There are many places where we could make use of Pathlib. 

Look for any places that uses `with open(...)` and ask yourself:

- is the argument a string ? 
- would it make sens to make it a `Path()`, 
- how far upstream in the code can I make it a Path.

Don't try to bite more than you can chew (or more than I can review), try to fix 1 place at a time.


Discussion:
for example see https://github.com/ipython/ipython/pull/12512
Hi @Carreau, if no one is working on /core/page.py for using Pathlib, can I take this part?
> Hi @Carreau, if no one is working on /core/page.py for using Pathlib, can I take this part?

Sure, please. Thanks. 
Hi, I would like to work on core/interactiveshell.py and add there more use of Pathlib.
Can I help with that?
Hey @Carreau can I take on testing/iptestcontroller.py and core/magics/execution.py ?
Might also be of use: https://docs.python.org/3/library/pathlib.html#correspondence-to-tools-in-the-os-module

There are many places other than `with open()` that might use pathlib treatment:

```diff
-    conda_history = os.path.join(sys.prefix, 'conda-meta', 'history')
-    return os.path.exists(conda_history)
+    return Path(sys.prefix, 'conda-meta', 'history').exists()
```

That's a good point.

On Sat, Oct 10, 2020 at 8:33 PM Blazej Michalik <notifications@github.com>
wrote:

> Might also be of use:
> https://docs.python.org/3/library/pathlib.html#correspondence-to-tools-in-the-os-module
>
> There are many places other than with open() that might use pathlib
> treatment:
>
> -    conda_history = os.path.join(sys.prefix, 'conda-meta', 'history')-    return os.path.exists(conda_history)+    return Path(sys.prefix, 'conda-meta', 'history').exists()
>
> —
> You are receiving this because you commented.
> Reply to this email directly, view it on GitHub
> <https://github.com/ipython/ipython/issues/12515#issuecomment-706630653>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/ADMY5F73MJDQ6CL32KEUZS3SKD4LXANCNFSM4QNPWX2Q>
> .
>

> Might also be of use: https://docs.python.org/3/library/pathlib.html#correspondence-to-tools-in-the-os-module
> 
> There are many places other than `with open()` that might use pathlib treatment:
> 


Although... some of them might be less trivial and more error prone, especially when they're interpreted as text. For example, when returning a `PosixPath` object breaks code in the scope above because it is being `' '.join()`-ed with other shell arguments.
There still any places left to fix this? Looks like a lot of people are working on it.
edit: found some, nevermind
> There still any places left to fix this? Looks like a lot of people are working on it.

I'm slowly checking the PRs and merging them, I'm not sure if there are other places left. 

THere are other things you can try; find all places that uses cast_unicode/cast_bytes, and see if they are removable. Many of those are due to old Python 2 compatibility. 

for example there is 

```
def find_file(obj) -> str:
  ...
    fname = None
    try:
        fname = inspect.getabsfile(obj)
    except TypeError:
        # For an instance, the file that matters is where its class was
        # declared.
        if hasattr(obj, '__class__'):
            try:
                fname = inspect.getabsfile(obj.__class__)
            except TypeError:
                # Can happen for builtins
                pass
    except:
        pass
    return cast_unicode(fname)
```

If you can prove that `inspect.getabsfil` always return str and not bytes, then `cast_unicode` is unnecessary. It's a bit more work, but that would cleanup a bt the codebase.



Resolving patch:
diff --git a/IPython/paths.py b/IPython/paths.py
--- a/IPython/paths.py
+++ b/IPython/paths.py
@@ -8,9 +8,14 @@
 import IPython
 from IPython.utils.importstring import import_item
 from IPython.utils.path import (
-    get_home_dir, get_xdg_dir, get_xdg_cache_dir, compress_user, _writable_dir,
-    ensure_dir_exists, fs_encoding)
-from IPython.utils import py3compat
+    get_home_dir,
+    get_xdg_dir,
+    get_xdg_cache_dir,
+    compress_user,
+    _writable_dir,
+    ensure_dir_exists,
+)
+
 
 def get_ipython_dir() -> str:
     """Get the IPython directory for this platform and user.
@@ -103,7 +108,8 @@ def get_ipython_module_path(module_str):
     mod = import_item(module_str)
     the_path = mod.__file__.replace('.pyc', '.py')
     the_path = the_path.replace('.pyo', '.py')
-    return py3compat.cast_unicode(the_path, fs_encoding)
+    return the_path
+
 
 def locate_profile(profile='default'):
     """Find the path to the folder associated with a given profile.


Test patch: