named ints act like proper sequences now

This commit is contained in:
Daniel Pavel 2012-12-07 13:50:44 +02:00
parent f0007d0a13
commit 9066003240
5 changed files with 65 additions and 32 deletions

View File

@ -8,11 +8,10 @@ from struct import pack as _pack
class NamedInt(int):
"""An integer with an attached name."""
# __slots__ = ['name']
def __new__(cls, value, name):
obj = int.__new__(cls, value)
obj.name = name
obj.name = str(name)
return obj
def bytes(self, count=2):
@ -22,6 +21,17 @@ class NamedInt(int):
return _pack('!L', value)[-count:]
def __eq__(self, other):
try:
if int(self) == int(other):
return True
except:
pass
return self.name.lower() == str(other).lower()
def __cmp__(self, other):
return int(self) - int(other)
def __str__(self):
return self.name
@ -30,30 +40,50 @@ class NamedInt(int):
class NamedInts(object):
__slots__ = ['__dict__', '_values', '_indexed', '_fallback']
def __init__(self, **kwargs):
values = dict((k, NamedInt(v, k if k == k.upper() else k.replace('__', '/').replace('_', ' '))) for (k, v) in kwargs.items())
self.__dict__.update(values)
self._indexed = dict((int(v), v) for v in values.values())
values = dict((k, NamedInt(v, k.lstrip('_') if k == k.upper() else
k.replace('__', '/').replace('_', ' '))) for (k, v) in kwargs.items())
self.__dict__ = values
self._values = sorted(list(values.values()))
self._indexed = dict((int(v), v) for v in self._values)
self._fallback = None
def __getitem__(self, index):
if index in self._indexed:
return self._indexed[index]
if self._fallback:
value = NamedInt(index, self._fallback(index))
self._indexed[index] = value
return value
def __contains__(self, value):
return int(value) in self._indexed
def __len__(self):
return len(self.values)
def flag_names(self, value):
return ', '.join(str(self._indexed[k]) for k in self._indexed if k & value == k)
def __getitem__(self, index):
if type(index) == int:
if index in self._indexed:
return self._indexed[index]
if self._fallback:
value = NamedInt(index, self._fallback(index))
self._indexed[index] = value
self._values = sorted(self._values + [value])
return value
elif type(index) == slice:
return self._values[index]
else:
if index in self._values:
index = self._values.index(index)
return self._values[index]
def __contains__(self, value):
return value in self._values
def __iter__(self):
return iter(sorted(self._values))
def __len__(self):
return len(self._values)
def __repr__(self):
return 'NamedInts(%s)' % ', '.join(repr(v) for v in self._values)
def strhex(x):
return _hexlify(x).decode('ascii').upper()

View File

@ -57,10 +57,6 @@ PAIRING_ERRORS = _NamedInts(
too_many_devices=0x03,
sequence_timeout=0x06)
REGISTERS = _NamedInts(
battery=0x0D,
dpi=0x63,
leds=0x51)
#
# functions

View File

@ -31,7 +31,7 @@ FEATURE = _NamedInts(
BATTERY=0x1000,
REPROGRAMMABLE_KEYS=0x1B00,
WIRELESS=0x1D4B,
FN_TOGGLE=0x40A0,
FN_STATUS=0x40A0,
SOLAR_CHARGE=0x4301,
TOUCH_MOUSE=0x6110)
FEATURE._fallback = lambda x: 'unknown:%04X' % x
@ -80,7 +80,7 @@ KEY = _NamedInts(
Calculator=0x000A,
Mail=0x000E,
Home=0x001A,
Tools=0x001D,
Music=0x001D,
Search=0x0029,
Sleep=0x002F)
KEY._fallback = lambda x: 'unknown:%04X' % x

View File

@ -118,7 +118,7 @@ class PairedDevice(object):
p = self.protocol
if p >= 2.0:
self._firmware = _hidpp20.get_firmware(self)
elif p >= 1.0:
if self._firmware is None and p == 1.0:
self._firmware = _hidpp10.get_firmware(self)
return self._firmware or ()

View File

@ -106,7 +106,7 @@ class DeviceStatus(dict):
return ', '.join(t)
def __bool__(self):
return self.updated and self._active
return bool(self._active)
__nonzero__ = __bool__
def _changed(self, active=True, alert=ALERT.NONE, reason=None, timestamp=None):
@ -131,13 +131,20 @@ class DeviceStatus(dict):
d.protocol, d.serial, d.firmware
if BATTERY_LEVEL not in self:
if d.protocol >= 2.0:
battery = _hidpp10.get_battery(d)
if battery is None and d.protocol >= 2.0:
battery = _hidpp20.get_battery(d)
else:
battery = _hidpp10.get_battery(d)
# if battery is None and _hidpp20.FEATURE.SOLAR_CHARGE in d.features:
# d.feature_request(_hidpp20.FEATURE.SOLAR_CHARGE, 0x00, 1, 1)
# return
if battery:
self[BATTERY_LEVEL], self[BATTERY_STATUS] = battery
self._changed(timestamp=timestamp)
elif BATTERY_STATUS in self:
self[BATTERY_STATUS] = None
self._changed(timestamp=timestamp)
elif len(self) > 0 and timestamp - self.updated > _STATUS_TIMEOUT:
# if the device has been inactive for too long, clear out any known
@ -191,7 +198,7 @@ class DeviceStatus(dict):
if event.sub_id >= 0x80:
# this can't possibly be an event, can it?
if _log.isEnabledFor(_DEBUG):
_log.debug("ignoring non-event %s", event)
_log.debug("ignoring %s (not an event)", event)
return False
if event.sub_id >= 0x40: