Example #1
0
    def __init__(self,
                 name,
                 default=Unconfigurable,
                 optional=False,
                 readonly=None):
        # freeze Unconfigurables by default
        readonly = default is Unconfigurable if readonly is None else readonly

        if not is_string(name):
            raise ValueError("'name' must be a string (got %r)" % name)
        if not isinstance(optional, bool):
            raise ValueError("'optional' must be boolean (got %r)" % optional)
        if not isinstance(readonly, bool):
            raise ValueError("'readonly' must be boolean (got %r)" % readonly)

        self.name = name
        self.default = default
        self.optional = optional
        self.readonly = readonly

        # default values set by config system
        self._defaults = WeakKeyIDDictionary()

        # param values set on objects
        self.data = WeakKeyIDDictionary()
Example #2
0
def test_weakkeydict_delitem():
    d = WeakKeyIDDictionary()
    o1 = C()
    o2 = C()
    d[o1] = 'something'
    d[o2] = 'something'
    assert len(d) == 2
    del d[o1]
    assert len(d) == 1
    assert list(d.keys()) == [o2]
Example #3
0
def test_weakkeydict_delitem():
    d = WeakKeyIDDictionary()
    o1 = C()
    o2 = C()
    d[o1] = 'something'
    d[o2] = 'something'
    assert len(d) == 2
    del d[o1]
    assert len(d) == 1
    assert list(d.keys()) == [o2]
Example #4
0
def test_weakkeyiddictionary_init():
    obj = C()
    val = 364

    # construct from dictionary
    d = WeakKeyIDDictionary({obj: val})
    assert d[obj] == val

    # construct from another WeakKeyIDDictionary
    d2 = WeakKeyIDDictionary(d)
    assert d2[obj] == val
Example #5
0
def test_weakkeydict_popitem(key1=C(), key2=C(), val1="v1", val2="v2"):
    d = WeakKeyIDDictionary()
    d[key1] = val1
    d[key2] = val2

    assert len(d) == 2
    k1, v1 = d.popitem()
    assert len(d) == 1
    assert k1 in (key1, key2) and v1 is (val1 if k1 is key1 else val2)

    k2, v2 = d.popitem()
    assert len(d) == 0
    assert k2 is (key2 if k1 is key1 else key1) and v2 is (val1 if k2 is key1 else val2)
Example #6
0
def test_weakkeydict_setdefault(key=C(), value1="v1", value2="v2"):
    d = WeakKeyIDDictionary()
    o = d.setdefault(key, value1)
    assert o is value1
    assert key in d
    assert d.get(key) is value1
    assert d[key] is value1

    o = d.setdefault(key, value2)
    assert o is value1
    assert key in d
    assert d.get(key) is value1
    assert d[key] is value1
Example #7
0
    def __init__(self, default=Unconfigurable, optional=False, readonly=None):
        self.default = default
        self.optional = optional

        if readonly is None:
            # freeze Unconfigurables by default
            readonly = default is Unconfigurable
        self.readonly = readonly

        # default values set by config system
        self._defaults = WeakKeyIDDictionary()

        # param values set on objects
        self.data = WeakKeyIDDictionary()
Example #8
0
    def __init__(self, default=Unconfigurable, optional=False, readonly=None):
        self.default = default
        self.optional = optional

        if readonly is None:
            # freeze Unconfigurables by default
            readonly = default is Unconfigurable
        self.readonly = readonly

        # default values set by config system
        self._defaults = WeakKeyIDDictionary()

        # param values set on objects
        self.data = WeakKeyIDDictionary()
Example #9
0
def test_weakkeydict_popitem(key1=C(), key2=C(), value1="v1", value2="v2"):
    d = WeakKeyIDDictionary()
    d[key1] = value1
    d[key2] = value2
    assert len(d) == 2
    k, v = d.popitem()
    assert len(d) == 1
    if k is key1:
        assert v is value1
    else:
        assert v is value2
    k, v = d.popitem()
    assert len(d) == 0
    if k is key1:
        assert v is value1
    else:
        assert v is value2
Example #10
0
def test_weakkeydict_popitem(key1=C(), key2=C(), value1="v1", value2="v2"):
    d = WeakKeyIDDictionary()
    d[key1] = value1
    d[key2] = value2
    assert len(d) == 2
    k, v = d.popitem()
    assert len(d) == 1
    if k is key1:
        assert v is value1
    else:
        assert v is value2
    k, v = d.popitem()
    assert len(d) == 0
    if k is key1:
        assert v is value1
    else:
        assert v is value2
Example #11
0
def test_weakkeydict_frees_values():
    d = WeakKeyIDDictionary()
    k = C()
    v = C()
    d[k] = v
    weak_v = weakref.ref(v)
    del v
    assert sys.getrefcount(weak_v()) > 1  # function argument might make it > 1
    del k
    v = weak_v()
    assert v is None, "Value in WeakKeyIDDictionary not garbage collected."
Example #12
0
    def __init__(self, name, default=Unconfigurable, optional=False, readonly=None):
        # freeze Unconfigurables by default
        readonly = default is Unconfigurable if readonly is None else readonly

        if not is_string(name):
            raise ValueError("'name' must be a string (got %r)" % name)
        if not isinstance(optional, bool):
            raise ValueError("'optional' must be boolean (got %r)" % optional)
        if not isinstance(readonly, bool):
            raise ValueError("'readonly' must be boolean (got %r)" % readonly)

        self.name = name
        self.default = default
        self.optional = optional
        self.readonly = readonly

        # default values set by config system
        self._defaults = WeakKeyIDDictionary()

        # param values set on objects
        self.data = WeakKeyIDDictionary()
Example #13
0
def test_weakkeyiddict_iter_functions():
    """Tests iterkeys and iteritems"""
    in_d = {C(): 1, C(): 2, C(): 3}
    d = WeakKeyIDDictionary(in_d)

    keys = list(in_d)
    for key in d.iterkeys():
        assert key in keys, "WeakKeyIDDictionary has extra key %d" % (key, )
        keys.remove(key)

    assert len(
        keys) == 0, "Keys not found in WeakKeyIDDictionary: %r" % (keys, )

    # copy, otherwise `d` will change size during iteration as references are removed
    in_d2 = dict(in_d)
    for k, v in d.iteritems():
        assert k in in_d
        assert in_d2.pop(k) == v

    assert len(
        in_d2) == 0, "Keys not found in WeakKeyIDDictionary: %r" % (in_d2, )
Example #14
0
def test_weakkeydict_bad_delitem():
    d = WeakKeyIDDictionary()
    o = C()
    # An attempt to delete an object that isn't there should raise KeyError.
    with pytest.raises(KeyError):
        del d[o]
    with pytest.raises(KeyError):
        d[o]

    # If a key isn't of a weakly referencable type, __getitem__ and
    # __setitem__ raise TypeError.  __delitem__ should too.
    with pytest.raises(TypeError):
        del d[13]
    with pytest.raises(TypeError):
        d[13]
    with pytest.raises(TypeError):
        d[13] = 13
Example #15
0
def test_weakkeydict_update(in_d={C(): 1, C(): 2, C(): 3}):
    """This exercises d.update(), len(d), d.keys(), in d,  d.get(), d[]."""
    d = WeakKeyIDDictionary()
    d.update(in_d)
    assert len(d) == len(in_d)
    for k in d.keys():
        assert k in in_d, "mysterious new key appeared in weak dict"
        v = in_d.get(k)
        assert v is d[k]
        assert v is d.get(k)
    for k in in_d.keys():
        assert k in d, "original key disappeared in weak dict"
        v = in_d[k]
        assert v is d[k]
        assert v is d.get(k)
Example #16
0
def test_weakkeydict_setdefault(key=C(), value1="v1", value2="v2"):
    d = WeakKeyIDDictionary()
    o = d.setdefault(key, value1)
    assert o is value1
    assert key in d
    assert d.get(key) is value1
    assert d[key] is value1

    o = d.setdefault(key, value2)
    assert o is value1
    assert key in d
    assert d.get(key) is value1
    assert d[key] is value1
Example #17
0
def test_weakkeydict_update(in_d={C(): 1, C(): 2, C(): 3}):
    """This exercises d.update(), len(d), d.keys(), in d,  d.get(), d[]."""
    d = WeakKeyIDDictionary()
    d.update(in_d)
    assert len(d) == len(in_d)
    for k in d.keys():
        assert k in in_d, "mysterious new key appeared in weak dict"
        v = in_d.get(k)
        assert v is d[k]
        assert v is d.get(k)
    for k in in_d.keys():
        assert k in d, "original key disappeared in weak dict"
        v = in_d[k]
        assert v is d[k]
        assert v is d.get(k)
Example #18
0
class Parameter:
    """Simple descriptor for storing configuration parameters.

    Parameters
    ----------
    name : str
        Name of the parameter.
    default : object
        The value returned if the parameter hasn't been explicitly set.
    optional : bool, optional
        Whether this parameter accepts the value None. By default,
        parameters are not optional (i.e., cannot be set to ``None``).
    readonly : bool, optional
        If true, the parameter can only be set once.
        By default, parameters can be set multiple times.

    Attributes
    ----------
    coerce_defaults : bool
        If True, validate values for this parameter when they are set in a
        `.Config` object. Setting a parameter directly on an object will
        always be validated.
    equatable : bool
        If True, parameter values can be compared for equality
        (``a==b``); otherwise equality checks will just compare object
        identity (``a is b``).
    """

    coerce_defaults = True
    equatable = False

    def __init__(self,
                 name,
                 default=Unconfigurable,
                 optional=False,
                 readonly=None):
        # freeze Unconfigurables by default
        readonly = default is Unconfigurable if readonly is None else readonly

        if not isinstance(name, str):
            raise ValueError("'name' must be a string (got %r)" % name)
        if not isinstance(optional, bool):
            raise ValueError("'optional' must be boolean (got %r)" % optional)
        if not isinstance(readonly, bool):
            raise ValueError("'readonly' must be boolean (got %r)" % readonly)

        self.name = name
        self.default = default
        self.optional = optional
        self.readonly = readonly

        # default values set by config system
        self._defaults = WeakKeyIDDictionary()

        # param values set on objects
        self.data = WeakKeyIDDictionary()

    def __getstate__(self):
        state = {}
        state.update(self.__dict__)
        state["_defaults"] = dict(state["_defaults"].items())
        state["data"] = dict(state["data"].items())
        return state

    def __setstate__(self, state):
        for k, v in state.items():
            if k in ["_defaults", "data"]:
                v = WeakKeyIDDictionary(v)
            setattr(self, k, v)

    def __contains__(self, key):
        return key in self.data or key in self._defaults

    def __delete__(self, instance):
        del self.data[instance]

    def __get__(self, instance, type_):
        if instance is None:
            # Return self so default can be inspected
            return self
        if not self.configurable and instance not in self.data:
            raise ValidationError(
                "Unconfigurable parameters have no defaults. Please ensure the"
                " value of the parameter is set before trying to access it.",
                attr=self.name,
                obj=instance,
            )
        return self.data.get(instance, self.default)

    def __set__(self, instance, value):
        self.data[instance] = self.coerce(instance, value)

    def __repr__(self):
        return "%s(%r, default=%s, optional=%s, readonly=%s)" % (
            type(self).__name__,
            self.name,
            self.default,
            self.optional,
            self.readonly,
        )

    @property
    def configurable(self):
        return self.default is not Unconfigurable

    def del_default(self, obj):
        del self._defaults[obj]

    def get_default(self, obj):
        return self._defaults.get(obj, self.default)

    def set_default(self, obj, value):
        if not self.configurable:
            raise ConfigError("Parameter '%s' is not configurable" % self)
        self._defaults[obj] = self.coerce(
            obj, value) if self.coerce_defaults else value

    def check_type(self, instance, value, type_):
        if value is not None and not isinstance(value, type_):
            if isinstance(type_, tuple):
                type_str = " or ".join((t.__name__ for t in type_))
            else:
                type_str = type_.__name__
            raise ValidationError(
                "Must be of type %r (got type %r)." %
                (type_str, type(value).__name__),
                attr=self.name,
                obj=instance,
            )

    def coerce(self, instance, value):
        if isinstance(value, DefaultType):
            raise ValidationError(
                "Default is not a valid value. To reset a parameter, use 'del'.",
                attr=self.name,
                obj=instance,
            )
        if self.readonly and instance in self.data:
            raise ReadonlyError(attr=self.name, obj=instance)
        if not self.optional and value is None:
            raise ValidationError(
                "Parameter is not optional; cannot set to None",
                attr=self.name,
                obj=instance,
            )
        return value

    def equal(self, instance_a, instance_b):
        a = self.__get__(instance_a, None)
        b = self.__get__(instance_b, None)
        if self.equatable:
            return equal(a, b)
        else:
            return a is b

    def hashvalue(self, instance):
        """Returns a hashable value (`hash` can be called on the output)."""
        value = self.__get__(instance, None)
        if self.equatable:
            return value
        else:
            return id(value)
Example #19
0
class Parameter(object):
    """Simple descriptor for storing configuration parameters.

    Parameters
    ----------
    default : object
        The value returned if the parameter hasn't been explicitly set.
    optional : bool, optional
        Whether this parameter accepts the value None. By default,
        parameters are not optional (i.e., cannot be set to ``None``).
    readonly : bool, optional
        If true, the parameter can only be set once.
        By default, parameters can be set multiple times.
    """

    equatable = False

    def __init__(self,
                 name,
                 default=Unconfigurable,
                 optional=False,
                 readonly=None):
        # freeze Unconfigurables by default
        readonly = default is Unconfigurable if readonly is None else readonly

        if not is_string(name):
            raise ValueError("'name' must be a string (got %r)" % name)
        if not isinstance(optional, bool):
            raise ValueError("'optional' must be boolean (got %r)" % optional)
        if not isinstance(readonly, bool):
            raise ValueError("'readonly' must be boolean (got %r)" % readonly)

        self.name = name
        self.default = default
        self.optional = optional
        self.readonly = readonly

        # default values set by config system
        self._defaults = WeakKeyIDDictionary()

        # param values set on objects
        self.data = WeakKeyIDDictionary()

    def __contains__(self, key):
        return key in self.data or key in self._defaults

    def __delete__(self, instance):
        del self.data[instance]

    def __get__(self, instance, type_):
        if instance is None:
            # Return self so default can be inspected
            return self
        if not self.configurable and instance not in self.data:
            raise ValidationError(
                "Unconfigurable parameters have no defaults. Please ensure the"
                " value of the parameter is set before trying to access it.",
                attr=self.name,
                obj=instance)
        return self.data.get(instance, self.default)

    def __set__(self, instance, value):
        self.validate(instance, value)
        self.data[instance] = value

    def __repr__(self):
        return "%s(default=%s, optional=%s, readonly=%s)" % (
            self.__class__.__name__, self.default, self.optional,
            self.readonly)

    @property
    def configurable(self):
        return self.default is not Unconfigurable

    def del_default(self, obj):
        del self._defaults[obj]

    def get_default(self, obj):
        return self._defaults.get(obj, self.default)

    def set_default(self, obj, value):
        if not self.configurable:
            raise ConfigError("Parameter '%s' is not configurable" % self)
        self.validate(obj, value)
        self._defaults[obj] = value

    def equal(self, instance_a, instance_b):
        a = self.__get__(instance_a, None)
        b = self.__get__(instance_b, None)
        if self.equatable:
            # always use array_equal, in case one argument is an array
            return np.array_equal(a, b)
        else:
            return a is b

    def hashvalue(self, instance):
        """Returns a hashable value (`hash` can be called on the output)."""
        value = self.__get__(instance, None)
        if self.equatable:
            return value
        else:
            return id(value)

    def validate(self, instance, value):
        if isinstance(value, DefaultType):
            raise ValidationError(
                "Default is not a valid value. To reset a "
                "parameter, use 'del'.",
                attr=self.name,
                obj=instance)
        if self.readonly and instance in self.data:
            raise ReadonlyError(attr=self.name, obj=instance)
        if not self.optional and value is None:
            raise ValidationError(
                "Parameter is not optional; cannot set to "
                "None",
                attr=self.name,
                obj=instance)
Example #20
0
class Parameter(object):
    """Simple descriptor for storing configuration parameters.

    Parameters
    ----------
    default : object
        The value returned if the parameter hasn't been explicitly set.
    optional : bool, optional
        Whether this parameter accepts the value None. By default,
        parameters are not optional (i.e., cannot be set to ``None``).
    readonly : bool, optional
        If true, the parameter can only be set once.
        By default, parameters can be set multiple times.
    """

    equatable = False

    def __init__(self, default=Unconfigurable, optional=False, readonly=None):
        self.default = default
        self.optional = optional

        if readonly is None:
            # freeze Unconfigurables by default
            readonly = default is Unconfigurable
        self.readonly = readonly

        # default values set by config system
        self._defaults = WeakKeyIDDictionary()

        # param values set on objects
        self.data = WeakKeyIDDictionary()

    def __contains__(self, key):
        return key in self.data or key in self._defaults

    def __delete__(self, instance):
        del self.data[instance]

    def __get__(self, instance, type_):
        if instance is None:
            # Return self so default can be inspected
            return self
        if not self.configurable and instance not in self.data:
            raise ValueError(
                "Unconfigurable parameters have no defaults. "
                "Please ensure the value of the parameter is "
                "set before trying to access it."
            )
        return self.data.get(instance, self.default)

    def __set__(self, instance, value):
        self.validate(instance, value)
        self.data[instance] = value

    def __repr__(self):
        return "%s(default=%s, optional=%s, readonly=%s)" % (
            self.__class__.__name__,
            self.default,
            self.optional,
            self.readonly,
        )

    @property
    def configurable(self):
        return self.default is not Unconfigurable

    def get_default(self, obj):
        return self._defaults.get(obj, self.default)

    def set_default(self, obj, value):
        if not self.configurable:
            raise ValueError("Parameter '%s' is not configurable" % self)
        self.validate(obj, value)
        self._defaults[obj] = value

    def del_default(self, obj):
        del self._defaults[obj]

    def validate(self, instance, value):
        if isinstance(value, DefaultType):
            raise ValueError("Default is not a valid value. To reset a " "parameter, use `del`.")
        if self.readonly and instance in self.data:
            raise ValueError("Parameter is read-only; cannot be changed.")
        if not self.optional and value is None:
            raise ValueError("Parameter is not optional; cannot set to None")

    def equal(self, instance_a, instance_b):
        a = self.__get__(instance_a, None)
        b = self.__get__(instance_b, None)
        if self.equatable:
            # always use array_equal, in case one argument is an array
            return np.array_equal(a, b)
        else:
            return a is b

    def hashvalue(self, instance):
        """Returns a hashable value (`hash` can be called on the output)."""
        value = self.__get__(instance, None)
        if self.equatable:
            return value
        else:
            return id(value)
Example #21
0
 def __setstate__(self, state):
     for k, v in state.items():
         if k in ['_defaults', 'data']:
             v = WeakKeyIDDictionary(v)
         setattr(self, k, v)
Example #22
0
def test_weakkeyiddict_contains_none():
    assert (None in WeakKeyIDDictionary()) is False
Example #23
0
class Parameter:
    """Simple descriptor for storing configuration parameters.

    Parameters
    ----------
    name : str
        Name of the parameter.
    default : object
        The value returned if the parameter hasn't been explicitly set.
    optional : bool, optional
        Whether this parameter accepts the value None. By default,
        parameters are not optional (i.e., cannot be set to ``None``).
    readonly : bool, optional
        If true, the parameter can only be set once.
        By default, parameters can be set multiple times.

    Attributes
    ----------
    coerce_defaults : bool (Default: True)
        If True, validate values for this parameter when they are set in a
        `.Config` object. Setting a parameter directly on an object will
        always be validated.
    equatable : bool (Default: False)
        If True, parameter values can be compared for equality
        (``a==b``); otherwise equality checks will just compare object
        identity (``a is b``).
    """

    coerce_defaults = True
    equatable = False

    def __init__(self, name,
                 default=Unconfigurable, optional=False, readonly=None):
        # freeze Unconfigurables by default
        readonly = default is Unconfigurable if readonly is None else readonly

        if not isinstance(name, str):
            raise ValueError("'name' must be a string (got %r)" % name)
        if not isinstance(optional, bool):
            raise ValueError("'optional' must be boolean (got %r)" % optional)
        if not isinstance(readonly, bool):
            raise ValueError("'readonly' must be boolean (got %r)" % readonly)

        self.name = name
        self.default = default
        self.optional = optional
        self.readonly = readonly

        # default values set by config system
        self._defaults = WeakKeyIDDictionary()

        # param values set on objects
        self.data = WeakKeyIDDictionary()

    def __getstate__(self):
        state = {}
        state.update(self.__dict__)
        state['_defaults'] = dict(state['_defaults'].items())
        state['data'] = dict(state['data'].items())
        return state

    def __setstate__(self, state):
        for k, v in state.items():
            if k in ['_defaults', 'data']:
                v = WeakKeyIDDictionary(v)
            setattr(self, k, v)

    def __contains__(self, key):
        return key in self.data or key in self._defaults

    def __delete__(self, instance):
        del self.data[instance]

    def __get__(self, instance, type_):
        if instance is None:
            # Return self so default can be inspected
            return self
        if not self.configurable and instance not in self.data:
            raise ValidationError(
                "Unconfigurable parameters have no defaults. Please ensure the"
                " value of the parameter is set before trying to access it.",
                attr=self.name, obj=instance)
        return self.data.get(instance, self.default)

    def __set__(self, instance, value):
        self.data[instance] = self.coerce(instance, value)

    def __repr__(self):
        return "%s(%r, default=%s, optional=%s, readonly=%s)" % (
            type(self).__name__,
            self.name,
            self.default,
            self.optional,
            self.readonly)

    @property
    def configurable(self):
        return self.default is not Unconfigurable

    def del_default(self, obj):
        del self._defaults[obj]

    def get_default(self, obj):
        return self._defaults.get(obj, self.default)

    def set_default(self, obj, value):
        if not self.configurable:
            raise ConfigError("Parameter '%s' is not configurable" % self)
        self._defaults[obj] = (self.coerce(obj, value) if self.coerce_defaults
                               else value)

    def check_type(self, instance, value, type_):
        if value is not None and not isinstance(value, type_):
            if isinstance(type_, tuple):
                type_str = " or ".join((t.__name__ for t in type_))
            else:
                type_str = type_.__name__
            raise ValidationError("Must be of type %r (got type %r)."
                                  % (type_str, type(value).__name__),
                                  attr=self.name, obj=instance)

    def coerce(self, instance, value):
        if isinstance(value, DefaultType):
            raise ValidationError("Default is not a valid value. To reset a "
                                  "parameter, use 'del'.",
                                  attr=self.name, obj=instance)
        if self.readonly and instance in self.data:
            raise ReadonlyError(attr=self.name, obj=instance)
        if not self.optional and value is None:
            raise ValidationError("Parameter is not optional; cannot set to "
                                  "None", attr=self.name, obj=instance)
        return value

    def equal(self, instance_a, instance_b):
        a = self.__get__(instance_a, None)
        b = self.__get__(instance_b, None)
        if self.equatable:
            return equal(a, b)
        else:
            return a is b

    def hashvalue(self, instance):
        """Returns a hashable value (`hash` can be called on the output)."""
        value = self.__get__(instance, None)
        if self.equatable:
            return value
        else:
            return id(value)
Example #24
0
def test_make_weakkeydict_from_dict():
    o = C()
    d = WeakKeyIDDictionary({o: 364})
    assert d[o] == 364
Example #25
0
def test_make_weakkeydict_from_weakkeydict():
    o = C()
    d1 = WeakKeyIDDictionary({o: 364})
    d2 = WeakKeyIDDictionary(d1)
    assert d1[o] == 364
    assert d2[o] == 364