I come from the __future__, come with me if you want to live.

This commit is contained in:
Daniel Pavel 2012-12-07 17:10:22 +02:00
parent c4be58f074
commit b86dcce381
25 changed files with 151 additions and 49 deletions

View File

@ -2,6 +2,8 @@
#
#
from __future__ import absolute_import, division, print_function, unicode_literals
from logging import getLogger, DEBUG as _DEBUG
_log = getLogger('listener')
del getLogger
@ -23,7 +25,7 @@ class _DUMMY_RECEIVER(object):
max_devices = Receiver.max_devices
status = 'Receiver not found.'
__bool__ = __nonzero__ = lambda self: False
__str__ = lambda self: 'DUMMY'
__unicode__ = __str__ = __repr__ = lambda self: 'DUMMY'
DUMMY = _DUMMY_RECEIVER()
from collections import namedtuple
@ -137,6 +139,7 @@ class ReceiverListener(_listener.EventsListener):
def __str__(self):
return '<ReceiverListener(%s,%s)>' % (self.receiver.path, self.receiver.handle)
__unicode__ = __str__
@classmethod
def open(self, status_changed_callback=None):

View File

@ -1,5 +1,7 @@
#!/usr/bin/env python -u
from __future__ import absolute_import, division, print_function, unicode_literals
NAME = 'Solaar'
VERSION = '0.8.2'
__author__ = "Daniel Pavel <daniel.pavel@gmail.com>"

View File

@ -1,5 +1,7 @@
#!/usr/bin/env python -u
from __future__ import absolute_import, division, print_function, unicode_literals
import sys
import solaar
@ -179,14 +181,13 @@ def pair_device(receiver, args):
from logitech.unifying_receiver import status
r_status = status.ReceiverStatus(receiver, lambda *args, **kwargs: None)
done = False
done = [False]
def _events_handler(event):
global done
if event.devnumber == 0xFF:
r_status.process_event(event)
if not r_status.lock_open:
done = True
done[0] = True
elif event.sub_id == 0x41 and event.address == 0x04:
if event.devnumber not in known_devices:
r_status.new_device = receiver[event.devnumber]
@ -203,7 +204,7 @@ def pair_device(receiver, args):
receiver.set_lock(False, timeout=20)
print ("Pairing: turn your new device on (timing out in 20 seconds).")
while not done:
while not done[0]:
event = base.read(receiver.handle, 2000)
if event:
event = base.make_event(*event)
@ -319,15 +320,15 @@ def _parse_arguments():
help='print all available information about the inspected device(s)')
sp.set_defaults(cmd=show_devices)
sp = subparsers.add_parser('config', help='read/write device-specific options',
sp = subparsers.add_parser('config', help='read/write device-specific settings',
epilog='Please note that configuration only works on active devices.')
sp.add_argument('device',
help='device to configure; may be a device number (1..6), a device serial, '
'or at least 3 characters of a device\'s name')
sp.add_argument('option', nargs='?',
help='device-specific option; leave empty to show available options')
sp.add_argument('setting', nargs='?',
help='device-specific setting; leave empty to list available settings')
sp.add_argument('value', nargs='?',
help='new value for the option')
help='new value for the setting')
sp.set_defaults(cmd=config_device)
sp = subparsers.add_parser('pair', help='pair a new device',

View File

@ -2,6 +2,8 @@
#
#
from __future__ import absolute_import, division, print_function, unicode_literals
from gi.repository import GObject, Gtk
GObject.threads_init()

View File

@ -2,6 +2,8 @@
#
#
from __future__ import absolute_import, division, print_function, unicode_literals
# from sys import version as PYTHON_VERSION
from gi.repository import Gtk, Gdk

View File

@ -2,6 +2,8 @@
#
#
from __future__ import absolute_import, division, print_function, unicode_literals
from gi.repository import Gtk, GObject
import ui

View File

@ -2,6 +2,8 @@
#
#
from __future__ import absolute_import, division, print_function, unicode_literals
from gi.repository import Gtk, Gdk, GObject
import ui

View File

@ -2,11 +2,13 @@
# Optional desktop notifications.
#
import logging
from __future__ import absolute_import, division, print_function, unicode_literals
try:
# this import is allowed to fail, in which case the entire feature is unavailable
from gi.repository import Notify
import logging
import ui

View File

@ -2,16 +2,20 @@
#
#
from __future__ import absolute_import, division, print_function, unicode_literals
from gi.repository import Gtk, GObject
from logging import getLogger, DEBUG as _DEBUG
_log = getLogger('pair-window')
del getLogger
import ui
from logitech.unifying_receiver import status as _status
#
#
#
_PAIRING_TIMEOUT = 30

View File

@ -2,11 +2,16 @@
#
#
from __future__ import absolute_import, division, print_function, unicode_literals
from gi.repository import Gtk, GdkPixbuf
import ui
from logitech.unifying_receiver import status as _status
#
#
#
def create(window, menu_actions=None):
name = window.get_title()

View File

@ -1,7 +1,9 @@
"""Generic Human Interface Device API."""
from __future__ import absolute_import, division, print_function, unicode_literals
__author__ = "Daniel Pavel"
__license__ = "GPL"
__version__ = "0.4"
__version__ = "0.5"
from hidapi.udev import *

View File

@ -1,5 +1,7 @@
#!/usr/bin/env python -u
from __future__ import absolute_import, division, print_function, unicode_literals
import os
import sys
from select import select as _select
@ -62,7 +64,7 @@ if __name__ == '__main__':
import hidapi
print (".. Opening device %s" % args.device)
handle = hidapi.open_path(args.device.encode('utf-8'))
handle = hidapi.open_path(args.device)
if handle:
print (".. Opened handle %s, vendor %s product %s serial %s" % (
repr(handle),

View File

@ -314,7 +314,7 @@ def send_feature_report(device_handle, data, report_number=None):
:returns: ``True`` if the report was successfully written to the device.
"""
if report_number is not None:
data = _pack('!B', report_number) + data
data = _pack(b'!B', report_number) + data
bytes_written = _native.hid_send_feature_report(device_handle, _C.c_char_p(data), len(data))
return bytes_written > -1
@ -330,7 +330,7 @@ def get_feature_report(device_handle, bytes_count, report_number=None):
"""
out_buffer = _C.create_string_buffer('\x00' * (bytes_count + 2))
if report_number is not None:
out_buffer[0] = _pack('!B', report_number)
out_buffer[0] = _pack(b'!B', report_number)
bytes_read = _native.hid_get_feature_report(device_handle, out_buffer, bytes_count)
if bytes_read > -1:
return out_buffer[:bytes_read]

View File

@ -7,6 +7,8 @@ The docstrings are mostly copied from the hidapi API header, with changes where
necessary.
"""
from __future__ import absolute_import, division, print_function, unicode_literals
import os as _os
import errno as _errno
from select import select as _select
@ -126,7 +128,7 @@ def open_path(device_path):
:returns: an opaque device handle, or ``None``.
"""
assert device_path
assert '/dev/hidraw' in device_path
assert device_path.startswith('/dev/hidraw')
return _os.open(device_path, _os.O_RDWR | _os.O_SYNC)

View File

@ -1,5 +1,9 @@
#
#
#
from __future__ import absolute_import, division, print_function, unicode_literals
__author__ = "Daniel Pavel"
__license__ = "GPL"
__version__ = "0.5"
__version__ = "0.8"

View File

@ -11,6 +11,8 @@ http://julien.danjou.info/blog/2012/logitech-k750-linux-support
http://6xq.net/git/lars/lshidpp.git/plain/doc/
"""
from __future__ import absolute_import, division, print_function, unicode_literals
import logging
_DEBUG = logging.DEBUG

View File

@ -3,6 +3,8 @@
# Unlikely to be used directly unless you're expanding the API.
#
from __future__ import absolute_import, division, print_function, unicode_literals
from time import time as _timestamp
from struct import pack as _pack
from random import getrandbits as _random_bits
@ -131,9 +133,9 @@ def write(handle, devnumber, data):
"""
# the data is padded to either 5 or 18 bytes
if len(data) > _SHORT_MESSAGE_SIZE - 2 or data[:1] == b'\x82':
wdata = _pack('!BB18s', 0x11, devnumber, data)
wdata = _pack(b'!BB18s', 0x11, devnumber, data)
else:
wdata = _pack('!BB5s', 0x10, devnumber, data)
wdata = _pack(b'!BB5s', 0x10, devnumber, data)
if _log.isEnabledFor(_DEBUG):
_log.debug("(%s) <= w[%02X %02X %s %s]", handle, ord(wdata[:1]), devnumber, _strhex(wdata[2:4]), _strhex(wdata[4:]))
@ -230,6 +232,7 @@ def _unhandled(report_id, devnumber, data):
from collections import namedtuple
_Event = namedtuple('_Event', ['devnumber', 'sub_id', 'address', 'data'])
_Event.__str__ = lambda self: 'Event(%d,%02X,%02X,%s)' % (self.devnumber, self.sub_id, self.address, _strhex(self.data))
_Event.__unicode__ = _Event.__str__
del namedtuple
def make_event(devnumber, data):
@ -265,9 +268,9 @@ def request(handle, devnumber, request_id, *params):
request_id = (request_id & 0xFFF0) | _random_bits(4) | 0x01
else:
timeout = _RECEIVER_REQUEST_TIMEOUT
request_str = _pack('!H', request_id)
request_str = _pack(b'!H', request_id)
params = b''.join(_pack('B', p) if type(p) == int else p for p in params)
params = b''.join(_pack(b'B', p) if type(p) == int else p for p in params)
# if _log.isEnabledFor(_DEBUG):
# _log.debug("(%s) device %d request_id {%04X} params [%s]", handle, devnumber, request_id, _strhex(params))
@ -349,8 +352,8 @@ def ping(handle, devnumber):
# and set the last (0) bit in swid to make it easier to distinguish requests
# from events
request_id = 0x0010 | _random_bits(4) | 0x01
request_str = _pack('!H', request_id)
ping_mark = _pack('B', _random_bits(8))
request_str = _pack(b'!H', request_id)
ping_mark = _pack(b'B', _random_bits(8))
write(ihandle, devnumber, request_str + b'\x00\x00' + ping_mark)
while True:

View File

@ -2,12 +2,17 @@
# Some common functions and types.
#
from __future__ import absolute_import, division, print_function, unicode_literals
from binascii import hexlify as _hexlify
from struct import pack as _pack
class NamedInt(int):
"""An integer with an attached name."""
"""An reqular Python integer with an attached name.
Careful when using this, because
"""
def __new__(cls, value, name):
obj = int.__new__(cls, value)
@ -17,23 +22,50 @@ class NamedInt(int):
def bytes(self, count=2):
value = int(self)
if value.bit_length() > count * 8:
raise ValueError("cannot fit %X into %d bytes" % (value, count))
raise ValueError('cannot fit %X into %d bytes' % (value, count))
return _pack('!L', value)[-count:]
return _pack(b'!L', value)[-count:]
def __hash__(self):
return int(self)
def __eq__(self, other):
try:
if int(self) == int(other):
return True
except:
pass
return self.name.lower() == str(other).lower()
if isinstance(other, int):
return int(self) == int(other)
def __cmp__(self, other):
return int(self) - int(other)
if isinstance(other, str):
return self.name.lower() == other.lower()
def __ne__(self, other):
if isinstance(other, int):
return int(self) != int(other)
if isinstance(other, str):
return self.name.lower() != other.lower()
def __lt__(self, other):
if not isinstance(other, int):
raise TypeError('unorderable types: %s < %s' % (type(self), type(other)))
return int(self) < int(other)
def __le__(self, other):
if not isinstance(other, int):
raise TypeError('unorderable types: %s <= %s' % (type(self), type(other)))
return int(self) <= int(other)
def __gt__(self, other):
if not isinstance(other, int):
raise TypeError('unorderable types: %s > %s' % (type(self), type(other)))
return int(self) > int(other)
def __ge__(self, other):
if not isinstance(other, int):
raise TypeError('unorderable types: %s >= %s' % (type(self), type(other)))
return int(self) >= int(other)
def __str__(self):
return self.name
__unicode__ = __str__
def __repr__(self):
return 'NamedInt(%d, %s)' % (int(self), repr(self.name))

View File

@ -2,6 +2,8 @@
#
#
from __future__ import absolute_import, division, print_function, unicode_literals
from collections import namedtuple
from .common import NamedInts as _NamedInts

View File

@ -2,6 +2,8 @@
#
#
from __future__ import absolute_import, division, print_function, unicode_literals
from .common import (strhex as _strhex,
NamedInts as _NamedInts,
FirmwareInfo as _FirmwareInfo)

View File

@ -2,6 +2,8 @@
# Logitech Unifying Receiver API.
#
from __future__ import absolute_import, division, print_function, unicode_literals
from struct import pack as _pack, unpack as _unpack
from weakref import proxy as _proxy
@ -152,7 +154,7 @@ class FeaturesArray(object):
self.device = None
return False
reply = self.device.request(int(FEATURE.ROOT), _pack('!H', FEATURE.FEATURE_SET))
reply = self.device.request(int(FEATURE.ROOT), _pack(b'!H', FEATURE.FEATURE_SET))
if reply is None:
self.supported = False
else:
@ -186,7 +188,7 @@ class FeaturesArray(object):
if self.features[index] is None:
feature = self.device.feature_request(FEATURE.FEATURE_SET, 0x10, index)
if feature:
feature, = _unpack('!H', feature[:2])
feature, = _unpack(b'!H', feature[:2])
self.features[index] = FEATURE[feature]
return self.features[index]
@ -203,7 +205,7 @@ class FeaturesArray(object):
break
if may_have:
reply = self.device.request(int(FEATURE.ROOT), _pack('!H', value))
reply = self.device.request(int(FEATURE.ROOT), _pack(b'!H', value))
if reply:
index = ord(reply[0:1])
if index:
@ -222,7 +224,7 @@ class FeaturesArray(object):
raise ValueError("%s not in list" % repr(value))
if may_have:
reply = self.device.request(int(FEATURE.ROOT), _pack('!H', value))
reply = self.device.request(int(FEATURE.ROOT), _pack(b'!H', value))
if reply:
index = ord(reply[0:1])
self.features[index] = FEATURE[int(value)]
@ -263,7 +265,7 @@ class KeysArray(object):
if self.keys[index] is None:
keydata = feature_request(self.device, FEATURE.REPROGRAMMABLE_KEYS, 0x10, index)
if keydata:
key, key_task, flags = _unpack('!HHB', keydata[:5])
key, key_task, flags = _unpack(b'!HHB', keydata[:5])
self.keys[index] = _ReprogrammableKeyInfo(index, KEY[key], KEY[key_task], flags)
return self.keys[index]
@ -293,7 +295,7 @@ class KeysArray(object):
class ToggleFN_Setting(_settings.Setting):
def __init__(self):
super(ToggleFN_Setting, self).__init__('fn-toggle', _settings.KIND.toggle, 'Swap Fx function',
super(ToggleFN_Setting, self).__init__('fn-swap', _settings.KIND.toggle, 'Swap Fx function',
'When set, the F1..F12 keys will activate their special function,\n'
'and you must hold the FN key to activate their standard function.\n'
'\n'
@ -339,7 +341,7 @@ def get_firmware(device):
if fw_info:
level = ord(fw_info[:1]) & 0x0F
if level == 0 or level == 1:
name, version_major, version_minor, build = _unpack('!3sBBH', fw_info[1:8])
name, version_major, version_minor, build = _unpack(b'!3sBBH', fw_info[1:8])
version = '%02X.%02X' % (version_major, version_minor)
if build:
version += '.B%04X' % build
@ -398,7 +400,7 @@ def get_battery(device):
"""
battery = feature_request(device, FEATURE.BATTERY)
if battery:
discharge, dischargeNext, status = _unpack('!BBB', battery[:3])
discharge, dischargeNext, status = _unpack(b'!BBB', battery[:3])
if _log.isEnabledFor(_DEBUG):
_log.debug("device %d battery %d%% charged, next level %d%% charge, status %d = %s",
device.number, discharge, dischargeNext, status, BATTERY_STATUS[status])

View File

@ -2,6 +2,8 @@
#
#
from __future__ import absolute_import, division, print_function, unicode_literals
import threading as _threading
from time import time as _timestamp
@ -70,6 +72,7 @@ class ThreadedHandle(object):
def __str__(self):
if self._local:
return str(int(self))
__unicode__ = __str__
def __repr__(self):
return '<ThreadedHandle(%s)>' % self.path

View File

@ -2,6 +2,8 @@
#
#
from __future__ import absolute_import, division, print_function, unicode_literals
import errno as _errno
from weakref import proxy as _proxy
from collections import defaultdict as _defaultdict
@ -175,18 +177,30 @@ class PairedDevice(object):
return self.number
__int__ = __index__
def __hash__(self):
return self.number
def __lt__(self, other):
return self.number < other.number
def __cmp__(self, other):
return self.number - other.number
def __le__(self, other):
return self.number <= other.number
def __gt__(self, other):
return self.number > other.number
def __ge__(self, other):
return self.number >= other.number
def __eq__(self, other):
return self.receiver == other.receiver and self.number == other.number
def __ne__(self, other):
return self.receiver != other.receiver or self.number != other.number
def __hash__(self):
return self.number
def __str__(self):
return '<PairedDevice(%d,%s)>' % (self.number, self.codename or '?')
__repr__ = __str__
__unicode__ = __repr__ = __str__
#
#
@ -330,7 +344,7 @@ class Receiver(object):
def __str__(self):
return '<Receiver(%s,%s%s)>' % (self.path, '' if type(self.handle) == int else 'T', self.handle)
__repr__ = __str__
__unicode__ = __repr__ = __str__
__bool__ = __nonzero__ = lambda self: self.handle is not None

View File

@ -2,6 +2,8 @@
#
#
from __future__ import absolute_import, division, print_function, unicode_literals
from weakref import proxy as _proxy
from copy import copy as _copy
@ -44,3 +46,4 @@ class Setting(object):
def __str__(self):
return '<%s(%s=%s)>' % (self.__class__.__name__, self.name, self._value)
__unicode__ = __repr__ = __str__

View File

@ -2,6 +2,8 @@
#
#
from __future__ import absolute_import, division, print_function, unicode_literals
from time import time as _timestamp
from struct import unpack as _unpack
from weakref import proxy as _proxy
@ -54,6 +56,7 @@ class ReceiverStatus(dict):
return ('No devices found.' if count == 0 else
'1 device found.' if count == 1 else
'%d devices found.' % count)
__unicode__ = __str__
def _changed(self, alert=ALERT.LOW, reason=None):
# self.updated = _timestamp()
@ -104,6 +107,7 @@ class DeviceStatus(dict):
if self.get(LIGHT_LEVEL) is not None:
t.append('Light: %d lux' % self[LIGHT_LEVEL])
return ', '.join(t)
__unicode__ = __str__
def __bool__(self):
return bool(self._active)
@ -247,7 +251,7 @@ class DeviceStatus(dict):
if feature == _hidpp20.FEATURE.SOLAR_CHARGE:
if event.data[5:9] == b'GOOD':
charge, lux, adc = _unpack('!BHH', event.data[:5])
charge, lux, adc = _unpack(b'!BHH', event.data[:5])
self[BATTERY_LEVEL] = charge
# guesstimate the battery voltage, emphasis on 'guess'
self[BATTERY_STATUS] = '%1.2fV' % (adc * 2.67793237653 / 0x0672)