Skip to content

Conversation

@scott-huberty
Copy link
Contributor

I have a few MFF files which contain a corrupt XML file (a tag didn't close properly).

This PR uses defensive programming to gracefully handle the scenario, while also providing more information to the user about the XML file that couldn't be parsed.

from pathlib import Path
import mne
import shutil
egi_fname = mne.datasets.testing.data_path() / "EGI" / "test_egi.mff"

test_fname = shutil.copytree(egi_fname, Path("./bad_xml_egi.mff").resolve())
bad_xml = test_fname / "bad.xml"
bad_xml.write_text("<bad>")
raw = mne.io.read_raw_egi(test_fname)
test_fname.unlink()

on main (crashes and doesn't give a hint)

Reading EGI MFF Header from /Users/scotterik/devel/repos/mne-python/bad_xml_egi.mff...
    Reading events ...
Traceback (most recent call last):

  File ~/.local/share/uv/python/cpython-3.10.16-macos-x86_64-none/lib/python3.10/xml/etree/ElementTree.py:1725 in close
    self.parser.Parse(b"", True) # end of data

ExpatError: no element found: line 1, column 5


During handling of the above exception, another exception occurred:

Traceback (most recent call last):

  File ~/devel/projects/IBIS-EEG/.venv/lib/python3.10/site-packages/IPython/core/interactiveshell.py:3577 in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)

  Cell In[4], line 9
    raw = mne.io.read_raw_egi(test_fname)

  File <decorator-gen-359>:12 in read_raw_egi

  File ~/devel/repos/mne-python/mne/io/egi/egi.py:175 in read_raw_egi
    return _read_raw_egi_mff(

  File <decorator-gen-356>:12 in _read_raw_egi_mff

  File ~/devel/repos/mne-python/mne/io/egi/egimff.py:361 in _read_raw_egi_mff
    return RawMff(

  File <decorator-gen-357>:12 in __init__

  File ~/devel/repos/mne-python/mne/io/egi/egimff.py:411 in __init__
    egi_events, egi_info, mff_events = _read_events(input_fname, egi_info)

  File ~/devel/repos/mne-python/mne/io/egi/events.py:26 in _read_events
    mff_events, event_codes = _read_mff_events(input_fname, info["sfreq"])

  File ~/devel/repos/mne-python/mne/io/egi/events.py:51 in _read_mff_events
    orig[xml_type] = _parse_xml(xml_file)

  File ~/devel/repos/mne-python/mne/io/egi/events.py:86 in _parse_xml
    xml = defusedxml.ElementTree.parse(xml_file)

  File ~/devel/projects/IBIS-EEG/.venv/lib/python3.10/site-packages/defusedxml/common.py:100 in parse
    return _parse(source, parser)

  File ~/.local/share/uv/python/cpython-3.10.16-macos-x86_64-none/lib/python3.10/xml/etree/ElementTree.py:1222 in parse
    tree.parse(source, parser)

  File ~/.local/share/uv/python/cpython-3.10.16-macos-x86_64-none/lib/python3.10/xml/etree/ElementTree.py:587 in parse
    self._root = parser.close()

  File ~/.local/share/uv/python/cpython-3.10.16-macos-x86_64-none/lib/python3.10/xml/etree/ElementTree.py:1727 in close
    self._raiseerror(v)

  File ~/.local/share/uv/python/cpython-3.10.16-macos-x86_64-none/lib/python3.10/xml/etree/ElementTree.py:1627 in _raiseerror
    raise err

  File <string>
ParseError: no element found: line 1, column 5

this branch:

Reading EGI MFF Header from /Users/scotterik/devel/repos/mne-python/bad_xml_egi.mff...
    Reading events ...
<ipython-input-17-ca7d688fd187>:1: RuntimeWarning: Could not parse the XML file /Users/scotterik/devel/repos/mne-python/bad_xml_egi.mff/bad.xml.
  raw = mne.io.read_raw_egi(test_fname)
    Assembling measurement info ...
    Excluding events {} ...

scott-huberty and others added 2 commits March 6, 2025 07:58
Eric suggestion

Co-authored-by: Eric Larson <larson.eric.d@gmail.com>
- use importorskip
- require testing data
- use context manager to open and write to file
- use tmp_path fixture
scott-huberty added a commit to scott-huberty/mne-python that referenced this pull request Mar 6, 2025
- As seen in The failing ubuntu-latest job of mne-tools#13145

https://github.com/mne-tools/mne-python/actions/runs/13702975846/job/38321283000?pr=13145#step:16:5679

I cannot replicate this locally on my MacOS, but from what I can gather, the .magic method is deprecated (ref ipython/ipython#10327 ), and so test_widget_abstraction_notebook fails with the lastest IPython (9.0.1)

Let's try to use run_line_magic instead, which seems to be the recommended way
@scott-huberty
Copy link
Contributor Author

scott-huberty commented Mar 6, 2025

Needs #13146 (or some other fix for the failing ubuntu-latest CI)

@larsoner
Copy link
Member

larsoner commented Mar 6, 2025

Okay let's wait for #13146 then and then we can click the Update button on this PR. In the meantime I'll mark for merge-when-green, thanks in advance @scott-huberty !

@larsoner larsoner enabled auto-merge (squash) March 6, 2025 18:31
Suggested by @larsoner

Co-authored-by: Eric Larson <larson.eric.d@gmail.com>
auto-merge was automatically disabled March 6, 2025 18:35

Head branch was pushed to by a user without write access

scott-huberty added a commit to scott-huberty/mne-python that referenced this pull request Mar 6, 2025
@larsoner larsoner enabled auto-merge (squash) March 6, 2025 20:59
@larsoner larsoner merged commit a5073bf into mne-tools:main Mar 6, 2025
30 checks passed
@scott-huberty scott-huberty deleted the egi_xml_parse branch March 6, 2025 22:27
larsoner added a commit to larsoner/mne-python that referenced this pull request Apr 4, 2025
* upstream/main: (149 commits)
  FIX make_watershed_bem to handle missing talairach_with_skull.lta courtesy Freesurfer 8 (mne-tools#13172)
  ENH: Add upsampling for MEG helmet surface (mne-tools#13179)
  MAINT: Update code credit (mne-tools#13180)
  BUG: Fix bug with least-squares sphere fit (mne-tools#13178)
  fix EDF export (mne-tools#13174)
  fix typo (mne-tools#13171)
  [pre-commit.ci] pre-commit autoupdate (mne-tools#13164)
  Fix dev installation guide (mne-tools#13163)
  expose 'mode' for plotting dipole on brain (mne-tools#13162)
  turn dipole attrs into properties (mne-tools#13153)
  remove misformatted (and unused) crossref anchor (mne-tools#13155)
  doc: point to read_dipole (mne-tools#13149)
  [pre-commit.ci] pre-commit autoupdate (mne-tools#13152)
  BUG: Fix bug with not short-circuiting n_jobs=1 (mne-tools#13147)
  FIX: Missing coordinates.xml in MFF file (mne-tools#13148)
  FIX: Gracefully handle bad XML files in EGI reader (mne-tools#13145)
  Fixes for Latest IPython (9.0.1) (mne-tools#13146)
  Fix intersphinx (mne-tools#13143)
  BUG: Fix bug with parallel doc build (mne-tools#13140)
  [pre-commit.ci] pre-commit autoupdate (mne-tools#13141)
  ...
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.

2 participants