Skip to content
Snippets Groups Projects
Commit 1c0c21b3 authored by Paul McCarthy's avatar Paul McCarthy
Browse files

Removed dependence on props. Little change to featdesign.FEATFSFDesign

interface
parent 5d12050f
No related branches found
No related tags found
No related merge requests found
......@@ -130,16 +130,20 @@ class FEATFSFDesign(object):
with FSL 5.0.9 and older.
"""
def __init__(self, featDir, settings):
def __init__(self, featDir, settings=None):
"""Create a ``FEATFSFDesign``.
:arg featDir: Path to the FEAT directory.
:arg settings: A dictionary containing the FEAT analysis
settings from its ``design.fsf`` file (see
:func:`.featanalysis.loadSettings`).
settings from its ``design.fsf``. If not provided,
is loaded via :func:`.featanalysis.loadSettings`.
"""
if settings is None:
from .featanalysis import loadSettings
settings = loadSettings(featDir)
# Get the design matrix, and some
# information about the analysis
designMatrix = loadDesignMat(featDir)
......
......@@ -16,9 +16,9 @@ import collections
import six
import props
import fsl.utils.async as async
import fsl.utils.async as async
import fsl.utils.weakfuncref as weakfuncref
log = logging.getLogger(__name__)
......@@ -41,7 +41,7 @@ class _Listener(object):
# We use a WeakFunctionRef so we can refer to
# both functions and class/instance methods
self.__callback = props.WeakFunctionRef(callback)
self.__callback = weakfuncref.WeakFunctionRef(callback)
self.topic = topic
self.runOnIdle = runOnIdle
self.enabled = True
......@@ -105,10 +105,6 @@ class Notifier(object):
# { topic : enabled } mappings.
new.__enabled = {}
if isinstance(new, props.HasProperties):
log.warning('Warning: {} is a sub-class of both '
'Notifier and props.HasProperties!')
return new
......
......@@ -28,12 +28,11 @@ class TypeDict(object):
Let's say we have a class with some properties::
import props
import fsl.utils.typedict as td
class Animal(props.HasProperties):
isMammal = props.Boolean()
numLegs = props.Int()
class Animal(object):
isMammal = True
numLegs = 4
And we want to associate some tooltips with those properties::
......@@ -63,7 +62,7 @@ class TypeDict(object):
This functionality also works across class hierarchies::
class Cat(Animal):
numYoutubeHits = props.Int()
numYoutubeHits = 10
tooltips = td.TypeDict({
......
#!/usr/bin/env python
#
# weakfuncref.py - The WeakFunctionRef class
#
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
"""This module provides the :class:`WeakFunctionRef` class. """
import six
import types
import weakref
import inspect
class WeakFunctionRef(object):
"""Class which encapsulates a :mod:`weakref` to a function or method.
This class is used by :class:`.Notifier` instances to reference
listeners which have been registered to be notified of property value
or attribute changes.
"""
def __init__(self, func):
"""Create a new ``WeakFunctionRef`` to encapsulate the given
function or bound/unbound method.
"""
# Bound method
if self.__isMethod(func):
boundMeth = six.get_method_function(func)
boundSelf = six.get_method_self( func)
# We can't take a weakref of the method
# object, so we have to weakref the object
# and the unbound class function. The
# function method will search for and
# return the bound method, though.
self.obj = weakref.ref(boundSelf)
self.func = weakref.ref(boundMeth)
self.objType = type(boundSelf).__name__
self.funcName = boundMeth .__name__
# Unbound/class method or function
else:
self.obj = None
self.objType = None
self.func = weakref.ref(func)
self.funcName = func.__name__
def __str__(self):
"""Return a string representation of the function."""
selftype = type(self).__name__
func = self.function()
if self.obj is None:
s = '{}: {}' .format(selftype, self.funcName)
else:
s = '{}: {}.{}'.format(selftype, self.objType, self.funcName)
if func is None: return '{} <dead>'.format(s)
else: return s
def __repr__(self):
"""Return a string representation of the function."""
return self.__str__()
def __isMethod(self, func):
"""Returns ``True`` if the given function is a bound method,
``False`` otherwise.
This seems to be one of the few areas where python 2 and 3 are
irreconcilably incompatible (or just where :mod:`six` does not have a
function to help us).
In Python 2 there is no difference between an unbound method and a
function. But in Python 3, an unbound method is still a method (and
inspect.ismethod returns True).
"""
ismethod = False
# Therefore, in python2 we need to test
# whether the function is a method, and
# also test whether it is bound.
if six.PY2:
ismethod = (inspect.ismethod(func) and
six.get_method_self(func) is not None)
# But in python3, if the function is a
# method it is, by definition, bound.
elif six.PY3:
ismethod = inspect.ismethod(func)
return ismethod
def __findPrivateMethod(self):
"""Finds and returns the bound method associated with the encapsulated
function.
"""
obj = self.obj()
func = self.func()
methName = self.funcName
# Find all attributes on the object which end with
# the method name - there will be more than one of
# these if the object has base classes which have
# private methods of the same name.
attNames = dir(obj)
attNames = [a for a in attNames if a.endswith(methName)]
# Find the attribute with the correct name, which
# is a method, and has the correct function.
for name in attNames:
att = getattr(obj, name)
if isinstance(att, types.MethodType) and \
six.get_method_function(att) is func:
return att
return None
def function(self):
"""Return a reference to the encapsulated function or method,
or ``None`` if the function has been garbage collected.
"""
# Unbound/class method or function
if self.obj is None:
return self.func()
# The instance owning the method has been destroyed
if self.obj() is None or self.func() is None:
return None
obj = self.obj()
# Return the bound method object
try: return getattr(obj, self.funcName)
# If the function is a bound private method,
# its name on the instance will have been
# mangled, so we need to search for it
except: return self.__findPrivateMethod()
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