MRtrix3 / mrtrix3

MRtrix3 provides a set of tools to perform various advanced diffusion MRI analyses, including constrained spherical deconvolution (CSD), probabilistic tractography, track-density imaging, and apparent fibre density
http://www.mrtrix.org
Mozilla Public License 2.0
281 stars 176 forks source link

Pathlib errors on Python 3.12.3/Ubuntu 24.04 LTS #2931

Open bjeurissen opened 1 week ago

bjeurissen commented 1 week ago

I recently installed the latest LTS version of ubuntu (24.04) on a new computer and found that our python commands are broken on Python 3.12.3 when using latest dev. The issue seems to be related to way the pathlib library is used:

$ dwibiascorrect ants dwi.mif dwi_bc.mif
Traceback (most recent call last):
  File "/usr/lib/python3.12/pathlib.py", line 441, in __str__
    return self._str
           ^^^^^^^^^
AttributeError: 'UserFileOutPath' object has no attribute '_str'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.12/pathlib.py", line 555, in drive
    return self._drv
           ^^^^^^^^^
AttributeError: 'UserFileOutPath' object has no attribute '_drv'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/bjeuriss/mrtrix3/bin/dwibiascorrect", line 87, in <module>
    mrtrix3.execute() #pylint: disable=no-member
    ^^^^^^^^^^^^^^^^^
  File "/home/bjeuriss/mrtrix3/lib/mrtrix3/__init__.py", line 90, in execute
    app._execute(inspect.getmodule(inspect.stack()[1][0])) # pylint: disable=protected-access
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/bjeuriss/mrtrix3/lib/mrtrix3/app.py", line 192, in _execute
    value.check_output()
  File "/home/bjeuriss/mrtrix3/lib/mrtrix3/app.py", line 619, in check_output
    return super().check_output('file')
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/bjeuriss/mrtrix3/lib/mrtrix3/app.py", line 608, in check_output
    if self.exists(): # pylint: disable=no-member
       ^^^^^^^^^^^^^
  File "/usr/lib/python3.12/pathlib.py", line 862, in exists
    self.stat(follow_symlinks=follow_symlinks)
  File "/usr/lib/python3.12/pathlib.py", line 842, in stat
    return os.stat(self, follow_symlinks=follow_symlinks)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/pathlib.py", line 448, in __fspath__
    return str(self)
           ^^^^^^^^^
  File "/usr/lib/python3.12/pathlib.py", line 443, in __str__
    self._str = self._format_parsed_parts(self.drive, self.root,
                                          ^^^^^^^^^^
  File "/usr/lib/python3.12/pathlib.py", line 557, in drive
    self._load_parts()
  File "/usr/lib/python3.12/pathlib.py", line 408, in _load_parts
    paths = self._raw_paths
            ^^^^^^^^^^^^^^^
AttributeError: 'UserFileOutPath' object has no attribute '_raw_paths'
Lestropie commented 1 week ago

Results from changes in #2678 not being tested against Python 3.12.

The pathlib specialisation was particularly nasty as ⁠it has its own funky runtime inheritance. I went back and forth with multiple different attempts. One concern I had was that some other library may take one of these paths as input and do a if isinstance(item, pathlib.XXX) check, which would fail for a composition implementation. Then again, given I'm changing the behaviour of __format__(), that might be unsafe anyways. I'll have a fresh go at doing via composition instead and see if I have any success.