Repository: spyder-ide/spyder

Issue:
Filenames are lowercased in debug mode
## Description

### What steps will reproduce the problem?

<!--- You can use Markdown here --->

When in debug mode, let's say file a.py calls a function within MixedCase.py, if MixedCase.py is not open, when debugging a.py, the debugger opens up MixedCase.py, but it shows as mixedcase.py, also, hovering the mouse over its tab show the entire directory address as lowercased.



## Versions

* Spyder version: 4.1.3 
* Python version: 3.7.7
* Qt version: 5.9.6
* PyQt5 version: 5.9.2
* Operating System: Windows 10

### Dependencies

```

# Mandatory:
atomicwrites >=1.2.0           :  1.3.0 (OK)
chardet >=2.0.0                :  3.0.4 (OK)
cloudpickle >=0.5.0            :  1.3.0 (OK)
diff_match_patch >=20181111    :  20181111 (OK)
intervaltree                   :  None (OK)
IPython >=4.0                  :  7.13.0 (OK)
jedi =0.15.2                   :  0.15.2 (OK)
nbconvert >=4.0                :  5.6.1 (OK)
numpydoc >=0.6.0               :  0.9.2 (OK)
paramiko >=2.4.0               :  2.7.1 (OK)
parso =0.5.2                   :  0.5.2 (OK)
pexpect >=4.4.0                :  4.8.0 (OK)
pickleshare >=0.4              :  0.7.5 (OK)
psutil >=5.3                   :  5.7.0 (OK)
pygments >=2.0                 :  2.6.1 (OK)
pylint >=0.25                  :  2.4.4 (OK)
pyls >=0.31.9;<0.32.0          :  0.31.9 (OK)
qdarkstyle >=2.8               :  2.8 (OK)
qtawesome >=0.5.7              :  0.7.0 (OK)
qtconsole >=4.6.0              :  4.7.2 (OK)
qtpy >=1.5.0                   :  1.9.0 (OK)
rtree >=0.8.3                  :  0.9.3 (OK)
sphinx >=0.6.6                 :  2.4.4 (OK)
spyder_kernels >=1.9.1;<1.10.0 :  1.9.1 (OK)
watchdog                       :  None (OK)
zmq >=17                       :  18.1.1 (OK)

# Optional:
cython >=0.21                  :  0.29.15 (OK)
matplotlib >=2.0.0             :  3.1.3 (OK)
numpy >=1.7                    :  1.18.1 (OK)
pandas >=0.13.1                :  1.0.3 (OK)
scipy >=0.17.0                 :  1.4.1 (OK)
sympy >=0.7.3                  :  1.5.1 (OK)
```



Discussion:
Hi @ma-sadeghi thanks for the report.

@impact27 do you know about this?
I think this is a windows issue.
I agree. Windows file names are case insensitive, so if they come like that from the debugger, I think there's little we can do about this.

@dalthviz, what do you think?
I think this is caused since pdb uses a canonical form of path filenames that, as stated in [the docstring of the canonic function](https://github.com/python/cpython/blob/b45af1a5691e83b86321fc52d173f66cf891ce5f/Lib/bdb.py#L37), transforms the filename into a case-normalized path on case insensitive filesystems (like for example Windows in the practice). So I think there is not much we can do about this
@dalthviz, what do you think about overriding that function in our debugger and using the filename as defined by the user and not the normalized one?

I can understand @ma-sadeghi's confusion after not seeing the file in Spyder with the capitalization shown everywhere else. And I think a lot of other people on Windows could be in the same situation too.
I'm unsure if possible problems could arise by doing some thing like that (the `canonic` function is used all around for path management inside pdb and maybe some internal things could relay in how it works). Checking a little bit more, seems like we could just send Spyder the nontransformed version of the path since we implemented the method that sets the pdb state for Spyder here (Although we would need to check if that change could break something too):

https://github.com/spyder-ide/spyder-kernels/blob/master/spyder_kernels/customize/spyderpdb.py#L407-L418


So do you think it's worthwhile exploring that possibility? We could check that things don't break by moving line by line with the debugger and see that things work as before.
Sure, we can explore the options (either overwriting canonic to prevent the case change of the path or handling the pdb state we send to Spyder to maintain the case of the path at least for Spyder).
Guys any progress on that? It's annoying when while debugging I save the changes, because file name is renamed to lowercase and imports doesn't work :( 
@degel123, could you better explain what you're doing? I mean, I don't understand what this has to do with saving files.
> @degel123, could you better explain what you're doing? I mean, I don't understand what this has to do with saving files.

The thing is the following: I have an import like `from MyPackage.MyModule import *`. When I am debugging a function from `MyModule`, the filename in Spyder is lowercased (`MyModule` -> `mymodule`). If I do any changes to the file while debugging,   `MyModule.py` is replace  by `mymodule.py` so the import doesnt work anymore. I have to manually change the name back to `MyModule.py` 
You mean that after saving the file in Spyder while you're debugging, the file is renamed on disk from `MyModule.py` to `mymodule.py`?
> 



> You mean that after saving the file in Spyder while you're debugging, the file is renamed on disk from `MyModule.py` to `mymodule.py`?

Yes 
We could open a new file by using https://docs.python.org/3/library/pathlib.html#pathlib.Path.resolve (see https://stackoverflow.com/a/54984701)
But the problem seems to be that Pdb uses canonical file names everywhere, according to what @dalthviz mentioned in https://github.com/spyder-ide/spyder/issues/12851#issuecomment-634215602. So we'd to override that.
Sure, but this is the same situation than if the file was already open. The problem here is:
 - if the file is already open, spyder handles that correctly, even if the filename is not canonical
 - if the file is not open, spyder opens the file with the filename given by pdb (which is canonical)
 I don't see a clear reason as to why we couldn't use the correct capitalisation in the second case

Resolving patch:
diff --git a/spyder/plugins/editor/plugin.py b/spyder/plugins/editor/plugin.py
--- a/spyder/plugins/editor/plugin.py
+++ b/spyder/plugins/editor/plugin.py
@@ -16,6 +16,7 @@
 import logging
 import os
 import os.path as osp
+from pathlib import Path
 import re
 import sys
 import time
@@ -2449,7 +2450,19 @@ def load(self, filenames=None, goto=None, word='',
             self.switch_to_plugin()
 
         def _convert(fname):
-            fname = osp.abspath(encoding.to_unicode_from_fs(fname))
+            fname = encoding.to_unicode_from_fs(fname)
+            if os.name == 'nt':
+                # Try to get the correct capitalization and absolute path
+                try:
+                    # This should correctly capitalize the path on Windows
+                    fname = str(Path(fname).resolve())
+                except OSError:
+                    # On Windows, "<string>" is not a valid path
+                    # But it can be used as filename while debugging
+                    fname = osp.abspath(fname)
+            else:
+                fname = osp.abspath(fname)
+
             if os.name == 'nt' and len(fname) >= 2 and fname[1] == ':':
                 fname = fname[0].upper()+fname[1:]
             return fname


Test patch: