Skip to content
Snippets Groups Projects
Commit bed22ace authored by Paul McCarthy's avatar Paul McCarthy :mountain_bicyclist:
Browse files

Merge branch 'mnt/warnings-deprecations' into 'master'

Mnt/warnings deprecations

See merge request fsl/fslpy!285
parents b45d290c 184f2938
No related branches found
No related tags found
No related merge requests found
...@@ -156,10 +156,6 @@ variables: ...@@ -156,10 +156,6 @@ variables:
script: script:
- bash ./.ci/test_template.sh - bash ./.ci/test_template.sh
test:3.6:
stage: test
image: pauldmccarthy/fsleyes-py36-wxpy4-gtk3
<<: *test_template
test:3.7: test:3.7:
stage: test stage: test
......
...@@ -15,6 +15,18 @@ Changed ...@@ -15,6 +15,18 @@ Changed
specified, which is run on the :mod:`.idle` loop. specified, which is run on the :mod:`.idle` loop.
Deprecated
^^^^^^^^^^
* Deprecated a number of GUI-specific properties in the
:mod:`fsl.utils.platform` module, including ``frozen``, ``haveGui``,
``canHaveGui``, ``inSSHSession``, ``inVNCSession``, ``wxPlatform``,
``wxFlavour``, ``glVersion``, ``glRenderer``, and ``glIsSoftwareRenderer``.
Equivalent functions are being added to the ``fsleyes-widgets`` library.
3.5.3 (Tuesday 9th February 2021) 3.5.3 (Tuesday 9th February 2021)
--------------------------------- ---------------------------------
......
...@@ -1206,7 +1206,8 @@ class Image(Nifti): ...@@ -1206,7 +1206,8 @@ class Image(Nifti):
def __del__(self): def __del__(self):
"""Closes any open file handles, and clears some references. """ """Closes any open file handles, and clears some references. """
Nifti.__del__(self) if Nifti is not None:
Nifti.__del__(self)
self.__nibImage = None self.__nibImage = None
self.__imageWrapper = None self.__imageWrapper = None
......
...@@ -89,7 +89,35 @@ except ImportError: import Queue as queue ...@@ -89,7 +89,35 @@ except ImportError: import Queue as queue
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
class IdleTask(object): @functools.lru_cache()
def _canHaveGui():
"""Return ``True`` if wxPython is installed, and a display is available,
``False`` otherwise.
"""
# Determine if a display is available. We do
# this once at init (instead of on-demand in
# the canHaveGui method) because calling the
# IsDisplayAvailable function will cause the
# application to steal focus under OSX!
try:
import wx
return wx.App.IsDisplayAvailable()
except ImportError:
return False
def _haveGui():
"""Return ``True`` if wxPython is installed, a display is available, and
a ``wx.App`` exists, ``False`` otherwise.
"""
try:
import wx
return _canHaveGui() and (wx.GetApp() is not None)
except ImportError:
return False
class IdleTask:
"""Container object used by the :class:`IdleLoop` class. """Container object used by the :class:`IdleLoop` class.
Used to encapsulate information about a queued task. Used to encapsulate information about a queued task.
""" """
...@@ -111,7 +139,7 @@ class IdleTask(object): ...@@ -111,7 +139,7 @@ class IdleTask(object):
self.kwargs = kwargs self.kwargs = kwargs
class IdleLoop(object): class IdleLoop:
"""This class contains logic for running tasks via ``wx.EVT_IDLE`` events. """This class contains logic for running tasks via ``wx.EVT_IDLE`` events.
A single ``IdleLoop`` instance is created when this module is first A single ``IdleLoop`` instance is created when this module is first
...@@ -370,8 +398,6 @@ class IdleLoop(object): ...@@ -370,8 +398,6 @@ class IdleLoop(object):
``timeout``, or ``alwaysQueue``. ``timeout``, or ``alwaysQueue``.
""" """
from fsl.utils.platform import platform as fslplatform
schedtime = time.time() schedtime = time.time()
timeout = kwargs.pop('timeout', 0) timeout = kwargs.pop('timeout', 0)
after = kwargs.pop('after', 0) after = kwargs.pop('after', 0)
...@@ -380,18 +406,15 @@ class IdleLoop(object): ...@@ -380,18 +406,15 @@ class IdleLoop(object):
skipIfQueued = kwargs.pop('skipIfQueued', False) skipIfQueued = kwargs.pop('skipIfQueued', False)
alwaysQueue = kwargs.pop('alwaysQueue', False) alwaysQueue = kwargs.pop('alwaysQueue', False)
canHaveGui = fslplatform.canHaveGui
haveGui = fslplatform.haveGui
# If there is no possibility of a # If there is no possibility of a
# gui being available in the future # gui being available in the future
# (determined by canHaveGui), then # (determined by _canHaveGui), then
# alwaysQueue is ignored. # alwaysQueue is ignored.
alwaysQueue = alwaysQueue and canHaveGui alwaysQueue = alwaysQueue and _canHaveGui()
# We don't have wx - run the task # We don't have wx - run the task
# directly/synchronously. # directly/synchronously.
if self.__neverQueue or not (haveGui or alwaysQueue): if self.__neverQueue or not (_haveGui() or alwaysQueue):
time.sleep(after) time.sleep(after)
log.debug('Running idle task directly') log.debug('Running idle task directly')
task(*args, **kwargs) task(*args, **kwargs)
...@@ -611,11 +634,13 @@ def block(secs, delta=0.01, until=None): ...@@ -611,11 +634,13 @@ def block(secs, delta=0.01, until=None):
determins when calls to ``block`` will return. determins when calls to ``block`` will return.
""" """
havewx = _haveGui()
def defaultUntil(): def defaultUntil():
return False return False
def tick(): def tick():
if fslplatform.haveGui: if havewx:
import wx import wx
wx.YieldIfNeeded() wx.YieldIfNeeded()
time.sleep(delta) time.sleep(delta)
...@@ -623,8 +648,6 @@ def block(secs, delta=0.01, until=None): ...@@ -623,8 +648,6 @@ def block(secs, delta=0.01, until=None):
if until is None: if until is None:
until = defaultUntil until = defaultUntil
from fsl.utils.platform import platform as fslplatform
start = time.time() start = time.time()
while (time.time() - start) < secs: while (time.time() - start) < secs:
tick() tick()
...@@ -653,12 +676,11 @@ def run(task, onFinish=None, onError=None, name=None): ...@@ -653,12 +676,11 @@ def run(task, onFinish=None, onError=None, name=None):
the return value will be ``None``. the return value will be ``None``.
""" """
from fsl.utils.platform import platform as fslplatform
if name is None: if name is None:
name = getattr(task, '__name__', '<unknown>') name = getattr(task, '__name__', '<unknown>')
haveWX = fslplatform.haveGui haveWX = _haveGui()
# Calls the onFinish or onError handler # Calls the onFinish or onError handler
def callback(cb, *args, **kwargs): def callback(cb, *args, **kwargs):
...@@ -727,14 +749,12 @@ def wait(threads, task, *args, **kwargs): ...@@ -727,14 +749,12 @@ def wait(threads, task, *args, **kwargs):
a keyword argument called ``wait_direct``. a keyword argument called ``wait_direct``.
""" """
from fsl.utils.platform import platform as fslplatform
direct = kwargs.pop('wait_direct', False) direct = kwargs.pop('wait_direct', False)
if not isinstance(threads, abc.Sequence): if not isinstance(threads, abc.Sequence):
threads = [threads] threads = [threads]
haveWX = fslplatform.haveGui haveWX = _haveGui()
def joinAll(): def joinAll():
log.debug('Wait thread joining on all targets') log.debug('Wait thread joining on all targets')
...@@ -755,7 +775,7 @@ def wait(threads, task, *args, **kwargs): ...@@ -755,7 +775,7 @@ def wait(threads, task, *args, **kwargs):
return None return None
class Task(object): class Task:
"""Container object which encapsulates a task that is run by a """Container object which encapsulates a task that is run by a
:class:`TaskThread`. :class:`TaskThread`.
""" """
...@@ -775,7 +795,6 @@ class TaskThreadVeto(Exception): ...@@ -775,7 +795,6 @@ class TaskThreadVeto(Exception):
handler (if one has been specified). See the :meth:`TaskThread.enqueue` handler (if one has been specified). See the :meth:`TaskThread.enqueue`
method for more details. method for more details.
""" """
pass
class TaskThread(threading.Thread): class TaskThread(threading.Thread):
...@@ -1005,7 +1024,7 @@ def mutex(*args, **kwargs): ...@@ -1005,7 +1024,7 @@ def mutex(*args, **kwargs):
return MutexFactory(*args, **kwargs) return MutexFactory(*args, **kwargs)
class MutexFactory(object): class MutexFactory:
"""The ``MutexFactory`` is a placeholder for methods which have been """The ``MutexFactory`` is a placeholder for methods which have been
decorated with the :func:`mutex` decorator. When the method of a class decorated with the :func:`mutex` decorator. When the method of a class
is decorated with ``@mutex``, a ``MutexFactory`` is created. is decorated with ``@mutex``, a ``MutexFactory`` is created.
......
...@@ -18,7 +18,8 @@ import os.path as op ...@@ -18,7 +18,8 @@ import os.path as op
import sys import sys
import importlib import importlib
import fsl.utils.notifier as notifier import fsl.utils.notifier as notifier
import fsl.utils.deprecated as deprecated
# An annoying consequence of using # An annoying consequence of using
# a system-module name for our own # a system-module name for our own
...@@ -150,6 +151,10 @@ class Platform(notifier.Notifier): ...@@ -150,6 +151,10 @@ class Platform(notifier.Notifier):
@property @property
@deprecated.deprecated(
'3.6.0',
'4.0.0',
'Equivalent functionality is available in fsleyes-widgets.')
def frozen(self): def frozen(self):
"""``True`` if we are running in a compiled/frozen application, """``True`` if we are running in a compiled/frozen application,
``False`` otherwise. ``False`` otherwise.
...@@ -158,6 +163,10 @@ class Platform(notifier.Notifier): ...@@ -158,6 +163,10 @@ class Platform(notifier.Notifier):
@property @property
@deprecated.deprecated(
'3.6.0',
'4.0.0',
'Equivalent functionality is available in fsleyes-widgets.')
def haveGui(self): def haveGui(self):
"""``True`` if we are running with a GUI, ``False`` otherwise. """``True`` if we are running with a GUI, ``False`` otherwise.
...@@ -201,12 +210,20 @@ class Platform(notifier.Notifier): ...@@ -201,12 +210,20 @@ class Platform(notifier.Notifier):
@property @property
@deprecated.deprecated(
'3.6.0',
'4.0.0',
'Equivalent functionality is available in fsleyes-widgets.')
def canHaveGui(self): def canHaveGui(self):
"""``True`` if it is possible to create a GUI, ``False`` otherwise. """ """``True`` if it is possible to create a GUI, ``False`` otherwise. """
return self.__canHaveGui return self.__canHaveGui
@property @property
@deprecated.deprecated(
'3.6.0',
'4.0.0',
'Equivalent functionality is available in fsleyes-widgets.')
def inSSHSession(self): def inSSHSession(self):
"""``True`` if this application is running over an SSH session, """``True`` if this application is running over an SSH session,
``False`` otherwise. ``False`` otherwise.
...@@ -215,6 +232,10 @@ class Platform(notifier.Notifier): ...@@ -215,6 +232,10 @@ class Platform(notifier.Notifier):
@property @property
@deprecated.deprecated(
'3.6.0',
'4.0.0',
'Equivalent functionality is available in fsleyes-widgets.')
def inVNCSession(self): def inVNCSession(self):
"""``True`` if this application is running over a VNC (or similar) """``True`` if this application is running over a VNC (or similar)
session, ``False`` otherwise. Currently, the following remote desktop session, ``False`` otherwise. Currently, the following remote desktop
...@@ -228,6 +249,10 @@ class Platform(notifier.Notifier): ...@@ -228,6 +249,10 @@ class Platform(notifier.Notifier):
@property @property
@deprecated.deprecated(
'3.6.0',
'4.0.0',
'Equivalent functionality is available in fsleyes-widgets.')
def wxPlatform(self): def wxPlatform(self):
"""One of :data:`WX_UNKNOWN`, :data:`WX_MAC_COCOA`, """One of :data:`WX_UNKNOWN`, :data:`WX_MAC_COCOA`,
:data:`WX_MAC_CARBON`, or :data:`WX_GTK`, indicating the wx platform. :data:`WX_MAC_CARBON`, or :data:`WX_GTK`, indicating the wx platform.
...@@ -253,6 +278,10 @@ class Platform(notifier.Notifier): ...@@ -253,6 +278,10 @@ class Platform(notifier.Notifier):
@property @property
@deprecated.deprecated(
'3.6.0',
'4.0.0',
'Equivalent functionality is available in fsleyes-widgets.')
def wxFlavour(self): def wxFlavour(self):
"""One of :data:`WX_UNKNOWN`, :data:`WX_PYTHON` or :data:`WX_PHOENIX`, """One of :data:`WX_UNKNOWN`, :data:`WX_PYTHON` or :data:`WX_PHOENIX`,
indicating the wx flavour. indicating the wx flavour.
...@@ -359,6 +388,10 @@ class Platform(notifier.Notifier): ...@@ -359,6 +388,10 @@ class Platform(notifier.Notifier):
@property @property
@deprecated.deprecated(
'3.6.0',
'4.0.0',
'Equivalent functionality is available in fsleyes-widgets.')
def glVersion(self): def glVersion(self):
"""Returns the available OpenGL version, or ``None`` if it has not """Returns the available OpenGL version, or ``None`` if it has not
been set. been set.
...@@ -367,12 +400,20 @@ class Platform(notifier.Notifier): ...@@ -367,12 +400,20 @@ class Platform(notifier.Notifier):
@glVersion.setter @glVersion.setter
@deprecated.deprecated(
'3.6.0',
'4.0.0',
'Equivalent functionality is available in fsleyes-widgets.')
def glVersion(self, value): def glVersion(self, value):
"""Set the available OpenGL version. """ """Set the available OpenGL version. """
self.__glVersion = value self.__glVersion = value
@property @property
@deprecated.deprecated(
'3.6.0',
'4.0.0',
'Equivalent functionality is available in fsleyes-widgets.')
def glRenderer(self): def glRenderer(self):
"""Returns the available OpenGL renderer, or ``None`` if it has not """Returns the available OpenGL renderer, or ``None`` if it has not
been set. been set.
...@@ -381,6 +422,10 @@ class Platform(notifier.Notifier): ...@@ -381,6 +422,10 @@ class Platform(notifier.Notifier):
@glRenderer.setter @glRenderer.setter
@deprecated.deprecated(
'3.6.0',
'4.0.0',
'Equivalent functionality is available in fsleyes-widgets.')
def glRenderer(self, value): def glRenderer(self, value):
"""Set the available OpenGL renderer. """ """Set the available OpenGL renderer. """
self.__glRenderer = value self.__glRenderer = value
...@@ -398,6 +443,10 @@ class Platform(notifier.Notifier): ...@@ -398,6 +443,10 @@ class Platform(notifier.Notifier):
@property @property
@deprecated.deprecated(
'3.6.0',
'4.0.0',
'Equivalent functionality is available in fsleyes-widgets.')
def glIsSoftwareRenderer(self): def glIsSoftwareRenderer(self):
"""Returns ``True`` if the OpenGL renderer is software based, """Returns ``True`` if the OpenGL renderer is software based,
``False`` otherwise, or ``None`` if the renderer has not yet been set. ``False`` otherwise, or ``None`` if the renderer has not yet been set.
......
...@@ -421,7 +421,7 @@ class Settings(object): ...@@ -421,7 +421,7 @@ class Settings(object):
try: try:
with open(configFile, 'wb') as f: with open(configFile, 'wb') as f:
pickle.dump(config, f, protocol=2) pickle.dump(config, f, protocol=2)
except (IOError, pickle.PicklingError, EOFError): except (IOError, pickle.PicklingError, EOFError, FileNotFoundError):
log.warning('Unable to save {} configuration file ' log.warning('Unable to save {} configuration file '
'{}'.format(self.__configID, configFile), '{}'.format(self.__configID, configFile),
exc_info=True) exc_info=True)
...@@ -38,6 +38,11 @@ def _run_with_wx(func, *args, **kwargs): ...@@ -38,6 +38,11 @@ def _run_with_wx(func, *args, **kwargs):
if callAfterApp is not None: if callAfterApp is not None:
callAfterApp() callAfterApp()
# canHaveGui caches its return val,
# so clear it otherwise we may
# affect subsequent tests
idle._canHaveGui.cache_clear()
def wrap(): def wrap():
try: try:
...@@ -64,6 +69,8 @@ def _run_with_wx(func, *args, **kwargs): ...@@ -64,6 +69,8 @@ def _run_with_wx(func, *args, **kwargs):
idle.idleLoop.reset() idle.idleLoop.reset()
idle._canHaveGui.cache_clear()
if raised[0] and propagateRaise: if raised[0] and propagateRaise:
raise raised[0] raise raised[0]
...@@ -413,10 +420,9 @@ def test_idle_alwaysQueue4(): ...@@ -413,10 +420,9 @@ def test_idle_alwaysQueue4():
import fsl.utils.platform import fsl.utils.platform
with mock.patch.dict('sys.modules', {'wx' : None}): with mock.patch.dict('sys.modules', {'wx' : None}):
# idle uses the platform module to # The idle._canHaveGui caches its result,
# determine whether a GUI is available, # so we need to invalidate it
# so we have to reload it idle._canHaveGui.cache_clear()
reload_module(fsl.utils.platform)
idle.idle(task, alwaysQueue=True) idle.idle(task, alwaysQueue=True)
with pytest.raises(ImportError): with pytest.raises(ImportError):
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment