Skip to content

Avoid changing the type of socket.socket to function.#50

Merged
miketheman merged 2 commits intomiketheman:masterfrom
matthewwardrop:fix_type_change_of_socket.socket
Feb 10, 2021
Merged

Avoid changing the type of socket.socket to function.#50
miketheman merged 2 commits intomiketheman:masterfrom
matthewwardrop:fix_type_change_of_socket.socket

Conversation

@matthewwardrop
Copy link
Copy Markdown
Contributor

@matthewwardrop matthewwardrop commented Feb 3, 2021

Thanks for providing this really useful extension to pytest.

Recently, using pytest-socket interfered with the docker package, which started subclassing socket.socket; and obviously failed since this package changes it to be a function rather than a class.

In this patch, I've replaced the socket guard with a class deriving from socket.socket, but overriding the __new__ method such that any attempt to instantiate it results in the same error as before.

@miketheman
Copy link
Copy Markdown
Owner

Hi @matthewwardrop ! This is an interesting change - how would this impact the docker package's subclassing? Would this allow the package to instantiate socket.socket?

Can you cadd a test to ensure that this new change to return a class remains tested in the future?

@miketheman miketheman added the enhancement New feature or request label Feb 7, 2021
@matthewwardrop
Copy link
Copy Markdown
Contributor Author

matthewwardrop commented Feb 9, 2021

Hi @miketheman! Thanks for your review.

Currently, pytest-socket changes socket.socket to be a function instead of a class, which means that any downstream code that subclasses it will get an error along the lines of:

def guard_func():
    raise RuntimeError("whoops!")
guard_func()
---> RuntimeError("whoops!")

class MyClass(guard_func):
    pass
--> TypeError: function() argument 1 must be code, not str

With this implementation, things behave like so:

class GuardClass:
    def __new__(cls, *args, **kwargs):
        raise RuntimeError("whoops!")
GuardClass()
---> RuntimeError("whoops!")

class MyClass(GuardClass):
    pass
MyClass()
--> RuntimeError("whoops!")

which has the desired behaviour.

The only way a subclass could be instantiated is if they override the __new__ method, which is pretty rare. If they were trying to get around the pytest-socket maliciously, they could do that anyway by directly importing from socket.socket and/or resetting the module cache.

I'll add a test that checks that the type of socket.socket is a class, and that under subclassing things continue to behave as normal (although if that ever fails something is seriously wrong with Python).

@matthewwardrop matthewwardrop force-pushed the fix_type_change_of_socket.socket branch from 095e234 to c831c14 Compare February 9, 2021 18:09
@qlty-cloud-legacy
Copy link
Copy Markdown

Code Climate has analyzed commit c831c14 and detected 0 issues on this pull request.

View more on Code Climate.

@miketheman miketheman merged commit abc3016 into miketheman:master Feb 10, 2021
@miketheman
Copy link
Copy Markdown
Owner

Thanks @matthewwardrop !

I'll include this in the next release - probably sometime later this month.

@matthewwardrop
Copy link
Copy Markdown
Contributor Author

Thanks @miketheman !

@matthewwardrop matthewwardrop deleted the fix_type_change_of_socket.socket branch February 10, 2021 18:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants