diff --git a/IPython/utils/tests/test_traitlets.py b/IPython/utils/tests/test_traitlets.py index fbf13c2..fcfc458 100755 --- a/IPython/utils/tests/test_traitlets.py +++ b/IPython/utils/tests/test_traitlets.py @@ -27,7 +27,7 @@ from unittest import TestCase from IPython.utils.traitlets import ( HasTraits, MetaHasTraits, TraitType, Any, Int, Long, Float, Complex, Str, Unicode, TraitError, - Undefined, Type, This, Instance + Undefined, Type, This, Instance, TCPAddress ) @@ -684,3 +684,16 @@ class TestUnicode(TraitTestBase): '-10.1', '', u'', 'string', u'string', ] _bad_values = [10, -10, 10L, -10L, 10.1, -10.1, 1j, [10], ['ten'], [u'ten'], {'ten': 10},(10,), None] + + +class TCPAddressTrait(HasTraits): + + value = TCPAddress() + +class TestTCPAddress(TraitTestBase): + + obj = TCPAddressTrait() + + _default_value = ('127.0.0.1',0) + _good_values = [('localhost',0),('192.168.0.1',1000),('www.google.com',80)] + _bad_values = [(0,0),('localhost',10.0),('localhost',-1)] diff --git a/IPython/utils/traitlets.py b/IPython/utils/traitlets.py index 67af9c2..b41f24f 100644 --- a/IPython/utils/traitlets.py +++ b/IPython/utils/traitlets.py @@ -230,8 +230,7 @@ class TraitType(object): def get_default_value(self): """Create a new instance of the default value.""" - dv = self.default_value - return dv + return self.default_value def instance_init(self, obj): """This is called by :meth:`HasTraits.__new__` to finish init'ing. @@ -798,7 +797,6 @@ class Any(TraitType): class Int(TraitType): """A integer trait.""" - evaluate = int default_value = 0 info_text = 'an integer' @@ -820,7 +818,6 @@ class CInt(Int): class Long(TraitType): """A long integer trait.""" - evaluate = long default_value = 0L info_text = 'a long' @@ -845,7 +842,6 @@ class CLong(Long): class Float(TraitType): """A float trait.""" - evaluate = float default_value = 0.0 info_text = 'a float' @@ -869,7 +865,6 @@ class CFloat(Float): class Complex(TraitType): """A trait for complex numbers.""" - evaluate = complex default_value = 0.0 + 0.0j info_text = 'a complex number' @@ -894,7 +889,6 @@ class CComplex(Complex): class Str(TraitType): """A trait for strings.""" - evaluate = lambda x: x default_value = '' info_text = 'a string' @@ -920,7 +914,6 @@ class CStr(Str): class Unicode(TraitType): """A trait for unicode strings.""" - evaluate = unicode default_value = u'' info_text = 'a unicode string' @@ -944,7 +937,7 @@ class CUnicode(Unicode): class Bool(TraitType): """A boolean (True, False) trait.""" - evaluate = bool + default_value = False info_text = 'a boolean' @@ -1023,3 +1016,23 @@ class List(Instance): super(List,self).__init__(klass=list, args=args, allow_none=allow_none, **metadata) + + +class TCPAddress(TraitType): + """A trait for an (ip, port) tuple. + + This allows for both IPv4 IP addresses as well as hostnames. + """ + + default_value = ('127.0.0.1', 0) + info_text = 'an (ip, port) tuple' + + def validate(self, obj, value): + if isinstance(value, tuple): + if len(value) == 2: + if isinstance(value[0], basestring) and isinstance(value[1], int): + port = value[1] + if port >= 0 and port <= 65535: + return value + self.error(obj, value) + diff --git a/IPython/zmq/kernelmanager.py b/IPython/zmq/kernelmanager.py index 00ed3c8..c09dba5 100644 --- a/IPython/zmq/kernelmanager.py +++ b/IPython/zmq/kernelmanager.py @@ -1,4 +1,4 @@ -"""Classes to manage the interaction with a running kernel. +"""Base classes to manage the interaction with a running kernel. Todo ==== @@ -29,7 +29,7 @@ from zmq import POLLIN, POLLOUT, POLLERR from zmq.eventloop import ioloop # Local imports. -from IPython.utils.traitlets import HasTraits, Any, Instance, Type +from IPython.utils.traitlets import HasTraits, Any, Instance, Type, TCPAddress from kernel import launch_kernel from session import Session @@ -61,9 +61,9 @@ class ZmqSocketChannel(Thread): Parameters ---------- - context : zmq.Context + context : :class:`zmq.Context` The ZMQ context to use. - session : session.Session + session : :class:`session.Session` The session to use. address : tuple Standard (ip, port) tuple that the kernel is listening on. @@ -289,6 +289,10 @@ class SubSocketChannel(ZmqSocketChannel): def flush(self, timeout=1.0): """Immediately processes all pending messages on the SUB channel. + Callers should use this method to ensure that :method:`call_handlers` + has been called for all messages that have been received on the + 0MQ SUB socket of this channel. + This method is thread safe. Parameters @@ -324,7 +328,7 @@ class SubSocketChannel(ZmqSocketChannel): msg = self.socket.recv_json(zmq.NOBLOCK) except zmq.ZMQError: # Check the errno? - # Will this tigger POLLERR? + # Will this trigger POLLERR? break else: self.call_handlers(msg) @@ -435,9 +439,9 @@ class KernelManager(HasTraits): rep_channel_class = Type(RepSocketChannel) # Protected traits. - _xreq_address = Any - _sub_address = Any - _rep_address = Any + _xreq_address = TCPAddress + _sub_address = TCPAddress + _rep_address = TCPAddress _xreq_channel = Any _sub_channel = Any _rep_channel = Any @@ -585,4 +589,3 @@ class KernelManager(HasTraits): def rep_address(self): return self._rep_address - diff --git a/IPython/zmq/ktest.py b/IPython/zmq/ktest.py deleted file mode 100644 index 592f935..0000000 --- a/IPython/zmq/ktest.py +++ /dev/null @@ -1,52 +0,0 @@ -from Queue import Queue, Empty -import time - -from kernelmanager import KernelManager - -xreq_addr = ('127.0.0.1',5575) -sub_addr = ('127.0.0.1', 5576) -rep_addr = ('127.0.0.1', 5577) - - -km = KernelManager(xreq_addr, sub_addr, rep_addr) -# xreq_channel = km.xreq_channel -sub_channel = km.sub_channel - -# xreq_channel.start() -sub_channel.start() - -print "Channels are started" - -def printer(msg): - print - print msg - -class CallHandler(object): - - def __init__(self): - self.queue = Queue() - - def __call__(self, handler, msg): - self.queue.put((handler, msg)) - - def handle(self): - try: - handler, msg = self.queue.get(block=False) - except Empty: - pass - else: - handler(msg) - -call_handler = CallHandler() -sub_channel.override_call_handler(call_handler) -sub_channel.add_handler(printer, 'pyin') -sub_channel.add_handler(printer, 'pyout') -sub_channel.add_handler(printer, 'stdout') -sub_channel.add_handler(printer, 'stderr') - -for i in range(100): - call_handler.handle() - time.sleep(1) - -# xreq_channel.join() -sub_channel.join()