Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Enforce Logical Inheritance From MustBeInstance #317

Closed
wants to merge 2 commits into from

Conversation

rmorshea
Copy link
Contributor

@rmorshea rmorshea commented Sep 18, 2016

Many trait implementations perform the same typical validation check:

if isinstance(value, some_type):
    # value is of the right type
    return value
elif isinstance(value, casting_types):
    # value can be cast to the right type
    return some_type(value)
else:
    raise TraitError()

I've introduced a base class MustBeInstance which encapsulates this formula in a way such that most TraitTypes can subclass it, and hook into this kind of simple validation check. Everything from Bool to List now inherit from MustBeInstance.

Some example implementations:

# NumberBase simply enforces min
# and max values (e.g. `Int(min=0)`)
# and inherits from MustBeInstance
class Int(NumberBase):
    """An int trait."""

    klass = int
    default_value = 0

class Unicode(MustBeInstance):
    """A trait for unicode strings."""

    default_value = u''
    info_text = 'a unicode string'
    klass = six.text_type

    _cast_types = (bytes,)
    def _cast(self, value):
        try:
            return value.decode('ascii', 'strict')
        except UnicodeDecodeError:
            msg = "Could not decode {!r} for unicode trait '{}' of {} instance."
            raise TraitError(msg.format(value, self.name, nameit(obj)))

I've also added nameit, a new function for naming values - this is a substitute for class_of.

Indefinite naming:

>>> nameit(object())
'an object'
>>> nameit(object)
'an object'
>>> nameit(type(object))
'a type'

Definite naming:

 >>> nameit(object(), definite=True)
"the object at '0x10741f1b0'"
>>> nameit(object, definite=True)
"the type 'object'"
>>> nameit(type(object), definite=True)
"the type 'type'"

@minrk
Copy link
Member

minrk commented Sep 22, 2016

Seems largely simpler. What's the difference now between Instance and MustBeInstance?

@rmorshea
Copy link
Contributor Author

rmorshea commented Sep 22, 2016

@minrk the difference comes down to Instance.make_dynamic_default and #315.

I should have linked to that issue before, because inheriting from MustBeInstance would be unnecessary if Instance traits with allow_none=True did not have a default value.

So whether we need MustBeInstance comes down to how we handle #315.

@rmorshea rmorshea changed the title Enforce Logical Inheritance From MustBeInstance [WIP] Enforce Logical Inheritance From MustBeInstance Nov 4, 2016
@rmorshea
Copy link
Contributor Author

rmorshea commented May 8, 2017

Reworking this...

@rmorshea rmorshea closed this May 8, 2017
@rmorshea rmorshea mentioned this pull request May 9, 2017
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