Skip to content

Instantly share code, notes, and snippets.

@kaharlichenko
Created September 19, 2014 12:06
Show Gist options
  • Save kaharlichenko/66443cf7afaf517dd67c to your computer and use it in GitHub Desktop.
Save kaharlichenko/66443cf7afaf517dd67c to your computer and use it in GitHub Desktop.
Unix Doman Sockets for Twisted@802ba0f on Python3
commit 37114709f33b0818ed3f18174d740015c786fff9
Author: Ihor Kaharlichenko <[email protected]>
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