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

BF: Fixes ioHub compatiblity issues with Python 3. #1770

Merged
merged 2 commits into from Mar 15, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
26 changes: 18 additions & 8 deletions psychopy/iohub/client/__init__.py
Expand Up @@ -20,6 +20,7 @@
import psychopy.logging as psycho_logging
except ImportError:
psycho_logging = None
from past.builtins import basestring
from ..lazy_import import lazy_import
from .. import _pkgroot, IOHUB_DIRECTORY
from ..util import yload, yLoader
Expand All @@ -29,6 +30,7 @@
from ..devices.computer import Computer
from ..devices.experiment import MessageEvent, LogEvent
from ..constants import DeviceConstants, EventConstants
from psychopy import constants

getTime = Computer.getTime

Expand Down Expand Up @@ -848,9 +850,8 @@ def _startServer(self, ioHubConfig=None, ioHubConfigAbsPath=None):
if len(rootScriptPath)<=1:
rootScriptPath = os.path.abspath(".")
# >>>>> Load / Create / Update iohub config file.....

cfpath = os.path.join(IOHUB_DIRECTORY, 'default_config.yaml')
with file(cfpath, 'r') as config_file:
with open(cfpath, 'r') as config_file:
hub_defaults_config = yload(config_file, Loader=yLoader)

if ioHubConfigAbsPath is None and ioHubConfig is None:
Expand All @@ -871,7 +872,7 @@ def _startServer(self, ioHubConfig=None, ioHubConfigAbsPath=None):
"contain both a 'experiment_info' and a "
"'session_info' entry.")
elif ioHubConfigAbsPath is not None and ioHubConfig is None:
with file(ioHubConfigAbsPath, 'r') as config_file:
with open(ioHubConfigAbsPath, 'r') as config_file:
ioHubConfig = yload(config_file, Loader=yLoader)
else:
raise ValueError('Both a ioHubConfig dict object AND a path to an '
Expand All @@ -893,7 +894,6 @@ def _startServer(self, ioHubConfig=None, ioHubConfigAbsPath=None):
delete=False) as tfile:
tfile.write(json.dumps(ioHubConfig))
ioHubConfigAbsPath = os.path.abspath(tfile.name)

# <<<<< Finished Load / Create / Update iohub config file.

self._iohub_server_config = ioHubConfig
Expand All @@ -903,7 +903,6 @@ def _startServer(self, ioHubConfig=None, ioHubConfigAbsPath=None):
server_udp_port = self._iohub_server_config.get('udp_port', 9000)
from ..net import UDPClientConnection
self.udp_client = UDPClientConnection(remote_port=server_udp_port)

# <<<<< Done Creating open UDP port to ioHub Server

# >>>> Check for orphaned ioHub Process and kill if found...
Expand Down Expand Up @@ -968,17 +967,15 @@ def _startServer(self, ioHubConfig=None, ioHubConfigAbsPath=None):
# for affinity and process priority setting.
Computer.iohub_process_id = self._server_process.pid
Computer.iohub_process = psutil.Process(self._server_process.pid)

# If ioHub server did not respond correctly,
# terminate process and exit the program.
if self._waitForServerInit() is False:
self._server_process.terminate()
return "'ioHub startup failed."
return "ioHub startup failed."

# <<<<< Done starting iohub subprocess

ioHubConnection.ACTIVE_CONNECTION = proxy(self)

# Send iohub server any existing open psychopy window handles.
try:
from psychopy.visual import window
Expand Down Expand Up @@ -1133,6 +1130,19 @@ def _sendToHubServer(self, tx_data):
raise ioHubError(result)

# Otherwise return the result
if constants.PY3 and not result is None:
if isinstance(result, list):
for ind, items in enumerate(result):
if isinstance(items, list) and not items is None:
for nextInd, nested in enumerate(items):
if type(nested) not in [dict, list, int, float, bool] and not nested is None :
result[ind][nextInd] = str(nested, 'utf-8')
elif type(items) not in [dict, list, int, float, bool] and not items is None:
result[ind] = str(items, 'utf-8')
elif type(items) is dict:
result[ind] = {str(keys, 'utf-8'): vals for keys, vals in items.items()}
else:
result = str(result, 'utf-8')
return result

def _sendExperimentInfo(self, experimentInfoDict):
Expand Down
16 changes: 8 additions & 8 deletions psychopy/iohub/client/keyboard.py
Expand Up @@ -5,9 +5,9 @@
from __future__ import division, absolute_import, print_function

from builtins import str
from past.builtins import unicode
from collections import deque
import time

from ..client import ioHubDeviceView, ioEvent, DeviceRPC
from ..devices import DeviceEvent, Computer
from ..util import win32MessagePump
Expand Down Expand Up @@ -50,7 +50,7 @@ def __init__(self, ioe_array):

@property
def key(self):
return self._key
return unicode(self._key, 'utf-8')

@property
def char(self):
Expand All @@ -61,7 +61,7 @@ def char(self):
:return: unicode, '' if no char value is available for the event.

"""
return self._char
return unicode(self._char, 'utf-8')

@property
def modifiers(self):
Expand Down Expand Up @@ -89,9 +89,9 @@ def modifiers(self):

def __str__(self):
return '%s, key: %s char: %s, modifiers: %s' % (
ioEvent.__str__(self), self.key,
self.char,
str(self.modifiers))
ioEvent.__str__(self), unicode(self.key, 'utf-8'),
unicode(self.char, 'utf-8'),
unicode(self.modifiers, 'utf-8'))

def __eq__(self, v):
if isinstance(v, KeyboardEvent):
Expand Down Expand Up @@ -190,9 +190,9 @@ def _syncDeviceState(self):
self._reporting = kb_state.get('reporting_events')
pressed_keys = kb_state.get('pressed_keys')
self._pressed_keys.clear()

akeyix = KeyboardEvent._attrib_index['key']
iotimeix = DeviceEvent.EVENT_HUB_TIME_INDEX

for _, (key_array, _) in list(pressed_keys.items()):
self._pressed_keys[key_array[akeyix]] = key_array[iotimeix]

Expand All @@ -214,6 +214,7 @@ def state(self):
:return: dict
"""
self._syncDeviceState()
self._pressed_keys = {unicode(keys, 'utf-8'): vals for keys, vals in self._pressed_keys.items()}
return self._pressed_keys

@property
Expand Down Expand Up @@ -314,7 +315,6 @@ def filterEvent(e):
if clear is True:
for e in return_events:
self._events[e._type].remove(e)

return return_events

def getPresses(self, keys=None, chars=None, mods=None, clear=True):
Expand Down
6 changes: 3 additions & 3 deletions psychopy/iohub/devices/keyboard/__init__.py
Expand Up @@ -101,11 +101,11 @@ def _close(self):
Device._close(self)

if Computer.platform == 'win32':
from win32 import Keyboard
from .win32 import Keyboard
elif Computer.platform.startswith('linux'):
from linux2 import Keyboard
from .linux2 import Keyboard
elif Computer.platform == 'darwin':
from darwin import Keyboard
from .darwin import Keyboard

############# OS independent Keyboard Event classes ####################

Expand Down
15 changes: 7 additions & 8 deletions psychopy/iohub/server.py
Expand Up @@ -20,6 +20,7 @@
except ImportError:
pass

from past.builtins import basestring, unicode
from . import _pkgroot
from . import IOHUB_DIRECTORY, EXP_SCRIPT_DIRECTORY, _DATA_STORE_AVAILABLE
from .errors import print2err, printExceptionDetailsToStdErr, ioHubError
Expand All @@ -30,7 +31,6 @@
from .devices import DeviceEvent, import_device
from .devices import Computer
from .devices.deviceConfigValidation import validateDeviceConfiguration

getTime = Computer.getTime

MAX_PACKET_SIZE = 64 * 1024
Expand Down Expand Up @@ -59,7 +59,7 @@ def handle(self, request, replyTo):
self.feed(request)
request = self.unpack()
# print2err(">> Rx Packet: {}, {}".format(request, replyTo))
request_type = request.pop(0)
request_type = unicode(request.pop(0), 'utf-8') # convert bytes to string for compatibility
if request_type == 'SYNC_REQ':
self.sendResponse(['SYNC_REPLY', getTime()], replyTo)
return True
Expand Down Expand Up @@ -88,7 +88,7 @@ def handle(self, request, replyTo):

result = None
try:
result = getattr(self, callable_name)
result = getattr(self, unicode(callable_name, 'utf-8'))
except Exception:
print2err('RPC_ATTRIBUTE_ERROR')
printExceptionDetailsToStdErr()
Expand Down Expand Up @@ -195,7 +195,7 @@ def handleGetEvents(self, replyTo):
return False

def handleExperimentDeviceRequest(self, request, replyTo):
request_type = request.pop(0)
request_type = unicode(request.pop(0), 'utf-8') # convert bytes to string for compatibility
io_dev_dict = ioServer.deviceDict
if request_type == 'EVENT_TX':
exp_events = request.pop(0)
Expand All @@ -205,8 +205,8 @@ def handleExperimentDeviceRequest(self, request, replyTo):
self.sendResponse(('EVENT_TX_RESULT', len(exp_events)), replyTo)
return True
elif request_type == 'DEV_RPC':
dclass = request.pop(0)
dmethod = request.pop(0)
dclass = unicode(request.pop(0), 'utf-8')
dmethod = unicode(request.pop(0), 'utf-8')
args = None
kwargs = None
if len(request) == 1:
Expand Down Expand Up @@ -273,7 +273,7 @@ def handleExperimentDeviceRequest(self, request, replyTo):
return False

elif request_type == 'GET_DEV_INTERFACE':
dclass = request.pop(0)
dclass = unicode(request.pop(0), 'utf-8')
data = None
if dclass in ['EyeTracker', 'DAQ']:
for dname, hdevice in ioServer.deviceDict.items():
Expand Down Expand Up @@ -521,7 +521,6 @@ def __init__(self, rootScriptPathDir, config=None):
self._running = True
# start UDP service
self.udpService = udpServer(self, ':%d' % config.get('udp_port', 9000))

self._initDataStore(config, rootScriptPathDir)

self._addDevices(config)
Expand Down