Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MRG: Add return type hints to read_evokeds(), read_raw() #12250

Merged
merged 14 commits into from
Dec 5, 2023

Conversation

hoechenberger
Copy link
Member

@hoechenberger hoechenberger commented Nov 30, 2023

Closes #12249
x-ref #12243

This PR adds return type hints for read_evokeds() and read_raw().

Screenshot 2023-11-30 at 18 43 30 Screenshot 2023-11-30 at 18 44 18

I decided to annotate read_raw() as BaseRaw, as this is the parent class shared among all raw readers.

Neat:
Turns out that since all specific raw readers (read_raw_*()) are structured in a simple fashion and have return RawXXX() as their last line of code, VS Code can trivially find out the correct return types of those functions without any additional type hints!

Same goes for read_epochs(), hence no changes are required there either.

Still, our docstrings are, strictly speaking, incorrect; read_raw_X() returns a RawX instance, not Raw; and read_epochs() returns EpochsFIF, not Epochs. Just something to keep in mind for a future cleanup or so.

@hoechenberger hoechenberger marked this pull request as ready for review November 30, 2023 17:47
@hoechenberger hoechenberger changed the title Add type hints to read_evokeds(), read_raw() Add return type hints to read_evokeds(), read_raw() Nov 30, 2023
@hoechenberger

This comment has been minimized.

@larsoner
Copy link
Member

larsoner commented Dec 1, 2023

Looks good to me so far. Is it reasonable to add mypy to check just these functions, or no? If so I can try adding it to this PR. And @hoechenberger we probably need a doc/changes/devel.rst update mentioning that some return type hints have been added.

@hoechenberger
Copy link
Member Author

I will look into this, @larsoner

@hoechenberger
Copy link
Member Author

hoechenberger commented Dec 1, 2023

@larsoner I added the foundations for MyPy testing, but I don't have time to adjust the CI configurations etc

❯ mypy ./mne
Success: no issues found in 638 source files

Changing the read_evokeds() return type from Union[List[Evoked], Evoked] to List[Evoked]:

❯ mypy ./mne
mne/evoked.py:1630: error: Incompatible return value type (got "object", expected "list[Evoked]")  [return-value]
Found 1 error in 1 file (checked 638 source files)

Not the greatest error message, but it does discover the bug!

There's an issue with BunchConstNamed, which has occurred to me for years but so far I managed to silently ignore it; but with MyPy, this is no longer an option and I had to explicitly # type: ignore lines where we're accessing FIFF.*, otherwise we'd get messages like:

mne/evoked.py:83: error: "BunchConstNamed" has no attribute "FIFFV_ASPECT_AVERAGE"  [attr-defined]

I've gotten red squiggly lines and no tab completion with BunchConstNamed ever since I started using VS Code, so something is not quite right there. Not sure how to fix it properly. I wonder if we should simply switch to SimpleNamespace?

@hoechenberger
Copy link
Member Author

I will write a changeog entry later

@larsoner
Copy link
Member

larsoner commented Dec 4, 2023

I don't have time to adjust the CI configurations etc... I've gotten red squiggly lines and no tab completion with BunchConstNamed ever since I started using VS Code, so something is not quite right there. Not sure how to fix it properly. I wonder if we should simply switch to SimpleNamespace

Maybe but for now I just ignore attr-defined, we hit it on other stuff, too, so it'll be a bigger undertaking. Now added to CIs via pre-commit.ci and it's passing, as is pre-commit run --all locally and mypy mne/ locally.

Based on the link @drammock posted in #12249, I think we're on step https://mypy.readthedocs.io/en/stable/existing_code.html#prioritise-annotating-widely-imported-modules at this point, so @hoechenberger if you add a devel.rst update we should be good to go here I think.

Comment on lines +340 to +344
'no-untyped-call',
'no-untyped-def',
'misc',
'assignment',
'operator',
Copy link
Member Author

@hoechenberger hoechenberger Dec 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@larsoner I don't need to add a single one of these to successfully run mypy mne/ without errors. Did you only add those in anticipation of future errors? I'd rather remove or comment out anything we don't need right now. I'm using MyPy 1.7.1.

Copy link
Member Author

@hoechenberger hoechenberger Dec 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, you were running it with --strict. Why?

I don't think we should run with --strict for now.

MNE is basically not typed at all; telling MyPy to be strict is just setting us up for all kinds of trouble

Also the MyPy docs say:

Note: the exact list of flags enabled by running --strict may change over time.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To me it's better to know and be explicit here but we can remove it if you want

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I'd like to keep the comments though because they do indicate things we can work on in the future)

* upstream/main:
  MRG: Use ruff-format instead of Black (mne-tools#12261)
  MAINT: Make selenium optional and use on CircleCI (mne-tools#12263)
  MAINT: Post-release deprecations (mne-tools#12265)
  MAINT: Replace `Path.parent.parent` with `Path.parents[N]` in tests (mne-tools#12257)
@larsoner
Copy link
Member

larsoner commented Dec 5, 2023

@hoechenberger fixed a conflict and added to .git-blame-revs-ignore from the other PR, good to go from your end?

Copy link
Member

@larsoner larsoner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@drammock feel free to review and approve then we can merge I think assuming @hoechenberger is also happy

@drammock
Copy link
Member

drammock commented Dec 5, 2023

I do see the type:

type-hint

but "loading" stays there for tens of seconds. Ctrl+space after raw. pops up a bigger box with "loading..." in a bigger font.

@hoechenberger
Copy link
Member Author

This looks like a problem with Pylance. Is there anything useful logged in the "Python language server" log window?

@drammock
Copy link
Member

drammock commented Dec 5, 2023

nothing useful to my eye:

2023-12-05 15:08:06.092 [info] [Info  - 3:08:06 PM] (2507452) Pylance language server 2023.11.10 (pyright 088ebaa5) starting
2023-12-05 15:08:06.092 [info] [Info  - 3:08:06 PM] (2507452) Server root directory: /home/drmccloy/.vscode/extensions/ms-python.vscode-pylance-2023.11.10/dist
2023-12-05 15:08:06.104 [info] [Info  - 3:08:06 PM] (2507452) Starting service instance "python"
2023-12-05 15:08:06.143 [info] [Info  - 3:08:06 PM] (2507452) Setting pythonPath for service "python": "/opt/mambaforge/envs/mnedev/bin/python"
2023-12-05 15:08:06.144 [info] [Info  - 3:08:06 PM] (2507452) Setting environmentName for service "python": "3.11.6 (mnedev conda)"
2023-12-05 15:08:06.147 [info] [Info  - 3:08:06 PM] (2507452) Loading pyproject.toml file at /opt/mne/python/pyproject.toml
2023-12-05 15:08:06.163 [info] [Info  - 3:08:06 PM] (2507452) Pyproject file "/opt/mne/python/pyproject.toml" has no "[tool.pyright]" section.
2023-12-05 15:08:06.214 [info] [Info  - 3:08:06 PM] (2507452) Assuming Python version 3.11
2023-12-05 15:08:06.620 [info] [Info  - 3:08:06 PM] (2507452) Found 1845 source files
2023-12-05 15:08:17.420 [info] [Info  - 3:08:17 PM] (2507452) [IDX(2)] Long operation: index execution environment /opt/mne/python (6534ms)
2023-12-05 15:08:17.421 [info] [Info  - 3:08:17 PM] (2507452) [IDX(2)] Long operation: index packages /opt/mne/python (6561ms)

all of this was up within ~15 seconds of opening vscode. did a Ctrl+space after raw. and waited about 90 seconds, no new log entries.

@hoechenberger
Copy link
Member Author

hoechenberger commented Dec 5, 2023

Thanks!

Can you check that you have the following settings in VS Code:

"python.analysis.indexing": true,  // this is the default, but check if it's really on
"python.analysis.userFileIndexingLimit": -1,

Lastly, you can set

"python.analysis.logLevel": "Trace"

to get debugging info – maybe this can give us some clues!

@drammock
Copy link
Member

drammock commented Dec 5, 2023

  • indexing was True
  • indexing limit was at 2000 (MNE has ~1800 files, so shouldn't have been a bottleneck?). I've changed it to -1
  • setting loglevel to Trace made the output pane explode with messages; I don't know where to start (dozens of lines per second, nearly continuously, too fast to read them)

I've also just enabled the "persist indices to disk for all 3rd party libraries" so maybe once it's gone through everything once it will actually become performant? 🤞🏻

@drammock
Copy link
Member

drammock commented Dec 5, 2023

it finally slowed down. every single message is info level. I searched for io/base and found these lines:

2023-12-05 15:39:08.324 [info] (2603285) [BG(1)] indexing: /opt/mne/python/mne/io/base.py [found 21] (7ms)

...

2023-12-05 15:39:12.858 [info] (2603285) [FG] parsing: /opt/mne/python/mne/io/base.py [fs read 1ms] (60ms)
2023-12-05 15:39:12.872 [info] (2603285) [FG] binding: /opt/mne/python/mne/io/base.py (14ms)

ctrl+space still shows "loading..." both before and after closing/reopening the IDE

@hoechenberger
Copy link
Member Author

How did you install MNE?

@drammock
Copy link
Member

drammock commented Dec 6, 2023 via email

@hoechenberger
Copy link
Member Author

hoechenberger commented Dec 6, 2023

Can you do a non-editable install?

After that one, I'm out of ideas…

@cbrnr
Copy link
Contributor

cbrnr commented Dec 6, 2023

FWIW, everything works fine for me, even with an editable install.

@hoechenberger
Copy link
Member Author

hoechenberger commented Dec 6, 2023

FWIW, everything works fine for me, even with an editable install.

If the editable install is working for you out of the box, this indicates that your Pylance is actually not picking up the "installed" MNE, but rather the one in your current working directory / workspace. So this is not a valid test for either, editable and non-editable install. You need to use a workspace outside of the mne-python directory for testing.

@cbrnr
Copy link
Contributor

cbrnr commented Dec 6, 2023

Can we please switch to Hatchling ASAP? I keep forgetting that editable installs do not work with Setuptools...

And yes, installing it as non-editable in a new venv outside of the MNE source works for me.

@hoechenberger
Copy link
Member Author

hoechenberger commented Dec 6, 2023

Can we please switch to Hatchling ASAP? I keep forgetting that editable installs do not work with Setuptools...

Sure but this still wouldn't resolve this issue here.
Pylance will always prioritize your workspace / CWD over the "global" installation.

As will Python…

@cbrnr
Copy link
Contributor

cbrnr commented Dec 6, 2023

OK, so as a dev I will basically never be able to check if these sorts of things are working? I am not going to roll a second venv just to test this.

@hoechenberger
Copy link
Member Author

hoechenberger commented Dec 6, 2023

OK, so as a dev I will basically never be able to check if these sorts of things are working?

Errm … If you're running all your tests from within the mne-python directory, you cannot rely on anything if your actual goal is to test behavior of an actual installation. If you run python -c "import mne", Python will pick mne from your CWD in that case, not the one from site-packages.

This just to say that this problem affects all parts of Python package development. It's not isolated to type hints. It has nothing to do with using a venv or not.

The Python import system is just awful in this regard.

@cbrnr
Copy link
Contributor

cbrnr commented Dec 6, 2023

Yes, that's what CI should test, not any dev.

@hoechenberger
Copy link
Member Author

So what was your point again? :D

@drammock
Copy link
Member

drammock commented Dec 6, 2023

FWIW, everything works fine for me, even with an editable install.

If the editable install is working for you out of the box, this indicates that your Pylance is actually not picking up the "installed" MNE, but rather the one in your current working directory / workspace. So this is not a valid test for either, editable and non-editable install. You need to use a workspace outside of the mne-python directory for testing.

update:

  • if I launch vscode from /opt/mne/python (where my editable install lives) I get "Loading..." for a very long time (this was already reported above)
  • if I launch vscode from some other directory, then I get "No suggestions" when I ctrl+space after raw.
  • if I do this:
$ mamba create -n typehints pip
$ mamba activate typehints
$ pip install git+https://github.com/mne-tools/mne-python.git@main

then launch vscode from anywhere (both ~/Desktop and /opt/mne/python work) then I get this:

type-hint

I can even get the suggestions to work if I launch vscode from a terminal with typehints env active, and then switch vscode to mnedev after launching the IDE (which is weird / I don't understand why that works). The only thing that seems to not work is exactly the situation that I always use: launch vscode from a terminal where mnedev is activated (i.e. where mne is installed with an editable install).

@hoechenberger
Copy link
Member Author

Thanks for testing, @drammock

I believe this will be resolved via #12269

Can you try with that branch?

@drammock
Copy link
Member

drammock commented Dec 6, 2023

I believe this will be resolved via #12269
Can you try with that branch?

Here's what I did:

$ cd /opt/mne/python
$ git checkout -b hatchling hoechenberger/hatchling
$ pip install -e .
$ code .

No completion, still "Loading..." forever. vscode's bottom bar shows mnedev as the active env

If I instead do code ~/Desktop then I do get completion, even if vscode's bottom bar shows mnedev as the active env.

Is that the expected pattern? Is there a chance that some cruft is causing the failure? in the root of my MNE clone I have (among other things) the folders .eggs, mne.egg-info, and .mypy-cache of which IDK if they might be stale/unnecessary.

@hoechenberger
Copy link
Member Author

It's definitely not the expected behavior

Can you try to create a fresh clone of my branch and use that?

@hoechenberger
Copy link
Member Author

hoechenberger commented Dec 6, 2023

Do you get completions with other Python packages?

Did the problem not occur before we merged this PR?

@larsoner
Copy link
Member

larsoner commented Dec 6, 2023

Can you try to create a fresh clone of my branch and use that?

Or use git clean -xdf which will remove all files not under version control. I wonder if it's the mne.egg-info specifically, those can be problematic

@cbrnr
Copy link
Contributor

cbrnr commented Dec 6, 2023

This sounds like your VS Code installation is broken. Can you try to reinstall and maybe clean out your user and workspace (.vscode) settings?

@drammock
Copy link
Member

drammock commented Dec 6, 2023

Can you try to create a fresh clone of my branch and use that?

Do you get completions with other Python packages?

yes, e.g., numpy

Did the problem not occur before we merged this PR?

not sure, I didn't typically use this feature before

Or use git clean -xdf

Nothing changed after doing this.

This sounds like your VS Code installation is broken. Can you try to reinstall and maybe clean out your user and workspace (.vscode) settings?

git clean -xdf nuked the workspace settings. I looked at my global settings, nothing likely to affect this was found

Ultimately I did just fix it, by disabling the reStructuredText extension (which runs esbonio language server in the background). Not a big surprise, I've hit trouble with that extension before.

@hoechenberger
Copy link
Member Author

hoechenberger commented Dec 6, 2023

reST is poision, I'm tellin' ya! 😅🥹

Great to hear things are working for you now!

@drammock
Copy link
Member

drammock commented Dec 6, 2023

rST is not the problem here. it's the vscode extension that relies on silently running sphinx builds in the background in order to offer rST completion hints for crossreferences. A small benefit that is not worth the complexity and cost.

@hoechenberger
Copy link
Member Author

I was really just trying to make a joke :) But I do dislike reST, that's for sure :D
Good to know this extension causes problems, I had just recently considered starting to use it; now I probably won't

snwnde pushed a commit to snwnde/mne-python that referenced this pull request Mar 20, 2024
…ls#12250)

Co-authored-by: Eric Larson <larson.eric.d@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants