# Buggy code
def validate(self, obj, value):
    """
    Validate that the passed in value is a valid memory specification

    It could either be a pure int, when it is taken as a byte value.
    If it has one of the suffixes, it is converted into the appropriate
    pure byte value.
    """
    if isinstance(value, int):
        return value
    num = value[:-1]
    suffix = value[-1]
    if not num.isdigit() and suffix not in ByteSpecification.UNIT_SUFFIXES:
        raise TraitError(
            "{val} is not a valid memory specification. Must be an int or a string with suffix K, M, G, T".format(
                val=value
            )
        )
    else:
        return int(num) * ByteSpecification.UNIT_SUFFIXES[suffix]


# Traceback (ValueError)
[E 2017-04-18 05:39:02.270 JupyterHub app:1527]
Traceback (most recent call last):
File "/usr/local/lib/python3.4/dist-packages/jupyterhub/app.py", line 1524, in launch_instance_async
yield self.initialize(argv)
File "/usr/local/lib/python3.4/dist-packages/jupyterhub/app.py", line 1315, in initialize
yield self.init_spawners()
File "/usr/local/lib/python3.4/dist-packages/jupyterhub/app.py", line 1084, in init_spawners
self.users[orm_user.id] = user = User(orm_user, self.tornado_settings)
File "/usr/local/lib/python3.4/dist-packages/jupyterhub/user.py", line 128, in __init__
config=self.settings.get('config'),
File "/usr/local/lib/python3.4/dist-packages/kubespawner/spawner.py", line 29, in __init__
super().__init__(*args, **kwargs)
File "/usr/local/lib/python3.4/dist-packages/jupyterhub/spawner.py", line 345, in __init__
super(Spawner, self).__init__(**kwargs)
File "/usr/local/lib/python3.4/dist-packages/traitlets/config/configurable.py", line 84, in __init__
self.config = config
File "/usr/local/lib/python3.4/dist-packages/traitlets/traitlets.py", line 585, in __set__
self.set(obj, value)
File "/usr/local/lib/python3.4/dist-packages/traitlets/traitlets.py", line 574, in set
obj._notify_trait(self.name, old_value, new_value)
File "/usr/local/lib/python3.4/dist-packages/traitlets/traitlets.py", line 1139, in _notify_trait
type='change',
File "/usr/local/lib/python3.4/dist-packages/traitlets/traitlets.py", line 1176, in notify_change
c(change)
File "/usr/local/lib/python3.4/dist-packages/traitlets/traitlets.py", line 819, in compatible_observer
return func(self, change)
File "/usr/local/lib/python3.4/dist-packages/traitlets/config/configurable.py", line 186, in _config_changed
self._load_config(change.new, traits=traits, section_names=section_names)
File "/usr/local/lib/python3.4/dist-packages/traitlets/config/configurable.py", line 153, in _load_config
setattr(self, name, deepcopy(config_value))
File "/usr/local/lib/python3.4/dist-packages/traitlets/traitlets.py", line 585, in __set__
self.set(obj, value)
File "/usr/local/lib/python3.4/dist-packages/traitlets/traitlets.py", line 559, in set
new_value = self._validate(obj, value)
File "/usr/local/lib/python3.4/dist-packages/traitlets/traitlets.py", line 591, in _validate
value = self.validate(obj, value)
File "/usr/local/lib/python3.4/dist-packages/jupyterhub/traitlets.py", line 71, in validate
return int(num) * ByteSpecification.UNIT_SUFFIXES[suffix]
ValueError: invalid literal for int() with base 10: '1.5'

# Fixed code
def validate(self, obj, value):
    """
    Validate that the passed in value is a valid memory specification

    It could either be a pure int, when it is taken as a byte value.
    If it has one of the suffixes, it is converted into the appropriate
    pure byte value.
    """
    if isinstance(value, (int, float)):
        return int(value)

    try:
        num = float(value[:-1])
    except ValueError:
        raise TraitError(
            "{val} is not a valid memory specification. Must be an int or a string with suffix K, M, G, T".format(
                val=value
            )
        )
    suffix = value[-1]
    if suffix not in self.UNIT_SUFFIXES:
        raise TraitError(
            "{val} is not a valid memory specification. Must be an int or a string with suffix K, M, G, T".format(
                val=value
            )
        )
    else:
        return int(float(num) * self.UNIT_SUFFIXES[suffix])