1

I'm trying to create a subclass of socket.socket class in Python2.7 with overridden send() and read() methods so that they dump the data transferred over the socket into the terminal. The code looks like this:

import socket

class SocketMonkey(socket.socket):
    def send(self, buf):
        print('BUF: {}'.format(buf))
        return super(SocketMonkey, self).send(buf)

    def recv(self, size=-1):
        buf = super(SocketMonkey, self).recv(size)
        print('BUF: {}'.format(buf))
        return buf

socket.socket = SocketMonkey

And then this is how I instantiate and use this class:

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('www.domain.com', 80))
sock.send('GET / HTTP/1.1\n\n')

I've monkey patched socket module, but while socket functionality works as before, data is not being dumped. Any idea where am I going wrong?

zaadeh
  • 1,711
  • 2
  • 23
  • 37
  • Can you show the code where you're instantiating and using a socket instance? – Jace Browning Oct 05 '15 at 14:12
  • @JaceBrowning I added the usage to question. – zaadeh Oct 05 '15 at 14:20
  • 2
    relevant: http://stackoverflow.com/questions/6976094/subclassing-and-built-in-methods-in-python; summary: sockets don't respect subclassing, use delegation instead. Quick confirmation: `print(sock.send)`. I expect this is a "feature" of `socket` being a C-library, not Python; I have some more exploration to do. – msw Oct 05 '15 at 16:05

1 Answers1

0

I had the same problem too, it's solved using the following code

import socket
import logging

class TestSocket:
    """
    Defines a custom socket class that'll be used for testing.
    """

    def __init__(self, af, sock_type):
        logging.log(logging.DEBUG,
                    f"FAKE SOCKET CONSTRUCT [{af}] [{sock_type}]")

    def sendto(self, data, address):
        logging.log(logging.DEBUG,
                    f"SEND TO [{data}] [{address}]")


def socket_get(af, sock_type):
    return TestSocket(af, sock_type)

def test_download_file(monkeypatch, submission):
    with monkeypatch.context() as m:
        # This replaces the socket constructor.
        m.setattr(socket, "socket", socket_get)
        # use socket now.
        # ...
shakram02
  • 10,812
  • 4
  • 22
  • 21