Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Unix Doman Sockets for Twisted@802ba0f on Python3
commit 37114709f33b0818ed3f18174d740015c786fff9
Author: Ihor Kaharlichenko <madkinder@gmail.com>
Date: Fri Sep 19 15:21:30 2014 +0400
Port Unix Domain Socket support to Python3
See https://twistedmatrix.com/trac/ticket/6466
diff --git a/twisted/internet/endpoints.py b/twisted/internet/endpoints.py
index 238c272..f851ee4 100644
--- a/twisted/internet/endpoints.py
+++ b/twisted/internet/endpoints.py
@@ -63,6 +63,7 @@ __all__ = ["clientFromString", "serverFromString",
__all3__ = ["TCP4ServerEndpoint", "TCP6ServerEndpoint",
"TCP4ClientEndpoint", "TCP6ClientEndpoint",
"SSL4ServerEndpoint", "SSL4ClientEndpoint",
+ "UNIXServerEndpoint", "UNIXClientEndpoint",
"connectProtocol", "HostnameEndpoint"]
diff --git a/twisted/internet/posixbase.py b/twisted/internet/posixbase.py
index 92ec6d2..23cae2b 100644
--- a/twisted/internet/posixbase.py
+++ b/twisted/internet/posixbase.py
@@ -21,7 +21,7 @@ from twisted.internet.interfaces import (
IReactorTCP, IReactorUDP, IReactorSSL, IReactorSocket)
from twisted.internet.interfaces import IReactorProcess, IReactorMulticast
from twisted.internet.interfaces import IHalfCloseableDescriptor
-from twisted.internet import error, udp, tcp
+from twisted.internet import error, udp, tcp, unix
from twisted.python import log, failure, util
from twisted.python.runtime import platformType, platform
@@ -392,18 +392,12 @@ class PosixReactorBase(_SignalReactorMixin, _DisconnectSelectableMixin,
def connectUNIX(self, address, factory, timeout=30, checkPID=0):
assert unixEnabled, "UNIX support is not present"
- # Move this import back up to main level when twisted.internet.unix is
- # ported to Python 3:
- from twisted.internet import unix
c = unix.Connector(address, factory, timeout, self, checkPID)
c.connect()
return c
def listenUNIX(self, address, factory, backlog=50, mode=0o666, wantPID=0):
assert unixEnabled, "UNIX support is not present"
- # Move this import back up to main level when twisted.internet.unix is
- # ported to Python 3:
- from twisted.internet import unix
p = unix.Port(address, factory, backlog, mode, self, wantPID)
p.startListening()
return p
@@ -421,9 +415,6 @@ class PosixReactorBase(_SignalReactorMixin, _DisconnectSelectableMixin,
@returns: object conforming to L{IListeningPort}.
"""
assert unixEnabled, "UNIX support is not present"
- # Move this import back up to main level when twisted.internet.unix is
- # ported to Python 3:
- from twisted.internet import unix
p = unix.DatagramPort(address, protocol, maxPacketSize, mode, self)
p.startListening()
return p
@@ -436,9 +427,6 @@ class PosixReactorBase(_SignalReactorMixin, _DisconnectSelectableMixin,
EXPERIMENTAL.
"""
assert unixEnabled, "UNIX support is not present"
- # Move this import back up to main level when twisted.internet.unix is
- # ported to Python 3:
- from twisted.internet import unix
p = unix.ConnectedDatagramPort(address, protocol, maxPacketSize, mode, bindAddress, self)
p.startListening()
return p
diff --git a/twisted/internet/test/test_unix.py b/twisted/internet/test/test_unix.py
index d6b48cb..42a5f39 100644
--- a/twisted/internet/test/test_unix.py
+++ b/twisted/internet/test/test_unix.py
@@ -5,6 +5,7 @@
Tests for implementations of L{IReactorUNIX}.
"""
+import sys
from stat import S_IMODE
from os import stat, close
from tempfile import mktemp
@@ -17,7 +18,7 @@ try:
except ImportError:
AF_UNIX = None
-from zope.interface import implements
+from zope.interface import implements, implementer
from twisted.python.log import addObserver, removeObserver, err
from twisted.python.failure import Failure
@@ -56,7 +57,7 @@ class UNIXFamilyMixin:
Assert that the mode of the created unix socket is set to the mode
specified to the reactor method.
"""
- mode = 0600
+ mode = 0o600
reactor = self.buildReactor()
unixPort = getattr(reactor, methodName)(path, factory, mode=mode)
unixPort.stopListening()
@@ -70,7 +71,7 @@ def _abstractPath(case):
# Use the test cases's mktemp to get something unique, but also squash it
# down to make sure it fits in the unix socket path limit (something around
# 110 bytes).
- return md5(case.mktemp()).hexdigest()
+ return md5(case.mktemp().encode(sys.getfilesystemencoding())).hexdigest()
@@ -135,7 +136,7 @@ class SendFileDescriptor(ConnectableProtocol):
self.reason = reason
-
+@implementer(IFileDescriptorReceiver)
class ReceiveFileDescriptor(ConnectableProtocol):
"""
L{ReceiveFileDescriptor} provides an API for waiting for file descriptors to
@@ -148,8 +149,6 @@ class ReceiveFileDescriptor(ConnectableProtocol):
received, or with a failure if the connection is lost with no descriptor
arriving.
"""
- implements(IFileDescriptorReceiver)
-
reason = None
waiting = None
diff --git a/twisted/internet/unix.py b/twisted/internet/unix.py
index 77b87cd..6838ec3 100644
--- a/twisted/internet/unix.py
+++ b/twisted/internet/unix.py
@@ -15,7 +15,7 @@ Maintainer: Itamar Shtull-Trauring
import os, sys, stat, socket, struct
from errno import EINTR, EMSGSIZE, EAGAIN, EWOULDBLOCK, ECONNREFUSED, ENOBUFS
-from zope.interface import implements, implementsOnly, implementedBy
+from zope.interface import implementedBy, implementer, implementer_only
if not hasattr(socket, 'AF_UNIX'):
raise ImportError("UNIX sockets not supported on this platform")
@@ -41,7 +41,7 @@ def _ancillaryDescriptor(fd):
return [(socket.SOL_SOCKET, sendmsg.SCM_RIGHTS, packed)]
-
+@implementer(interfaces.IUNIXTransport)
class _SendmsgMixin(object):
"""
Mixin for stream-oriented UNIX transports which uses sendmsg and recvmsg to
@@ -60,7 +60,6 @@ class _SendmsgMixin(object):
descriptors to accept and queue for sending before pausing the
registered producer, if there is one.
"""
- implements(interfaces.IUNIXTransport)
_writeSomeDataBase = None
_fileDescriptorBufferSize = 64
@@ -126,7 +125,7 @@ class _SendmsgMixin(object):
untilConcludes(
sendmsg.send1msg, self.socket.fileno(), data[index], 0,
_ancillaryDescriptor(fd))
- except socket.error, se:
+ except socket.error as se:
if se.args[0] in (EWOULDBLOCK, ENOBUFS):
return index
else:
@@ -159,7 +158,7 @@ class _SendmsgMixin(object):
try:
data, flags, ancillary = untilConcludes(
sendmsg.recv1msg, self.socket.fileno(), 0, self.bufferSize)
- except socket.error, se:
+ except socket.error as se:
if se.args[0] == EWOULDBLOCK:
return
else:
@@ -244,7 +243,7 @@ class Port(_UNIXPort, tcp.Port):
transport = Server
lockFile = None
- def __init__(self, fileName, factory, backlog=50, mode=0666, reactor=None, wantPID = 0):
+ def __init__(self, fileName, factory, backlog=50, mode=0o666, reactor=None, wantPID=0):
tcp.Port.__init__(self, fileName, factory, backlog, reactor=reactor)
self.mode = mode
self.wantPID = wantPID
@@ -271,7 +270,7 @@ class Port(_UNIXPort, tcp.Port):
if self.wantPID:
self.lockFile = lockfile.FilesystemLock(self.port + ".lock")
if not self.lockFile.lock():
- raise CannotListenError, (None, self.port, "Cannot acquire lock")
+ raise CannotListenError(None, self.port, "Cannot acquire lock")
else:
if not self.lockFile.clean:
try:
@@ -289,8 +288,8 @@ class Port(_UNIXPort, tcp.Port):
try:
skt = self.createInternetSocket()
skt.bind(self.port)
- except socket.error, le:
- raise CannotListenError, (None, self.port, le)
+ except socket.error as le:
+ raise CannotListenError(None, self.port, le)
else:
if _inFilesystemNamespace(self.port):
# Make the socket readable and writable to the world.
@@ -355,14 +354,13 @@ class Connector(base.BaseConnector):
return address.UNIXAddress(self.address)
+@implementer(interfaces.IUNIXDatagramTransport)
class DatagramPort(_UNIXPort, udp.Port):
"""Datagram UNIX port, listening for packets."""
- implements(interfaces.IUNIXDatagramTransport)
-
addressFamily = socket.AF_UNIX
- def __init__(self, addr, proto, maxPacketSize=8192, mode=0666, reactor=None):
+ def __init__(self, addr, proto, maxPacketSize=8192, mode=0o666, reactor=None):
"""Initialize with address to listen on.
"""
udp.Port.__init__(self, addr, proto, maxPacketSize=maxPacketSize, reactor=reactor)
@@ -383,8 +381,8 @@ class DatagramPort(_UNIXPort, udp.Port):
skt = self.createInternetSocket() # XXX: haha misnamed method
if self.port:
skt.bind(self.port)
- except socket.error, le:
- raise error.CannotListenError, (None, self.port, le)
+ except socket.error as le:
+ raise error.CannotListenError(None, self.port, le)
if self.port and _inFilesystemNamespace(self.port):
# Make the socket readable and writable to the world.
os.chmod(self.port, self.mode)
@@ -396,12 +394,12 @@ class DatagramPort(_UNIXPort, udp.Port):
"""Write a datagram."""
try:
return self.socket.sendto(datagram, address)
- except socket.error, se:
+ except socket.error as se:
no = se.args[0]
if no == EINTR:
return self.write(datagram, address)
elif no == EMSGSIZE:
- raise error.MessageLengthError, "message too long"
+ raise error.MessageLengthError("message too long")
elif no == EAGAIN:
# oh, well, drop the data. The only difference from UDP
# is that UDP won't ever notice.
@@ -431,16 +429,14 @@ class DatagramPort(_UNIXPort, udp.Port):
self.logstr = reflect.qual(self.protocol.__class__) + " (UDP)"
-
+@implementer_only(interfaces.IUNIXDatagramConnectedTransport,
+ *(implementedBy(base.BasePort)))
class ConnectedDatagramPort(DatagramPort):
"""
A connected datagram UNIX socket.
"""
- implementsOnly(interfaces.IUNIXDatagramConnectedTransport,
- *(implementedBy(base.BasePort)))
-
- def __init__(self, addr, proto, maxPacketSize=8192, mode=0666,
+ def __init__(self, addr, proto, maxPacketSize=8192, mode=0o666,
bindAddress=None, reactor=None):
assert isinstance(proto, protocol.ConnectedDatagramProtocol)
DatagramPort.__init__(self, bindAddress, proto, maxPacketSize, mode,
@@ -479,7 +475,7 @@ class ConnectedDatagramPort(DatagramPort):
data, addr = self.socket.recvfrom(self.maxPacketSize)
read += len(data)
self.protocol.datagramReceived(data)
- except socket.error, se:
+ except socket.error as se:
no = se.args[0]
if no in (EAGAIN, EINTR, EWOULDBLOCK):
return
@@ -497,12 +493,12 @@ class ConnectedDatagramPort(DatagramPort):
"""
try:
return self.socket.send(data)
- except socket.error, se:
+ except socket.error as se:
no = se.args[0]
if no == EINTR:
return self.write(data)
elif no == EMSGSIZE:
- raise error.MessageLengthError, "message too long"
+ raise error.MessageLengthError("message too long")
elif no == ECONNREFUSED:
self.protocol.connectionRefused()
elif no == EAGAIN:
diff --git a/twisted/python/dist3.py b/twisted/python/dist3.py
index a754eee..b632774 100644
--- a/twisted/python/dist3.py
+++ b/twisted/python/dist3.py
@@ -65,6 +65,7 @@ modules = [
"twisted.internet.test.reactormixins",
"twisted.internet.threads",
"twisted.internet.udp",
+ "twisted.internet.unix",
"twisted.internet.utils",
"twisted.names",
"twisted.names.cache",
@@ -173,6 +174,7 @@ testModules = [
"twisted.internet.test.test_tls",
"twisted.internet.test.test_udp",
"twisted.internet.test.test_udp_internals",
+ "twisted.internet.test.test_unix",
"twisted.names.test.test_cache",
"twisted.names.test.test_client",
"twisted.names.test.test_common",
diff --git a/twisted/python/reflect.py b/twisted/python/reflect.py
index 363553e..4f66fce 100644
--- a/twisted/python/reflect.py
+++ b/twisted/python/reflect.py
@@ -9,6 +9,8 @@ with Python's reflection capabilities.
from __future__ import division, absolute_import, print_function
+from __future__ import print_function
+
import sys
import types
import os
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.